diff options
author | George Rimar <grimar@accesssoftek.com> | 2015-11-13 16:28:53 +0000 |
---|---|---|
committer | George Rimar <grimar@accesssoftek.com> | 2015-11-13 16:28:53 +0000 |
commit | 687138c7d1b14027e3fa7dbb69d3edffe57f21ec (patch) | |
tree | 161d25b45d8eca44d1ac7de58bbb1dcc04667a3a | |
parent | 225d65f1e66d865076f57b31152357b4ad0e383f (diff) | |
download | bcm5719-llvm-687138c7d1b14027e3fa7dbb69d3edffe57f21ec.tar.gz bcm5719-llvm-687138c7d1b14027e3fa7dbb69d3edffe57f21ec.zip |
[ELF2] - Implemented R_X86_64_GOTTPOFF relocation
Generates single GOT entry, R_X86_64_TPOFF64 is added to RelaDyn.
Differential revision: http://reviews.llvm.org/D14621
llvm-svn: 253049
-rw-r--r-- | lld/ELF/InputSection.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 13 | ||||
-rw-r--r-- | lld/ELF/OutputSections.h | 1 | ||||
-rw-r--r-- | lld/ELF/Target.cpp | 6 | ||||
-rw-r--r-- | lld/ELF/Target.h | 4 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 9 | ||||
-rw-r--r-- | lld/test/elf2/Inputs/tls-got.s | 14 | ||||
-rw-r--r-- | lld/test/elf2/tls-got.s | 58 |
8 files changed, 97 insertions, 10 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index ed21a51831e..bd11ab58e4c 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -140,7 +140,7 @@ void InputSectionBase<ELFT>::relocate( Type = Target->getPLTRefReloc(Type); } else if (Target->relocNeedsGot(Type, Body)) { SymVA = Out<ELFT>::Got->getEntryAddr(Body); - Type = Target->getGotRefReloc(); + Type = Body.isTLS() ? Target->getTlsGotReloc() : Target->getGotRefReloc(); } else if (Target->relocPointsToGot(Type)) { SymVA = Out<ELFT>::Got->getVA(); Type = Target->getPCRelReloc(); diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index b06dfd0e57d..70d458b0829 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -80,9 +80,13 @@ GotSection<ELFT>::GotSection() template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody *Sym) { Sym->GotIndex = Target->getGotHeaderEntriesNum() + Entries.size(); Entries.push_back(Sym); +} + +template <class ELFT> void GotSection<ELFT>::addDynTlsEntry(SymbolBody *Sym) { + Sym->GotIndex = Target->getGotHeaderEntriesNum() + Entries.size(); // Global Dynamic TLS entries take two GOT slots. - if (Sym->isTLS()) - Entries.push_back(nullptr); + Entries.push_back(Sym); + Entries.push_back(nullptr); } template <class ELFT> uint32_t GotSection<ELFT>::addLocalModuleTlsIndex() { @@ -231,10 +235,11 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { Target->relocNeedsPlt(Type, *Body); if (CanBePreempted) { + unsigned GotReloc = + Body->isTLS() ? Target->getTlsGotReloc() : Target->getGotReloc(); if (NeedsGot) P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), - LazyReloc ? Target->getPltReloc() - : Target->getGotReloc(), + LazyReloc ? Target->getPltReloc() : GotReloc, Config->Mips64EL); else P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 83136b01a0e..f3266f5640d 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -118,6 +118,7 @@ public: void finalize() override; void writeTo(uint8_t *Buf) override; void addEntry(SymbolBody *Sym); + void addDynTlsEntry(SymbolBody *Sym); uint32_t addLocalModuleTlsIndex(); bool empty() const { return Entries.empty(); } uintX_t getEntryAddr(const SymbolBody &B) const; diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index cc033fcf9aa..d28fcfee2b1 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -215,10 +215,12 @@ X86_64TargetInfo::X86_64TargetInfo() { GotRefReloc = R_X86_64_PC32; PltReloc = R_X86_64_JUMP_SLOT; RelativeReloc = R_X86_64_RELATIVE; + TlsGotReloc = R_X86_64_TPOFF64; TlsLocalDynamicReloc = R_X86_64_TLSLD; TlsGlobalDynamicReloc = R_X86_64_TLSGD; TlsModuleIndexReloc = R_X86_64_DTPMOD64; TlsOffsetReloc = R_X86_64_DTPOFF64; + TlsPcRelGotReloc = R_X86_64_GOTTPOFF; LazyRelocations = true; PltEntrySize = 16; PltZeroEntrySize = 16; @@ -266,7 +268,8 @@ bool X86_64TargetInfo::relocNeedsCopy(uint32_t Type, } bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { - return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S); + return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_GOTPCREL || + relocNeedsPlt(Type, S); } unsigned X86_64TargetInfo::getPLTRefReloc(unsigned Type) const { @@ -338,6 +341,7 @@ void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, case R_X86_64_PLT32: case R_X86_64_TLSLD: case R_X86_64_TLSGD: + case R_X86_64_TPOFF64: write32le(Loc, SA - P); break; case R_X86_64_64: diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 578aab8cdb1..ae85d7762ba 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -29,6 +29,8 @@ public: unsigned getPltReloc() const { return PltReloc; } unsigned getGotRefReloc() const { return GotRefReloc; } unsigned getRelativeReloc() const { return RelativeReloc; } + unsigned getTlsGotReloc() const { return TlsGotReloc; } + unsigned getTlsPcRelGotReloc() const { return TlsPcRelGotReloc; } bool isTlsLocalDynamicReloc(unsigned Type) const { return Type == TlsLocalDynamicReloc; } @@ -75,10 +77,12 @@ protected: unsigned GotReloc; unsigned PltReloc; unsigned RelativeReloc; + unsigned TlsGotReloc = 0; unsigned TlsLocalDynamicReloc = 0; unsigned TlsGlobalDynamicReloc = 0; unsigned TlsModuleIndexReloc; unsigned TlsOffsetReloc; + unsigned TlsPcRelGotReloc = 0; unsigned PltEntrySize = 8; unsigned PltZeroEntrySize = 0; unsigned GotHeaderEntriesNum = 0; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index fe744b2b053..22c7ed33eba 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -216,18 +216,19 @@ void Writer<ELFT>::scanRelocs( if (Body) Body = Body->repl(); - if (Body && Body->isTLS()) { - if (!Target->isTlsGlobalDynamicReloc(Type)) - continue; + if (Body && Body->isTLS() && Target->isTlsGlobalDynamicReloc(Type)) { if (Body->isInGot()) continue; - Out<ELFT>::Got->addEntry(Body); + Out<ELFT>::Got->addDynTlsEntry(Body); Out<ELFT>::RelaDyn->addReloc({&C, &RI}); Out<ELFT>::RelaDyn->addReloc({nullptr, nullptr}); Body->setUsedInDynamicReloc(); continue; } + if ((Body && Body->isTLS()) && Type != Target->getTlsPcRelGotReloc()) + continue; + bool NeedsGot = false; bool NeedsPlt = false; if (Body) { diff --git a/lld/test/elf2/Inputs/tls-got.s b/lld/test/elf2/Inputs/tls-got.s new file mode 100644 index 00000000000..5681d001fd9 --- /dev/null +++ b/lld/test/elf2/Inputs/tls-got.s @@ -0,0 +1,14 @@ +.type tls0,@object +.section .tbss,"awT",@nobits +.globl tls0 +.align 4 +tls0: + .long 0 + .size tls0, 4 + +.type tls1,@object +.globl tls1 +.align 4 +tls1: + .long 0 + .size tls1, 4 diff --git a/lld/test/elf2/tls-got.s b/lld/test/elf2/tls-got.s new file mode 100644 index 00000000000..ed228fcee3c --- /dev/null +++ b/lld/test/elf2/tls-got.s @@ -0,0 +1,58 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-got.s -o %t2.o +// RUN: ld.lld2 -shared %t2.o -o %t2.so +// RUN: ld.lld2 -e main %t1.o %t2.so -o %t3 +// RUN: llvm-readobj -s -r %t3 | FileCheck %s +// RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM %s + +// CHECK: Section { +// CHECK: Index: 8 +// CHECK-NEXT: Name: .got +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_WRITE +// CHECK-NEXT: ] +// CHECK-NEXT: Address: [[ADDR:.*]] +// CHECK-NEXT: Offset: 0x20A0 +// CHECK-NEXT: Size: 16 +// CHECK-NEXT: Link: 0 +// CHECK-NEXT: Info: 0 +// CHECK-NEXT: AddressAlignment: 8 +// CHECK-NEXT: EntrySize: 0 +// CHECK-NEXT: } + +// CHECK: Relocations [ +// CHECK-NEXT: Section (4) .rela.dyn { +// CHECK-NEXT: [[ADDR]] R_X86_64_TPOFF64 tls1 0x0 +// CHECK-NEXT: 0x120A8 R_X86_64_TPOFF64 tls0 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: ] + +//0x11000 + 4249 + 7 = 0x120A0 +//0x1100A + 4247 + 7 = 0x120A8 +//0x11014 + 4237 + 7 = 0x120A8 +//DISASM: Disassembly of section .text: +//DISASM-NEXT: main: +//DISASM-NEXT: 11000: 48 8b 05 99 10 00 00 movq 4249(%rip), %rax +//DISASM-NEXT: 11007: 64 8b 00 movl %fs:(%rax), %eax +//DISASM-NEXT: 1100a: 48 8b 05 97 10 00 00 movq 4247(%rip), %rax +//DISASM-NEXT: 11011: 64 8b 00 movl %fs:(%rax), %eax +//DISASM-NEXT: 11014: 48 8b 05 8d 10 00 00 movq 4237(%rip), %rax +//DISASM-NEXT: 1101b: 64 8b 00 movl %fs:(%rax), %eax +//DISASM-NEXT: 1101e: c3 retq + +.section .tdata,"awT",@progbits + +.text + .globl main + .align 16, 0x90 + .type main,@function +main: + movq tls1@GOTTPOFF(%rip), %rax + movl %fs:0(%rax), %eax + movq tls0@GOTTPOFF(%rip), %rax + movl %fs:0(%rax), %eax + movq tls0@GOTTPOFF(%rip), %rax + movl %fs:0(%rax), %eax + ret |