Skip to content

Commit

Permalink
[lld/mac] Implement the missing bits of -undefined
Browse files Browse the repository at this point in the history
This adds support for `-undefined dynamic_lookup`, and for
`-undefined warning` and `-undefined suppress` with `-flat_namespace`.

We just replace undefined symbols with a DynamicLookup when we hit them.

With this, `check-llvm` passes when using ld64.lld.darwinnew as host linker.

Differential Revision: https://reviews.llvm.org/D97642
  • Loading branch information
nico committed Mar 1, 2021
1 parent 6ca5281 commit 0658fc6
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 23 deletions.
25 changes: 12 additions & 13 deletions lld/MachO/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,24 +174,23 @@ Symbol *SymbolTable::addDSOHandle(const MachHeaderSection *header) {
}

void lld::macho::treatUndefinedSymbol(const Undefined &sym) {
std::string message = "undefined symbol: " + toString(sym);
std::string fileName = toString(sym.getFile());

if (!fileName.empty())
message += "\n>>> referenced by " + fileName;
auto message = [](const Undefined &sym) {
std::string message = "undefined symbol: " + toString(sym);
std::string fileName = toString(sym.getFile());
if (!fileName.empty())
message += "\n>>> referenced by " + fileName;
return message;
};
switch (config->undefinedSymbolTreatment) {
case UndefinedSymbolTreatment::suppress:
error("-undefined suppress unimplemented");
break;
case UndefinedSymbolTreatment::error:
error(message);
error(message(sym));
break;
case UndefinedSymbolTreatment::warning:
warn(message);
error("-undefined warning unimplemented");
break;
warn(message(sym));
LLVM_FALLTHROUGH;
case UndefinedSymbolTreatment::dynamic_lookup:
error("dynamic_lookup unimplemented for " + message);
case UndefinedSymbolTreatment::suppress:
symtab->addDynamicLookup(sym.getName());
break;
case UndefinedSymbolTreatment::unknown:
llvm_unreachable("unknown -undefined TREATMENT");
Expand Down
4 changes: 3 additions & 1 deletion lld/MachO/UnwindInfoSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ void macho::prepareCompactUnwind(InputSection *isec) {
if (auto *s = r.referent.dyn_cast<lld::macho::Symbol *>()) {
if (auto *undefined = dyn_cast<Undefined>(s)) {
treatUndefinedSymbol(*undefined);
continue;
// treatUndefinedSymbol() can replace s with a DylibSymbol; re-check.
if (isa<Undefined>(s))
continue;
}
if (auto *defined = dyn_cast<Defined>(s)) {
// Check if we have created a synthetic symbol at the same address.
Expand Down
4 changes: 3 additions & 1 deletion lld/MachO/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,9 @@ void Writer::scanRelocations() {
if (auto *sym = r.referent.dyn_cast<lld::macho::Symbol *>()) {
if (auto *undefined = dyn_cast<Undefined>(sym))
treatUndefinedSymbol(*undefined);
else if (target->validateSymbolRelocation(sym, isec, r))
// treatUndefinedSymbol() can replace sym with a DylibSymbol; re-check.
if (!isa<Undefined>(sym) &&
target->validateSymbolRelocation(sym, isec, r))
prepareSymbolRelocation(sym, isec, r);
} else {
assert(r.referent.is<InputSection *>());
Expand Down
29 changes: 21 additions & 8 deletions lld/test/MachO/treat-undef-sym.s
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,24 @@
# RUN: FileCheck %s -check-prefix=INVAL-WARNING
# RUN: not %lld -undefined suppress -o /dev/null %t.o 2>&1 | \
# RUN: FileCheck %s -check-prefix=INVAL-SUPPRESS

# FIXME: Enable these -undefined checks once -flat_namespace is implemented.
# RN: %no_fatal_warnings_lld -flat_namespace -undefined warning \
# RN: -o /dev/null %t.o 2>&1 | \
# RN: FileCheck %s -check-prefix=WARNING
# RN: %lld -flat_namespace -undefined suppress -o /dev/null %t.o 2>&1 | \
# RN: FileCheck %s -check-prefix=SUPPRESS --allow-empty
# RUN: %lld -undefined dynamic_lookup -lSystem -o %t.out %t.o 2>&1 | \
# RUN: FileCheck %s -check-prefix=SUPPRESS --allow-empty
# RUN: llvm-objdump --macho --lazy-bind %t.out \
# RUN: | FileCheck --check-prefix=BIND %s

# RUN: %no_fatal_warnings_lld -lSystem -flat_namespace -undefined warning \
# RUN: -o %t.out %t.o 2>&1 | \
# RUN: FileCheck %s -check-prefix=WARNING
# RUN: llvm-objdump --macho --lazy-bind %t.out \
# RUN: | FileCheck --check-prefix=BIND %s
# RUN: %lld -flat_namespace -lSystem -undefined suppress -o %t.out %t.o 2>&1 | \
# RUN: FileCheck %s -check-prefix=SUPPRESS --allow-empty
# RUN: llvm-objdump --macho --lazy-bind %t.out \
# RUN: | FileCheck --check-prefix=BIND %s
# RUN: %lld -flat_namespace -lSystem -undefined dynamic_lookup -o %t.out %t.o 2>&1 | \
# RUN: FileCheck %s -check-prefix=SUPPRESS --allow-empty
# RUN: llvm-objdump --macho --lazy-bind %t.out \
# RUN: | FileCheck --check-prefix=BIND %s

# ERROR: error: undefined symbol: _bar
# ERROR-NEXT: >>> referenced by
Expand All @@ -27,7 +38,6 @@
# INVAL-SUPPRESS: error: '-undefined suppress' only valid with '-flat_namespace'
# INVAL-SUPPRESS-NEXT: error: undefined symbol: _bar


# WARNING: warning: undefined symbol: _bar
# WARNING-NEXT: >>> referenced by

Expand All @@ -37,6 +47,9 @@
# UNKNOWN-NEXT: error: undefined symbol: _bar
# UNKNOWN-NEXT: >>> referenced by

# BIND: Lazy bind table:
# BIND: __DATA __la_symbol_ptr 0x{{[0-9a-f]*}} flat-namespace _bar

.globl _main
_main:
callq _bar
Expand Down

0 comments on commit 0658fc6

Please sign in to comment.