diff options
| author | Sean Fertile <sfertile@ca.ibm.com> | 2018-05-31 18:44:12 +0000 |
|---|---|---|
| committer | Sean Fertile <sfertile@ca.ibm.com> | 2018-05-31 18:44:12 +0000 |
| commit | 1a8343fce3bfff06864a86d33ec3c1acf58cc9b7 (patch) | |
| tree | 4f2033c6d01059a42bb942417c198c4b58eb27fe | |
| parent | 26fc531dbc652a7738f3c8a421b3023ca12ca1ad (diff) | |
| download | bcm5719-llvm-1a8343fce3bfff06864a86d33ec3c1acf58cc9b7.tar.gz bcm5719-llvm-1a8343fce3bfff06864a86d33ec3c1acf58cc9b7.zip | |
[PPC64] Support R_PPC64_GOT_TLSLD16 relocations.
Add support for the R_PPC64_GOT_TLSLD16 relocations used to build the address of
the tls_index struct used in local-dynamic tls.
Differential Revision: https://reviews.llvm.org/D47538
llvm-svn: 333681
| -rw-r--r-- | lld/ELF/Arch/PPC64.cpp | 10 | ||||
| -rw-r--r-- | lld/ELF/InputSection.cpp | 2 | ||||
| -rw-r--r-- | lld/ELF/Relocations.cpp | 2 | ||||
| -rw-r--r-- | lld/ELF/Relocations.h | 1 | ||||
| -rw-r--r-- | lld/test/ELF/ppc64-local-dynamic.s | 112 |
5 files changed, 126 insertions, 1 deletions
diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index b1f27c0c6cd..37fbcd5efcc 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -175,7 +175,13 @@ RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S, case R_PPC64_GOT_TLSGD16_HI: case R_PPC64_GOT_TLSGD16_LO: return R_TLSGD_GOT; + case R_PPC64_GOT_TLSLD16: + case R_PPC64_GOT_TLSLD16_HA: + case R_PPC64_GOT_TLSLD16_HI: + case R_PPC64_GOT_TLSLD16_LO: + return R_TLSLD_GOT; case R_PPC64_TLSGD: + case R_PPC64_TLSLD: return R_HINT; default: return R_ABS; @@ -221,17 +227,21 @@ static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) { uint64_t V = Val - PPC64TocOffset; switch (Type) { case R_PPC64_GOT_TLSGD16: + case R_PPC64_GOT_TLSLD16: case R_PPC64_TOC16: return {R_PPC64_ADDR16, V}; case R_PPC64_TOC16_DS: return {R_PPC64_ADDR16_DS, V}; case R_PPC64_GOT_TLSGD16_HA: + case R_PPC64_GOT_TLSLD16_HA: case R_PPC64_TOC16_HA: return {R_PPC64_ADDR16_HA, V}; case R_PPC64_GOT_TLSGD16_HI: + case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_TOC16_HI: return {R_PPC64_ADDR16_HI, V}; case R_PPC64_GOT_TLSGD16_LO: + case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_TOC16_LO: return {R_PPC64_ADDR16_LO, V}; case R_PPC64_TOC16_LO_DS: diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index ad8cbfa6880..09bc39eaed1 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -639,6 +639,8 @@ static uint64_t getRelocTargetVA(RelType Type, int64_t A, uint64_t P, return InX::Got->getGlobalDynAddr(Sym) + A - P; case R_TLSLD_GOT_FROM_END: return InX::Got->getTlsIndexOff() + A - InX::Got->getSize(); + case R_TLSLD_GOT: + return InX::Got->getTlsIndexOff() + A; case R_TLSLD_PC: return InX::Got->getTlsIndexVA() + A - P; } diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 55d381fcc1f..5c4a797a17e 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -198,7 +198,7 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C, return 1; } - if (isRelExprOneOf<R_TLSLD_PC, R_TLSLD_GOT_FROM_END>(Expr)) { + if (isRelExprOneOf<R_TLSLD_GOT, R_TLSLD_GOT_FROM_END, R_TLSLD_PC>(Expr)) { // Local-Dynamic relocs can be relaxed to Local-Exec. if (!Config->Shared) { C.Relocations.push_back( diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index 4289826ba12..3a930d935b0 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -81,6 +81,7 @@ enum RelExpr { R_TLSGD_GOT_FROM_END, R_TLSGD_PC, R_TLSLD_GOT_FROM_END, + R_TLSLD_GOT, R_TLSLD_PC, }; diff --git a/lld/test/ELF/ppc64-local-dynamic.s b/lld/test/ELF/ppc64-local-dynamic.s new file mode 100644 index 00000000000..a051eae3d44 --- /dev/null +++ b/lld/test/ELF/ppc64-local-dynamic.s @@ -0,0 +1,112 @@ +// REQUIRES: ppc + +// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o +// RUN: ld.lld -shared %t.o -o %t.so +// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s +// RUN: llvm-readelf -relocations --wide %t.so | FileCheck --check-prefix=OutputRelocs %s +// RUN: llvm-objdump --section-headers %t.so | FileCheck --check-prefix=CheckGot %s +// RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s + +// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o +// RUN: ld.lld -shared %t.o -o %t.so +// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s +// RUN: llvm-readelf -relocations --wide %t.so | FileCheck --check-prefix=OutputRelocs %s +// RUN: llvm-objdump --section-headers %t.so | FileCheck --check-prefix=CheckGot %s +// RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s + + .text + .abiversion 2 + .globl test + .p2align 4 + .type test,@function +test: +.Lfunc_gep0: + addis 2, 12, .TOC.-.Lfunc_gep0@ha + addi 2, 2, .TOC.-.Lfunc_gep0@l +.Lfunc_lep0: + .localentry test, .Lfunc_lep0-.Lfunc_gep0 + mflr 0 + std 0, 16(1) + stdu 1, -32(1) + addis 3, 2, i@got@tlsld@ha + addi 3, 3, i@got@tlsld@l + bl __tls_get_addr(i@tlsld) + nop + ld 0, 16(1) + mtlr 0 + blr + + .globl test_hi + .p2align 4 + .type test_hi,@function +test_hi: + lis 3, j@got@tlsld@h + blr + + .globl test_16 + .p2align 4 + .type test_16,@function +test_16: + li 3, k@got@tlsld + blr + + .type i,@object + .section .tdata,"awT",@progbits + .p2align 2 +i: + .long 55 + .size i, 4 + + .type j,@object + .section .tbss,"awT",@nobits + .p2align 2 +j: + .long 0 + .size j, 4 + + .type k,@object + .section .tdata,"awT",@progbits + .p2align 3 +k: + .quad 66 + .size k, 8 + +// Verify that the input contains all the R_PPC64_GOT_TLSLD16* relocations. +// InputRelocs: Relocation section '.rela.text' +// InputRelocs: R_PPC64_GOT_TLSLD16_HA 0000000000000000 i + 0 +// InputRelocs: R_PPC64_GOT_TLSLD16_LO 0000000000000000 i + 0 +// InputRelocs: R_PPC64_TLSLD 0000000000000000 i + 0 +// InputRelocs: R_PPC64_GOT_TLSLD16_HI 0000000000000000 j + 0 +// InputRelocs: R_PPC64_GOT_TLSLD16 0000000000000008 k + 0 + +// The local dynamic version of tls needs to use the same mechanism to look up +// a variables address as general-dynamic. ie a call to __tls_get_addr with the +// address of a tls_index struct as the argument. However for local-dynamic +// variables all will have the same ti_module, and the offset field is left as +// as 0, so the same struct can be used for every local-dynamic variable +// used in the shared-object. +// OutputRelocs: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 1 entries: +// OutputRelocs-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +// OutputRelocs-NEXT: R_PPC64_DTPMOD64 + +// Check that the got has 3 entries, 1 for the TOC and 1 stucture of 2 entries +// for the tls variables. Also verify the address so we can check the offsets +// we calculate for each relocation type. +// CheckGot: got 00000018 0000000000020100 + +// got starts at 0x20100 so .TOC. will be 0x28100, and the tls_index struct is +// at 0x20108. + +// #ha(i@got@tlsld) --> (0x20108 - 0x28100 + 0x8000) >> 16 = 0 +// #lo(i@got@tlsld) --> (0x20108 - 0x28100) = -7ff8 = -32760 +// Dis: test: +// Dis: addis 3, 2, 0 +// Dis-NEXT: addi 3, 3, -32760 + +// #hi(j@got@tlsld) --> (0x20108 - 0x28100 ) > 16 = -1 +// Dis: test_hi: +// Dis: lis 3, -1 + +// k@got@tlsld --> (0x20108 - 0x28100) = -7ff8 = -32760 +// Dis: test_16: +// Dis: li 3, -32760 |

