[lld] db7a413 - [lld-macho] Re-root absolute input file paths if -syslibroot is specified
Jez Ng via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 15 18:16:47 PDT 2021
Author: Jez Ng
Date: 2021-04-15T21:16:33-04:00
New Revision: db7a413e51c5134375d564a1599b8657ca1c8161
URL: https://github.com/llvm/llvm-project/commit/db7a413e51c5134375d564a1599b8657ca1c8161
DIFF: https://github.com/llvm/llvm-project/commit/db7a413e51c5134375d564a1599b8657ca1c8161.diff
LOG: [lld-macho] Re-root absolute input file paths if -syslibroot is specified
Reviewed By: #lld-macho, gkm
Differential Revision: https://reviews.llvm.org/D100147
Added:
lld/test/MachO/reroot-path.s
Modified:
lld/MachO/Driver.cpp
lld/test/MachO/dependency-info.s
Removed:
################################################################################
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index ec20bdc92419..527829726648 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -76,16 +76,19 @@ static HeaderFileType getOutputType(const InputArgList &args) {
}
}
-static Optional<std::string>
-findAlongPathsWithExtensions(StringRef name, ArrayRef<StringRef> extensions) {
+// Search for all possible combinations of `{root}/{name}.{extension}`.
+// If \p extensions are not specified, then just search for `{root}/{name}`.
+static Optional<StringRef>
+findPathCombination(const Twine &name, const std::vector<StringRef> &roots,
+ ArrayRef<StringRef> extensions = {""}) {
SmallString<261> base;
- for (StringRef dir : config->librarySearchPaths) {
+ for (StringRef dir : roots) {
base = dir;
- path::append(base, Twine("lib") + name);
+ path::append(base, name);
for (StringRef ext : extensions) {
Twine location = base + ext;
if (fs::exists(location))
- return location.str();
+ return saver.save(location.str());
else
depTracker->logFileNotFound(location);
}
@@ -93,14 +96,29 @@ findAlongPathsWithExtensions(StringRef name, ArrayRef<StringRef> extensions) {
return {};
}
-static Optional<std::string> findLibrary(StringRef name) {
+static Optional<StringRef> findLibrary(StringRef name) {
if (config->searchDylibsFirst) {
- if (Optional<std::string> path =
- findAlongPathsWithExtensions(name, {".tbd", ".dylib"}))
+ if (Optional<StringRef> path = findPathCombination(
+ "lib" + name, config->librarySearchPaths, {".tbd", ".dylib"}))
return path;
- return findAlongPathsWithExtensions(name, {".a"});
+ return findPathCombination("lib" + name, config->librarySearchPaths,
+ {".a"});
}
- return findAlongPathsWithExtensions(name, {".tbd", ".dylib", ".a"});
+ return findPathCombination("lib" + name, config->librarySearchPaths,
+ {".tbd", ".dylib", ".a"});
+}
+
+// If -syslibroot is specified, absolute paths to non-object files may be
+// rerooted.
+static StringRef rerootPath(StringRef path) {
+ if (!path::is_absolute(path, path::Style::posix) || path.endswith(".o"))
+ return path;
+
+ if (Optional<StringRef> rerootedPath =
+ findPathCombination(path, config->systemLibraryRoots))
+ return *rerootedPath;
+
+ return path;
}
static Optional<std::string> findFramework(StringRef name) {
@@ -337,7 +355,7 @@ static InputFile *addFile(StringRef path, bool forceLoadArchive,
}
static void addLibrary(StringRef name, bool isWeak) {
- if (Optional<std::string> path = findLibrary(name)) {
+ if (Optional<StringRef> path = findLibrary(name)) {
auto *dylibFile = dyn_cast_or_null<DylibFile>(addFile(*path, false));
if (isWeak && dylibFile)
dylibFile->forceWeakImport = true;
@@ -396,7 +414,7 @@ static void addFileList(StringRef path) {
return;
MemoryBufferRef mbref = *buffer;
for (StringRef path : args::getLines(mbref))
- addFile(path, false);
+ addFile(rerootPath(path), false);
}
// An order file has one entry per line, in the following format:
@@ -814,18 +832,18 @@ void createFiles(const InputArgList &args) {
switch (opt.getID()) {
case OPT_INPUT:
- addFile(arg->getValue(), false);
+ addFile(rerootPath(arg->getValue()), false);
break;
case OPT_weak_library:
- if (auto *dylibFile =
- dyn_cast_or_null<DylibFile>(addFile(arg->getValue(), false)))
+ if (auto *dylibFile = dyn_cast_or_null<DylibFile>(
+ addFile(rerootPath(arg->getValue()), false)))
dylibFile->forceWeakImport = true;
break;
case OPT_filelist:
addFileList(arg->getValue());
break;
case OPT_force_load:
- addFile(arg->getValue(), true);
+ addFile(rerootPath(arg->getValue()), true);
break;
case OPT_l:
case OPT_weak_l:
diff --git a/lld/test/MachO/dependency-info.s b/lld/test/MachO/dependency-info.s
index 9e69ea16980f..761fb4393ae0 100644
--- a/lld/test/MachO/dependency-info.s
+++ b/lld/test/MachO/dependency-info.s
@@ -20,7 +20,7 @@
# CHECK-DAG: input-file: {{.*}}{{[/\]}}main.o
# CHECK-DAG: input-file: {{.*}}bar.o
-# CHECK-NEXT: not-found: {{.*}}{{[/\]}}libdyld.{{.*}}
+# CHECK: not-found: {{.*}}{{[/\]}}libdyld.{{.*}}
## There could be more not-found here but we are not checking those because it's brittle.
# CHECK: output-file: {{.*}}{{[/\]}}test.out
diff --git a/lld/test/MachO/reroot-path.s b/lld/test/MachO/reroot-path.s
new file mode 100644
index 000000000000..b70c72e14984
--- /dev/null
+++ b/lld/test/MachO/reroot-path.s
@@ -0,0 +1,64 @@
+# REQUIRES: x86
+# UNSUPPORTED: system-windows
+## FIXME: In principle this test should pass on Windows
+# RUN: rm -rf %t; split-file %s %t
+
+## This test verifies that we attempt to re-root absolute paths if -syslibroot
+## is specified. Therefore we would like to be able to specify an absolute path
+## without worrying that it may match an actual file on the system outside the
+## syslibroot. `chroot` would do the job but isn't cross-platform, so I've used
+## this %t/%:t hack instead.
+# RUN: mkdir -p %t/%:t
+
+# 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/test.s -o %t/test.o
+
+## bar.a is under %t/%:t, and so verifies that rerooting happens. foo.a isn't,
+## and therefore verifies that we still fall back to the original path if no
+## file exists at the rerooted path.
+# RUN: llvm-ar rcs %t/foo.a %t/foo.o
+# RUN: %lld -dylib %t/foo.o -o %t/libfoo.dylib
+# RUN: llvm-ar rcs %t/%:t/bar.a %t/bar.o
+# RUN: %lld -dylib %t/bar.o -o %t/%:t/libbar.dylib
+
+## Test our various file-loading flags to make sure all bases are covered.
+# RUN: %lld -lSystem -syslibroot %t %t/foo.a %t/bar.a %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t"
+# RUN: %lld -lSystem -syslibroot %t -force_load %t/foo.a -force_load %t/bar.a %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t"
+# RUN: %lld -lSystem -syslibroot %t %t/libfoo.dylib %t/libbar.dylib %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t"
+# RUN: %lld -lSystem -syslibroot %t -weak_library %t/libfoo.dylib -weak_library %t/libbar.dylib %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t"
+# RUN: echo "%t/libfoo.dylib" > %t/filelist
+# RUN: echo "%t/libbar.dylib" >> %t/filelist
+# RUN: %lld -lSystem -syslibroot %t -filelist %t/filelist %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t"
+# CHECK: [[DIR]]/{{(lib)?}}bar
+
+## Paths to object files don't get rerooted.
+# RUN: mv %t/bar.o %t/%:t/bar.o
+# RUN: not %lld -lSystem -syslibroot %t %t/foo.o %t/bar.o %t/test.o -o \
+# RUN: /dev/null 2>&1 | FileCheck %s --check-prefix=OBJ
+# OBJ: error: cannot open {{.*[\\/]}}bar.o: {{[Nn]}}o such file or directory
+
+## Now create a "decoy" libfoo.dylib under %t/%:t to demonstrate that the
+## rerooted path takes precedence over the original path. We will get an
+## undefined symbol error since we aren't loading %t/libfoo.dylib.
+# RUN: cp %t/%:t/libbar.dylib %t/%:t/libfoo.dylib
+# RUN: not %lld -lSystem -syslibroot %t %t/libfoo.dylib %t/libbar.dylib %t/test.o \
+# RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNDEF
+# UNDEF: error: undefined symbol: _foo
+
+#--- foo.s
+.globl _foo
+_foo:
+
+#--- bar.s
+.globl _bar
+_bar:
+
+#--- test.s
+.text
+.globl _main
+
+_main:
+ callq _foo
+ callq _bar
+ ret
More information about the llvm-commits
mailing list