writeFromHalf16(loc, 0x3c6d0000); // addis r3, r13
relocateNoSym(loc, R_PPC64_TPREL16_HA, val);
break;
- case R_PPC64_TLSGD:
- write32(loc, NOP);
- write32(loc + 4, 0x38630000); // addi r3, r3
- // Since we are relocating a half16 type relocation and Loc + 4 points to
- // the start of an instruction we need to advance the buffer by an extra
- // 2 bytes on BE.
- relocateNoSym(loc + 4 + (config->ekind == ELF64BEKind ? 2 : 0),
- R_PPC64_TPREL16_LO, val);
+ case R_PPC64_GOT_TLSGD_PCREL34:
+ // Relax from paddi r3, 0, x@got@tlsgd@pcrel, 1 to
+ // paddi r3, r13, x@tprel, 0
+ writePrefixedInstruction(loc, 0x06000000386d0000);
+ relocateNoSym(loc, R_PPC64_TPREL34, val);
+ break;
+ case R_PPC64_TLSGD: {
+ // PC Relative Relaxation:
+ // Relax from bl __tls_get_addr@notoc(x@tlsgd) to
+ // nop
+ // TOC Relaxation:
+ // Relax from bl __tls_get_addr(x@tlsgd)
+ // nop
+ // to
+ // nop
+ // addi r3, r3, x@tprel@l
+ const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc);
+ if (locAsInt % 4 == 0) {
+ write32(loc, NOP); // nop
+ write32(loc + 4, 0x38630000); // addi r3, r3
+ // Since we are relocating a half16 type relocation and Loc + 4 points to
+ // the start of an instruction we need to advance the buffer by an extra
+ // 2 bytes on BE.
+ relocateNoSym(loc + 4 + (config->ekind == ELF64BEKind ? 2 : 0),
+ R_PPC64_TPREL16_LO, val);
+ } else if (locAsInt % 4 == 1) {
+ write32(loc - 1, NOP);
+ } else {
+ errorOrWarn("R_PPC64_TLSGD has unexpected byte alignment");
+ }
break;
+ }
default:
llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
}
case R_PPC64_GOT_TLSGD16_HI:
case R_PPC64_GOT_TLSGD16_LO:
return R_TLSGD_GOT;
+ case R_PPC64_GOT_TLSGD_PCREL34:
+ return R_TLSGD_PC;
case R_PPC64_GOT_TLSLD16:
case R_PPC64_GOT_TLSLD16_HA:
case R_PPC64_GOT_TLSLD16_HI:
break;
case R_PPC64_PCREL34:
case R_PPC64_GOT_PCREL34:
+ case R_PPC64_GOT_TLSGD_PCREL34:
case R_PPC64_GOT_TPREL_PCREL34:
case R_PPC64_TPREL34: {
const uint64_t si0Mask = 0x00000003ffff0000;
if ((readPrefixedInstruction(data) & 0xfc000000) == 0xe4000000)
return R_PPC64_RELAX_GOT_PC;
}
- if (expr == R_RELAX_TLS_GD_TO_IE)
+
+ if (type != R_PPC64_GOT_TLSGD_PCREL34 && expr == R_RELAX_TLS_GD_TO_IE)
return R_RELAX_TLS_GD_TO_IE_GOT_OFF;
if (expr == R_RELAX_TLS_LD_TO_LE)
return R_RELAX_TLS_LD_TO_LE_ABS;
relocateNoSym(loc, R_PPC64_GOT_TPREL16_LO_DS, val);
return;
}
- case R_PPC64_TLSGD:
- write32(loc, NOP); // bl __tls_get_addr(sym@tlsgd) --> nop
- write32(loc + 4, 0x7c636A14); // nop --> add r3, r3, r13
+ case R_PPC64_GOT_TLSGD_PCREL34: {
+ // Relax from paddi r3, 0, sym@got@tlsgd@pcrel, 1 to
+ // pld r3, sym@got@tprel@pcrel
+ writePrefixedInstruction(loc, 0x04100000e4600000);
+ relocateNoSym(loc, R_PPC64_GOT_TPREL_PCREL34, val);
+ return;
+ }
+ case R_PPC64_TLSGD: {
+ // PC Relative Relaxation:
+ // Relax from bl __tls_get_addr@notoc(x@tlsgd) to
+ // nop
+ // TOC Relaxation:
+ // Relax from bl __tls_get_addr(x@tlsgd)
+ // nop
+ // to
+ // nop
+ // add r3, r3, r13
+ const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc);
+ if (locAsInt % 4 == 0) {
+ write32(loc, NOP); // bl __tls_get_addr(sym@tlsgd) --> nop
+ write32(loc + 4, 0x7c636A14); // nop --> add r3, r3, r13
+ } else if (locAsInt % 4 == 1) {
+ // bl __tls_get_addr(sym@tlsgd) --> add r3, r3, r13
+ write32(loc - 1, 0x7c636a14);
+ } else {
+ errorOrWarn("R_PPC64_TLSGD has unexpected byte alignment");
+ }
return;
+ }
default:
llvm_unreachable("unsupported relocation for TLS GD to IE relaxation");
}
--- /dev/null
+# REQUIRES: ppc
+# RUN: split-file %s %t
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/asm -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/defs -o %t-defs.o
+# RUN: ld.lld --shared %t-defs.o --soname=t-defs -o %t-defs.so
+# RUN: ld.lld -T %t/lds --shared %t.o -o %t-gd.so
+# RUN: ld.lld -T %t/lds %t.o %t-defs.so -o %t-gdtoie
+# RUN: ld.lld -T %t/lds %t.o %t-defs.o -o %t-gdtole
+
+# RUN: llvm-readelf -r %t-gd.so | FileCheck %s --check-prefix=GD-RELOC
+# RUN: llvm-readelf -s %t-gd.so | FileCheck %s --check-prefix=GD-SYM
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t-gd.so | FileCheck %s --check-prefix=GD
+
+# RUN: llvm-readelf -r %t-gdtoie | FileCheck %s --check-prefix=GDTOIE-RELOC
+# RUN: llvm-readelf -s %t-gdtoie | FileCheck %s --check-prefix=GDTOIE-SYM
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t-gdtoie | FileCheck %s --check-prefix=GDTOIE
+
+# RUN: llvm-readelf -r %t-gdtole | FileCheck %s --check-prefix=GDTOLE-RELOC
+# RUN: llvm-readelf -s %t-gdtole | FileCheck %s --check-prefix=GDTOLE-SYM
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t-gdtole | FileCheck %s --check-prefix=GDTOLE
+
+## This test checks the General Dynamic PC Relative TLS implementation for lld.
+## GD - General Dynamic with no relaxation possible
+## GDTOIE - General Dynamic relaxed to Initial Exec
+## GDTOLE - General Dynamic relaxed to Local Exec
+
+#--- lds
+SECTIONS {
+ .text_addr 0x1001000 : { *(.text_addr) }
+}
+
+#--- defs
+.section .tbss,"awT",@nobits
+.globl x
+x:
+ .long 0
+.globl y
+y:
+ .long 0
+
+#--- asm
+
+# GD-RELOC: Relocation section '.rela.dyn' at offset 0x100b8 contains 4 entries:
+# GD-RELOC: 0000000001001160 0000000200000044 R_PPC64_DTPMOD64 0000000000000000 x + 0
+# GD-RELOC: 0000000001001168 000000020000004e R_PPC64_DTPREL64 0000000000000000 x + 0
+# GD-RELOC: 0000000001001170 0000000300000044 R_PPC64_DTPMOD64 0000000000000000 y + 0
+# GD-RELOC: 0000000001001178 000000030000004e R_PPC64_DTPREL64 0000000000000000 y + 0
+
+# GD-SYM: Symbol table '.dynsym' contains 4 entries:
+# GD-SYM: 2: 0000000000000000 0 TLS GLOBAL DEFAULT UND x
+# GD-SYM: 3: 0000000000000000 0 TLS GLOBAL DEFAULT UND y
+
+
+# GDTOIE-RELOC: Relocation section '.rela.dyn' at offset 0x{{.*}} contains 2 entries:
+# GDTOIE-RELOC: 00000000010010e0 0000000200000049 R_PPC64_TPREL64 0000000000000000 x + 0
+# GDTOIE-RELOC: 00000000010010e8 0000000300000049 R_PPC64_TPREL64 0000000000000000 y + 0
+
+# GDTOIE-SYM: Symbol table '.dynsym' contains 4 entries:
+# GDTOIE-SYM: 2: 0000000000000000 0 TLS GLOBAL DEFAULT UND x
+# GDTOIE-SYM: 3: 0000000000000000 0 TLS GLOBAL DEFAULT UND y
+
+
+# GDTOLE-RELOC: There are no relocations in this file.
+
+# GDTOLE-SYM: Symbol table '.symtab' contains 5 entries:
+# GDTOLE-SYM: 3: 0000000000000000 0 TLS GLOBAL DEFAULT 3 x
+# GDTOLE-SYM: 4: 0000000000000004 0 TLS GLOBAL DEFAULT 3 y
+
+# GD-LABEL: <GDTwoVal>:
+# GD-NEXT: paddi 3, 0, 352, 1
+# GD-NEXT: bl
+# GD-NEXT: paddi 3, 0, 356, 1
+# GD-NEXT: bl
+# GD-NEXT: blr
+# GDTOIE-LABEL: <GDTwoVal>:
+# GDTOIE-NEXT: pld 3, 224(0), 1
+# GDTOIE-NEXT: add 3, 3, 13
+# GDTOIE-NEXT: pld 3, 220(0), 1
+# GDTOIE-NEXT: add 3, 3, 13
+# GDTOIE-NEXT: blr
+# GDTOLE-LABEL: <GDTwoVal>:
+# GDTOLE-NEXT: paddi 3, 13, -28672, 0
+# GDTOLE-NEXT: nop
+# GDTOLE-NEXT: paddi 3, 13, -28668, 0
+# GDTOLE-NEXT: nop
+# GDTOLE-NEXT: blr
+.section .text_addr, "ax", %progbits
+GDTwoVal:
+ paddi 3, 0, x@got@tlsgd@pcrel, 1
+ bl __tls_get_addr@notoc(x@tlsgd)
+ paddi 3, 0, y@got@tlsgd@pcrel, 1
+ bl __tls_get_addr@notoc(y@tlsgd)
+ blr