[lld] r254443 - [ELF] - Fixed bug leading to miss of tls relocation when @tlsgd and @gottpoff relocations were used at the same time.
George Rimar via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 1 11:20:28 PST 2015
Author: grimar
Date: Tue Dec 1 13:20:26 2015
New Revision: 254443
URL: http://llvm.org/viewvc/llvm-project?rev=254443&view=rev
Log:
[ELF] - Fixed bug leading to miss of tls relocation when @tlsgd and @gottpoff relocations were used at the same time.
Combination of @tlsgd and @gottpoff at the same time leads to miss of R_X86_64_TPOFF64 dynamic relocation. Patch fixes that.
@tlsgd(%rip) - Allocate two contiguous entries in the GOT to hold a tls index
structure (for passing to tls get addr).
@gottpoff(%rip) - Allocate one GOT entry to hold a variable offset in initial TLS
block (relative to TLS block end, %fs:0).
The same situation can be observed for x86 (probably others too, not sure) with corresponding for that target relocations: @tlsgd, @gotntpoff.
Differential revision: http://reviews.llvm.org/D15105
Modified:
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/OutputSections.h
lld/trunk/ELF/Symbols.h
lld/trunk/ELF/Writer.cpp
lld/trunk/test/ELF/tls-dynamic.s
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=254443&r1=254442&r2=254443&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Tue Dec 1 13:20:26 2015
@@ -132,7 +132,7 @@ void InputSectionBase<ELFT>::relocate(
if (Target->isTlsGlobalDynamicReloc(Type) &&
!Target->isTlsOptimized(Type, &Body)) {
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
- Out<ELFT>::Got->getEntryAddr(Body) +
+ Out<ELFT>::Got->getGlobalDynAddr(Body) +
getAddend<ELFT>(RI));
continue;
}
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=254443&r1=254442&r2=254443&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Tue Dec 1 13:20:26 2015
@@ -80,11 +80,14 @@ template <class ELFT> void GotSection<EL
Entries.push_back(Sym);
}
-template <class ELFT> void GotSection<ELFT>::addDynTlsEntry(SymbolBody *Sym) {
- Sym->GotIndex = Target->getGotHeaderEntriesNum() + Entries.size();
+template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody *Sym) {
+ if (Sym->hasGlobalDynIndex())
+ return false;
+ Sym->GlobalDynIndex = Target->getGotHeaderEntriesNum() + Entries.size();
// Global Dynamic TLS entries take two GOT slots.
Entries.push_back(Sym);
Entries.push_back(nullptr);
+ return true;
}
template <class ELFT> bool GotSection<ELFT>::addLocalModelTlsIndex() {
@@ -103,6 +106,12 @@ GotSection<ELFT>::getEntryAddr(const Sym
}
template <class ELFT>
+typename GotSection<ELFT>::uintX_t
+GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const {
+ return this->getVA() + B.GlobalDynIndex * sizeof(uintX_t);
+}
+
+template <class ELFT>
const SymbolBody *GotSection<ELFT>::getMipsFirstGlobalEntry() const {
return Entries.empty() ? nullptr : Entries.front();
}
@@ -211,10 +220,10 @@ bool RelocationSection<ELFT>::applyTlsDy
if (Body && Target->isTlsGlobalDynamicReloc(Type)) {
P->setSymbolAndType(Body->getDynamicSymbolTableIndex(),
Target->getTlsModuleIndexReloc(), Config->Mips64EL);
- P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
+ P->r_offset = Out<ELFT>::Got->getGlobalDynAddr(*Body);
N->setSymbolAndType(Body->getDynamicSymbolTableIndex(),
Target->getTlsOffsetReloc(), Config->Mips64EL);
- N->r_offset = Out<ELFT>::Got->getEntryAddr(*Body) + sizeof(uintX_t);
+ N->r_offset = Out<ELFT>::Got->getGlobalDynAddr(*Body) + sizeof(uintX_t);
return true;
}
return false;
Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=254443&r1=254442&r2=254443&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Tue Dec 1 13:20:26 2015
@@ -118,10 +118,11 @@ public:
void finalize() override;
void writeTo(uint8_t *Buf) override;
void addEntry(SymbolBody *Sym);
- void addDynTlsEntry(SymbolBody *Sym);
+ bool addDynTlsEntry(SymbolBody *Sym);
bool addLocalModelTlsIndex();
bool empty() const { return Entries.empty(); }
uintX_t getEntryAddr(const SymbolBody &B) const;
+ uintX_t getGlobalDynAddr(const SymbolBody &B) const;
// Returns the symbol which corresponds to the first entry of the global part
// of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic
Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=254443&r1=254442&r2=254443&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Tue Dec 1 13:20:26 2015
@@ -90,9 +90,11 @@ public:
}
void setDynamicSymbolTableIndex(unsigned V) { DynamicSymbolTableIndex = V; }
+ uint32_t GlobalDynIndex = -1;
uint32_t GotIndex = -1;
uint32_t GotPltIndex = -1;
uint32_t PltIndex = -1;
+ bool hasGlobalDynIndex() { return GlobalDynIndex != uint32_t(-1); }
bool isInGot() const { return GotIndex != -1U; }
bool isInGotPlt() const { return GotPltIndex != -1U; }
bool isInPlt() const { return PltIndex != -1U; }
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=254443&r1=254442&r2=254443&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Dec 1 13:20:26 2015
@@ -221,12 +221,11 @@ void Writer<ELFT>::scanRelocs(
if (Body && Body->isTLS() && Target->isTlsGlobalDynamicReloc(Type)) {
if (Target->isTlsOptimized(Type, Body))
continue;
- if (Body->isInGot())
- continue;
- Out<ELFT>::Got->addDynTlsEntry(Body);
- Out<ELFT>::RelaDyn->addReloc({&C, &RI});
- Out<ELFT>::RelaDyn->addReloc({nullptr, nullptr});
- Body->setUsedInDynamicReloc();
+ if (Out<ELFT>::Got->addDynTlsEntry(Body)) {
+ Out<ELFT>::RelaDyn->addReloc({&C, &RI});
+ Out<ELFT>::RelaDyn->addReloc({nullptr, nullptr});
+ Body->setUsedInDynamicReloc();
+ }
continue;
}
Modified: lld/trunk/test/ELF/tls-dynamic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/tls-dynamic.s?rev=254443&r1=254442&r2=254443&view=diff
==============================================================================
--- lld/trunk/test/ELF/tls-dynamic.s (original)
+++ lld/trunk/test/ELF/tls-dynamic.s Tue Dec 1 13:20:26 2015
@@ -15,6 +15,9 @@
rex64
callq __tls_get_addr at PLT
leaq c at dtpoff(%rax), %rcx
+ // Initial Exec Model Code Sequence, II
+ movq c at gottpoff(%rip),%rax
+ movq %fs:(%rax),%rax
.global a
.hidden a
@@ -44,18 +47,20 @@ c:
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x20D0
// CHECK-NEXT: Offset:
-// CHECK-NEXT: Size: 32
+// CHECK-NEXT: Size: 40
// CHECK: Relocations [
// CHECK: Section ({{.+}}) .rela.dyn {
// CHECK-NEXT: 0x20D0 R_X86_64_DTPMOD64 - 0x0
// CHECK-NEXT: 0x20E0 R_X86_64_DTPMOD64 c 0x0
// CHECK-NEXT: 0x20E8 R_X86_64_DTPOFF64 c 0x0
+// CHECK-NEXT: 0x20F0 R_X86_64_TPOFF64 c 0x0
// CHECK-NEXT: }
// 4297 = (0x20D0 + -4) - (0x1000 + 3) // PC relative offset to got entry.
// 4285 = (0x20D0 + -4) - (0x100c + 3) // PC relative offset to got entry.
// 4267 = (0x20E0 + -4) - (0x102e + 3) // PC relative offset to got entry.
+// 4263 = (0x20F0 + -4) - (0x1042 + 3) // PC relative offset to got entry.
// DIS: Disassembly of section .text:
// DIS-NEXT: .text:
@@ -72,3 +77,5 @@ c:
// DIS-NEXT: 102e: {{.+}} leaq 4267(%rip), %rdi
// DIS-NEXT: 1035: {{.+}} callq
// DIS-NEXT: 103b: {{.+}} leaq 8(%rax), %rcx
+// DIS-NEXT: 1042: {{.+}} movq 4263(%rip), %rax
+// DIS-NEXT: 1049: {{.+}} movq %fs:(%rax), %rax
More information about the llvm-commits
mailing list