[lld] 0eec7e2 - Reland "[lld-macho] Group undefined symbol diagnostics by symbol".

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 15 16:22:58 PDT 2022


Author: Daniel Bertalan
Date: 2022-06-15T19:22:39-04:00
New Revision: 0eec7e2a89abc6e626cad3c6493b3a1c15c10704

URL: https://github.com/llvm/llvm-project/commit/0eec7e2a89abc6e626cad3c6493b3a1c15c10704
DIFF: https://github.com/llvm/llvm-project/commit/0eec7e2a89abc6e626cad3c6493b3a1c15c10704.diff

LOG: Reland "[lld-macho] Group undefined symbol diagnostics by symbol".

This reverts commit 36e7c9a450db5e22af1ec21412d918ceb2313942.

This relands d61341768cf0cff7c with the fix described in
https://reviews.llvm.org/D127753#3587390

Added: 
    lld/test/MachO/invalid/undef-multi.s

Modified: 
    lld/ELF/Relocations.cpp
    lld/MachO/SymbolTable.cpp
    lld/MachO/SymbolTable.h
    lld/MachO/Writer.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index a272be5480e3..76d448fe471b 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -558,6 +558,7 @@ static std::string maybeReportDiscarded(Undefined &sym) {
   return msg;
 }
 
+namespace {
 // Undefined diagnostics are collected in a vector and emitted once all of
 // them are known, so that some postprocessing on the list of undefined symbols
 // can happen before lld emits diagnostics.
@@ -571,7 +572,8 @@ struct UndefinedDiag {
   bool isWarning;
 };
 
-static std::vector<UndefinedDiag> undefs;
+std::vector<UndefinedDiag> undefs;
+}
 
 // Check whether the definition name def is a mangled function name that matches
 // the reference name ref.

diff  --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp
index b0c83a568eb6..5bc622126071 100644
--- a/lld/MachO/SymbolTable.cpp
+++ b/lld/MachO/SymbolTable.cpp
@@ -345,35 +345,82 @@ 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();
-
-  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");
+namespace {
+struct UndefinedDiag {
+  struct SectionAndOffset {
+    const InputSection *isec;
+    uint64_t offset;
+  };
+
+  std::vector<SectionAndOffset> codeReferences;
+  std::vector<std::string> otherReferences;
+};
+
+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) {
+void macho::treatUndefinedSymbol(const Undefined &sym, StringRef source) {
   if (recoverFromUndefinedSymbol(sym))
     return;
-  printUndefinedDiagnostic(sym.getName(), source);
+
+  undefs[&sym].otherReferences.push_back(source.str());
 }
 
-void lld::macho::treatUndefinedSymbol(const Undefined &sym,
-                                      const InputSection *isec,
-                                      uint64_t offset) {
+void 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));
+  undefs[&sym].codeReferences.push_back({isec, offset});
 }
 
 std::unique_ptr<SymbolTable> macho::symtab;

diff  --git a/lld/MachO/SymbolTable.h b/lld/MachO/SymbolTable.h
index a433f41318ea..0ecfa6dcd093 100644
--- a/lld/MachO/SymbolTable.h
+++ b/lld/MachO/SymbolTable.h
@@ -69,6 +69,9 @@ class SymbolTable {
   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);

diff  --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index f2634076e080..74612409bc53 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -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;
 

diff  --git a/lld/test/MachO/invalid/undef-multi.s b/lld/test/MachO/invalid/undef-multi.s
new file mode 100644
index 000000000000..c59bff2a5e63
--- /dev/null
+++ b/lld/test/MachO/invalid/undef-multi.s
@@ -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


        


More information about the llvm-commits mailing list