forked from OSchip/llvm-project
[lld-macho] Print the name of functions containing undefined references
The error used to look like this: ld64.lld: error: undefined symbol: _foo >>> referenced by /path/to/bar.o Now it displays the name of the function that contains the undefined reference as well: ld64.lld: error: undefined symbol: _foo >>> referenced by /path/to/bar.o:(symbol _baz+0x4) Differential Revision: https://reviews.llvm.org/D127696
This commit is contained in:
parent
cbcce82ef6
commit
f2e92cf60e
|
@ -302,50 +302,78 @@ static void handleSegmentBoundarySymbol(const Undefined &sym, StringRef segName,
|
|||
seg->segmentEndSymbols.push_back(createBoundarySymbol(sym));
|
||||
}
|
||||
|
||||
void lld::macho::treatUndefinedSymbol(const Undefined &sym, StringRef source) {
|
||||
// Try to find a definition for an undefined symbol.
|
||||
// Returns true if a definition was found and no diagnostics are needed.
|
||||
static bool recoverFromUndefinedSymbol(const Undefined &sym) {
|
||||
// Handle start/end symbols.
|
||||
StringRef name = sym.getName();
|
||||
if (name.consume_front("section$start$"))
|
||||
return handleSectionBoundarySymbol(sym, name, Boundary::Start);
|
||||
if (name.consume_front("section$end$"))
|
||||
return handleSectionBoundarySymbol(sym, name, Boundary::End);
|
||||
if (name.consume_front("segment$start$"))
|
||||
return handleSegmentBoundarySymbol(sym, name, Boundary::Start);
|
||||
if (name.consume_front("segment$end$"))
|
||||
return handleSegmentBoundarySymbol(sym, name, Boundary::End);
|
||||
if (name.consume_front("section$start$")) {
|
||||
handleSectionBoundarySymbol(sym, name, Boundary::Start);
|
||||
return true;
|
||||
}
|
||||
if (name.consume_front("section$end$")) {
|
||||
handleSectionBoundarySymbol(sym, name, Boundary::End);
|
||||
return true;
|
||||
}
|
||||
if (name.consume_front("segment$start$")) {
|
||||
handleSegmentBoundarySymbol(sym, name, Boundary::Start);
|
||||
return true;
|
||||
}
|
||||
if (name.consume_front("segment$end$")) {
|
||||
handleSegmentBoundarySymbol(sym, name, Boundary::End);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle -U.
|
||||
if (config->explicitDynamicLookups.count(sym.getName())) {
|
||||
symtab->addDynamicLookup(sym.getName());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle -undefined.
|
||||
auto message = [source, &sym]() {
|
||||
std::string message = "undefined symbol";
|
||||
if (config->archMultiple)
|
||||
message += (" for arch " + getArchitectureName(config->arch())).str();
|
||||
message += ": " + toString(sym);
|
||||
if (!source.empty())
|
||||
message += "\n>>> referenced by " + source.str();
|
||||
else
|
||||
message += "\n>>> referenced by " + toString(sym.getFile());
|
||||
return message;
|
||||
};
|
||||
switch (config->undefinedSymbolTreatment) {
|
||||
case UndefinedSymbolTreatment::error:
|
||||
error(message());
|
||||
break;
|
||||
case UndefinedSymbolTreatment::warning:
|
||||
warn(message());
|
||||
LLVM_FALLTHROUGH;
|
||||
case UndefinedSymbolTreatment::dynamic_lookup:
|
||||
case UndefinedSymbolTreatment::suppress:
|
||||
if (config->undefinedSymbolTreatment ==
|
||||
UndefinedSymbolTreatment::dynamic_lookup ||
|
||||
config->undefinedSymbolTreatment == UndefinedSymbolTreatment::suppress) {
|
||||
symtab->addDynamicLookup(sym.getName());
|
||||
break;
|
||||
case UndefinedSymbolTreatment::unknown:
|
||||
llvm_unreachable("unknown -undefined TREATMENT");
|
||||
return true;
|
||||
}
|
||||
|
||||
// We do not return true here, as we still need to print diagnostics.
|
||||
if (config->undefinedSymbolTreatment == UndefinedSymbolTreatment::warning)
|
||||
symtab->addDynamicLookup(sym.getName());
|
||||
|
||||
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();
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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) {
|
||||
if (recoverFromUndefinedSymbol(sym))
|
||||
return;
|
||||
|
||||
// TODO: Get source file/line from debug information.
|
||||
printUndefinedDiagnostic(toString(sym), isec->getLocation(offset));
|
||||
}
|
||||
|
||||
std::unique_ptr<SymbolTable> macho::symtab;
|
||||
|
|
|
@ -69,7 +69,9 @@ private:
|
|||
std::vector<Symbol *> symVector;
|
||||
};
|
||||
|
||||
void treatUndefinedSymbol(const Undefined &, StringRef source = "");
|
||||
void treatUndefinedSymbol(const Undefined &, StringRef source);
|
||||
void treatUndefinedSymbol(const Undefined &, const InputSection *,
|
||||
uint64_t offset);
|
||||
|
||||
extern std::unique_ptr<SymbolTable> symtab;
|
||||
|
||||
|
|
|
@ -273,7 +273,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
|
|||
r.referent = s = sym;
|
||||
}
|
||||
if (auto *undefined = dyn_cast<Undefined>(s)) {
|
||||
treatUndefinedSymbol(*undefined);
|
||||
treatUndefinedSymbol(*undefined, isec, r.offset);
|
||||
// treatUndefinedSymbol() can replace s with a DylibSymbol; re-check.
|
||||
if (isa<Undefined>(s))
|
||||
continue;
|
||||
|
|
|
@ -659,7 +659,7 @@ void Writer::scanRelocations() {
|
|||
}
|
||||
if (auto *sym = r.referent.dyn_cast<Symbol *>()) {
|
||||
if (auto *undefined = dyn_cast<Undefined>(sym))
|
||||
treatUndefinedSymbol(*undefined);
|
||||
treatUndefinedSymbol(*undefined, isec, r.offset);
|
||||
// treatUndefinedSymbol() can replace sym with a DylibSymbol; re-check.
|
||||
if (!isa<Undefined>(sym) && validateSymbolRelocation(sym, isec, r))
|
||||
prepareSymbolRelocation(sym, isec, r);
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o
|
||||
# RUN: llvm-ar crs %t/foo.a %t/foo.o
|
||||
# RUN: not %lld --icf=all -o /dev/null %t/main.o 2>&1 | \
|
||||
# RUN: FileCheck %s -DSYM=_foo -DFILENAME=%t/main.o
|
||||
# RUN: FileCheck %s -DSYM=_foo -DLOC='%t/main.o:(symbol _main+0x1)'
|
||||
# RUN: not %lld -o /dev/null %t/main.o %t/foo.a 2>&1 | \
|
||||
# RUN: FileCheck %s -DSYM=_bar -DFILENAME='%t/foo.a(foo.o)'
|
||||
# RUN: FileCheck %s -DSYM=_bar -DLOC='%t/foo.a(foo.o):(symbol _foo+0x1)'
|
||||
# RUN: not %lld -o /dev/null %t/main.o -force_load %t/foo.a 2>&1 | \
|
||||
# RUN: FileCheck %s -DSYM=_bar -DFILENAME='%t/foo.a(foo.o)'
|
||||
# RUN: FileCheck %s -DSYM=_bar -DLOC='%t/foo.a(foo.o):(symbol _foo+0x1)'
|
||||
# CHECK: error: undefined symbol: [[SYM]]
|
||||
# CHECK-NEXT: >>> referenced by [[FILENAME]]
|
||||
# CHECK-NEXT: >>> referenced by [[LOC]]
|
||||
|
||||
#--- foo.s
|
||||
.globl _foo
|
||||
|
|
Loading…
Reference in New Issue