[lld] b1864a8 - [lld-macho] Ignore duplicate `-rpath` entries (#99289)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 18 01:49:22 PDT 2024


Author: Daniel Bertalan
Date: 2024-07-18T10:49:19+02:00
New Revision: b1864a8d6ab8bfd346922e36d80e684a4eaf3248

URL: https://github.com/llvm/llvm-project/commit/b1864a8d6ab8bfd346922e36d80e684a4eaf3248
DIFF: https://github.com/llvm/llvm-project/commit/b1864a8d6ab8bfd346922e36d80e684a4eaf3248.diff

LOG: [lld-macho] Ignore duplicate `-rpath` entries (#99289)

Starting with Xcode 16 (dyld-1122), Apple's binary utilities, e.g.
`dyld_info` (but not dyld itself), will refuse to load binaries built
against the macOS 15 SDK or newer that contain the same `LC_RPATH`
entry multiple times:

https://github.com/apple-oss-distributions/dyld/blob/rel/dyld-1122/mach_o/Policy.cpp#L246-L249

`ld-prime` deduplicates entries (regardless of the deployment target),
we now do the same. We also match `ld-prime`'s and `ld64`'s behavior by
warning on duplicate `-rpath` arguments. This can be disabled by the
LLD-specific `--no-warn-duplicate-rpath` flag.

Added: 
    

Modified: 
    lld/MachO/Config.h
    lld/MachO/Driver.cpp
    lld/MachO/Options.td
    lld/test/MachO/link-search-at-rpath.s
    lld/test/MachO/rpath.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index 4d3f3d05c2338..5c354e0fe8821 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -199,6 +199,7 @@ struct Configuration {
   std::vector<llvm::StringRef> systemLibraryRoots;
   std::vector<llvm::StringRef> librarySearchPaths;
   std::vector<llvm::StringRef> frameworkSearchPaths;
+  bool warnDuplicateRpath = true;
   llvm::SmallVector<llvm::StringRef, 0> runtimePaths;
   std::vector<std::string> astPaths;
   std::vector<Symbol *> explicitUndefineds;

diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index a370d5734124a..ffb3feae25ca4 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -1402,6 +1402,19 @@ static void eraseInitializerSymbols() {
       sym->used = false;
 }
 
+static SmallVector<StringRef, 0> getRuntimePaths(opt::InputArgList &args) {
+  SmallVector<StringRef, 0> vals;
+  DenseSet<StringRef> seen;
+  for (const Arg *arg : args.filtered(OPT_rpath)) {
+    StringRef val = arg->getValue();
+    if (seen.insert(val).second)
+      vals.push_back(val);
+    else if (config->warnDuplicateRpath)
+      warn("duplicate -rpath '" + val + "' ignored [--warn-duplicate-rpath]");
+  }
+  return vals;
+}
+
 namespace lld {
 namespace macho {
 bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
@@ -1642,7 +1655,9 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
     error("--thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with "
           "--thinlto-index-only=");
   }
-  config->runtimePaths = args::getStrings(args, OPT_rpath);
+  config->warnDuplicateRpath =
+      args.hasFlag(OPT_warn_duplicate_rpath, OPT_no_warn_duplicate_rpath, true);
+  config->runtimePaths = getRuntimePaths(args);
   config->allLoad = args.hasFlag(OPT_all_load, OPT_noall_load, false);
   config->archMultiple = args.hasArg(OPT_arch_multiple);
   config->applicationExtension = args.hasFlag(

diff  --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index aecced9279da4..dc2212399222f 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -111,6 +111,12 @@ def no_warn_dylib_install_name: Flag<["--"], "no-warn-dylib-install-name">,
 def warn_dylib_install_name: Flag<["--"], "warn-dylib-install-name">,
     HelpText<"Warn on -install_name if -dylib is not passed">,
     Group<grp_lld>;
+def warn_duplicate_rpath: Flag<["--"], "warn-duplicate-rpath">,
+    HelpText<"Warn if the same -rpath is specified multiple times (default)">,
+    Group<grp_lld>;
+def no_warn_duplicate_rpath: Flag<["--"], "no-warn-duplicate-rpath">,
+    HelpText<"Do not warn if the same -rpath is specified multiple times">,
+    Group<grp_lld>;
 def call_graph_profile_sort: Flag<["--"], "call-graph-profile-sort">,
     HelpText<"Reorder sections with call graph profile (default)">,
     Group<grp_lld>;

diff  --git a/lld/test/MachO/link-search-at-rpath.s b/lld/test/MachO/link-search-at-rpath.s
index dbc0d4b3cbf63..71d27fc5033bb 100644
--- a/lld/test/MachO/link-search-at-rpath.s
+++ b/lld/test/MachO/link-search-at-rpath.s
@@ -14,6 +14,7 @@
 # RUN:     -rpath @loader_path/../foo \
 # RUN:     -rpath @loader_path/../subdir \
 # RUN:     -rpath @loader_path/../foo \
+# RUN:     --no-warn-duplicate-rpath \
 # RUN:     %t/bar.o -o %t/subdir2/libbar.dylib
 
 # RUN: %lld -lSystem %t/main.o %t/subdir2/libbar.dylib -o %t/test

diff  --git a/lld/test/MachO/rpath.s b/lld/test/MachO/rpath.s
index 5b404a36b26b0..09ae108b34a21 100644
--- a/lld/test/MachO/rpath.s
+++ b/lld/test/MachO/rpath.s
@@ -12,6 +12,21 @@
 # CHECK-NEXT: cmdsize 32
 # CHECK-NEXT: path /another/rpath
 
+## Check that -rpath entries are deduplicated.
+# RUN: not %lld %t.o -o /dev/null -rpath /some/rpath -rpath /other/rpath -rpath /some/rpath 2>&1 | \
+# RUN:     FileCheck --check-prefix=FATAL %s
+# FATAL: error: duplicate -rpath '/some/rpath' ignored [--warn-duplicate-rpath]
+
+# RUN: %lld -o %t-dup %t.o -rpath /some/rpath -rpath /other/rpath -rpath /some/rpath --no-warn-duplicate-rpath
+# RUN: llvm-objdump --macho --all-headers %t-dup | FileCheck %s --check-prefix=DEDUP
+# DEDUP:      LC_RPATH
+# DEDUP-NEXT: cmdsize 24
+# DEDUP-NEXT: path /some/rpath
+# DEDUP:      LC_RPATH
+# DEDUP-NEXT: cmdsize 32
+# DEDUP-NEXT: path /other/rpath
+# DEDUP-NOT:  LC_RPATH
+
 .text
 .global _main
 _main:


        


More information about the llvm-commits mailing list