[lld] check cache in loadDylib before real_path (#143595)

This commit is contained in:
Richard Howell 2025-06-17 07:18:50 -07:00 committed by GitHub
parent 414710c753
commit 35f6d91720
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 108 additions and 6 deletions

View File

@ -225,14 +225,21 @@ std::optional<StringRef> macho::resolveDylibPath(StringRef dylibPath) {
// especially if it's a commonly re-exported core library.
static DenseMap<CachedHashStringRef, DylibFile *> loadedDylibs;
static StringRef realPathIfDifferent(StringRef path) {
SmallString<128> realPathBuf;
if (fs::real_path(path, realPathBuf))
return StringRef();
SmallString<128> absPathBuf = path;
if (!fs::make_absolute(absPathBuf) && realPathBuf == absPathBuf)
return StringRef();
return uniqueSaver().save(StringRef(realPathBuf));
}
DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
bool isBundleLoader, bool explicitlyLinked) {
// Frameworks can be found from different symlink paths, so resolve
// symlinks before looking up in the dylib cache.
SmallString<128> realPath;
std::error_code err = fs::real_path(mbref.getBufferIdentifier(), realPath);
CachedHashStringRef path(!err ? uniqueSaver().save(StringRef(realPath))
: mbref.getBufferIdentifier());
CachedHashStringRef path(mbref.getBufferIdentifier());
DylibFile *&file = loadedDylibs[path];
if (file) {
if (explicitlyLinked)
@ -240,6 +247,22 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
return file;
}
// Frameworks can be found from different symlink paths, so resolve
// symlinks and look up in the dylib cache.
CachedHashStringRef realPath(
realPathIfDifferent(mbref.getBufferIdentifier()));
if (!realPath.val().empty()) {
// Avoid map insertions here so that we do not invalidate the "file"
// reference.
auto it = loadedDylibs.find(realPath);
if (it != loadedDylibs.end()) {
DylibFile *realfile = it->second;
if (explicitlyLinked)
realfile->setExplicitlyLinked();
return realfile;
}
}
DylibFile *newFile;
file_magic magic = identify_magic(mbref.getBuffer());
if (magic == file_magic::tapi_file) {
@ -292,6 +315,11 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
sys::path::filename(newFile->installName) + "' because " +
config->clientName + " is not an allowed client");
}
// If the load path was a symlink, cache the real path too.
if (!realPath.val().empty())
loadedDylibs[realPath] = newFile;
return newFile;
}

View File

@ -0,0 +1,74 @@
# REQUIRES: aarch64, shell
# RUN: rm -rf %t; split-file %s %t
# RUN: ln -s Versions/A/Developer %t/Developer/Library/Frameworks/Developer.framework/
# RUN: llvm-mc -filetype obj -triple arm64-apple-macos11.0 %t/test.s -o %t/test.o
# RUN: %lld -arch arm64 -platform_version macos 11.0 11.0 -o %t/test -framework Developer -F %t/Developer/Library/Frameworks -L %t/Developer/usr/lib %t/test.o -t | FileCheck %s
# CHECK: {{.*}}/Developer/Library/Frameworks/Developer.framework/Developer
# CHECK: {{.*}}/Developer/usr/lib/libDeveloperSupport.tbd(@rpath/libDeveloperSupport.dylib)
# CHECK-NOT: {{.*}}/Developer/Library/Frameworks/Developer.framework/Versions/A/Developer
#--- Developer/Library/Frameworks/Developer.framework/Versions/A/Developer
{
"tapi_tbd_version": 5,
"main_library": {
"target_info": [
{
"target": "arm64-macos"
}
],
"install_names": [
{
"name": "@rpath/Developer.framework/Developer"
}
],
"exported_symbols": [
{
"text": {
"global": ["_funcPublic"]
}
}
]
}
}
#--- Developer/usr/lib/libDeveloperSupport.tbd
{
"tapi_tbd_version": 5,
"main_library": {
"target_info": [
{
"target": "arm64-macos"
}
],
"install_names": [
{
"name": "@rpath/libDeveloperSupport.dylib"
}
],
"reexported_libraries": [
{
"names": [
"@rpath/Developer.framework/Versions/A/Developer"
]
}
],
"exported_symbols": [
{
"text": {
"global": ["_funcSupport"]
}
}
]
}
}
#--- test.s
.text
.globl _main
.linker_option "-lDeveloperSupport"
_main:
ret
.data
.quad _funcPublic
.quad _funcSupport