Skip to content

Commit 0658fc6

Browse files
committed
[lld/mac] Implement the missing bits of -undefined
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
1 parent 6ca5281 commit 0658fc6

File tree

4 files changed

+39
-23
lines changed

4 files changed

+39
-23
lines changed

lld/MachO/SymbolTable.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -174,24 +174,23 @@ Symbol *SymbolTable::addDSOHandle(const MachHeaderSection *header) {
174174
}
175175

176176
void lld::macho::treatUndefinedSymbol(const Undefined &sym) {
177-
std::string message = "undefined symbol: " + toString(sym);
178-
std::string fileName = toString(sym.getFile());
179-
180-
if (!fileName.empty())
181-
message += "\n>>> referenced by " + fileName;
177+
auto message = [](const Undefined &sym) {
178+
std::string message = "undefined symbol: " + toString(sym);
179+
std::string fileName = toString(sym.getFile());
180+
if (!fileName.empty())
181+
message += "\n>>> referenced by " + fileName;
182+
return message;
183+
};
182184
switch (config->undefinedSymbolTreatment) {
183-
case UndefinedSymbolTreatment::suppress:
184-
error("-undefined suppress unimplemented");
185-
break;
186185
case UndefinedSymbolTreatment::error:
187-
error(message);
186+
error(message(sym));
188187
break;
189188
case UndefinedSymbolTreatment::warning:
190-
warn(message);
191-
error("-undefined warning unimplemented");
192-
break;
189+
warn(message(sym));
190+
LLVM_FALLTHROUGH;
193191
case UndefinedSymbolTreatment::dynamic_lookup:
194-
error("dynamic_lookup unimplemented for " + message);
192+
case UndefinedSymbolTreatment::suppress:
193+
symtab->addDynamicLookup(sym.getName());
195194
break;
196195
case UndefinedSymbolTreatment::unknown:
197196
llvm_unreachable("unknown -undefined TREATMENT");

lld/MachO/UnwindInfoSection.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ void macho::prepareCompactUnwind(InputSection *isec) {
121121
if (auto *s = r.referent.dyn_cast<lld::macho::Symbol *>()) {
122122
if (auto *undefined = dyn_cast<Undefined>(s)) {
123123
treatUndefinedSymbol(*undefined);
124-
continue;
124+
// treatUndefinedSymbol() can replace s with a DylibSymbol; re-check.
125+
if (isa<Undefined>(s))
126+
continue;
125127
}
126128
if (auto *defined = dyn_cast<Defined>(s)) {
127129
// Check if we have created a synthetic symbol at the same address.

lld/MachO/Writer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,9 @@ void Writer::scanRelocations() {
462462
if (auto *sym = r.referent.dyn_cast<lld::macho::Symbol *>()) {
463463
if (auto *undefined = dyn_cast<Undefined>(sym))
464464
treatUndefinedSymbol(*undefined);
465-
else if (target->validateSymbolRelocation(sym, isec, r))
465+
// treatUndefinedSymbol() can replace sym with a DylibSymbol; re-check.
466+
if (!isa<Undefined>(sym) &&
467+
target->validateSymbolRelocation(sym, isec, r))
466468
prepareSymbolRelocation(sym, isec, r);
467469
} else {
468470
assert(r.referent.is<InputSection *>());

lld/test/MachO/treat-undef-sym.s

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,24 @@
1010
# RUN: FileCheck %s -check-prefix=INVAL-WARNING
1111
# RUN: not %lld -undefined suppress -o /dev/null %t.o 2>&1 | \
1212
# RUN: FileCheck %s -check-prefix=INVAL-SUPPRESS
13-
14-
# FIXME: Enable these -undefined checks once -flat_namespace is implemented.
15-
# RN: %no_fatal_warnings_lld -flat_namespace -undefined warning \
16-
# RN: -o /dev/null %t.o 2>&1 | \
17-
# RN: FileCheck %s -check-prefix=WARNING
18-
# RN: %lld -flat_namespace -undefined suppress -o /dev/null %t.o 2>&1 | \
19-
# RN: FileCheck %s -check-prefix=SUPPRESS --allow-empty
13+
# RUN: %lld -undefined dynamic_lookup -lSystem -o %t.out %t.o 2>&1 | \
14+
# RUN: FileCheck %s -check-prefix=SUPPRESS --allow-empty
15+
# RUN: llvm-objdump --macho --lazy-bind %t.out \
16+
# RUN: | FileCheck --check-prefix=BIND %s
17+
18+
# RUN: %no_fatal_warnings_lld -lSystem -flat_namespace -undefined warning \
19+
# RUN: -o %t.out %t.o 2>&1 | \
20+
# RUN: FileCheck %s -check-prefix=WARNING
21+
# RUN: llvm-objdump --macho --lazy-bind %t.out \
22+
# RUN: | FileCheck --check-prefix=BIND %s
23+
# RUN: %lld -flat_namespace -lSystem -undefined suppress -o %t.out %t.o 2>&1 | \
24+
# RUN: FileCheck %s -check-prefix=SUPPRESS --allow-empty
25+
# RUN: llvm-objdump --macho --lazy-bind %t.out \
26+
# RUN: | FileCheck --check-prefix=BIND %s
27+
# RUN: %lld -flat_namespace -lSystem -undefined dynamic_lookup -o %t.out %t.o 2>&1 | \
28+
# RUN: FileCheck %s -check-prefix=SUPPRESS --allow-empty
29+
# RUN: llvm-objdump --macho --lazy-bind %t.out \
30+
# RUN: | FileCheck --check-prefix=BIND %s
2031

2132
# ERROR: error: undefined symbol: _bar
2233
# ERROR-NEXT: >>> referenced by
@@ -27,7 +38,6 @@
2738
# INVAL-SUPPRESS: error: '-undefined suppress' only valid with '-flat_namespace'
2839
# INVAL-SUPPRESS-NEXT: error: undefined symbol: _bar
2940

30-
3141
# WARNING: warning: undefined symbol: _bar
3242
# WARNING-NEXT: >>> referenced by
3343

@@ -37,6 +47,9 @@
3747
# UNKNOWN-NEXT: error: undefined symbol: _bar
3848
# UNKNOWN-NEXT: >>> referenced by
3949

50+
# BIND: Lazy bind table:
51+
# BIND: __DATA __la_symbol_ptr 0x{{[0-9a-f]*}} flat-namespace _bar
52+
4053
.globl _main
4154
_main:
4255
callq _bar

0 commit comments

Comments
 (0)