diff --git a/lld/MachO/SymbolTable.h b/lld/MachO/SymbolTable.h --- a/lld/MachO/SymbolTable.h +++ b/lld/MachO/SymbolTable.h @@ -72,6 +72,7 @@ }; void reportPendingUndefinedSymbols(); +void reportPendingDuplicateSymbols(); // Call reportPendingUndefinedSymbols() to emit diagnostics. void treatUndefinedSymbol(const Undefined &, StringRef source); diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp --- a/lld/MachO/SymbolTable.cpp +++ b/lld/MachO/SymbolTable.cpp @@ -45,6 +45,17 @@ return {sym, p.second}; } +namespace { +struct DuplicateSymbolReporter { + const Symbol *sym; + const std::string errorMessage; + + DuplicateSymbolReporter(const Symbol *sym, const std::string errorMessage) + : sym(sym), errorMessage(errorMessage) {} +}; +std::vector dupSymReporter; +} // namespace + Defined *SymbolTable::addDefined(StringRef name, InputFile *file, InputSection *isec, uint64_t value, uint64_t size, bool isWeakDef, @@ -90,7 +101,7 @@ message += toString(defined->getFile()) + "\n>>> defined in "; if (!src2.empty()) message += src2 + "\n>>> "; - error(message + toString(file)); + dupSymReporter.push_back({defined, message + toString(file)}); } } else if (auto *dysym = dyn_cast(s)) { @@ -366,6 +377,12 @@ MapVector undefs; } +void macho::reportPendingDuplicateSymbols() { + for (const auto &duplicate : dupSymReporter) + if (duplicate.sym->isLive()) + error(duplicate.errorMessage); +} + void macho::reportPendingUndefinedSymbols() { for (const auto &undef : undefs) { const UndefinedDiag &locations = undef.second; diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -1185,8 +1185,9 @@ if (in.initOffsets->isNeeded()) in.initOffsets->setUp(); - // Do not proceed if there was an undefined symbol. + // Do not proceed if there were undefined or duplicate symbols. reportPendingUndefinedSymbols(); + reportPendingDuplicateSymbols(); if (errorCount()) return; diff --git a/lld/test/MachO/abs-duplicate.s b/lld/test/MachO/abs-duplicate.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/abs-duplicate.s @@ -0,0 +1,40 @@ +# REQUIRES: x86 +# RUN: rm -rf %t; split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/weakfoo.s -o %t/weakfoo.o +# RUN: not %lld -lSystem %t/test.o %t/weakfoo.o -o /dev/null 2>&1 | FileCheck %s + +# CHECK: error: duplicate symbol: _weakfoo +# CHECK-NEXT: >>> defined in {{.*}}/test.o +# CHECK-NEXT: >>> defined in {{.*}}/weakfoo.o + +## Duplicate absolute symbols that will be dead stripped later should not fail. +# RUN: %lld -lSystem -dead_strip -map %t/stripped-duplicate-map %t/test.o %t/weakfoo.o -o %t/test +# RUN: llvm-objdump --syms %t/test | FileCheck %s --check-prefix=DUP +# DUP-LABEL: SYMBOL TABLE: +# DUP-NEXT: g F __TEXT,__text _main +# DUP-NEXT: g F __TEXT,__text __mh_execute_header +# DUP-NEXT: *UND* dyld_stub_binder + +## Dead stripped non-section symbols don't show up in map files because there's no input section. +## Check that _weakfoo doesn't show up. This matches ld64. +# RUN: FileCheck --check-prefix=DUPMAP %s < %t/stripped-duplicate-map +# DUPMAP: _main +# DUPMAP-LABEL: Dead Stripped Symbols +# DUPMAP-NOT: _weakfoo + +#--- weakfoo.s +.globl _weakfoo +## The weak attribute is ignored for absolute symbols, so we will have a +## duplicate symbol error for _weakfoo. +.weak_definition _weakfoo +_weakfoo = 0x1234 + +#--- test.s +.globl _main, _weakfoo +.weak_definition _weakfoo +_weakfoo = 0x5678 + +.text +_main: + ret diff --git a/lld/test/MachO/dead-strip.s b/lld/test/MachO/dead-strip.s --- a/lld/test/MachO/dead-strip.s +++ b/lld/test/MachO/dead-strip.s @@ -321,7 +321,6 @@ # RUN: %lld -dylib -dead_strip --deduplicate-literals %t/literals.o -o %t/literals # RUN: llvm-objdump --macho --section="__TEXT,__cstring" --section="__DATA,str_ptrs" \ # RUN: --section="__TEXT,__literals" %t/literals | FileCheck %s --check-prefix=LIT - # LIT: Contents of (__TEXT,__cstring) section # LIT-NEXT: foobar # LIT-NEXT: Contents of (__DATA,str_ptrs) section @@ -330,6 +329,44 @@ # LIT-NEXT: Contents of (__TEXT,__literals) section # LIT-NEXT: ef be ad de {{$}} +## Duplicate symbols that will be dead stripped later should not fail. +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos \ +# RUN: %t/duplicate1.s -o %t/duplicate1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos \ +# RUN: %t/duplicate2.s -o %t/duplicate2.o +# RUN: %lld -lSystem -dead_strip -map %t/stripped-duplicate-map %t/duplicate1.o \ +# RUN: %t/duplicate2.o -o %t/duplicate +# RUN: llvm-objdump --syms %t/duplicate | FileCheck %s --check-prefix=DUP +# DUP-LABEL: SYMBOL TABLE: +# DUP-NEXT: g F __TEXT,__text _main +# DUP-NEXT: g F __TEXT,__text __mh_execute_header +# DUP-NEXT: *UND* dyld_stub_binder + +## Check that the duplicate dead stripped symbols get listed properly. +# RUN: FileCheck --check-prefix=DUPMAP %s < %t/stripped-duplicate-map +# DUPMAP: _main +# DUPMAP-LABEL: Dead Stripped Symbols +# DUPMAP: <> [ 2] _foo + +#--- duplicate1.s +.text +.globl _main, _foo +_foo: + retq + +_main: + retq + +.subsections_via_symbols + +#--- duplicate2.s +.text +.globl _foo +_foo: + retq + +.subsections_via_symbols + #--- basics.s .comm _ref_com, 1 .comm _unref_com, 1 diff --git a/lld/test/MachO/invalid/abs-duplicate.s b/lld/test/MachO/invalid/abs-duplicate.s deleted file mode 100644 --- a/lld/test/MachO/invalid/abs-duplicate.s +++ /dev/null @@ -1,25 +0,0 @@ -# REQUIRES: x86 -# RUN: rm -rf %t; split-file %s %t -# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o -# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/weakfoo.s -o %t/weakfoo.o -# RUN: not %lld -lSystem %t/test.o %t/weakfoo.o -o %t/test 2>&1 | FileCheck %s - -# CHECK: error: duplicate symbol: _weakfoo -# CHECK-NEXT: >>> defined in {{.*}}/test.o -# CHECK-NEXT: >>> defined in {{.*}}/weakfoo.o - -#--- weakfoo.s -.globl _weakfoo -## The weak attribute is ignored for absolute symbols, so we will have a -## duplicate symbol error for _weakfoo. -.weak_definition _weakfoo -_weakfoo = 0x1234 - -#--- test.s -.globl _main, _weakfoo -.weak_definition _weakfoo -_weakfoo = 0x5678 - -.text -_main: - ret