[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