From a48bd587f7d28ce71b8d7ba6f0fb6499072acf40 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sun, 6 Jun 2021 16:57:19 -0400 Subject: [PATCH] [lld/mac] Implement support for searching dylibs with @executable_path/ in install name Differential Revision: https://reviews.llvm.org/D103775 --- lld/MachO/InputFiles.cpp | 10 +++++- lld/test/MachO/link-search-at-executable-path.s | 41 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 lld/test/MachO/link-search-at-executable-path.s diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp index 288a3ac..ac34920 100644 --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -760,7 +760,15 @@ DylibFile *findDylib(StringRef path, DylibFile *umbrella, resolveDylibPath((root + path).str())) return loadDylib(*dylibPath, umbrella); - // TODO: Expand @loader_path, @executable_path, @rpath etc, handle -dylib_path + // TODO: Expand @loader_path, @rpath etc, handle -dylib_file + SmallString<128> newPath; + if (config->outputType == MH_EXECUTE && + path.consume_front("@executable_path/")) { + // ld64 allows overriding this with the undocumented flag -executable_path. + // lld doesn't currently implement that flag. + path::append(newPath, sys::path::parent_path(config->outputFile), path); + path = newPath; + } if (currentTopLevelTapi) { for (InterfaceFile &child : diff --git a/lld/test/MachO/link-search-at-executable-path.s b/lld/test/MachO/link-search-at-executable-path.s new file mode 100644 index 0000000..29f2ac8 --- /dev/null +++ b/lld/test/MachO/link-search-at-executable-path.s @@ -0,0 +1,41 @@ +# REQUIRES: x86 + +# RUN: rm -rf %t; split-file %s %t +# RUN: mkdir %t/subdir + +# RUN: llvm-mc -filetype obj -triple x86_64-apple-darwin %t/foo.s -o %t/foo.o +# RUN: llvm-mc -filetype obj -triple x86_64-apple-darwin %t/bar.s -o %t/bar.o +# RUN: llvm-mc -filetype obj -triple x86_64-apple-darwin %t/main.s -o %t/main.o + +# RUN: %lld -dylib -install_name @executable_path/libfoo.dylib %t/foo.o -o %t/subdir/libfoo.dylib + +# RUN: %lld -dylib -reexport_library %t/subdir/libfoo.dylib %t/bar.o -o %t/libbar.dylib + +## When linking executables, @executable_path/ in install_name should be replaced +## by the path of the executable. +# RUN: %lld -lSystem %t/main.o %t/libbar.dylib -o %t/subdir/test + +## This doesn't work for non-executables. +# RUN: not %lld -dylib -lSystem %t/main.o %t/libbar.dylib -o %t/subdir/libtest.dylib 2>&1 | FileCheck --check-prefix=ERR %s + +## It also doesn't help if the needed reexport isn't next to the library. +# RUN: not %lld -lSystem %t/main.o %t/libbar.dylib -o %t/test 2>&1 | FileCheck --check-prefix=ERR %s +# ERR: error: unable to locate re-export with install name @executable_path/libfoo.dylib + +#--- foo.s +.globl _foo +_foo: + retq + +#--- bar.s +.globl _bar +_bar: + retq + +#--- main.s +.section __TEXT,__text +.global _main +_main: + callq _foo + callq _bar + ret -- 2.7.4