Index: lld/trunk/ELF/SymbolTable.cpp =================================================================== --- lld/trunk/ELF/SymbolTable.cpp +++ lld/trunk/ELF/SymbolTable.cpp @@ -206,13 +206,6 @@ return {Sym, IsNew}; } -// 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 "'" + toString(*Existing) + "' in " + toString(Existing->File) + - " and " + toString(NewFile); -} - // Find an existing symbol or create and insert a new one, then apply the given // attributes. template @@ -226,13 +219,19 @@ // Merge in the new symbol's visibility. S->Visibility = getMinVisibility(S->Visibility, Visibility); + if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic)) S->ExportDynamic = true; + if (IsUsedInRegularObj) 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)); + ((Type == STT_TLS) != S->body()->isTls())) { + error("TLS attribute mismatch: " + toString(*S->body()) + + "\n>>> defined in " + toString(S->body()->File) + + "\n>>> defined in " + toString(File)); + } return {S, WasInserted}; } @@ -349,32 +348,49 @@ return S; } -static void print(const Twine &Msg) { +static void warnOrError(const Twine &Msg) { if (Config->AllowMultipleDefinition) warn(Msg); else error(Msg); } -static void reportDuplicate(SymbolBody *Existing, InputFile *NewFile) { - print("duplicate symbol " + conflictMsg(Existing, NewFile)); +static void reportDuplicate(SymbolBody *Sym, InputFile *NewFile) { + warnOrError("duplicate symbol: " + toString(*Sym) + + "\n>>> defined in " + toString(Sym->File) + + "\n>>> defined in " + toString(NewFile)); } template -static void reportDuplicate(SymbolBody *Existing, InputSectionBase *ErrSec, +static void reportDuplicate(SymbolBody *Sym, InputSectionBase *ErrSec, typename ELFT::uint ErrOffset) { - DefinedRegular *D = dyn_cast(Existing); + DefinedRegular *D = dyn_cast(Sym); if (!D || !D->Section || !ErrSec) { - reportDuplicate(Existing, ErrSec ? ErrSec->getFile() : nullptr); + reportDuplicate(Sym, ErrSec ? ErrSec->getFile() : nullptr); return; } - std::string OldLoc = - cast(D->Section)->template getLocation(D->Value); - std::string NewLoc = ErrSec->getLocation(ErrOffset); - - print(NewLoc + ": duplicate symbol '" + toString(*Existing) + "'"); - print(OldLoc + ": previous definition was here"); + // Construct and print an error message in the form of: + // + // ld.lld: error: duplicate symbol: foo + // >>> defined at bar.c:30 + // >>> bar.o (/home/alice/src/bar.o) + // >>> defined at baz.c:563 + // >>> baz.o in archive libbaz.a + auto *Sec1 = cast(D->Section); + std::string Src1 = Sec1->getSrcMsg(D->Value); + std::string Obj1 = Sec1->getObjMsg(D->Value); + std::string Src2 = ErrSec->getSrcMsg(ErrOffset); + std::string Obj2 = ErrSec->getObjMsg(ErrOffset); + + std::string Msg = "duplicate symbol: " + toString(*Sym) + "\n>>> defined at "; + if (!Src1.empty()) + Msg += Src1 + "\n>>> "; + Msg += Obj1 + "\n>>> defined at "; + if (!Src2.empty()) + Msg += Src2 + "\n>>> "; + Msg += Obj2; + warnOrError(Msg); } template Index: lld/trunk/test/ELF/abs-conflict.s =================================================================== --- lld/trunk/test/ELF/abs-conflict.s +++ lld/trunk/test/ELF/abs-conflict.s @@ -13,4 +13,6 @@ // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t2.s -o %t2.o // RUN: not ld.lld %t.o %t2.o -o %t.so -shared 2>&1 | FileCheck --check-prefix=DUP %s -// DUP: duplicate symbol 'foo' +// DUP: duplicate symbol: foo +// DUP-NEXT: >>> defined in {{.*}}.o +// DUP-NEXT: >>> defined in (internal) Index: lld/trunk/test/ELF/basic.s =================================================================== --- lld/trunk/test/ELF/basic.s +++ lld/trunk/test/ELF/basic.s @@ -238,8 +238,9 @@ # 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: {{.*}}:(.text+0x0): duplicate symbol '_start' -# DUP: {{.*}}:(.text+0x0): previous definition was here +# DUP: duplicate symbol: _start +# DUP-NEXT: >>> defined at {{.*}}:(.text+0x0) +# DUP-NEXT: >>> defined at {{.*}}:(.text+0x0) # 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: lld/trunk/test/ELF/conflict.s =================================================================== --- lld/trunk/test/ELF/conflict.s +++ lld/trunk/test/ELF/conflict.s @@ -3,18 +3,22 @@ # 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: {{.*}}:(.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 +# DEMANGLE: duplicate symbol: mul(double, double) +# DEMANGLE-NEXT: >>> defined at {{.*}}:(.text+0x0) +# DEMANGLE-NEXT: >>> defined at {{.*}}:(.text+0x0) +# DEMANGLE: duplicate symbol: foo +# DEMANGLE-NEXT: >>> defined at {{.*}}:(.text+0x0) +# DEMANGLE-NEXT: >>> defined at {{.*}}:(.text+0x0) # RUN: not ld.lld %t1.o %t1.o -o %t2 --no-demangle 2>&1 | \ # RUN: FileCheck -check-prefix=NO_DEMANGLE %s -# 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 +# NO_DEMANGLE: duplicate symbol: _Z3muldd +# NO_DEMANGLE-NEXT: >>> defined at {{.*}}:(.text+0x0) +# NO_DEMANGLE-NEXT: >>> defined at {{.*}}:(.text+0x0) +# NO_DEMANGLE: duplicate symbol: foo +# NO_DEMANGLE-NEXT: >>> defined at {{.*}}:(.text+0x0) +# NO_DEMANGLE-NEXT: >>> defined at {{.*}}:(.text+0x0) # RUN: not ld.lld %t1.o %t1.o -o %t2 --demangle --no-demangle 2>&1 | \ # RUN: FileCheck -check-prefix=NO_DEMANGLE %s @@ -25,14 +29,18 @@ # 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: {{.*}}3.a({{.*}}2.o):(.text+0x0): duplicate symbol 'foo' -# ARCHIVE-NEXT: {{.*}}1.o:(.text+0x0): previous definition was here +# ARCHIVE: duplicate symbol: foo +# ARCHIVE-NEXT: >>> defined at {{.*}}:(.text+0x0) +# ARCHIVE-NEXT: >>> defined at {{.*}}:(.text+0x0) in archive {{.*}}.a # 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 +# DBGINFO: duplicate symbol: zed +# DBGINFO-NEXT: >>> defined at conflict-debug.s:4 +# DBGINFO-NEXT: >>> {{.*}}:(.text+0x0) +# DBGINFO-NEXT: >>> defined at conflict-debug.s:4 +# DBGINFO-NEXT: >>> {{.*}}:(.text+0x0) .globl _Z3muldd, foo _Z3muldd: Index: lld/trunk/test/ELF/lto/duplicated.ll =================================================================== --- lld/trunk/test/ELF/lto/duplicated.ll +++ lld/trunk/test/ELF/lto/duplicated.ll @@ -1,7 +1,11 @@ ; 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 +; CHECK-NEXT: >>> defined in {{.*}}.o +; CHECK-NEXT: >>> defined in {{.*}}.o + target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" Index: lld/trunk/test/ELF/tls-mismatch.s =================================================================== --- lld/trunk/test/ELF/tls-mismatch.s +++ lld/trunk/test/ELF/tls-mismatch.s @@ -2,7 +2,10 @@ // 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: tlsvar +// CHECK: >>> defined in +// CHECK: >>> defined in .globl _start,tlsvar _start: