[lld] c6561cc - [PowerPC][LLD] Support for PC Relative TLS for Local Dynamic

Stefan Pintilie via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 23 06:24:32 PDT 2020


Author: Stefan Pintilie
Date: 2020-10-23T08:23:56-05:00
New Revision: c6561ccfd982f03fc9f572c6c27ddab336158e18

URL: https://github.com/llvm/llvm-project/commit/c6561ccfd982f03fc9f572c6c27ddab336158e18
DIFF: https://github.com/llvm/llvm-project/commit/c6561ccfd982f03fc9f572c6c27ddab336158e18.diff

LOG: [PowerPC][LLD] Support for PC Relative TLS for Local Dynamic

Add support to LLD for PC Relative Thread Local Storage for Local Dynamic.
This patch adds support for two relocations: R_PPC64_GOT_TLSLD_PCREL34 and
R_PPC64_DTPREL34.

The Local Dynamic code is:
```
pla r3, x at got@tlsld at pcrel        R_PPC64_GOT_TLSLD_PCREL34
bl __tls_get_addr at notoc(x at tlsld) R_PPC64_TLSLD
                                 R_PPC64_REL24_NOTOC
...
paddi r9, r3, x at dtprel           R_PPC64_DTPREL34
```

After relaxation to Local Exec:
```
paddi r3, r13, 0x1000
nop
...
paddi r9, r3, x at dtprel          R_PPC64_DTPREL34
```

Reviewed By: NeHuang, sfertile

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

Added: 
    lld/test/ELF/ppc64-tls-pcrel-ld.s

Modified: 
    lld/ELF/Arch/PPC64.cpp
    lld/ELF/Relocations.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp
index 2e7b20d46cb0..8a3de2b3cbb2 100644
--- a/lld/ELF/Arch/PPC64.cpp
+++ b/lld/ELF/Arch/PPC64.cpp
@@ -788,16 +788,40 @@ void PPC64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
   case R_PPC64_GOT_TLSLD16_LO:
     writeFromHalf16(loc, 0x3c6d0000); // addis r3, r13, 0
     break;
-  case R_PPC64_TLSLD:
-    write32(loc, NOP);
-    write32(loc + 4, 0x38631000); // addi r3, r3, 4096
+  case R_PPC64_GOT_TLSLD_PCREL34:
+    // Relax from paddi r3, 0, x1 at got@tlsld at pcrel, 1 to
+    //            paddi r3, r13, 0x1000, 0
+    writePrefixedInstruction(loc, 0x06000000386d1000);
+    break;
+  case R_PPC64_TLSLD: {
+    // PC Relative Relaxation:
+    // Relax from bl __tls_get_addr at notoc(x at tlsld)
+    // to
+    //            nop
+    // TOC Relaxation:
+    // Relax from bl __tls_get_addr(x at tlsld)
+    //            nop
+    // to
+    //            nop
+    //            addi r3, r3, 4096
+    const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc);
+    if (locAsInt % 4 == 0) {
+      write32(loc, NOP);
+      write32(loc + 4, 0x38631000); // addi r3, r3, 4096
+    } else if (locAsInt % 4 == 1) {
+      write32(loc - 1, NOP);
+    } else {
+      errorOrWarn("R_PPC64_TLSLD has unexpected byte alignment");
+    }
     break;
+  }
   case R_PPC64_DTPREL16:
   case R_PPC64_DTPREL16_HA:
   case R_PPC64_DTPREL16_HI:
   case R_PPC64_DTPREL16_DS:
   case R_PPC64_DTPREL16_LO:
   case R_PPC64_DTPREL16_LO_DS:
+  case R_PPC64_DTPREL34:
     relocate(loc, rel, val);
     break;
   default:
