[lld] [lld-macho] Ignore duplicate `-rpath` entries (PR #99289)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 17 01:05:19 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld
@llvm/pr-subscribers-lld-macho
Author: Daniel Bertalan (BertalanD)
<details>
<summary>Changes</summary>
Starting with Xcode 16 (dyld-1122), Apple's binary utilities, e.g. `dyld_info`, 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.
---
Full diff: https://github.com/llvm/llvm-project/pull/99289.diff
5 Files Affected:
- (modified) lld/MachO/Config.h (+1)
- (modified) lld/MachO/Driver.cpp (+16-1)
- (modified) lld/MachO/Options.td (+6)
- (modified) lld/test/MachO/link-search-at-rpath.s (+1)
- (modified) lld/test/MachO/rpath.s (+15)
``````````diff
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:
``````````
</details>
https://github.com/llvm/llvm-project/pull/99289
More information about the llvm-commits
mailing list