mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-13 19:24:21 +00:00
[lld-macho] Group undefined symbol diagnostics by symbol
ld64.lld used to print the "undefined symbol" line for each reference to an undefined symbol previously: ld64.lld: error: undefined symbol: _foo >>> referenced by /path/to/bar.o:(symbol _baz+0x0) ld64.lld: error: undefined symbol: _foo >>> referenced by /path/to/bar.o:(symbol _quux+0x1) Now they are deduplicated: ld64.lld: error: undefined symbol: _foo >>> referenced by /path/to/bar.o:(symbol _baz+0x0) >>> referenced by /path/to/bar.o:(symbol _quux+0x1) As with the other lld ports, only the first 3 references are printed. Differential Revision: https://reviews.llvm.org/D127753
This commit is contained in:
parent
7c0089d735
commit
d61341768c
@ -345,35 +345,80 @@ static bool recoverFromUndefinedSymbol(const Undefined &sym) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void printUndefinedDiagnostic(StringRef name, StringRef source) {
|
||||
std::string message = "undefined symbol";
|
||||
if (config->archMultiple)
|
||||
message += (" for arch " + getArchitectureName(config->arch())).str();
|
||||
message += (": " + name + "\n>>> referenced by " + source).str();
|
||||
struct UndefinedDiag {
|
||||
struct SectionAndOffset {
|
||||
const InputSection *isec;
|
||||
uint64_t offset;
|
||||
};
|
||||
|
||||
if (config->undefinedSymbolTreatment == UndefinedSymbolTreatment::error)
|
||||
error(message);
|
||||
else if (config->undefinedSymbolTreatment ==
|
||||
UndefinedSymbolTreatment::warning)
|
||||
warn(message);
|
||||
else
|
||||
assert(false && "diagnostics make sense for -undefined error|warning only");
|
||||
std::vector<SectionAndOffset> codeReferences;
|
||||
std::vector<std::string> otherReferences;
|
||||
};
|
||||
|
||||
static MapVector<const Undefined *, UndefinedDiag> undefs;
|
||||
|
||||
void macho::reportPendingUndefinedSymbols() {
|
||||
for (const auto &undef : undefs) {
|
||||
const UndefinedDiag &locations = undef.second;
|
||||
|
||||
std::string message = "undefined symbol";
|
||||
if (config->archMultiple)
|
||||
message += (" for arch " + getArchitectureName(config->arch())).str();
|
||||
message += ": " + toString(*undef.first);
|
||||
|
||||
const size_t maxUndefinedReferences = 3;
|
||||
size_t i = 0;
|
||||
for (const std::string &loc : locations.otherReferences) {
|
||||
if (i >= maxUndefinedReferences)
|
||||
break;
|
||||
message += "\n>>> referenced by " + loc;
|
||||
++i;
|
||||
}
|
||||
|
||||
for (const UndefinedDiag::SectionAndOffset &loc :
|
||||
locations.codeReferences) {
|
||||
if (i >= maxUndefinedReferences)
|
||||
break;
|
||||
// TODO: Get source file/line from debug information.
|
||||
message += "\n>>> referenced by " + loc.isec->getLocation(loc.offset);
|
||||
++i;
|
||||
}
|
||||
|
||||
size_t totalReferences =
|
||||
locations.otherReferences.size() + locations.codeReferences.size();
|
||||
if (totalReferences > i)
|
||||
message +=
|
||||
("\n>>> referenced " + Twine(totalReferences - i) + " more times")
|
||||
.str();
|
||||
|
||||
if (config->undefinedSymbolTreatment == UndefinedSymbolTreatment::error)
|
||||
error(message);
|
||||
else if (config->undefinedSymbolTreatment ==
|
||||
UndefinedSymbolTreatment::warning)
|
||||
warn(message);
|
||||
else
|
||||
assert(false &&
|
||||
"diagnostics make sense for -undefined error|warning only");
|
||||
}
|
||||
|
||||
// This function is called multiple times during execution. Clear the printed
|
||||
// diagnostics to avoid printing the same things again the next time.
|
||||
undefs.clear();
|
||||
}
|
||||
|
||||
void lld::macho::treatUndefinedSymbol(const Undefined &sym, StringRef source) {
|
||||
if (recoverFromUndefinedSymbol(sym))
|
||||
return;
|
||||
printUndefinedDiagnostic(sym.getName(), source);
|
||||
}
|
||||
|
||||
void lld::macho::treatUndefinedSymbol(const Undefined &sym,
|
||||
const InputSection *isec,
|
||||
uint64_t offset) {
|
||||
void macho::treatUndefinedSymbol(const Undefined &sym, StringRef source) {
|
||||
if (recoverFromUndefinedSymbol(sym))
|
||||
return;
|
||||
|
||||
// TODO: Get source file/line from debug information.
|
||||
printUndefinedDiagnostic(toString(sym), isec->getLocation(offset));
|
||||
undefs[&sym].otherReferences.push_back(source.str());
|
||||
}
|
||||
|
||||
void macho::treatUndefinedSymbol(const Undefined &sym, const InputSection *isec,
|
||||
uint64_t offset) {
|
||||
if (recoverFromUndefinedSymbol(sym))
|
||||
return;
|
||||
|
||||
undefs[&sym].codeReferences.push_back({isec, offset});
|
||||
}
|
||||
|
||||
std::unique_ptr<SymbolTable> macho::symtab;
|
||||
|
@ -69,6 +69,9 @@ private:
|
||||
std::vector<Symbol *> symVector;
|
||||
};
|
||||
|
||||
void reportPendingUndefinedSymbols();
|
||||
|
||||
// Call reportPendingUndefinedSymbols() to emit diagnostics.
|
||||
void treatUndefinedSymbol(const Undefined &, StringRef source);
|
||||
void treatUndefinedSymbol(const Undefined &, const InputSection *,
|
||||
uint64_t offset);
|
||||
|
@ -1133,6 +1133,7 @@ void Writer::writeCodeSignature() {
|
||||
void Writer::writeOutputFile() {
|
||||
TimeTraceScope timeScope("Write output file");
|
||||
openFile();
|
||||
reportPendingUndefinedSymbols();
|
||||
if (errorCount())
|
||||
return;
|
||||
writeSections();
|
||||
@ -1155,6 +1156,7 @@ template <class LP> void Writer::run() {
|
||||
scanRelocations();
|
||||
|
||||
// Do not proceed if there was an undefined symbol.
|
||||
reportPendingUndefinedSymbols();
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
|
28
lld/test/MachO/invalid/undef-multi.s
Normal file
28
lld/test/MachO/invalid/undef-multi.s
Normal file
@ -0,0 +1,28 @@
|
||||
# REQUIRES: aarch64
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t.o
|
||||
# RUN: not %lld -arch arm64 %t.o -o /dev/null 2>&1 | FileCheck -DFILE=%t.o %s
|
||||
|
||||
# CHECK: error: undefined symbol: _undef
|
||||
# CHECK-NEXT: >>> referenced by [[FILE]]:(symbol _main+0x0)
|
||||
# CHECK-NEXT: >>> referenced by [[FILE]]:(symbol _foo+0x0)
|
||||
# CHECK-NEXT: >>> referenced by [[FILE]]:(symbol _bar+0x0)
|
||||
# CHECK-NEXT: >>> referenced 1 more times
|
||||
|
||||
.globl _main
|
||||
_main:
|
||||
b _undef
|
||||
|
||||
.globl _foo
|
||||
_foo:
|
||||
b _undef
|
||||
|
||||
.global _bar
|
||||
_bar:
|
||||
b _undef
|
||||
|
||||
.globl _baz
|
||||
_baz:
|
||||
b _undef
|
||||
|
||||
.subsections_via_symbols
|
Loading…
Reference in New Issue
Block a user