[lld] 2516b0b - [lld-macho] Treat undefined symbols uniformly

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Mon May 10 12:46:37 PDT 2021


Author: Jez Ng
Date: 2021-05-10T15:45:54-04:00
New Revision: 2516b0b5261d5f1fe7cfe357550a826f88fc68b7

URL: https://github.com/llvm/llvm-project/commit/2516b0b5261d5f1fe7cfe357550a826f88fc68b7
DIFF: https://github.com/llvm/llvm-project/commit/2516b0b5261d5f1fe7cfe357550a826f88fc68b7.diff

LOG: [lld-macho] Treat undefined symbols uniformly

In particular, we should apply the `-undefined` behavior to all
such symbols, include those that are specified via the command line
(i.e.  `-e`, `-u`, and `-exported_symbol`). ld64 supports this too.

Reviewed By: #lld-macho, thakis

Differential Revision: https://reviews.llvm.org/D102143

Added: 
    

Modified: 
    lld/MachO/Driver.cpp
    lld/MachO/SymbolTable.cpp
    lld/MachO/SymbolTable.h
    lld/MachO/Writer.cpp
    lld/test/MachO/entry-symbol.s
    lld/test/MachO/export-options.s
    lld/test/MachO/u.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 8a03e584945bd..00c9b41f2a559 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -1144,30 +1144,28 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
     if (!orderFile.empty())
       parseOrderFile(orderFile);
 
-    if (config->outputType == MH_EXECUTE && isa<Undefined>(config->entry)) {
-      error("undefined symbol: " + toString(*config->entry));
-      return false;
-    }
+    if (config->entry)
+      if (auto *undefined = dyn_cast<Undefined>(config->entry))
+        treatUndefinedSymbol(*undefined, "the entry point");
+
     // FIXME: This prints symbols that are undefined both in input files and
     // via -u flag twice.
