Skip to content

Commit d2f3d25

Browse files
BertalanDyuxuanchen1997
authored andcommitted
[lld-macho] Ignore duplicate -rpath entries (#99289)
Summary: 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. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60250827
1 parent 2aeb303 commit d2f3d25

File tree

5 files changed

+39
-1
lines changed

5 files changed

+39
-1
lines changed

lld/MachO/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ struct Configuration {
199199
std::vector<llvm::StringRef> systemLibraryRoots;
200200
std::vector<llvm::StringRef> librarySearchPaths;
201201
std::vector<llvm::StringRef> frameworkSearchPaths;
202+
bool warnDuplicateRpath = true;
202203
llvm::SmallVector<llvm::StringRef, 0> runtimePaths;
203204
std::vector<std::string> astPaths;
204205
std::vector<Symbol *> explicitUndefineds;

lld/MachO/Driver.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1402,6 +1402,19 @@ static void eraseInitializerSymbols() {
14021402
sym->used = false;
14031403
}
14041404

1405+
static SmallVector<StringRef, 0> getRuntimePaths(opt::InputArgList &args) {
1406+
SmallVector<StringRef, 0> vals;
1407+
DenseSet<StringRef> seen;
1408+
for (const Arg *arg : args.filtered(OPT_rpath)) {
1409+
StringRef val = arg->getValue();
1410+
if (seen.insert(val).second)
1411+
vals.push_back(val);
1412+
else if (config->warnDuplicateRpath)
1413+
warn("duplicate -rpath '" + val + "' ignored [--warn-duplicate-rpath]");
1414+
}
1415+
return vals;
1416+
}
1417+
14051418
namespace lld {
14061419
namespace macho {
14071420
bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
@@ -1642,7 +1655,9 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
16421655
error("--thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with "
16431656
"--thinlto-index-only=");
16441657
}
1645-
config->runtimePaths = args::getStrings(args, OPT_rpath);
1658+
config->warnDuplicateRpath =
1659+
args.hasFlag(OPT_warn_duplicate_rpath, OPT_no_warn_duplicate_rpath, true);
1660+
config->runtimePaths = getRuntimePaths(args);
16461661
config->allLoad = args.hasFlag(OPT_all_load, OPT_noall_load, false);
16471662
config->archMultiple = args.hasArg(OPT_arch_multiple);
16481663
config->applicationExtension = args.hasFlag(

lld/MachO/Options.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ def no_warn_dylib_install_name: Flag<["--"], "no-warn-dylib-install-name">,
111111
def warn_dylib_install_name: Flag<["--"], "warn-dylib-install-name">,
112112
HelpText<"Warn on -install_name if -dylib is not passed">,
113113
Group<grp_lld>;
114+
def warn_duplicate_rpath: Flag<["--"], "warn-duplicate-rpath">,
115+
HelpText<"Warn if the same -rpath is specified multiple times (default)">,
116+
Group<grp_lld>;
117+
def no_warn_duplicate_rpath: Flag<["--"], "no-warn-duplicate-rpath">,
118+
HelpText<"Do not warn if the same -rpath is specified multiple times">,
119+
Group<grp_lld>;
114120
def call_graph_profile_sort: Flag<["--"], "call-graph-profile-sort">,
115121
HelpText<"Reorder sections with call graph profile (default)">,
116122
Group<grp_lld>;

lld/test/MachO/link-search-at-rpath.s

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# RUN: -rpath @loader_path/../foo \
1515
# RUN: -rpath @loader_path/../subdir \
1616
# RUN: -rpath @loader_path/../foo \
17+
# RUN: --no-warn-duplicate-rpath \
1718
# RUN: %t/bar.o -o %t/subdir2/libbar.dylib
1819

1920
# RUN: %lld -lSystem %t/main.o %t/subdir2/libbar.dylib -o %t/test

lld/test/MachO/rpath.s

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@
1212
# CHECK-NEXT: cmdsize 32
1313
# CHECK-NEXT: path /another/rpath
1414

15+
## Check that -rpath entries are deduplicated.
16+
# RUN: not %lld %t.o -o /dev/null -rpath /some/rpath -rpath /other/rpath -rpath /some/rpath 2>&1 | \
17+
# RUN: FileCheck --check-prefix=FATAL %s
18+
# FATAL: error: duplicate -rpath '/some/rpath' ignored [--warn-duplicate-rpath]
19+
20+
# RUN: %lld -o %t-dup %t.o -rpath /some/rpath -rpath /other/rpath -rpath /some/rpath --no-warn-duplicate-rpath
21+
# RUN: llvm-objdump --macho --all-headers %t-dup | FileCheck %s --check-prefix=DEDUP
22+
# DEDUP: LC_RPATH
23+
# DEDUP-NEXT: cmdsize 24
24+
# DEDUP-NEXT: path /some/rpath
25+
# DEDUP: LC_RPATH
26+
# DEDUP-NEXT: cmdsize 32
27+
# DEDUP-NEXT: path /other/rpath
28+
# DEDUP-NOT: LC_RPATH
29+
1530
.text
1631
.global _main
1732
_main:

0 commit comments

Comments
 (0)