Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -80,7 +80,8 @@ template void init(uint16_t EMachine); template void resolve(SymbolBody *Body); template - void reportConflict(const SymbolBody &Old, const SymbolBody &New); + void reportConflict(const SymbolBody &Old, const SymbolBody &New, + const Twine &Message, bool Warning); std::vector> ArchiveFiles; Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -175,7 +175,8 @@ } template -void SymbolTable::reportConflict(const SymbolBody &Old, const SymbolBody &New) { +void SymbolTable::reportConflict(const SymbolBody &Old, const SymbolBody &New, + const Twine &Message, bool Warning) { typedef typename ELFFile::Elf_Sym Elf_Sym; typedef typename ELFFile::Elf_Sym_Range Elf_Sym_Range; @@ -193,10 +194,10 @@ NewFile = F.get(); } - std::string Msg = (Twine("duplicate symbol: ") + Old.getName() + " in " + + std::string Msg = (Message + ": " + Old.getName() + " in " + OldFile->getName() + " and " + NewFile->getName()) .str(); - if (Config->AllowMultipleDefinition) + if (Warning) warning(Msg); else error(Msg); @@ -229,13 +230,18 @@ return; } + if (New->isTLS() != Existing->isTLS()) + reportConflict(*Existing, *New, "TLS attribute mismatch for symbol", + false); + // compare() returns -1, 0, or 1 if the lhs symbol is less preferable, // equivalent (conflicting), or more preferable, respectively. int comp = Existing->compare(New); if (comp < 0) Sym->Body = New; else if (comp == 0) - reportConflict(*Existing, *New); + reportConflict(*Existing, *New, "duplicate symbol", + Config->AllowMultipleDefinition); } Symbol *SymbolTable::insert(SymbolBody *New) { Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -63,6 +63,7 @@ bool isUsedInRegularObj() const { return IsUsedInRegularObj; } bool isUsedInDynamicReloc() const { return IsUsedInDynamicReloc; } void setUsedInDynamicReloc() { IsUsedInDynamicReloc = true; } + bool isTLS() const { return IsTLS; } // Returns the symbol name. StringRef getName() const { return Name; } @@ -99,9 +100,10 @@ template int compare(SymbolBody *Other); protected: - SymbolBody(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility) + SymbolBody(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility, + bool IsTLS) : SymbolKind(K), IsWeak(IsWeak), MostConstrainingVisibility(Visibility), - Name(Name) { + IsTLS(IsTLS), Name(Name) { IsUsedInRegularObj = K != SharedKind && K != LazyKind; IsUsedInDynamicReloc = 0; } @@ -111,6 +113,7 @@ unsigned MostConstrainingVisibility : 2; unsigned IsUsedInRegularObj : 1; unsigned IsUsedInDynamicReloc : 1; + unsigned IsTLS : 1; unsigned DynamicSymbolTableIndex = 0; unsigned GotIndex = -1; unsigned PltIndex = -1; @@ -130,7 +133,7 @@ typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; ELFSymbolBody(Kind K, StringRef Name, const Elf_Sym &Sym) : SymbolBody(K, Name, Sym.getBinding() == llvm::ELF::STB_WEAK, - Sym.getVisibility()), + Sym.getVisibility(), Sym.getType() == llvm::ELF::STT_TLS), Sym(Sym) {} public: @@ -277,7 +280,7 @@ class Lazy : public SymbolBody { public: Lazy(ArchiveFile *F, const llvm::object::Archive::Symbol S) - : SymbolBody(LazyKind, S.getName(), false, llvm::ELF::STV_DEFAULT), + : SymbolBody(LazyKind, S.getName(), false, llvm::ELF::STV_DEFAULT, false), File(F), Sym(S) {} static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; } Index: test/elf2/Inputs/tls-mismatch.s =================================================================== --- /dev/null +++ test/elf2/Inputs/tls-mismatch.s @@ -0,0 +1,4 @@ +.tbss +.globl tlsvar +tlsvar: + .space 4 Index: test/elf2/tls-mismatch.s =================================================================== --- /dev/null +++ test/elf2/tls-mismatch.s @@ -0,0 +1,9 @@ +// REQUIRES: x86 +// 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 lld -flavor gnu2 %t %t2 -o %t3 2>&1 | FileCheck %s +// CHECK: TLS attribute mismatch for symbol: tlsvar + +.globl _start +_start: + movl (tlsvar),%edx