Skip to content

Commit 34a44b2

Browse files
authored
[lld/COFF] Handle -start-lib / -end-lib better in /reproduce: output (#119752)
Previously, we'd collect all input files in Driver::filePaths, and then write filePaths after all other flags in createResponseFile(). This meant that `-start-lib foo.obj -end-lib` would be written as `-start-lib -end-lib foo.obj`, changing semantics. Instead, remove Driver::filePaths, and handle things that fed into it directly: * OPT_INPUT is now handled in the same way as other flags, so that we now get `-start-lib foo.obj -end-lib` in response.txt as desired. Add a test for -start-lib / -end-lib and /reproduce:. * OPT_wholearchive_file needs explicit handling now -- but before, this was buggy as well: We'd put the flag without a rewritten path in response.txt, but also the rewritten input file without wholearchive semantics via filePaths. So this commit makes --whole-archive work with /reproduce: too, and adds test coverage. * /defaultlib:foo is now written as /defaultlib:foo into response.txt, instead of writing the resolved path previously. While response.txt looks slightly differently, both should have the same semantics, and this should be mostly a no-op. (It does require updating a test.) * /defaultlib: from .drectve sections are no longer recorded in response.txt. This seems like a progression -- in the non-repro case they come from .obj files, so they should come (only) from there in the repro case too. This adds test coverage for this case. Makes createResponseFile() look more like the versions in the ELF and MachO ports too.
1 parent 7ab8dd7 commit 34a44b2

File tree

3 files changed

+111
-16
lines changed

3 files changed

+111
-16
lines changed

lld/COFF/Driver.cpp

+9-10
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,6 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
204204
StringRef filename = mb->getBufferIdentifier();
205205

206206
MemoryBufferRef mbref = takeBuffer(std::move(mb));
207-
filePaths.push_back(filename);
208207

209208
// File type is detected by contents, not by file extension.
210209
switch (identify_magic(mbref.getBuffer())) {
@@ -866,7 +865,6 @@ static std::string rewritePath(StringRef s) {
866865
// Reconstructs command line arguments so that so that you can re-run
867866
// the same command with the same inputs. This is for --reproduce.
868867
static std::string createResponseFile(const opt::InputArgList &args,
869-
ArrayRef<StringRef> filePaths,
870868
ArrayRef<StringRef> searchPaths) {
871869
SmallString<0> data;
872870
raw_svector_ostream os(data);
@@ -875,11 +873,15 @@ static std::string createResponseFile(const opt::InputArgList &args,
875873
switch (arg->getOption().getID()) {
876874
case OPT_linkrepro:
877875
case OPT_reproduce:
878-
case OPT_INPUT:
879-
case OPT_defaultlib:
880876
case OPT_libpath:
881877
case OPT_winsysroot:
882878
break;
879+
case OPT_INPUT:
880+
os << quote(rewritePath(arg->getValue())) << "\n";
881+
break;
882+
case OPT_wholearchive_file:
883+
os << arg->getSpelling() << quote(rewritePath(arg->getValue())) << "\n";
884+
break;
883885
case OPT_call_graph_ordering_file:
884886
case OPT_deffile:
885887
case OPT_manifestinput:
@@ -916,9 +918,6 @@ static std::string createResponseFile(const opt::InputArgList &args,
916918
os << "/libpath:" << quote(relPath) << "\n";
917919
}
918920

919-
for (StringRef path : filePaths)
920-
os << quote(relativeToRoot(path)) << "\n";
921-
922921
return std::string(data);
923922
}
924923

@@ -2355,9 +2354,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
23552354

23562355
if (tar) {
23572356
llvm::TimeTraceScope timeScope("Reproducer: response file");
2358-
tar->append("response.txt",
2359-
createResponseFile(args, filePaths,
2360-
ArrayRef<StringRef>(searchPaths).slice(1)));
2357+
tar->append(
2358+
"response.txt",
2359+
createResponseFile(args, ArrayRef<StringRef>(searchPaths).slice(1)));
23612360
}
23622361

23632362
// Handle /largeaddressaware

lld/COFF/Driver.h

-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ class LinkerDriver {
197197
bool run();
198198

199199
std::list<std::function<void()>> taskQueue;
200-
std::vector<StringRef> filePaths;
201200
std::vector<MemoryBufferRef> resources;
202201

203202
llvm::DenseSet<StringRef> directivesExports;

lld/test/COFF/linkrepro.test

+102-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
# REQUIRES: x86, shell
22

33
# RUN: rm -rf %t.dir
4+
# RUN: split-file %s %t.dir
5+
46
# RUN: yaml2obj %p/Inputs/hello32.yaml -o %t.obj
7+
# RUN: llvm-mc -filetype=obj -triple=i386-windows %t.dir/drectve.s -o %t.dir/drectve.obj
58
# RUN: echo '_main@0' > %t.order
69
# RUN: touch %t.def
710
# RUN: touch %t.cg
@@ -46,7 +49,7 @@ and various other flags.
4649
# RUN: diff %t.order repro/%:t.order
4750
# RUN: diff %t.def repro/%:t.def
4851
# RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib
49-
# RUN: FileCheck %s --check-prefix=RSP < repro/response.txt
52+
# RUN: FileCheck %s --check-prefix=RSP-DEFAULTLIB < repro/response.txt
5053
# RUN: cd repro; lld-link @response.txt
5154

5255
Test adding .lib files with LIB env var to repro archive,
@@ -61,7 +64,7 @@ and various other flags.
6164
# RUN: diff %t.order repro/%:t.order
6265
# RUN: diff %t.def repro/%:t.def
6366
# RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib
64-
# RUN: FileCheck %s --check-prefix=RSP < repro/response.txt
67+
# RUN: FileCheck %s --check-prefix=RSP-DEFAULTLIB < repro/response.txt
6568
# RUN: cd repro; lld-link @response.txt
6669

6770
# LIST: .obj
@@ -70,14 +73,21 @@ and various other flags.
7073
# LIST: .def
7174
# LIST: .order
7275

76+
# RSP: linkrepro.test.tmp.obj
77+
# RSP: std32.lib
7378
# RSP: /subsystem:console
7479
# RSP: /entry:main@0
7580
# RSP: /out:
7681
# RSP-NOT: /order:@/
7782
# RSP-NOT: /def:/
78-
# RSP: linkrepro.test.tmp.obj
79-
# RSP-NOT: defaultlib
80-
# RSP: std32.lib
83+
84+
# RSP-DEFAULTLIB: linkrepro.test.tmp.obj
85+
# RSP-DEFAULTLIB: /defaultlib:std32
86+
# RSP-DEFAULTLIB: /subsystem:console
87+
# RSP-DEFAULTLIB: /entry:main@0
88+
# RSP-DEFAULTLIB: /out:
89+
# RSP-DEFAULTLIB-NOT: /order:@/
90+
# RSP-DEFAULTLIB-NOT: /def:/
8191

8292
Test /call-graph-ordering-file (can't be used with /order:, needs separate test)
8393
# RUN: mkdir -p %t.dir/build5
@@ -96,3 +106,90 @@ Test /call-graph-ordering-file (can't be used with /order:, needs separate test)
96106
# LISTCG: .cg
97107

98108
# RSPCG-NOT: /call-graph-ordering-file:/
109+
110+
Test /defaultlib: from a .drectve section
111+
# RUN: mkdir -p %t.dir/build6
112+
# RUN: cd %t.dir/build6
113+
# RUN: lld-link %t.obj %t.dir/drectve.obj /libpath:%p/Inputs /subsystem:console \
114+
# RUN: /entry:main@0 /linkrepro:. -safeseh:no /out:%t.exe /order:@%t.order /def:%t.def
115+
# RUN: tar tf repro.tar | FileCheck --check-prefix=LIST %s
116+
# RUN: tar xf repro.tar
117+
# RUN: diff %t.obj repro/%:t.obj
118+
# RUN: diff %t.order repro/%:t.order
119+
# RUN: diff %t.def repro/%:t.def
120+
# RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib
121+
# RUN: FileCheck %s --check-prefix=RSP-DRECTVE < repro/response.txt
122+
# RUN: cd repro; lld-link @response.txt
123+
124+
# RSP-DRECTVE: linkrepro.test.tmp.obj
125+
# RSP-DRECTVE: drectve.obj
126+
# RSP-DRECTVE: /subsystem:console
127+
# RSP-DRECTVE: /entry:main@0
128+
# RSP-DRECTVE: -safeseh:no
129+
# RSP-DRECTVE: /out:
130+
131+
Test /wholearchive: with /linkrepro:
132+
# RUN: llvm-mc -filetype=obj -triple=i386-windows %t.dir/archive.s -o %t.dir/archive.obj
133+
# RUN: rm -f %t.dir/build7/archive.lib
134+
# RUN: llvm-ar rcs %t.dir/archive.lib %t.dir/archive.obj
135+
# RUN: mkdir -p %t.dir/build7
136+
# RUN: cd %t.dir/build7
137+
RUN: lld-link %t.obj /defaultlib:std32 /libpath:%p/Inputs /subsystem:console \
138+
# RUN: /entry:main@0 /linkrepro:. -safeseh:no /wholearchive:%t.dir/archive.lib \
139+
# RUN: /out:%t.exe /order:@%t.order /def:%t.def
140+
# RUN: tar tf repro.tar | FileCheck --check-prefix=LIST %s
141+
# RUN: tar xf repro.tar
142+
# RUN: diff %t.obj repro/%:t.obj
143+
# RUN: diff %t.order repro/%:t.order
144+
# RUN: diff %t.def repro/%:t.def
145+
# RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib
146+
# RUN: FileCheck %s --check-prefix=RSP-WHOLEARCHIVE < repro/response.txt
147+
# RUN: cd repro; lld-link @response.txt
148+
149+
# RSP-WHOLEARCHIVE: linkrepro.test.tmp.obj
150+
# RSP-WHOLEARCHIVE: /defaultlib:std32
151+
# RSP-WHOLEARCHIVE: /subsystem:console
152+
# RSP-WHOLEARCHIVE: /entry:main@0
153+
# RSP-WHOLEARCHIVE: -safeseh:no
154+
# RSP-WHOLEARCHIVE: /wholearchive:{{.*}}archive.lib
155+
# RSP-WHOLEARCHIVE: /out:
156+
157+
Test /start-lib / /end-lib with /linkrepro:
158+
# RUN: mkdir -p %t.dir/build8
159+
# RUN: cd %t.dir/build8
160+
# RUN: lld-link %t.obj /defaultlib:std32 /libpath:%p/Inputs /subsystem:console \
161+
# RUN: /entry:main@0 /linkrepro:. -safeseh:no /start-lib %t.dir/drectve.obj /end-lib \
162+
# RUN: /out:%t.exe /order:@%t.order /def:%t.def
163+
# RUN: tar tf repro.tar | FileCheck --check-prefix=LIST %s
164+
# RUN: tar xf repro.tar
165+
# RUN: diff %t.obj repro/%:t.obj
166+
# RUN: diff %t.order repro/%:t.order
167+
# RUN: diff %t.def repro/%:t.def
168+
# RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib
169+
# RUN: FileCheck %s --check-prefix=RSP-STARTLIB < repro/response.txt
170+
# RUN: cd repro; lld-link @response.txt
171+
172+
# RSP-STARTLIB: linkrepro.test.tmp.obj
173+
# RSP-STARTLIB: /defaultlib:std32
174+
# RSP-STARTLIB: /subsystem:console
175+
# RSP-STARTLIB: /entry:main@0
176+
# RSP-STARTLIB: -safeseh:no
177+
# RSP-STARTLIB: /start-lib
178+
# RSP-STARTLIB-NEXT: drectve.obj
179+
# RSP-STARTLIB-NEXT: /end-lib
180+
# RSP-STARTLIB: /out:
181+
182+
#--- drectve.s
183+
.section .drectve, "yn"
184+
.ascii "/defaultlib:std32"
185+
186+
#--- archive.s
187+
.text
188+
.intel_syntax noprefix
189+
.globl exportfn3
190+
.p2align 4
191+
exportfn3:
192+
ret
193+
194+
.section .drectve,"yni"
195+
.ascii " /EXPORT:exportfn3"

0 commit comments

Comments
 (0)