-    for (const Symbol *undefined : config->explicitUndefineds) {
-      if (isa<Undefined>(undefined)) {
-        error("undefined symbol: " + toString(*undefined) +
-              "\n>>> referenced by flag -u " + toString(*undefined));
-        return false;
-      }
+    for (const Symbol *sym : config->explicitUndefineds) {
+      if (const auto *undefined = dyn_cast<Undefined>(sym))
+        treatUndefinedSymbol(*undefined, "-u");
     }
     // Literal exported-symbol names must be defined, but glob
     // patterns need not match.
     for (const CachedHashStringRef &cachedName :
          config->exportedSymbols.literals) {
       if (const Symbol *sym = symtab->find(cachedName))
-        if (isa<Defined>(sym))
-          continue;
-      error("undefined symbol: " + cachedName.val() +
-            "\n>>> referenced from option -exported_symbol(s_list)");
+        if (const auto *undefined = dyn_cast<Undefined>(sym))
+          treatUndefinedSymbol(*undefined, "-exported_symbol(s_list)");
     }
 
+    // FIXME: should terminate the link early based on errors encountered so
+    // far?
+
     createSyntheticSections();
     createSyntheticSymbols();
 

diff  --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp
index ff55119e167f1..ad163d314c7be 100644
--- a/lld/MachO/SymbolTable.cpp
+++ b/lld/MachO/SymbolTable.cpp
@@ -186,20 +186,21 @@ Defined *SymbolTable::addSynthetic(StringRef name, InputSection *isec,
   return s;
 }
 
-void lld::macho::treatUndefinedSymbol(const Undefined &sym) {
-  auto message = [](const Undefined &sym) {
+void lld::macho::treatUndefinedSymbol(const Undefined &sym, StringRef source) {
+  auto message = [source, &sym]() {
     std::string message = "undefined symbol: " + toString(sym);
-    std::string fileName = toString(sym.getFile());
-    if (!fileName.empty())
-      message += "\n>>> referenced by " + fileName;
+    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(sym));
+    error(message());
     break;
   case UndefinedSymbolTreatment::warning:
-    warn(message(sym));
+    warn(message());
     LLVM_FALLTHROUGH;
   case UndefinedSymbolTreatment::dynamic_lookup:
   case UndefinedSymbolTreatment::suppress:

diff  --git a/lld/MachO/SymbolTable.h b/lld/MachO/SymbolTable.h
index 611eb8b005090..1239cd9a9cb3a 100644
--- a/lld/MachO/SymbolTable.h
+++ b/lld/MachO/SymbolTable.h
@@ -65,7 +65,7 @@ class SymbolTable {
   std::vector<Symbol *> symVector;
 };
 
-void treatUndefinedSymbol(const Undefined &);
+void treatUndefinedSymbol(const Undefined &, StringRef source = "");
 
 extern SymbolTable *symtab;
 

diff  --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 8929b524bf9a6..8236760e74e49 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -1055,7 +1055,7 @@ void Writer::writeOutputFile() {
 }
 
 template <class LP> void Writer::run() {
-  if (config->entry)
+  if (config->entry && !isa<Undefined>(config->entry))
     prepareBranchTarget(config->entry);
   scanRelocations();
   if (in.stubHelper->isNeeded())

diff  --git a/lld/test/MachO/entry-symbol.s b/lld/test/MachO/entry-symbol.s
index f4ead9cb8556b..36fdeb6b44223 100644
--- a/lld/test/MachO/entry-symbol.s
+++ b/lld/test/MachO/entry-symbol.s
@@ -22,7 +22,11 @@
 # CHECK-NEXT: entryoff [[#ENTRYOFF]]
 
 # RUN: %lld -lSystem -o %t/dysym-main %t/not-main.o %t/libfoo.dylib -e _dysym_main
-# RUN: llvm-objdump --macho --all-headers --indirect-symbols --lazy-bind %t/dysym-main | FileCheck %s --check-prefix=DYSYM
+# RUN: llvm-objdump --macho --all-headers --indirect-symbols --lazy-bind %t/dysym-main | FileCheck %s --check-prefix=DYSYM -DDYLIB=libfoo
+
+# RUN: %lld -lSystem -o %t/dyn-lookup %t/not-main.o -e _dysym_main -undefined dynamic_lookup
+# RUN: llvm-objdump --macho --all-headers --indirect-symbols --lazy-bind %t/dyn-lookup | FileCheck %s --check-prefix=DYSYM -DDYLIB=flat-namespace
+
 # DYSYM-LABEL: Indirect symbols for (__TEXT,__stubs) 1 entries
 # DYSYM-NEXT:  address                      index  name
 # DYSYM-NEXT:  0x[[#%x,DYSYM_ENTRY_ADDR:]]  [[#]]  _dysym_main
@@ -30,8 +34,8 @@
 # DYSYM-NEXT:  cmdsize  24
 # DYSYM-NEXT:  entryoff [[#%u, DYSYM_ENTRY_ADDR - 0x100000000]]
 # DYSYM-LABEL: Lazy bind table:
-# DYSYM-NEXT:  segment  section            address     dylib            symbol
-# DYSYM-NEXT:  __DATA   __la_symbol_ptr    {{.*}}      libfoo       _dysym_main
+# DYSYM-NEXT:  segment  section            address     dylib        symbol
+# DYSYM-NEXT:  __DATA   __la_symbol_ptr    {{.*}}      [[DYLIB]]    _dysym_main
 
 # RUN: %lld -lSystem -o %t/weak-dysym-main %t/not-main.o %t/libfoo.dylib -e _weak_dysym_main
 # RUN: llvm-objdump --macho --all-headers --indirect-symbols --bind --weak-bind %t/weak-dysym-main | FileCheck %s --check-prefix=WEAK-DYSYM
@@ -42,8 +46,8 @@
 # WEAK-DYSYM-NEXT:  cmdsize  24
 # WEAK-DYSYM-NEXT:  entryoff [[#%u, DYSYM_ENTRY_ADDR - 0x100000000]]
 # WEAK-DYSYM-LABEL: Bind table:
-# WEAK-DYSYM-NEXT:  segment  section          address  type     addend  dylib      symbol
-# WEAK-DYSYM:       __DATA   __la_symbol_ptr  {{.*}}   pointer       0  libfoo _weak_dysym_main
+# WEAK-DYSYM-NEXT:  segment  section          address  type     addend  dylib   symbol
+# WEAK-DYSYM:       __DATA   __la_symbol_ptr  {{.*}}   pointer       0  libfoo  _weak_dysym_main
 # WEAK-DYSYM-LABEL: Weak bind table:
 # WEAK-DYSYM-NEXT:  segment  section          address  type     addend  symbol
 # WEAK-DYSYM-NEXT:  __DATA   __la_symbol_ptr  {{.*}}   pointer       0  _weak_dysym_main
@@ -55,7 +59,8 @@
 # RUN: not %lld -o /dev/null %t/not-main.o -e _missing 2>&1 | FileCheck %s --check-prefix=UNDEFINED
 # UNDEFINED: error: undefined symbol: _missing
 # RUN: not %lld -o /dev/null %t/not-main.o 2>&1 | FileCheck %s --check-prefix=DEFAULT-ENTRY
-# DEFAULT-ENTRY: error: undefined symbol: _main
+# DEFAULT-ENTRY:      error: undefined symbol: _main
+# DEFAULT-ENTRY-NEXT: >>> referenced by the entry point
 
 #--- libfoo.s
 .text

diff  --git a/lld/test/MachO/export-options.s b/lld/test/MachO/export-options.s
index 0ef8a3d0e1e86..113a2c3fcd52e 100644
--- a/lld/test/MachO/export-options.s
+++ b/lld/test/MachO/export-options.s
@@ -21,9 +21,15 @@
 # RUN:     FileCheck --check-prefix=UNDEF %s
 
 # UNDEF: error: undefined symbol: absent_literal
-# UNDEF-NEXT: >>> referenced from option -exported_symbol(s_list)
+# UNDEF-NEXT: >>> referenced by -exported_symbol(s_list)
 # UNDEF-NOT: error: {{.*}} absent_gl{{.}}b
 
+## Check that dynamic_lookup suppresses the error
+# RUN: %lld -dylib %t/default.o -undefined dynamic_lookup -o %t/dyn-lookup \
+# RUN:      -exported_symbol absent_literal
+# RUN: llvm-objdump --macho --syms %t/dyn-lookup | FileCheck %s --check-prefix=DYN
+# DYN: *UND* absent_literal
+
 ## Check that exported literal symbols are present in output's
 ## symbol table, even lazy symbols which would otherwise be omitted
 # RUN: %lld -dylib %t/default.o %t/lazydef.a -o %t/lazydef \

diff  --git a/lld/test/MachO/u.s b/lld/test/MachO/u.s
index fb5159aa6a07e..58519230c7c62 100644
--- a/lld/test/MachO/u.s
+++ b/lld/test/MachO/u.s
@@ -6,18 +6,25 @@
 
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/main.o %t/main.s
 
-# RUN: %lld %t/main.o %t/lib.a -o /dev/null -why_load | \
+# RUN: %lld -lSystem %t/main.o %t/lib.a -o /dev/null -why_load | \
 # RUN:     FileCheck %s --check-prefix=NOFOO --allow-empty
 
-# RUN: %lld %t/main.o %t/lib.a -u _foo -o /dev/null -why_load | \
+# RUN: %lld -lSystem %t/main.o %t/lib.a -u _foo -o /dev/null -why_load | \
 # RUN:     FileCheck %s --check-prefix=FOO
 
-# RUN: not %lld %t/main.o %t/lib.a -u _asdf -o /dev/null 2>&1 | \
+# RUN: not %lld %t/main.o %t/lib.a -u _asdf -u _fdsa -o /dev/null 2>&1 | \
 # RUN:     FileCheck %s --check-prefix=UNDEF
 
+# RUN: %lld -lSystem %t/main.o %t/lib.a -u _asdf -undefined dynamic_lookup -o %t/dyn-lookup
+# RUN: llvm-objdump --macho --syms %t/dyn-lookup | FileCheck %s --check-prefix=DYN
+
 # NOFOO-NOT: _foo forced load of {{.+}}lib.a(foo.o)
 # FOO: _foo forced load of {{.+}}lib.a(foo.o)
-# UNDEF: error: undefined symbol: _asdf
+# UNDEF:      error: undefined symbol: _asdf
+# UNDEF-NEXT: >>> referenced by -u
+# UNDEF:      error: undefined symbol: _fdsa
+# UNDEF-NEXT: >>> referenced by -u
+# DYN: *UND* _asdf
 
 #--- foo.s
 .globl _foo


        


More information about the llvm-commits mailing list