From 825e538559266a29fb94a46885e1d448fb381e3b Mon Sep 17 00:00:00 2001 From: Eugene Leviant Date: Tue, 8 Nov 2016 16:26:32 +0000 Subject: [PATCH] [ELF] Better error reporting for duplicate symbol Differential revision: https://reviews.llvm.org/D26397 llvm-svn: 286244 --- lld/ELF/Relocations.cpp | 21 +++++++++++++++++---- lld/ELF/Relocations.h | 4 ++++ lld/ELF/SymbolTable.cpp | 33 ++++++++++++++++++++++++++------- lld/ELF/SymbolTable.h | 2 -- lld/test/ELF/Inputs/conflict-debug.s | 5 +++++ lld/test/ELF/basic.s | 3 ++- lld/test/ELF/conflict.s | 21 ++++++++++++++++----- lld/test/ELF/lto/duplicated.ll | 2 +- lld/test/ELF/tls-mismatch.s | 2 +- 9 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 lld/test/ELF/Inputs/conflict-debug.s diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index d111c75..2df9e98 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -539,8 +539,8 @@ static DefinedRegular *getSymbolAt(InputSectionBase *S, } 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 @@ static std::string getLocation(SymbolBody &Sym, InputSectionBase &S, // 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 @@ static void reportUndefined(SymbolBody &Sym, InputSectionBase &S, 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 @@ template void createThunks(InputSectionBase &, 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); } } diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index 728034b..27ac152 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -88,6 +88,10 @@ template 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; } diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index c3e9f2e..63d199a 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -234,7 +234,7 @@ std::pair SymbolTable::insert(StringRef &Name) { // 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 @@ SymbolTable::insert(StringRef &Name, uint8_t Type, uint8_t Visibility, 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 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, 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 @@ Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, replaceBody>(S, Name, StOther, Type, Value, Size, Section); else if (Cmp == 0) - reportDuplicate(S->body(), Section->getFile()); + reportDuplicate(S->body(), Section, Value); return S; } diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index e5c10ea..9587309 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -100,8 +100,6 @@ private: uint8_t Visibility, bool CanOmitFromDynSym, InputFile *File); - void reportDuplicate(SymbolBody *Existing, InputFile *NewFile); - std::map> getDemangledSyms(); void handleAnonymousVersion(); diff --git a/lld/test/ELF/Inputs/conflict-debug.s b/lld/test/ELF/Inputs/conflict-debug.s new file mode 100644 index 0000000..03fb013 --- /dev/null +++ b/lld/test/ELF/Inputs/conflict-debug.s @@ -0,0 +1,5 @@ +.file 1 "conflict-debug.s" +.globl zed +.loc 1 4 +zed: + nop diff --git a/lld/test/ELF/basic.s b/lld/test/ELF/basic.s index f1b5def..935dd0e 100644 --- a/lld/test/ELF/basic.s +++ b/lld/test/ELF/basic.s @@ -221,7 +221,8 @@ _start: # 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 diff --git a/lld/test/ELF/conflict.s b/lld/test/ELF/conflict.s index 3ca033a..fde285d 100644 --- a/lld/test/ELF/conflict.s +++ b/lld/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: diff --git a/lld/test/ELF/lto/duplicated.ll b/lld/test/ELF/lto/duplicated.ll index 6ef6772..903592c 100644 --- a/lld/test/ELF/lto/duplicated.ll +++ b/lld/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" diff --git a/lld/test/ELF/tls-mismatch.s b/lld/test/ELF/tls-mismatch.s index fb70229..aee1f73 100644 --- a/lld/test/ELF/tls-mismatch.s +++ b/lld/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: -- 2.7.4