Skip to content

Commit 3a108ab

Browse files
committed
[LLD][COFF] Skip computation of the undefined symbols references that are not shown
The "undefined symbol" error message from lld-link displays up to 3 references to that symbol, and the number of extra references not shown. This patch removes the computation of the strings for those extra references. It fixes a freeze of lld-link we accidentally encountered when activating asan on a large project, without linking with the asan library. In that case, __asan_report_load8 was referenced more than 2 million times, causing the computation of that many display strings, of which only 3 were used. Differential Revision: https://reviews.llvm.org/D83510
1 parent 877b259 commit 3a108ab

File tree

3 files changed

+69
-21
lines changed

3 files changed

+69
-21
lines changed

lld/COFF/SymbolTable.cpp

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,16 @@ getFileLine(const SectionChunk *c, uint32_t addr) {
136136
// of all references to that symbol from that file. If no debug information is
137137
// available, returns just the name of the file, else one string per actual
138138
// reference as described in the debug info.
139-
std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex) {
139+
// Returns up to maxStrings string descriptions, along with the total number of
140+
// locations found.
141+
static std::pair<std::vector<std::string>, size_t>
142+
getSymbolLocations(ObjFile *file, uint32_t symIndex, size_t maxStrings) {
140143
struct Location {
141144
Symbol *sym;
142145
std::pair<StringRef, uint32_t> fileLine;
143146
};
144147
std::vector<Location> locations;
148+
size_t numLocations = 0;
145149

146150
for (Chunk *c : file->getChunks()) {
147151
auto *sc = dyn_cast<SectionChunk>(c);
@@ -150,6 +154,10 @@ std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex) {
150154
for (const coff_relocation &r : sc->getRelocs()) {
151155
if (r.SymbolTableIndex != symIndex)
152156
continue;
157+
numLocations++;
158+
if (locations.size() >= maxStrings)
159+
continue;
160+
153161
Optional<std::pair<StringRef, uint32_t>> fileLine =
154162
getFileLine(sc, r.VirtualAddress);
155163
Symbol *sym = getSymbol(sc, r.VirtualAddress);
@@ -160,8 +168,12 @@ std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex) {
160168
}
161169
}
162170

163-
if (locations.empty())
164-
return std::vector<std::string>({"\n>>> referenced by " + toString(file)});
171+
if (maxStrings == 0)
172+
return std::make_pair(std::vector<std::string>(), numLocations);
173+
174+
if (numLocations == 0)
175+
return std::make_pair(
176+
std::vector<std::string>{"\n>>> referenced by " + toString(file)}, 1);
165177

166178
std::vector<std::string> symbolLocations(locations.size());
167179
size_t i = 0;
@@ -175,17 +187,26 @@ std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex) {
175187
if (loc.sym)
176188
os << ":(" << toString(*loc.sym) << ')';
177189
}
178-
return symbolLocations;
190+
return std::make_pair(symbolLocations, numLocations);
191+
}
192+
193+
std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex) {
194+
return getSymbolLocations(file, symIndex, SIZE_MAX).first;
179195
}
180196

181-
std::vector<std::string> getSymbolLocations(InputFile *file,
182-
uint32_t symIndex) {
197+
static std::pair<std::vector<std::string>, size_t>
198+
getSymbolLocations(InputFile *file, uint32_t symIndex, size_t maxStrings) {
183199
if (auto *o = dyn_cast<ObjFile>(file))
184-
return getSymbolLocations(o, symIndex);
185-
if (auto *b = dyn_cast<BitcodeFile>(file))
186-
return getSymbolLocations(b);
200+
return getSymbolLocations(o, symIndex, maxStrings);
201+
if (auto *b = dyn_cast<BitcodeFile>(file)) {
202+
std::vector<std::string> symbolLocations = getSymbolLocations(b);
203+
size_t numLocations = symbolLocations.size();
204+
if (symbolLocations.size() > maxStrings)
205+
symbolLocations.resize(maxStrings);
206+
return std::make_pair(symbolLocations, numLocations);
207+
}
187208
llvm_unreachable("unsupported file type passed to getSymbolLocations");
188-
return {};
209+
return std::make_pair(std::vector<std::string>(), (size_t)0);
189210
}
190211

191212
// For an undefined symbol, stores all files referencing it and the index of
@@ -205,20 +226,21 @@ static void reportUndefinedSymbol(const UndefinedDiag &undefDiag) {
205226
os << "undefined symbol: " << toString(*undefDiag.sym);
206227

207228
const size_t maxUndefReferences = 3;
208-
size_t i = 0, numRefs = 0;
229+
size_t numDisplayedRefs = 0, numRefs = 0;
209230
for (const UndefinedDiag::File &ref : undefDiag.files) {
210-
std::vector<std::string> symbolLocations =
211-
getSymbolLocations(ref.file, ref.symIndex);
212-
numRefs += symbolLocations.size();
231+
std::vector<std::string> symbolLocations;
232+
size_t totalLocations = 0;
233+
std::tie(symbolLocations, totalLocations) = getSymbolLocations(
234+
ref.file, ref.symIndex, maxUndefReferences - numDisplayedRefs);
235+
236+
numRefs += totalLocations;
237+
numDisplayedRefs += symbolLocations.size();
213238
for (const std::string &s : symbolLocations) {
214-
if (i >= maxUndefReferences)
215-
break;
216239
os << s;
217-
i++;
218240
}
219241
}
220-
if (i < numRefs)
221-
os << "\n>>> referenced " << numRefs - i << " more times";
242+
if (numDisplayedRefs < numRefs)
243+
os << "\n>>> referenced " << numRefs - numDisplayedRefs << " more times";
222244
errorOrWarn(os.str());
223245
}
224246

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
2+
target triple = "x86_64-unknown-windows-msvc"
3+
4+
define dso_local i32 @"?baz@@YAHXZ"() #0 {
5+
%1 = call i32 @"?foo@@YAHXZ"()
6+
%2 = call i32 @"?foo@@YAHXZ"()
7+
%3 = call i32 @"?bar@@YAHXZ"()
8+
%4 = call i32 @"?bar@@YAHXZ"()
9+
ret i32 0
10+
}
11+
12+
declare dso_local i32 @"?foo@@YAHXZ"() #1
13+
14+
declare dso_local i32 @"?bar@@YAHXZ"() #1
15+
16+
attributes #0 = { noinline optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
17+
attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
18+
19+
!llvm.module.flags = !{!0}
20+
!llvm.ident = !{!1}
21+
22+
!0 = !{i32 1, !"wchar_size", i32 2}
23+
!1 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project.git bed3e1a99b41f5a9525bc0edf12ecbcf63aab0cf)"}

lld/test/COFF/undefined-symbol-multi.s

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@
1616
# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
1717
# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
1818
# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t2.obj %t.moreref.s
19-
# RUN: not lld-link /out:/dev/null %t.obj %t2.obj 2>&1 | FileCheck %s
19+
# RUN: llvm-as %S/Inputs/undefined-symbol-multi-lto.ll -o %t3.obj
20+
# RUN: not lld-link /out:/dev/null %t.obj %t2.obj %t3.obj 2>&1 | FileCheck %s
2021

2122
# CHECK: error: undefined symbol: int __cdecl foo(void)
2223
# CHECK-NEXT: >>> referenced by {{.*}}tmp.obj:(main)
2324
# CHECK-NEXT: >>> referenced by {{.*}}tmp.obj:(main)
2425
# CHECK-NEXT: >>> referenced by {{.*}}tmp2.obj:(bar)
25-
# CHECK-NEXT: >>> referenced 9 more times
26+
# CHECK-NEXT: >>> referenced 10 more times
2627
# CHECK-EMPTY:
2728
# CHECK-NEXT: error: undefined symbol: int __cdecl bar(void)
2829
# CHECK-NEXT: >>> referenced by {{.*}}.obj:(main)
2930
# CHECK-NEXT: >>> referenced by {{.*}}.obj:(f1)
31+
# CHECK-NEXT: >>> referenced by {{.*}}undefined-symbol-multi-lto.ll
32+
# CHECK-NEXT: >>> {{.*}}tmp3.obj
3033

3134
.section .text,"xr",one_only,main
3235
.globl main

0 commit comments

Comments
 (0)