@@ -977,6 +1001,8 @@ RelExpr PPC64::getRelExpr(RelType type, const Symbol &s,
   case R_PPC64_GOT_TLSLD16_HI:
   case R_PPC64_GOT_TLSLD16_LO:
     return R_TLSLD_GOT;
+  case R_PPC64_GOT_TLSLD_PCREL34:
+    return R_TLSLD_PC;
   case R_PPC64_GOT_TPREL16_HA:
   case R_PPC64_GOT_TPREL16_LO_DS:
   case R_PPC64_GOT_TPREL16_DS:
@@ -1010,6 +1036,7 @@ RelExpr PPC64::getRelExpr(RelType type, const Symbol &s,
   case R_PPC64_DTPREL16_LO:
   case R_PPC64_DTPREL16_LO_DS:
   case R_PPC64_DTPREL64:
+  case R_PPC64_DTPREL34:
     return R_DTPREL;
   case R_PPC64_TLSGD:
     return R_TLSDESC_CALL;
@@ -1284,9 +1311,16 @@ void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_PPC64_DTPREL64:
     write64(loc, val - dynamicThreadPointerOffset);
     break;
+  case R_PPC64_DTPREL34:
+    // The Dynamic Thread Vector actually points 0x8000 bytes past the start
+    // of the TLS block. Therefore, in the case of R_PPC64_DTPREL34 we first
+    // need to subtract that value then fallthrough to the general case.
+    val -= dynamicThreadPointerOffset;
+    LLVM_FALLTHROUGH;
   case R_PPC64_PCREL34:
   case R_PPC64_GOT_PCREL34:
   case R_PPC64_GOT_TLSGD_PCREL34:
+  case R_PPC64_GOT_TLSLD_PCREL34:
   case R_PPC64_GOT_TPREL_PCREL34:
   case R_PPC64_TPREL34: {
     const uint64_t si0Mask = 0x00000003ffff0000;

diff  --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index ea6aa3c6a12a..499b1b6f0a66 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1358,9 +1358,11 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
         cast<Defined>(sym).section->name == ".toc")
       ppc64noTocRelax.insert({&sym, addend});
 
-    if (type == R_PPC64_TLSGD && expr == R_TLSDESC_CALL) {
+    if ((type == R_PPC64_TLSGD && expr == R_TLSDESC_CALL) ||
+        (type == R_PPC64_TLSLD && expr == R_TLSLD_HINT)) {
       if (i == end) {
-        errorOrWarn("R_PPC64_TLSGD may not be the last relocation" +
+        errorOrWarn("R_PPC64_TLSGD/R_PPC64_TLSLD may not be the last "
+                    "relocation" +
                     getLocation(sec, sym, offset));
         return;
       }

diff  --git a/lld/test/ELF/ppc64-tls-pcrel-ld.s b/lld/test/ELF/ppc64-tls-pcrel-ld.s
new file mode 100644
index 000000000000..811a6c20d8ab
--- /dev/null
+++ b/lld/test/ELF/ppc64-tls-pcrel-ld.s
@@ -0,0 +1,144 @@
+# REQUIRES: ppc
+# RUN: split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/asm -o %t.o
+# RUN: ld.lld -T %t/lds --shared -soname=t-ld %t.o -o %t-ld.so
+# RUN: ld.lld -T %t/lds %t.o -o %t-ldtole
+
+# RUN: llvm-readelf -r %t-ld.so | FileCheck %s --check-prefix=LD-RELOC
+# RUN: llvm-readelf -s %t-ld.so | FileCheck %s --check-prefix=LD-SYM
+# RUN: llvm-readelf -x .got %t-ld.so | FileCheck %s --check-prefix=LD-GOT
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t-ld.so | FileCheck %s --check-prefix=LD
+
+# RUN: llvm-readelf -r %t-ldtole | FileCheck %s --check-prefix=LDTOLE-RELOC
+# RUN: llvm-readelf -s %t-ldtole | FileCheck %s --check-prefix=LDTOLE-SYM
+# RUN: llvm-readelf -x .got %t-ldtole 2>&1 | FileCheck %s --check-prefix=LDTOLE-GOT
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t-ldtole | FileCheck %s --check-prefix=LDTOLE
+
+## This test checks the Local Dynamic PC Relative TLS implementation for lld.
+## LD - Local Dynamic with no relaxation possible
+## LDTOLE - Local Dynamic relaxed to Local Exec
+
+# LD-RELOC: Relocation section '.rela.dyn' at offset 0x10080 contains 1 entries:
+# LD-RELOC: 0000000001004168  0000000000000044 R_PPC64_DTPMOD64                  0
+
+# LD-SYM:      Symbol table '.symtab' contains 11 entries:
+# LD-SYM:      5: 0000000000000000     0 TLS     LOCAL  DEFAULT    13 x
+# LD-SYM-NEXT: 6: 0000000000000004     0 TLS     LOCAL  DEFAULT    13 y
+
+# LD-GOT:      section '.got':
+# LD-GOT-NEXT: 0x01004160 60c10001 00000000 00000000 00000000
+# LD-GOT-NEXT: 0x01004170 00000000 00000000
+
+# LDTOLE-RELOC: There are no relocations in this file.
+
+# LDTOLE-SYM:      Symbol table '.symtab' contains 9 entries:
+# LDTOLE-SYM:      5: 0000000000000000     0 TLS     LOCAL  DEFAULT     6 x
+# LDTOLE-SYM-NEXT: 6: 0000000000000004     0 TLS     LOCAL  DEFAULT     6 y
+
+# LDTOLE-GOT:      section '.got':
+# LDTOLE-GOT-NEXT: 0x01004020 20c00001 00000000
+
+//--- lds
+SECTIONS {
+  .text_addr 0x1001000 : { *(.text_addr) }
+  .text_val 0x1002000 : { *(.text_val) }
+  .text_twoval 0x1003000 : { *(.text_twoval) }
+  .text_incrval 0x1004000 : { *(.text_incrval) }
+}
+
+//--- asm
+# LD-LABEL: <LDAddr>:
+# LD:         paddi 3, 0, 12644, 1
+# LD-NEXT:    bl 0x1001020
+# LD-NEXT:    paddi 3, 3, -32768, 0
+# LD-NEXT:    blr
+# LDTOLE-LABEL: <LDAddr>:
+# LDTOLE:         paddi 3, 13, 4096, 0
+# LDTOLE-NEXT:    nop
+# LDTOLE-NEXT:    paddi 3, 3, -32768, 0
+# LDTOLE-NEXT:    blr
+.section .text_addr, "ax", %progbits
+LDAddr:
+  ## TODO: Adding a reference to .TOC. since LLD doesn't gracefully handle the
+  ## case where we define a .got section but have no references to the toc base
+  ## yet.
+  addis 2, 12, .TOC.-LDAddr at ha
+  paddi 3, 0, x at got@tlsld at pcrel, 1
+  bl __tls_get_addr at notoc(x at tlsld)
+  paddi 3, 3, x at dtprel, 0
+  blr
+
+# LD-LABEL: <LDVal>:
+# LD:         paddi 3, 0, 8552, 1
+# LD-NEXT:    bl 0x1001020
+# LD-NEXT:    paddi 3, 3, -32768, 0
+# LD-NEXT:    lwz 3, 0(3)
+# LD-NEXT:    blr
+# LDTOLE-LABEL: <LDVal>:
+# LDTOLE:         paddi 3, 13, 4096, 0
+# LDTOLE-NEXT:    nop
+# LDTOLE-NEXT:    paddi 3, 3, -32768, 0
+# LDTOLE-NEXT:    lwz 3, 0(3)
+# LDTOLE-NEXT:    blr
+.section .text_val, "ax", %progbits
+LDVal:
+  paddi 3, 0, x at got@tlsld at pcrel, 1
+  bl __tls_get_addr at notoc(x at tlsld)
+  paddi 3, 3, x at dtprel, 0
+  lwz 3, 0(3)
+  blr
+
+# LD-LABEL: <LDTwoVal>:
+# LD:         paddi 3, 0, 4456, 1
+# LD-NEXT:    bl 0x1001020
+# LD-NEXT:    paddi 3, 3, -32768, 0
+# LD-NEXT:    lwz 2, 0(3)
+# LD-NEXT:    paddi 3, 3, -32764, 0
+# LD-NEXT:    lwz 3, 0(3)
+# LD-NEXT:    blr
+# LDTOLE-LABEL: <LDTwoVal>:
+# LDTOLE:         paddi 3, 13, 4096, 0
+# LDTOLE-NEXT:    nop
+# LDTOLE-NEXT:    paddi 3, 3, -32768, 0
+# LDTOLE-NEXT:    lwz 2, 0(3)
+# LDTOLE-NEXT:    paddi 3, 3, -32764, 0
+# LDTOLE-NEXT:    lwz 3, 0(3)
+# LDTOLE-NEXT:    blr
+.section .text_twoval, "ax", %progbits
+LDTwoVal:
+  paddi 3, 0, x at got@tlsld at pcrel, 1
+  bl __tls_get_addr at notoc(x at tlsld)
+  paddi 3, 3, x at dtprel, 0
+  lwz 2, 0(3)
+  paddi 3, 3, y at dtprel, 0
+  lwz 3, 0(3)
+  blr
+
+# LD-LABEL: <LDIncrementVal>:
+# LD:         paddi 3, 0, 360, 1
+# LD-NEXT:    bl 0x1001020
+# LD-NEXT:    paddi 9, 3, -32764, 0
+# LD-NEXT:    lwz 4, 0(9)
+# LD-NEXT:    stw 5, 0(9)
+# LD-NEXT:    blr
+# LDTOLE-LABEL: <LDIncrementVal>:
+# LDTOLE:         paddi 3, 13, 4096, 0
+# LDTOLE-NEXT:    nop
+# LDTOLE-NEXT:    paddi 9, 3, -32764, 0
+# LDTOLE-NEXT:    lwz 4, 0(9)
+# LDTOLE-NEXT:    stw 5, 0(9)
+# LDTOLE-NEXT:    blr
+.section .text_incrval, "ax", %progbits
+LDIncrementVal:
+  paddi 3, 0, y at got@tlsld at pcrel, 1
+  bl __tls_get_addr at notoc(y at tlsld)
+  paddi 9, 3, y at dtprel, 0
+  lwz 4, 0(9)
+  stw 5, 0(9)
+  blr
+
+.section .tbss,"awT", at nobits
+x:
+  .long   0
+y:
+  .long   0


        


More information about the llvm-commits mailing list