diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -85,7 +85,7 @@ } std::string InputSection::getSourceLocation(uint64_t off) const { - auto *obj = dyn_cast(getFile()); + auto *obj = dyn_cast_or_null(getFile()); if (!obj) return {}; diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp --- a/lld/MachO/SymbolTable.cpp +++ b/lld/MachO/SymbolTable.cpp @@ -83,9 +83,17 @@ concatIsec->symbols.erase(llvm::find(concatIsec->symbols, defined)); } } else { - error("duplicate symbol: " + toString(*defined) + "\n>>> defined in " + - toString(defined->getFile()) + "\n>>> defined in " + - toString(file)); + std::string src1 = defined->getSourceLocation(); + std::string src2 = isec ? isec->getSourceLocation(value) : ""; + + std::string message = + "duplicate symbol: " + toString(*defined) + "\n>>> defined in "; + if (!src1.empty()) + message += src1 + "\n>>> "; + message += toString(defined->getFile()) + "\n>>> defined in "; + if (!src2.empty()) + message += src2 + "\n>>> "; + error(message + toString(file)); } } else if (auto *dysym = dyn_cast(s)) { diff --git a/lld/MachO/Symbols.h b/lld/MachO/Symbols.h --- a/lld/MachO/Symbols.h +++ b/lld/MachO/Symbols.h @@ -132,6 +132,8 @@ uint64_t getVA() const override; + std::string getSourceLocation(); + // Ensure this symbol's pointers to InputSections point to their canonical // copies. void canonicalize(); diff --git a/lld/MachO/Symbols.cpp b/lld/MachO/Symbols.cpp --- a/lld/MachO/Symbols.cpp +++ b/lld/MachO/Symbols.cpp @@ -100,6 +100,12 @@ isec = isec->canonical(); } +std::string Defined::getSourceLocation() { + if (!isec) + return {}; + return isec->getSourceLocation(value); +} + uint64_t DylibSymbol::getVA() const { return isInStubs() ? getStubVA() : Symbol::getVA(); } diff --git a/lld/test/MachO/invalid/duplicate-symbol-debug.s b/lld/test/MachO/invalid/duplicate-symbol-debug.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/invalid/duplicate-symbol-debug.s @@ -0,0 +1,43 @@ +# REQUIRES: aarch64 +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t-dup.o +# RUN: not %lld -dylib -arch arm64 -o /dev/null %t.o %t-dup.o 2>&1 | FileCheck %s -DFILE_1=%t.o -DFILE_2=%t-dup.o + +# CHECK: error: duplicate symbol: _foo +# CHECK-NEXT: >>> defined in duplicate-symbol-debug.s:20 +# CHECK-NEXT: >>> [[FILE_1]] +# CHECK-NEXT: >>> defined in duplicate-symbol-debug.s:20 +# CHECK-NEXT: >>> [[FILE_2]] + +## Test case adapted from lld/test/ELF/Inputs/vs-diagnostics-duplicate2.s + +.file 1 "" "duplicate-symbol-debug.s" + +.text + +.globl _foo +.loc 1 20 +_foo: + nop + +.section __DWARF,__debug_abbrev,regular,debug + .byte 1 ; Abbreviation code + .byte 17 ; DW_TAG_compile_unit + .byte 0 ; DW_CHILDREN_no + .byte 16 ; DW_AT_stmt_list + .byte 23 ; DW_FORM_sec_offset + .byte 0 ; EOM(1) + .byte 0 ; EOM(2) + .byte 0 ; EOM(3) + +.section __DWARF,__debug_info,regular,debug + .long Lend0 - Lbegin0 ; Length of Unit +Lbegin0: + .short 4 ; DWARF version number + .long __debug_abbrev ; Offset Into Abbrev. Section + .byte 8 ; Address Size (in bytes) + .byte 1 ; Abbrev [1] 0xb:0x1f DW_TAG_compile_unit + .long __debug_line ; DW_AT_stmt_list +Lend0: + .section __DWARF,__debug_line,regular,debug +