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 <class ELFT>
// 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};
}
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 <class ELFT>
-static void reportDuplicate(SymbolBody *Existing, InputSectionBase *ErrSec,
+static void reportDuplicate(SymbolBody *Sym, InputSectionBase *ErrSec,
typename ELFT::uint ErrOffset) {
- DefinedRegular *D = dyn_cast<DefinedRegular>(Existing);
+ DefinedRegular *D = dyn_cast<DefinedRegular>(Sym);
if (!D || !D->Section || !ErrSec) {
- reportDuplicate(Existing, ErrSec ? ErrSec->getFile<ELFT>() : nullptr);
+ reportDuplicate(Sym, ErrSec ? ErrSec->getFile<ELFT>() : nullptr);
return;
}
- std::string OldLoc =
- cast<InputSectionBase>(D->Section)->template getLocation<ELFT>(D->Value);
- std::string NewLoc = ErrSec->getLocation<ELFT>(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<InputSectionBase>(D->Section);
+ std::string Src1 = Sec1->getSrcMsg<ELFT>(D->Value);
+ std::string Obj1 = Sec1->getObjMsg<ELFT>(D->Value);
+ std::string Src2 = ErrSec->getSrcMsg<ELFT>(ErrOffset);
+ std::string Obj2 = ErrSec->getObjMsg<ELFT>(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 <typename ELFT>
// 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)
# 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
# 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
# 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:
; 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"
// 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: