Skip to content

Commit

Permalink
[PowerPC][LLD] Support for PC Relative TLS for Local Dynamic
Browse files Browse the repository at this point in the history
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@got@tlsld@pcrel        R_PPC64_GOT_TLSLD_PCREL34
bl __tls_get_addr@notoc(x@tlsld) R_PPC64_TLSLD
                                 R_PPC64_REL24_NOTOC
...
paddi r9, r3, x@dtprel           R_PPC64_DTPREL34
```

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

Reviewed By: NeHuang, sfertile

Differential Revision: https://reviews.llvm.org/D87504
  • Loading branch information
stefanp-ibm committed Oct 23, 2020
1 parent 6d83e3b commit c6561cc
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 5 deletions.
40 changes: 37 additions & 3 deletions lld/ELF/Arch/PPC64.cpp
Expand Up @@ -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@got@tlsld@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@notoc(x@tlsld)
// to
// nop
// TOC Relaxation:
// Relax from bl __tls_get_addr(x@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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions lld/ELF/Relocations.cpp
Expand Up @@ -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;
}
Expand Down
144 changes: 144 additions & 0 deletions 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@ha
paddi 3, 0, x@got@tlsld@pcrel, 1
bl __tls_get_addr@notoc(x@tlsld)
paddi 3, 3, x@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@got@tlsld@pcrel, 1
bl __tls_get_addr@notoc(x@tlsld)
paddi 3, 3, x@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@got@tlsld@pcrel, 1
bl __tls_get_addr@notoc(x@tlsld)
paddi 3, 3, x@dtprel, 0
lwz 2, 0(3)
paddi 3, 3, y@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@got@tlsld@pcrel, 1
bl __tls_get_addr@notoc(y@tlsld)
paddi 9, 3, y@dtprel, 0
lwz 4, 0(9)
stw 5, 0(9)
blr

.section .tbss,"awT",@nobits
x:
.long 0
y:
.long 0

0 comments on commit c6561cc

Please sign in to comment.