Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -88,6 +88,10 @@ void createThunks(InputSectionBase &, const typename ELFT::Shdr &); template +std::string getLocation(SymbolBody *Sym, InputSectionBase &S, + typename ELFT::uint Offset); + +template static inline typename ELFT::uint getAddend(const typename ELFT::Rel &Rel) { return 0; } Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -539,8 +539,8 @@ } template -static std::string getLocation(SymbolBody &Sym, InputSectionBase &S, - typename ELFT::uint Offset) { +std::string getLocation(SymbolBody *Sym, InputSectionBase &S, + typename ELFT::uint Offset) { ObjectFile *File = S.getFile(); // First check if we can get desired values from debugging information. @@ -552,7 +552,7 @@ // use object file name. std::string SrcFile = File->SourceFile; if (SrcFile.empty()) - SrcFile = Sym.File ? getFilename(Sym.File) : getFilename(File); + SrcFile = Sym && Sym->File ? getFilename(Sym->File) : getFilename(File); // Find a symbol at a given location. DefinedRegular *Encl = getSymbolAt(&S, Offset); @@ -576,7 +576,7 @@ Config->UnresolvedSymbols != UnresolvedPolicy::NoUndef) return; - std::string Msg = getLocation(Sym, S, Offset) + ": undefined symbol '" + + std::string Msg = getLocation(&Sym, S, Offset) + ": undefined symbol '" + maybeDemangle(Sym.getName()) + "'"; if (Config->UnresolvedSymbols == UnresolvedPolicy::Warn) @@ -853,5 +853,18 @@ const ELF64LE::Shdr &); template void createThunks(InputSectionBase &, const ELF64BE::Shdr &); + +template std::string getLocation(SymbolBody *Sym, + InputSectionBase &S, + uint32_t Offset); +template std::string getLocation(SymbolBody *Sym, + InputSectionBase &S, + uint32_t Offset); +template std::string getLocation(SymbolBody *Sym, + InputSectionBase &S, + uint64_t Offset); +template std::string getLocation(SymbolBody *Sym, + InputSectionBase &S, + uint64_t Offset); } } Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -100,8 +100,6 @@ uint8_t Visibility, bool CanOmitFromDynSym, InputFile *File); - void reportDuplicate(SymbolBody *Existing, InputFile *NewFile); - std::map> getDemangledSyms(); void handleAnonymousVersion(); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -234,7 +234,7 @@ // Construct a string in the form of "Sym in File1 and File2". // Used to construct an error message. static std::string conflictMsg(SymbolBody *Existing, InputFile *NewFile) { - return maybeDemangle(Existing->getName()) + " in " + + return "'" + maybeDemangle(Existing->getName()) + "' in " + getFilename(Existing->File) + " and " + getFilename(NewFile); } @@ -257,7 +257,7 @@ S->IsUsedInRegularObj = true; if (!WasInserted && S->body()->Type != SymbolBody::UnknownType && ((Type == STT_TLS) != S->body()->isTls())) - error("TLS attribute mismatch for symbol: " + conflictMsg(S->body(), File)); + error("TLS attribute mismatch for symbol " + conflictMsg(S->body(), File)); return {S, WasInserted}; } @@ -365,16 +365,35 @@ return S; } -template -void SymbolTable::reportDuplicate(SymbolBody *Existing, - InputFile *NewFile) { - std::string Msg = "duplicate symbol: " + conflictMsg(Existing, NewFile); +static void reportDuplicate(const std::string &Msg) { if (Config->AllowMultipleDefinition) warn(Msg); else error(Msg); } +static void reportDuplicate(SymbolBody *Existing, InputFile *NewFile) { + reportDuplicate("duplicate symbol " + conflictMsg(Existing, NewFile)); +} + +template +static void reportDuplicate(SymbolBody *Existing, + InputSectionBase *ErrSec, + typename ELFT::uint ErrOffset) { + DefinedRegular *D = dyn_cast>(Existing); + if (!D || !D->Section || !ErrSec) { + reportDuplicate(Existing, ErrSec ? ErrSec->getFile() : nullptr); + return; + } + + std::string OldLoc = getLocation(Existing, *D->Section, D->Value); + std::string NewLoc = getLocation(nullptr, *ErrSec, ErrOffset); + + reportDuplicate(NewLoc + ": duplicate symbol '" + + maybeDemangle(Existing->getName()) + "'"); + reportDuplicate(OldLoc + ": previous definition was here"); +} + template Symbol *SymbolTable::addRegular(StringRef Name, const Elf_Sym &Sym, InputSectionBase *Section) { @@ -397,7 +416,7 @@ replaceBody>(S, Name, StOther, Type, Value, Size, Section); else if (Cmp == 0) - reportDuplicate(S->body(), Section->getFile()); + reportDuplicate(S->body(), Section, Value); return S; } Index: test/ELF/Inputs/conflict-debug.s =================================================================== --- test/ELF/Inputs/conflict-debug.s +++ test/ELF/Inputs/conflict-debug.s @@ -0,0 +1,5 @@ +.file 1 "conflict-debug.s" +.globl zed +.loc 1 4 +zed: + nop Index: test/ELF/basic.s =================================================================== --- test/ELF/basic.s +++ test/ELF/basic.s @@ -221,7 +221,8 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: not ld.lld %t %t -o %t2 2>&1 | FileCheck --check-prefix=DUP %s -# DUP: duplicate symbol: _start in {{.*}} and {{.*}} +# DUP: {{.*}} (.text+0x0): duplicate symbol '_start' +# DUP: {{.*}} (.text+0x0): previous definition was here # RUN: not ld.lld %t -o %t -m wrong_emul_fbsd 2>&1 | FileCheck --check-prefix=UNKNOWN_EMUL %s # UNKNOWN_EMUL: unknown emulation: wrong_emul_fbsd Index: test/ELF/conflict.s =================================================================== --- test/ELF/conflict.s +++ test/ELF/conflict.s @@ -3,14 +3,18 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o # RUN: not ld.lld %t1.o %t1.o -o %t2 2>&1 | FileCheck -check-prefix=DEMANGLE %s -# DEMANGLE: duplicate symbol: mul(double, double) in -# DEMANGLE: duplicate symbol: foo in +# DEMANGLE: {{.*}} (.text+0x0): duplicate symbol 'mul(double, double)' +# DEMANGLE-NEXT: {{.*}} (.text+0x0): previous definition was here +# DEMANGLE-NEXT: {{.*}} (.text+0x0): duplicate symbol 'foo' +# DEMANGLE-NEXT: {{.*}} (.text+0x0): previous definition was here # RUN: not ld.lld %t1.o %t1.o -o %t2 --no-demangle 2>&1 | \ # RUN: FileCheck -check-prefix=NO_DEMANGLE %s -# NO_DEMANGLE: duplicate symbol: _Z3muldd in -# NO_DEMANGLE: duplicate symbol: foo in +# NO_DEMANGLE: {{.*}} (.text+0x0): duplicate symbol '_Z3muldd' +# NO_DEMANGLE-NEXT: {{.*}} (.text+0x0): previous definition was here +# NO_DEMANGLE-NEXT: {{.*}} (.text+0x0): duplicate symbol 'foo' +# NO_DEMANGLE-NEXT: {{.*}} (.text+0x0): previous definition was here # RUN: not ld.lld %t1.o %t1.o -o %t2 --demangle --no-demangle 2>&1 | \ # RUN: FileCheck -check-prefix=NO_DEMANGLE %s @@ -21,7 +25,14 @@ # RUN: llvm-ar rcs %t3.a %t2.o # RUN: not ld.lld %t1.o %t3.a -u baz -o %t2 2>&1 | FileCheck -check-prefix=ARCHIVE %s -# ARCHIVE: duplicate symbol: foo in {{.*}}1.o and {{.*}}3.a({{.*}}2.o) +# ARCHIVE: {{.*}}3.a({{.*}}2.o) (.text+0x0): duplicate symbol 'foo' +# ARCHIVE-NEXT: {{.*}}1.o (.text+0x0): previous definition was here + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/conflict-debug.s -o %t-dbg.o +# RUN: not ld.lld %t-dbg.o %t-dbg.o -o %t-dbg 2>&1 | FileCheck -check-prefix=DBGINFO %s + +# DBGINFO: conflict-debug.s (4): duplicate symbol 'zed' +# DBGINFO-NEXT: conflict-debug.s (4): previous definition was here .globl _Z3muldd, foo _Z3muldd: Index: test/ELF/lto/duplicated.ll =================================================================== --- test/ELF/lto/duplicated.ll +++ test/ELF/lto/duplicated.ll @@ -1,7 +1,7 @@ ; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o ; RUN: not ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -shared 2>&1 | FileCheck %s -; CHECK: duplicate symbol: f in {{.*}}.o and {{.*}}.o +; CHECK: duplicate symbol 'f' in {{.*}}.o and {{.*}}.o target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: test/ELF/tls-mismatch.s =================================================================== --- test/ELF/tls-mismatch.s +++ test/ELF/tls-mismatch.s @@ -2,7 +2,7 @@ // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/tls-mismatch.s -o %t2 // RUN: not ld.lld %t %t2 -o %t3 2>&1 | FileCheck %s -// CHECK: TLS attribute mismatch for symbol: tlsvar +// CHECK: TLS attribute mismatch for symbol 'tlsvar' .globl _start,tlsvar _start: