forked from OSchip/llvm-project
[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:
parent
b352b9ce69
commit
65bddeaacf
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
.tbss
|
||||
.globl tlsvar
|
||||
tlsvar:
|
||||
.space 4
|
|
@ -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
|
Loading…
Reference in New Issue