summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/SymbolTable.cpp14
-rw-r--r--lld/ELF/SymbolTable.h3
-rw-r--r--lld/ELF/Symbols.h11
-rw-r--r--lld/test/elf2/Inputs/tls-mismatch.s4
-rw-r--r--lld/test/elf2/tls-mismatch.s9
5 files changed, 32 insertions, 9 deletions
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 025b4e15d42..cef2b916b94 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -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) {
diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h
index 93b9b20b175..f33a36c7a9b 100644
--- a/lld/ELF/SymbolTable.h
+++ b/lld/ELF/SymbolTable.h
@@ -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;
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index a6e62fc4b43..0e8c005a359 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -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; }
diff --git a/lld/test/elf2/Inputs/tls-mismatch.s b/lld/test/elf2/Inputs/tls-mismatch.s
new file mode 100644
index 00000000000..8c14f58a742
--- /dev/null
+++ b/lld/test/elf2/Inputs/tls-mismatch.s
@@ -0,0 +1,4 @@
+.tbss
+.globl tlsvar
+tlsvar:
+ .space 4
diff --git a/lld/test/elf2/tls-mismatch.s b/lld/test/elf2/tls-mismatch.s
new file mode 100644
index 00000000000..0002c3a97c9
--- /dev/null
+++ b/lld/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 ld.lld2 %t %t2 -o %t3 2>&1 | FileCheck %s
+// CHECK: TLS attribute mismatch for symbol: tlsvar
+
+.globl _start,tlsvar
+_start:
+ movl tlsvar,%edx
OpenPOWER on IntegriCloud