diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp index f7f6be049f0e..a3b722f13dac 100644 --- a/lld/MachO/DriverUtils.cpp +++ b/lld/MachO/DriverUtils.cpp @@ -225,14 +225,21 @@ std::optional macho::resolveDylibPath(StringRef dylibPath) { // especially if it's a commonly re-exported core library. static DenseMap 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; } diff --git a/lld/test/MachO/reexport-with-symlink.s b/lld/test/MachO/reexport-with-symlink.s new file mode 100644 index 000000000000..a6b5992713f3 --- /dev/null +++ b/lld/test/MachO/reexport-with-symlink.s @@ -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