[lld] check cache in loadDylib before real_path (#143595)
This commit is contained in:
@@ -225,14 +225,21 @@ std::optional<StringRef> macho::resolveDylibPath(StringRef dylibPath) {
|
|||||||
// especially if it's a commonly re-exported core library.
|
// especially if it's a commonly re-exported core library.
|
||||||
static DenseMap<CachedHashStringRef, DylibFile *> loadedDylibs;
|
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,
|
DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
|
||||||
bool isBundleLoader, bool explicitlyLinked) {
|
bool isBundleLoader, bool explicitlyLinked) {
|
||||||
// Frameworks can be found from different symlink paths, so resolve
|
CachedHashStringRef path(mbref.getBufferIdentifier());
|
||||||
// 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());
|
|
||||||
DylibFile *&file = loadedDylibs[path];
|
DylibFile *&file = loadedDylibs[path];
|
||||||
if (file) {
|
if (file) {
|
||||||
if (explicitlyLinked)
|
if (explicitlyLinked)
|
||||||
@@ -240,6 +247,22 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
|
|||||||
return file;
|
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;
|
DylibFile *newFile;
|
||||||
file_magic magic = identify_magic(mbref.getBuffer());
|
file_magic magic = identify_magic(mbref.getBuffer());
|
||||||
if (magic == file_magic::tapi_file) {
|
if (magic == file_magic::tapi_file) {
|
||||||
@@ -292,6 +315,11 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
|
|||||||
sys::path::filename(newFile->installName) + "' because " +
|
sys::path::filename(newFile->installName) + "' because " +
|
||||||
config->clientName + " is not an allowed client");
|
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;
|
return newFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
74
lld/test/MachO/reexport-with-symlink.s
Normal file
74
lld/test/MachO/reexport-with-symlink.s
Normal 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
|
||||||
Reference in New Issue
Block a user