[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