[lld] [lld][MachO] Fix --reproduce paths for non-global symbol lists and SDK libraries/frameworks (PR #223687)
Vy Nguyen via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 17 06:53:59 PDT 2026
https://github.com/oontvoo updated https://github.com/llvm/llvm-project/pull/223687
>From 6f51c1f6ab47bce632e860a832c15d5a89d9523c Mon Sep 17 00:00:00 2001
From: xiaoyanggong <xiaoyanggong at bytedance.com>
Date: Tue, 15 Sep 2026 16:55:10 +0800
Subject: [PATCH 1/4] [lld][MachO] Rewrite symbol-strip list paths in
reproducers
Rewrite non_global_symbols_strip_list and non_global_symbols_no_strip_list paths to their archived locations. Extend the existing reproduce.s cases to check both rewritten paths and replay the generated response files.
---
lld/MachO/DriverUtils.cpp | 2 ++
lld/test/MachO/reproduce.s | 10 ++++++++--
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index 3ff9d96ed53ce8..f7d69f28732ee8 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -178,6 +178,8 @@ std::string macho::createResponseFile(const InputArgList &args) {
break;
case OPT_F:
case OPT_L:
+ case OPT_non_global_symbols_strip_list:
+ case OPT_non_global_symbols_no_strip_list:
case OPT_bundle_loader:
case OPT_exported_symbols_list:
case OPT_order_file:
diff --git a/lld/test/MachO/reproduce.s b/lld/test/MachO/reproduce.s
index 68d94cab2c7ee7..f6949fbab068b8 100644
--- a/lld/test/MachO/reproduce.s
+++ b/lld/test/MachO/reproduce.s
@@ -7,6 +7,7 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos %s -o %t.dir/build1/foo.o
# RUN: echo '_main' > %t.dir/main.exports
# RUN: echo '_main' > %t.dir/main.order
+# RUN: echo '_local' > %t.dir/main.locals
# RUN: echo 'not a virus' > %t.dir/sectdata.txt
# RUN: cd %t.dir
# RUN: %lld -platform_version macos 10.10.0 11.0 \
@@ -14,6 +15,7 @@
# RUN: -order_file main.order \
# RUN: -sectcreate __COMPLETELY __legit sectdata.txt \
# RUN: -rpath /usr/lib/swift \
+# RUN: -non_global_symbols_strip_list main.locals \
# RUN: build1/foo.o -o bar --reproduce repro1.tar
# RUN: tar tf repro1.tar | FileCheck -DPATH='%:t.dir' --check-prefix=LIST %s
@@ -34,6 +36,7 @@
# RSP1-NEXT: -order_file [[BASEDIR]]/main.order
# RSP1-NEXT: -sectcreate __COMPLETELY __legit [[BASEDIR]]/sectdata.txt
# RSP1-NEXT: -rpath /usr/lib/swift
+# RSP1-NEXT: -non_global_symbols_strip_list [[BASEDIR]]/main.locals
# RSP1-NOT: {{^}}repro1{{[/\\]}}
# RSP1-NEXT: [[BASEDIR]]/build1/foo.o
# RSP1-NEXT: -o bar
@@ -48,11 +51,14 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos %s -o %t.dir/build2/foo.o
# RUN: cd %t.dir/build2/a/b/c
# RUN: echo ./../../../foo.o > %t.dir/build2/filelist
-# RUN: env LLD_REPRODUCE=repro2.tar %lld -filelist %t.dir/build2/filelist -o /dev/null
+# RUN: env LLD_REPRODUCE=repro2.tar %lld \
+# RUN: -non_global_symbols_no_strip_list %t.dir/main.locals \
+# RUN: -filelist %t.dir/build2/filelist -o /dev/null
# RUN: tar xf repro2.tar
# RUN: cmp %t.dir/build2/foo.o repro2/%:t.dir/build2/foo.o
-# RUN: FileCheck %s --check-prefix=RSP2 < repro2/response.txt
+# RUN: FileCheck %s --check-prefix=RSP2 -DPATH=%:t.dir < repro2/response.txt
# RSP2-NOT: {{^}}repro2{{[/\\]}}
+# RSP2: -non_global_symbols_no_strip_list [[PATH]]/main.locals
# RSP2: {{[/\\]}}foo.o
# RUN: cd repro2; %no-arg-lld @response.txt
>From 3a72b69f29a78512b0510b617318c01b38cb88b2 Mon Sep 17 00:00:00 2001
From: xiaoyanggong <xiaoyanggong at bytedance.com>
Date: Tue, 15 Sep 2026 16:58:08 +0800
Subject: [PATCH 2/4] [lld][MachO] Resolve SDK search paths in reproducers
Share SDK rerooting between search-path setup and response-file generation. Resolve absolute -L and -F paths before making them relative so replay retains SDK order, host fallback, and relative-path behavior.
---
lld/MachO/Driver.cpp | 21 +++--------
lld/MachO/Driver.h | 3 ++
lld/MachO/DriverUtils.cpp | 26 ++++++++++++++
lld/test/MachO/reproduce-search-paths.s | 48 +++++++++++++++++++++++++
4 files changed, 81 insertions(+), 17 deletions(-)
create mode 100644 lld/test/MachO/reproduce-search-paths.s
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 8edaff6e386575..f14cef7737f0eb 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -170,23 +170,10 @@ getSearchPaths(unsigned optionCode, InputArgList &args,
const SmallVector<StringRef, 2> &systemPaths) {
std::vector<StringRef> paths;
StringRef optionLetter{optionCode == OPT_F ? "F" : "L"};
- for (StringRef path : args::getStrings(args, optionCode)) {
- // NOTE: only absolute paths are re-rooted to syslibroot(s)
- bool found = false;
- if (path::is_absolute(path, path::Style::posix)) {
- for (StringRef root : roots) {
- SmallString<261> buffer(root);
- path::append(buffer, path);
- // Do not warn about paths that are computed via the syslib roots
- if (fs::is_directory(buffer)) {
- paths.push_back(saver().save(buffer.str()));
- found = true;
- }
- }
- }
- if (!found && warnIfNotDirectory(optionLetter, path))
- paths.push_back(path);
- }
+ for (StringRef path : args::getStrings(args, optionCode))
+ for (StringRef searchPath : getRerootedSearchPaths(path, roots))
+ if (warnIfNotDirectory(optionLetter, searchPath))
+ paths.push_back(searchPath);
// `-Z` suppresses the standard "system" search paths.
if (args.hasArg(OPT_Z))
diff --git a/lld/MachO/Driver.h b/lld/MachO/Driver.h
index bd1cd960768bf5..0d3d40d7cfa0dd 100644
--- a/lld/MachO/Driver.h
+++ b/lld/MachO/Driver.h
@@ -49,6 +49,9 @@ void parseLCLinkerOption(llvm::SmallVectorImpl<StringRef> &LCLinkerOptions,
InputFile *f, unsigned argc, StringRef data);
void resolveLCLinkerOptions();
+std::vector<StringRef> getRerootedSearchPaths(StringRef path,
+ ArrayRef<StringRef> roots);
+
std::string createResponseFile(const llvm::opt::InputArgList &args);
// Check for both libfoo.dylib and libfoo.tbd (in that order).
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index f7d69f28732ee8..81e00ce80e6cf9 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -134,6 +134,26 @@ void MachOOptTable::printHelp(CommonLinkerContext &ctx, const char *argv0,
outs << '\n';
}
+// If any SDK contains the directory, use those directories in SDK order
+// instead of falling back to the host.
+std::vector<StringRef>
+macho::getRerootedSearchPaths(StringRef searchPath, ArrayRef<StringRef> roots) {
+ std::vector<StringRef> paths;
+ // NOTE: only absolute paths are re-rooted to syslibroot(s)
+ if (path::is_absolute(searchPath, path::Style::posix)) {
+ for (StringRef root : roots) {
+ SmallString<261> buffer(root);
+ path::append(buffer, searchPath);
+ // Do not warn about paths that are computed via the syslib roots
+ if (fs::is_directory(buffer))
+ paths.push_back(saver().save(buffer.str()));
+ }
+ }
+ if (paths.empty())
+ paths.push_back(searchPath);
+ return paths;
+}
+
static std::string rewritePath(StringRef s) {
if (fs::exists(s))
return relativeToRoot(s);
@@ -178,6 +198,12 @@ std::string macho::createResponseFile(const InputArgList &args) {
break;
case OPT_F:
case OPT_L:
+ // Resolve SDK prefixes before making search paths relative: relative
+ // search paths are not rerooted when the reproducer is replayed.
+ for (StringRef path :
+ getRerootedSearchPaths(arg->getValue(), config->systemLibraryRoots))
+ os << arg->getSpelling() << " " << quote(rewritePath(path)) << "\n";
+ break;
case OPT_non_global_symbols_strip_list:
case OPT_non_global_symbols_no_strip_list:
case OPT_bundle_loader:
diff --git a/lld/test/MachO/reproduce-search-paths.s b/lld/test/MachO/reproduce-search-paths.s
new file mode 100644
index 00000000000000..51e6e0c91f8473
--- /dev/null
+++ b/lld/test/MachO/reproduce-search-paths.s
@@ -0,0 +1,48 @@
+# REQUIRES: x86
+# UNSUPPORTED: system-windows
+
+# RUN: rm -rf %t; mkdir -p %t/host %t/sdk1/%:t/host/Foo.framework %t/sdk2/%:t/host/Bar.framework
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos %s -o %t/foo.o
+# RUN: %no-arg-lld -arch x86_64 -platform_version macos 11.0 11.0 -dylib -Z \
+# RUN: %t/foo.o -o %t/sdk1/%:t/host/libfoo.dylib
+# RUN: cp %t/sdk1/%:t/host/libfoo.dylib %t/sdk1/%:t/host/Foo.framework/Foo
+# RUN: cp %t/sdk1/%:t/host/libfoo.dylib %t/sdk2/%:t/host/libbar.dylib
+# RUN: cp %t/sdk1/%:t/host/libfoo.dylib %t/sdk2/%:t/host/Bar.framework/Bar
+
+## Libraries and frameworks exist in SDKs only.
+# RUN: %no-arg-lld -arch x86_64 -platform_version macos 11.0 11.0 -dylib -Z \
+# RUN: -syslibroot %t/sdk1 -syslibroot %t/sdk2 -L %t/host -F %t/host \
+# RUN: -lfoo -lbar -framework Foo -framework Bar -o %t/out --reproduce %t/repro.tar
+# RUN: cd %t; tar xf repro.tar
+# RUN: FileCheck %s --check-prefix=SDK -DPATH=%:t < repro/response.txt
+# SDK: -L [[PATH]]/sdk1/[[PATH]]/host
+# SDK-NEXT: -L [[PATH]]/sdk2/[[PATH]]/host
+# SDK-NEXT: -F [[PATH]]/sdk1/[[PATH]]/host
+# SDK-NEXT: -F [[PATH]]/sdk2/[[PATH]]/host
+# RUN: rm -rf sdk1 sdk2
+# RUN: cd repro; %no-arg-lld @response.txt
+
+## Libraries and frameworks exist outside the SDK only.
+## Absolute paths fall back to host directories; relative paths ignore SDK roots.
+# RUN: mkdir -p %t/sdk/relative %t/fallback/Foo.framework %t/relative/Bar.framework
+# RUN: %no-arg-lld -arch x86_64 -platform_version macos 11.0 11.0 -dylib -Z \
+# RUN: %t/foo.o -o %t/fallback/libfoo.dylib
+# RUN: cp %t/fallback/libfoo.dylib %t/fallback/Foo.framework/Foo
+# RUN: cp %t/fallback/libfoo.dylib %t/relative/libbar.dylib
+# RUN: cp %t/fallback/libfoo.dylib %t/relative/Bar.framework/Bar
+# RUN: cd %t
+# RUN: %no-arg-lld -arch x86_64 -platform_version macos 11.0 11.0 -dylib -Z \
+# RUN: -syslibroot %t/sdk -L %t/fallback -F %t/fallback -L relative -F relative \
+# RUN: -lfoo -lbar -framework Foo -framework Bar -o out --reproduce fallback.tar
+# RUN: tar xf fallback.tar
+# RUN: FileCheck %s --check-prefix=FALLBACK -DPATH=%:t < fallback/response.txt
+# FALLBACK: -L [[PATH]]/fallback
+# FALLBACK-NEXT: -F [[PATH]]/fallback
+# FALLBACK-NEXT: -L [[PATH]]/relative
+# FALLBACK-NEXT: -F [[PATH]]/relative
+# RUN: rm -rf sdk relative fallback/libfoo.dylib fallback/Foo.framework
+# RUN: cd fallback; %no-arg-lld @response.txt
+
+.globl _foo
+_foo:
+ ret
>From cbbd0c52799de762d5dcdb20f70c4a695116a544 Mon Sep 17 00:00:00 2001
From: Xiaoyang Gong <xyg_aster at outlook.com>
Date: Wed, 16 Sep 2026 11:17:27 +0800
Subject: [PATCH 3/4] Skip directory checking when SDK resolved successfully
Co-authored-by: Vy Nguyen <1762963+oontvoo at users.noreply.github.com>
---
lld/MachO/Driver.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index f14cef7737f0eb..5603dcba5a38a5 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -172,7 +172,7 @@ getSearchPaths(unsigned optionCode, InputArgList &args,
StringRef optionLetter{optionCode == OPT_F ? "F" : "L"};
for (StringRef path : args::getStrings(args, optionCode))
for (StringRef searchPath : getRerootedSearchPaths(path, roots))
- if (warnIfNotDirectory(optionLetter, searchPath))
+ if (searchPath != path || warnIfNotDirectory(optionLetter, searchPath))
paths.push_back(searchPath);
// `-Z` suppresses the standard "system" search paths.
>From 8567843f8e1ca5e9407e4dc957264f54b6ca41c1 Mon Sep 17 00:00:00 2001
From: xiaoyanggong <xiaoyanggong at bytedance.com>
Date: Wed, 16 Sep 2026 11:32:20 +0800
Subject: [PATCH 4/4] Use SmallVector to reduce heap allocations in
getRerootedSearchPaths
---
lld/MachO/Driver.h | 3 ++-
lld/MachO/DriverUtils.cpp | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/lld/MachO/Driver.h b/lld/MachO/Driver.h
index 0d3d40d7cfa0dd..9374dffffd8bdd 100644
--- a/lld/MachO/Driver.h
+++ b/lld/MachO/Driver.h
@@ -11,6 +11,7 @@
#include "lld/Common/LLVM.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Option/OptTable.h"
@@ -49,7 +50,7 @@ void parseLCLinkerOption(llvm::SmallVectorImpl<StringRef> &LCLinkerOptions,
InputFile *f, unsigned argc, StringRef data);
void resolveLCLinkerOptions();
-std::vector<StringRef> getRerootedSearchPaths(StringRef path,
+SmallVector<StringRef> getRerootedSearchPaths(StringRef path,
ArrayRef<StringRef> roots);
std::string createResponseFile(const llvm::opt::InputArgList &args);
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index 81e00ce80e6cf9..bbfc4477bb978b 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -136,9 +136,9 @@ void MachOOptTable::printHelp(CommonLinkerContext &ctx, const char *argv0,
// If any SDK contains the directory, use those directories in SDK order
// instead of falling back to the host.
-std::vector<StringRef>
+SmallVector<StringRef>
macho::getRerootedSearchPaths(StringRef searchPath, ArrayRef<StringRef> roots) {
- std::vector<StringRef> paths;
+ SmallVector<StringRef> paths;
// NOTE: only absolute paths are re-rooted to syslibroot(s)
if (path::is_absolute(searchPath, path::Style::posix)) {
for (StringRef root : roots) {
More information about the llvm-commits
mailing list