[lld] r334465 - [PPC64] Support R_PPC64_DTPREL relocations.
Sean Fertile via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 11 18:47:02 PDT 2018
Author: sfertile
Date: Mon Jun 11 18:47:02 2018
New Revision: 334465
URL: http://llvm.org/viewvc/llvm-project?rev=334465&view=rev
Log:
[PPC64] Support R_PPC64_DTPREL relocations.
Patch adds support for most of the dynamic thread pointer based relocations
for local-dynamic tls. The HIGH and HIGHA versions are missing becuase they
are not supported by the llvm integrated assembler yet.
Added:
lld/trunk/test/ELF/ppc64-dtprel.s
Modified:
lld/trunk/ELF/Arch/PPC64.cpp
lld/trunk/test/ELF/ppc64-local-dynamic.s
Modified: lld/trunk/ELF/Arch/PPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC64.cpp?rev=334465&r1=334464&r2=334465&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Mon Jun 11 18:47:02 2018
@@ -21,6 +21,7 @@ using namespace lld;
using namespace lld::elf;
static uint64_t PPC64TocOffset = 0x8000;
+static uint64_t DynamicThreadPointerOffset = 0x8000;
uint64_t elf::getPPC64TocBase() {
// The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The
@@ -200,6 +201,17 @@ RelExpr PPC64::getRelExpr(RelType Type,
case R_PPC64_TPREL16_HIGHEST:
case R_PPC64_TPREL16_HIGHESTA:
return R_TLS;
+ case R_PPC64_DTPREL16:
+ case R_PPC64_DTPREL16_DS:
+ case R_PPC64_DTPREL16_HA:
+ case R_PPC64_DTPREL16_HI:
+ case R_PPC64_DTPREL16_HIGHER:
+ case R_PPC64_DTPREL16_HIGHERA:
+ case R_PPC64_DTPREL16_HIGHEST:
+ case R_PPC64_DTPREL16_HIGHESTA:
+ case R_PPC64_DTPREL16_LO:
+ case R_PPC64_DTPREL16_LO_DS:
+ return R_ABS;
case R_PPC64_TLSGD:
case R_PPC64_TLSLD:
case R_PPC64_TLS:
@@ -245,32 +257,60 @@ void PPC64::writePlt(uint8_t *Buf, uint6
}
static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) {
- uint64_t V = Val - PPC64TocOffset;
+ // Relocations relative to the toc-base need to be adjusted by the Toc offset.
+ uint64_t TocBiasedVal = Val - PPC64TocOffset;
+ // Relocations relative to dtv[dtpmod] need to be adjusted by the DTP offset.
+ uint64_t DTPBiasedVal = Val - DynamicThreadPointerOffset;
+
switch (Type) {
+ // TOC biased relocation.
case R_PPC64_GOT_TLSGD16:
case R_PPC64_GOT_TLSLD16:
case R_PPC64_TOC16:
- return {R_PPC64_ADDR16, V};
+ return {R_PPC64_ADDR16, TocBiasedVal};
case R_PPC64_TOC16_DS:
case R_PPC64_GOT_TPREL16_DS:
- return {R_PPC64_ADDR16_DS, V};
+ return {R_PPC64_ADDR16_DS, TocBiasedVal};
case R_PPC64_GOT_TLSGD16_HA:
case R_PPC64_GOT_TLSLD16_HA:
case R_PPC64_GOT_TPREL16_HA:
case R_PPC64_TOC16_HA:
- return {R_PPC64_ADDR16_HA, V};
+ return {R_PPC64_ADDR16_HA, TocBiasedVal};
case R_PPC64_GOT_TLSGD16_HI:
case R_PPC64_GOT_TLSLD16_HI:
case R_PPC64_GOT_TPREL16_HI:
case R_PPC64_TOC16_HI:
- return {R_PPC64_ADDR16_HI, V};
+ return {R_PPC64_ADDR16_HI, TocBiasedVal};
case R_PPC64_GOT_TLSGD16_LO:
case R_PPC64_GOT_TLSLD16_LO:
case R_PPC64_TOC16_LO:
- return {R_PPC64_ADDR16_LO, V};
+ return {R_PPC64_ADDR16_LO, TocBiasedVal};
case R_PPC64_TOC16_LO_DS:
case R_PPC64_GOT_TPREL16_LO_DS:
- return {R_PPC64_ADDR16_LO_DS, V};
+ return {R_PPC64_ADDR16_LO_DS, TocBiasedVal};
+
+ // Dynamic Thread pointer biased relocation types.
+ case R_PPC64_DTPREL16:
+ return {R_PPC64_ADDR16, DTPBiasedVal};
+ case R_PPC64_DTPREL16_DS:
+ return {R_PPC64_ADDR16_DS, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HA:
+ return {R_PPC64_ADDR16_HA, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HI:
+ return {R_PPC64_ADDR16_HI, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HIGHER:
+ return {R_PPC64_ADDR16_HIGHER, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HIGHERA:
+ return {R_PPC64_ADDR16_HIGHERA, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HIGHEST:
+ return {R_PPC64_ADDR16_HIGHEST, DTPBiasedVal};
+ case R_PPC64_DTPREL16_HIGHESTA:
+ return {R_PPC64_ADDR16_HIGHESTA, DTPBiasedVal};
+ case R_PPC64_DTPREL16_LO:
+ return {R_PPC64_ADDR16_LO, DTPBiasedVal};
+ case R_PPC64_DTPREL16_LO_DS:
+ return {R_PPC64_ADDR16_LO_DS, DTPBiasedVal};
+
default:
return {Type, Val};
}
Added: lld/trunk/test/ELF/ppc64-dtprel.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-dtprel.s?rev=334465&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc64-dtprel.s (added)
+++ lld/trunk/test/ELF/ppc64-dtprel.s Mon Jun 11 18:47:02 2018
@@ -0,0 +1,158 @@
+// 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 -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 -D %t.so | FileCheck --check-prefix=Dis %s
+
+ .text
+ .abiversion 2
+ .globl test
+ .p2align 4
+ .type test, at function
+test:
+.Lfunc_gep0:
+ addis 2, 12, .TOC.-.Lfunc_gep0 at ha
+ addi 2, 2, .TOC.-.Lfunc_gep0 at l
+.Lfunc_lep0:
+ .localentry test, .Lfunc_lep0-.Lfunc_gep0
+ mflr 0
+ std 0, 16(1)
+ stdu 1, -32(1)
+ addis 3, 2, i at got@tlsld at ha
+ addi 3, 3, i at got@tlsld at l
+ bl __tls_get_addr(i at tlsld)
+ nop
+ addi 4, 3, i at dtprel
+ lwa 4, i at dtprel(3)
+ ld 0, 16(1)
+ mtlr 0
+ blr
+
+ .globl test_64
+ .p2align 4
+ .type test_64, at function
+
+ .globl test_adjusted
+ .p2align 4
+ .type test_adjusted, at function
+test_adjusted:
+.Lfunc_gep1:
+ addis 2, 12, .TOC.-.Lfunc_gep1 at ha
+ addi 2, 2, .TOC.-.Lfunc_gep1 at l
+.Lfunc_lep1:
+ .localentry test_adjusted, .Lfunc_lep1-.Lfunc_gep1
+ mflr 0
+ std 0, 16(1)
+ stdu 1, -32(1)
+ addis 3, 2, k at got@tlsld at ha
+ addi 3, 3, k at got@tlsld at l
+ bl __tls_get_addr(k at tlsld)
+ nop
+ lis 4, k at dtprel@highesta
+ ori 4, 4, k at dtprel@highera
+ lis 5, k at dtprel@ha
+ addi 5, 5, k at dtprel@l
+ sldi 4, 4, 32
+ or 4, 4, 5
+ add 3, 3, 4
+ addi 1, 1, 32
+ ld 0, 16(1)
+ mtlr 0
+ blr
+
+ .globl test_not_adjusted
+ .p2align 4
+ .type test_not_adjusted, at function
+test_not_adjusted:
+.Lfunc_gep2:
+ addis 2, 12, .TOC.-.Lfunc_gep2 at ha
+ addi 2, 2, .TOC.-.Lfunc_gep2 at l
+.Lfunc_lep2:
+ .localentry test_not_adjusted, .Lfunc_lep2-.Lfunc_gep2
+ mflr 0
+ std 0, 16(1)
+ stdu 1, -32(1)
+ addis 3, 2, i at got@tlsld at ha
+ addi 3, 3, i at got@tlsld at l
+ bl __tls_get_addr(k at tlsld)
+ nop
+ lis 4, k at dtprel@highest
+ ori 4, 4, k at dtprel@higher
+ sldi 4, 4, 32
+ oris 4, 4, k at dtprel@h
+ ori 4, 4, k at dtprel@l
+ add 3, 3, 4
+ addi 1, 1, 32
+ ld 0, 16(1)
+ mtlr 0
+ blr
+
+ .type i, at object
+ .section .tdata,"awT", at progbits
+ .space 1024
+ .p2align 2
+i:
+ .long 55
+ .size i, 4
+
+ .space 1024 * 1024 * 4
+ .type k, at object
+ .p2align 2
+k:
+ .long 128
+ .size k,4
+
+// Verify the input has all the remaining DTPREL based relocations we want to
+// test.
+// InputRelocs: Relocation section '.rela.text'
+// InputRelocs: R_PPC64_DTPREL16 {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_DTPREL16_DS {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_DTPREL16_HIGHESTA {{[0-9a-f]+}} k + 0
+// InputRelocs: R_PPC64_DTPREL16_HIGHERA {{[0-9a-f]+}} k + 0
+// InputRelocs: R_PPC64_DTPREL16_HA {{[0-9a-f]+}} k + 0
+// InputRelocs: R_PPC64_DTPREL16_LO {{[0-9a-f]+}} k + 0
+// InputRelocs: R_PPC64_DTPREL16_HIGHEST {{[0-9a-f]+}} k + 0
+// InputRelocs: R_PPC64_DTPREL16_HIGHER {{[0-9a-f]+}} k + 0
+// InputRelocs: R_PPC64_DTPREL16_HI {{[0-9a-f]+}} k + 0
+// InputRelocs: R_PPC64_DTPREL16_LO {{[0-9a-f]+}} k + 0
+
+// Expect a single dynamic relocation in the '.rela.dyn section for the module id.
+// 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
+
+
+// i at dtprel --> (1024 - 0x8000) = -31744
+// Dis: test:
+// Dis: addi 4, 3, -31744
+// Dis: lwa 4, -31744(3)
+
+// #k at dtprel(1024 + 4 + 1024 * 1024 * 4) = 0x400404
+
+// #highesta(k at dtprel) --> ((0x400404 - 0x8000 + 0x8000) >> 48) & 0xffff = 0
+// #highera(k at dtprel) --> ((0x400404 - 0x8000 + 0x8000) >> 32) & 0xffff = 0
+// #ha(k at dtprel) --> ((0x400404 - 0x8000 + 0x8000) >> 16) & 0xffff = 64
+// #lo(k at dtprel) --> ((0x400404 - 0x8000) & 0xffff = -31740
+// Dis: test_adjusted:
+// Dis: lis 4, 0
+// Dis: ori 4, 4, 0
+// Dis: lis 5, 64
+// Dis: addi 5, 5, -31740
+
+// #highest(k at dtprel) --> ((0x400404 - 0x8000) >> 48) & 0xffff = 0
+// #higher(k at dtprel) --> ((0x400404 - 0x8000) >> 32) & 0xffff = 0
+// #hi(k at dtprel) --> ((0x400404 - 0x8000) >> 16) & 0xffff = 63
+// #lo(k at dtprel) --> ((0x400404 - 0x8000) & 0xffff = 33796
+// Dis: test_not_adjusted:
+// Dis: lis 4, 0
+// Dis: ori 4, 4, 0
+// Dis: oris 4, 4, 63
+// Dis: ori 4, 4, 33796
Modified: lld/trunk/test/ELF/ppc64-local-dynamic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-local-dynamic.s?rev=334465&r1=334464&r2=334465&view=diff
==============================================================================
--- lld/trunk/test/ELF/ppc64-local-dynamic.s (original)
+++ lld/trunk/test/ELF/ppc64-local-dynamic.s Mon Jun 11 18:47:02 2018
@@ -32,6 +32,8 @@ test:
addi 3, 3, i at got@tlsld at l
bl __tls_get_addr(i at tlsld)
nop
+ addis 3, 3, i at dtprel@ha
+ lwa 3, i at dtprel@l(3)
ld 0, 16(1)
mtlr 0
blr
@@ -71,13 +73,17 @@ k:
.quad 66
.size k, 8
-// Verify that the input contains all the R_PPC64_GOT_TLSLD16* relocations.
+// Verify that the input contains all the R_PPC64_GOT_TLSLD16* relocations, as
+// well as the DTPREL relocations used in a typical medium code model
+// local-dynamic variable access.
// 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
+// InputRelocs: R_PPC64_GOT_TLSLD16_HA {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_GOT_TLSLD16_LO {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_TLSLD {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_DTPREL16_HA {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_DTPREL16_LO_DS {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_GOT_TLSLD16_HI {{[0-9a-f]+}} j + 0
+// InputRelocs: R_PPC64_GOT_TLSLD16 {{[0-9a-f]+}} 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
@@ -99,9 +105,19 @@ k:
// #ha(i at got@tlsld) --> (0x20108 - 0x28100 + 0x8000) >> 16 = 0
// #lo(i at got@tlsld) --> (0x20108 - 0x28100) = -7ff8 = -32760
+// When calculating offset relative to the dynamic thread pointer we have to
+// adjust by 0x8000 since each DTV pointer points 0x8000 bytes past the start of
+// its TLS block.
+// #ha(i at dtprel) --> (0x0 -0x8000 + 0x8000) >> 16 = 0
+// #lo(i at dtprel) --> (0x0 -0x8000) = -0x8000 = -32768
// Dis: test:
// Dis: addis 3, 2, 0
// Dis-NEXT: addi 3, 3, -32760
+// Dis-NEXT: bl .+67108804
+// Dis-NEXT: ld 2, 24(1)
+// Dis-NEXT: addis 3, 3, 0
+// Dis-NEXT: lwa 3, -32768(3)
+
// #hi(j at got@tlsld) --> (0x20108 - 0x28100 ) > 16 = -1
// Dis: test_hi:
More information about the llvm-commits
mailing list