[lld] c5ffe97 - [lld/mac] Implement support for searching dylibs with @rpath/ in install name
Nico Weber via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 7 03:23:02 PDT 2021
Author: Nico Weber
Date: 2021-06-07T06:22:52-04:00
New Revision: c5ffe9798850a699c2229899712ca9d153f2a4b8
URL: https://github.com/llvm/llvm-project/commit/c5ffe9798850a699c2229899712ca9d153f2a4b8
DIFF: https://github.com/llvm/llvm-project/commit/c5ffe9798850a699c2229899712ca9d153f2a4b8.diff
LOG: [lld/mac] Implement support for searching dylibs with @rpath/ in install name
Also adjust a few comments, and move the DylibFile comment talking about
umbrella next to the parameter again.
Differential Revision: https://reviews.llvm.org/D103783
Added:
lld/test/MachO/link-search-at-rpath.s
Modified:
lld/MachO/DriverUtils.cpp
lld/MachO/InputFiles.cpp
lld/MachO/InputFiles.h
lld/test/MachO/rpath.s
Removed:
################################################################################
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index 01b174297e52..f04327456350 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -216,10 +216,10 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
file = make<DylibFile>(**result, umbrella, isBundleLoader);
// parseReexports() can recursively call loadDylib(). That's fine since
- // we wrote DylibFile we just loaded to the loadDylib cache via the `file`
- // reference. But the recursive load can grow loadDylibs, so the `file`
- // reference might become invalid after parseReexports() -- so copy the
- // pointer it refers to before going on.
+ // we wrote the DylibFile we just loaded to the loadDylib cache via the
+ // `file` reference. But the recursive load can grow loadDylibs, so the
+ // `file` reference might become invalid after parseReexports() -- so copy
+ // the pointer it refers to before continuing.
newFile = file;
if (newFile->exportingFile)
newFile->parseReexports(**result);
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 2fe338f3489f..9051ae12d023 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -760,7 +760,8 @@ static DylibFile *findDylib(StringRef path, DylibFile *umbrella,
resolveDylibPath((root + path).str()))
return loadDylib(*dylibPath, umbrella);
- // TODO: Expand @rpath, handle -dylib_file
+ // TODO: Handle -dylib_file
+
SmallString<128> newPath;
if (config->outputType == MH_EXECUTE &&
path.consume_front("@executable_path/")) {
@@ -771,6 +772,15 @@ static DylibFile *findDylib(StringRef path, DylibFile *umbrella,
} else if (path.consume_front("@loader_path/")) {
path::append(newPath, sys::path::parent_path(umbrella->getName()), path);
path = newPath;
+ } else if (path.startswith("@rpath/")) {
+ for (StringRef rpath : umbrella->rpaths) {
+ newPath.clear();
+ if (rpath.consume_front("@loader_path/"))
+ path::append(newPath, sys::path::parent_path(umbrella->getName()));
+ path::append(newPath, rpath, path.drop_front(strlen("@rpath/")));
+ if (Optional<std::string> dylibPath = resolveDylibPath(newPath))
+ return loadDylib(*dylibPath, umbrella);
+ }
}
if (currentTopLevelTapi) {
@@ -854,6 +864,11 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella,
if (!checkCompatibility(this))
return;
+ for (auto *cmd : findCommands<rpath_command>(hdr, LC_RPATH)) {
+ StringRef rpath{reinterpret_cast<const char *>(cmd) + cmd->path};
+ rpaths.push_back(rpath);
+ }
+
// Initialize symbols.
exportingFile = isImplicitlyLinked(installName) ? this : this->umbrella;
if (const load_command *cmd = findCommand(hdr, LC_DYLD_INFO_ONLY)) {
diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h
index 3c723948242b..29640b6c5fae 100644
--- a/lld/MachO/InputFiles.h
+++ b/lld/MachO/InputFiles.h
@@ -127,16 +127,9 @@ class OpaqueFile : public InputFile {
static bool classof(const InputFile *f) { return f->kind() == OpaqueKind; }
};
-// .dylib file
+// .dylib or .tbd file
class DylibFile : public InputFile {
public:
- explicit DylibFile(MemoryBufferRef mb, DylibFile *umbrella,
- bool isBundleLoader = false);
-
- explicit DylibFile(const llvm::MachO::InterfaceFile &interface,
- DylibFile *umbrella = nullptr,
- bool isBundleLoader = false);
-
// Mach-O dylibs can re-export other dylibs as sub-libraries, meaning that the
// symbols in those sub-libraries will be available under the umbrella
// library's namespace. Those sub-libraries can also have their own
@@ -144,6 +137,12 @@ class DylibFile : public InputFile {
// the root dylib to ensure symbols in the child library are correctly bound
// to the root. On the other hand, if a dylib is being directly loaded
// (through an -lfoo flag), then `umbrella` should be a nullptr.
+ explicit DylibFile(MemoryBufferRef mb, DylibFile *umbrella,
+ bool isBundleLoader = false);
+ explicit DylibFile(const llvm::MachO::InterfaceFile &interface,
+ DylibFile *umbrella = nullptr,
+ bool isBundleLoader = false);
+
void parseLoadCommands(MemoryBufferRef mb);
void parseReexports(const llvm::MachO::InterfaceFile &interface);
@@ -152,6 +151,7 @@ class DylibFile : public InputFile {
StringRef installName;
DylibFile *exportingFile = nullptr;
DylibFile *umbrella;
+ SmallVector<StringRef, 2> rpaths;
uint32_t compatibilityVersion = 0;
uint32_t currentVersion = 0;
int64_t ordinal = 0; // Ordinal numbering starts from 1, so 0 is a sentinel
diff --git a/lld/test/MachO/link-search-at-rpath.s b/lld/test/MachO/link-search-at-rpath.s
new file mode 100644
index 000000000000..dbc0d4b3cbf6
--- /dev/null
+++ b/lld/test/MachO/link-search-at-rpath.s
@@ -0,0 +1,38 @@
+# REQUIRES: x86
+
+# RUN: rm -rf %t; split-file %s %t
+# RUN: mkdir %t/subdir
+# RUN: mkdir %t/subdir2
+
+# 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 @rpath/libfoo.dylib %t/foo.o -o %t/subdir/libfoo.dylib
+
+# RUN: %lld -dylib -reexport_library %t/subdir/libfoo.dylib \
+# RUN: -rpath @loader_path/../foo \
+# RUN: -rpath @loader_path/../subdir \
+# RUN: -rpath @loader_path/../foo \
+# RUN: %t/bar.o -o %t/subdir2/libbar.dylib
+
+# RUN: %lld -lSystem %t/main.o %t/subdir2/libbar.dylib -o %t/test
+# RUN: %lld -dylib -lSystem %t/main.o %t/subdir2/libbar.dylib -o %t/libtest.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
diff --git a/lld/test/MachO/rpath.s b/lld/test/MachO/rpath.s
index dc998889a47c..5b404a36b26b 100644
--- a/lld/test/MachO/rpath.s
+++ b/lld/test/MachO/rpath.s
@@ -3,11 +3,14 @@
# RUN: %lld -o %t %t.o
## Check that -rpath generates LC_RPATH.
-# RUN: %lld -o %t %t.o -rpath /some/rpath
+# RUN: %lld -o %t %t.o -rpath /some/rpath -rpath /another/rpath
# RUN: llvm-objdump --macho --all-headers %t | FileCheck %s
# CHECK: LC_RPATH
# CHECK-NEXT: cmdsize 24
# CHECK-NEXT: path /some/rpath
+# CHECK: LC_RPATH
+# CHECK-NEXT: cmdsize 32
+# CHECK-NEXT: path /another/rpath
.text
.global _main
More information about the llvm-commits
mailing list