[lld] r335732 - [PPC64] Add support for R_PPC64_GOT_DTPREL16* relocations

Zaara Syeda via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 27 06:55:41 PDT 2018


Author: syzaara
Date: Wed Jun 27 06:55:41 2018
New Revision: 335732

URL: http://llvm.org/viewvc/llvm-project?rev=335732&view=rev
Log:
[PPC64] Add support for R_PPC64_GOT_DTPREL16* relocations

The local dynamic TLS access on PPC64 ELF v2 ABI uses R_PPC64_GOT_DTPREL16*
relocations when a TLS variables falls outside 2 GB of the thread storage
block. This patch adds support for these relocations by adding a new RelExpr
called R_TLSLD_GOT_OFF which emits a got entry for the TLS variable relative
to the dynamic thread pointer using the relocation R_PPC64_DTPREL64. It then
evaluates the R_PPC64_GOT_DTPREL16* relocations as the got offset for the
R_PPC64_DTPREL64 got entries.

Differential Revision: https://reviews.llvm.org/D48484

Modified:
    lld/trunk/ELF/Arch/PPC64.cpp
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Relocations.h
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/test/ELF/ppc64-dtprel.s

Modified: lld/trunk/ELF/Arch/PPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC64.cpp?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Wed Jun 27 06:55:41 2018
@@ -230,6 +230,11 @@ RelExpr PPC64::getRelExpr(RelType Type,
   case R_PPC64_GOT_TPREL16_DS:
   case R_PPC64_GOT_TPREL16_HI:
     return R_GOT_OFF;
+  case R_PPC64_GOT_DTPREL16_HA:
+  case R_PPC64_GOT_DTPREL16_LO_DS:
+  case R_PPC64_GOT_DTPREL16_DS:
+  case R_PPC64_GOT_DTPREL16_HI:
+    return R_TLSLD_GOT_OFF;
   case R_PPC64_TPREL16:
   case R_PPC64_TPREL16_HA:
   case R_PPC64_TPREL16_LO:
@@ -312,15 +317,18 @@ static std::pair<RelType, uint64_t> toAd
     return {R_PPC64_ADDR16, TocBiasedVal};
   case R_PPC64_TOC16_DS:
   case R_PPC64_GOT_TPREL16_DS:
+  case R_PPC64_GOT_DTPREL16_DS:
     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_GOT_DTPREL16_HA:
   case R_PPC64_TOC16_HA:
     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_GOT_DTPREL16_HI:
   case R_PPC64_TOC16_HI:
     return {R_PPC64_ADDR16_HI, TocBiasedVal};
   case R_PPC64_GOT_TLSGD16_LO:
@@ -329,6 +337,7 @@ static std::pair<RelType, uint64_t> toAd
     return {R_PPC64_ADDR16_LO, TocBiasedVal};
   case R_PPC64_TOC16_LO_DS:
   case R_PPC64_GOT_TPREL16_LO_DS:
+  case R_PPC64_GOT_DTPREL16_LO_DS:
     return {R_PPC64_ADDR16_LO_DS, TocBiasedVal};
 
   // Dynamic Thread pointer biased relocation types.
@@ -434,6 +443,9 @@ void PPC64::relocateOne(uint8_t *Loc, Re
     write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask));
     break;
   }
