[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