[lld] f2e92cf - [lld-macho] Print the name of functions containing undefined references
Nico Weber via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 14 06:42:09 PDT 2022
Author: Daniel Bertalan
Date: 2022-06-14T09:41:28-04:00
New Revision: f2e92cf60e45c517ef8a7b20812a6ac407cad091
URL: https://github.com/llvm/llvm-project/commit/f2e92cf60e45c517ef8a7b20812a6ac407cad091
DIFF: https://github.com/llvm/llvm-project/commit/f2e92cf60e45c517ef8a7b20812a6ac407cad091.diff
LOG: [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
Added:
Modified:
lld/MachO/SymbolTable.cpp
lld/MachO/SymbolTable.h
lld/MachO/UnwindInfoSection.cpp
lld/MachO/Writer.cpp
lld/test/MachO/invalid/undefined-symbol.s
Removed:
################################################################################
diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp
index b9248e6f381c9..b0c83a568eb69 100644
--- a/lld/MachO/SymbolTable.cpp
+++ b/lld/MachO/SymbolTable.cpp
@@ -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;
diff --git a/lld/MachO/SymbolTable.h b/lld/MachO/SymbolTable.h
index 5f844170efe04..a433f41318eae 100644
--- a/lld/MachO/SymbolTable.h
+++ b/lld/MachO/SymbolTable.h
@@ -69,7 +69,9 @@ class SymbolTable {
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;
diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index 1d6d658f97888..5822d668b4c06 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -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;
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 3e9641ba5ef7b..f2634076e0803 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -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);
diff --git a/lld/test/MachO/invalid/undefined-symbol.s b/lld/test/MachO/invalid/undefined-symbol.s
index 97a300494b277..4b80716347bb3 100644
--- a/lld/test/MachO/invalid/undefined-symbol.s
+++ b/lld/test/MachO/invalid/undefined-symbol.s
@@ -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
More information about the llvm-commits
mailing list