+  case R_PPC64_DTPREL64:
+    write64(Loc, Val - DynamicThreadPointerOffset);
+    break;
   default:
     error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
   }

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Wed Jun 27 06:55:41 2018
@@ -503,6 +503,7 @@ static uint64_t getRelocTargetVA(const I
   case R_GOT_FROM_END:
   case R_RELAX_TLS_GD_TO_IE_END:
     return Sym.getGotOffset() + A - InX::Got->getSize();
+  case R_TLSLD_GOT_OFF:
   case R_GOT_OFF:
   case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
     return Sym.getGotOffset() + A;

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Wed Jun 27 06:55:41 2018
@@ -209,6 +209,23 @@ handleTlsRelocation(RelType Type, Symbol
     return 1;
   }
 
+  // Local-Dynamic sequence where offset of tls variable relative to dynamic
+  // thread pointer is stored in the got.
+  if (Expr == R_TLSLD_GOT_OFF) {
+    // Local-Dynamic relocs can be relaxed to local-exec
+    if (!Config->Shared) {
+      C.Relocations.push_back({R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym});
+      return 1;
+    }
+    if (!Sym.isInGot()) {
+      InX::Got->addEntry(Sym);
+      uint64_t Off = Sym.getGotOffset();
+      InX::Got->Relocations.push_back({R_ABS, Target->TlsOffsetRel, Off, 0, &Sym});
+    }
+    C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
+    return 1;
+  }
+
   if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL, R_TLSGD_GOT,
                      R_TLSGD_GOT_FROM_END, R_TLSGD_PC>(Expr)) {
     if (Config->Shared) {
@@ -335,12 +352,13 @@ static bool isRelExpr(RelExpr Expr) {
 static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
                                      InputSectionBase &S, uint64_t RelOff) {
   // These expressions always compute a constant
-  if (isRelExprOneOf<R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
-                     R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32,
-                     R_MIPS_GOT_GP_PC, R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC,
-                     R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT,
-                     R_TLSGD_GOT_FROM_END, R_TLSGD_PC, R_PPC_CALL_PLT,
-                     R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(E))
+  if (isRelExprOneOf<
+          R_GOT_FROM_END, R_GOT_OFF, R_TLSLD_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
+          R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
+          R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC,
+          R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOT_FROM_END,
+          R_TLSGD_PC, R_PPC_CALL_PLT, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(
+          E))
     return true;
 
   // These never do, except if the entire file is position dependent or if

Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Wed Jun 27 06:55:41 2018
@@ -81,8 +81,9 @@ enum RelExpr {
   R_TLSGD_GOT,
   R_TLSGD_GOT_FROM_END,
   R_TLSGD_PC,
-  R_TLSLD_GOT_FROM_END,
   R_TLSLD_GOT,
+  R_TLSLD_GOT_FROM_END,
+  R_TLSLD_GOT_OFF,
   R_TLSLD_PC,
 };
 

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Jun 27 06:55:41 2018
@@ -633,7 +633,6 @@ void GotSection::writeTo(uint8_t *Buf) {
   // whereas InputSectionBase::relocateAlloc() expects its argument
   // to point to the start of the output section.
   Target->writeGotHeader(Buf);
-  Buf += Target->GotHeaderEntriesNum * Target->GotEntrySize;
   relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + Size);
 }
 

Modified: lld/trunk/test/ELF/ppc64-dtprel.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-dtprel.s?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/test/ELF/ppc64-dtprel.s (original)
+++ lld/trunk/test/ELF/ppc64-dtprel.s Wed Jun 27 06:55:41 2018
@@ -5,12 +5,14 @@
 // 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-objdump -D %t.so | FileCheck --check-prefix=GotDisLE %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
+// RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=GotDisBE %s
 
         .text
         .abiversion 2
@@ -95,6 +97,15 @@ test_not_adjusted:
         mtlr 0
         blr
 
+        .globl test_got_dtprel
+        .p2align 4
+        .type test_got_dtprel, at function
+test_got_dtprel:
+         addis 3, 2, i at got@dtprel at ha
+         ld 3, i at got@dtprel at l(3)
+         addis 3, 2, i at got@dtprel at h
+         addi 3, 2, i at got@dtprel
+
         .section        .debug_addr,"", at progbits
         .quad   i at dtprel+32768
 
@@ -126,6 +137,10 @@ k:
 // 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
+// InputRelocs: R_PPC64_GOT_DTPREL16_HA    {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_GOT_DTPREL16_LO_DS {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_GOT_DTPREL16_HI    {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_GOT_DTPREL16_DS    {{[0-9a-f]+}} i + 0
 // InputRelocs: Relocation section '.rela.debug_addr'
 // InputRelocs: R_PPC64_DTPREL64          {{[0-9a-f]+}} i + 8000
 
@@ -161,3 +176,29 @@ k:
 // Dis:    ori 4, 4, 0
 // Dis:    oris 4, 4, 63
 // Dis:    ori 4, 4, 33796
+
+// Check for GOT entry for i. There should be a got entry which holds the offset
+// of i relative to the dynamic thread pointer.
+// i at dtprel ->  (1024 - 0x8000) = 0xffff8400
+// GotDisBE: Disassembly of section .got:
+// GotDisBE: 4204f8: 00 00 00 00
+// GotDisBE: 4204fc: 00 42 84 f8
+// GotDisBE: 420510: ff ff ff ff
+// GotDisBE: 420514: ff ff 84 00
+
+// GotDisLE: Disassembly of section .got:
+// GotDisLE: 4204f8: f8 84 42 00
+// GotDisLE: 420510: 00 84 ff ff
+// GotDisLE: 420514: ff ff ff ff
+
+// Check that we have the correct offset to the got entry for i at got@dtprel
+// The got entry for i is 0x420510, and the TOC pointer is 0x4284f8.
+// #ha(i at got@dtprel) --> ((0x420510 - 0x4284f8 + 0x8000) >> 16) & 0xffff = 0
+// #lo(i at got@dtprel) --> (0x420510 - 0x4284f8) & 0xffff = -32744
+// #hi(i at got@dtprel) --> ((0x420510 - 0x4284f8) >> 16) & 0xffff = -1
+// i at got@dtprel --> 0x420510 - 0x4284f8 = -32744
+// Dis: test_got_dtprel:
+// Dis:    addis 3, 2, 0
+// Dis:    ld 3, -32744(3)
+// Dis:    addis 3, 2, -1
+// Dis:    addi 3, 2, -32744




More information about the llvm-commits mailing list