[ELF2] Check for TLS mismatch in symbol resolution.

The linker should generate an error if a TLS symbol is resolved
for a non-TLS reference and vice versa.

The patch addresses PR24244 (https://llvm.org/bugs/show_bug.cgi?id=24244)

Differential Revision: http://reviews.llvm.org/D13550

llvm-svn: 249817
This commit is contained in:
Igor Kudrin 2015-10-09 09:58:39 +00:00
parent b352b9ce69
commit 65bddeaacf
5 changed files with 32 additions and 9 deletions

View File

@ -175,7 +175,8 @@ void SymbolTable::addELFFile(ELFFileBase *File) {
}
template <class ELFT>
void SymbolTable::reportConflict(const SymbolBody &Old, const SymbolBody &New) {
void SymbolTable::reportConflict(const Twine &Message, const SymbolBody &Old,
const SymbolBody &New, bool Warning) {
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
@ -193,10 +194,10 @@ void SymbolTable::reportConflict(const SymbolBody &Old, const SymbolBody &New) {
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 @@ template <class ELFT> void SymbolTable::resolve(SymbolBody *New) {
return;
}
if (New->isTLS() != Existing->isTLS())
reportConflict<ELFT>("TLS attribute mismatch for symbol", *Existing, *New,
false);
// compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
// equivalent (conflicting), or more preferable, respectively.
int comp = Existing->compare<ELFT>(New);
if (comp < 0)
Sym->Body = New;
else if (comp == 0)
reportConflict<ELFT>(*Existing, *New);
reportConflict<ELFT>("duplicate symbol", *Existing, *New,
Config->AllowMultipleDefinition);
}
Symbol *SymbolTable::insert(SymbolBody *New) {

View File

@ -80,7 +80,8 @@ private:
template <class ELFT> void init(uint16_t EMachine);
template <class ELFT> void resolve(SymbolBody *Body);
template <class ELFT>
void reportConflict(const SymbolBody &Old, const SymbolBody &New);
void reportConflict(const Twine &Message, const SymbolBody &Old,
const SymbolBody &New, bool Warning);
std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;

View File

@ -63,6 +63,7 @@ public:
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; }
@ -96,9 +97,10 @@ public:
template <class ELFT> 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;
}
@ -108,6 +110,7 @@ protected:
unsigned MostConstrainingVisibility : 2;
unsigned IsUsedInRegularObj : 1;
unsigned IsUsedInDynamicReloc : 1;
unsigned IsTLS : 1;
unsigned DynamicSymbolTableIndex = 0;
StringRef Name;
Symbol *Backref = nullptr;
@ -125,7 +128,7 @@ protected:
typedef typename llvm::object::ELFFile<ELFT>::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:
@ -272,7 +275,7 @@ public:
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; }

View File

@ -0,0 +1,4 @@
.tbss
.globl tlsvar
tlsvar:
.space 4

View File

@ -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 ld.lld2 %t %t2 -o %t3 2>&1 | FileCheck %s
// CHECK: TLS attribute mismatch for symbol: tlsvar
.globl _start,tlsvar
_start:
movl tlsvar,%edx