[lld] r334304 - [PPC64] Add support for local-exec TLS model
Zaara Syeda via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 8 10:04:09 PDT 2018
Author: syzaara
Date: Fri Jun 8 10:04:09 2018
New Revision: 334304
URL: http://llvm.org/viewvc/llvm-project?rev=334304&view=rev
Log:
[PPC64] Add support for local-exec TLS model
This patch adds the relocations needed support the local-exec TLS model:
R_PPC64_TPREL16
R_PPC64_TPREL16_HA
R_PPC64_TPREL16_LO
R_PPC64_TPREL16_HI
R_PPC64_TPREL16_DS
R_PPC64_TPREL16_LO_DS
R_PPC64_TPREL16_HIGHER
R_PPC64_TPREL16_HIGHERA
R_PPC64_TPREL16_HIGHEST
R_PPC64_TPREL16_HIGHESTA
Differential Revision: https://reviews.llvm.org/D47598
Added:
lld/trunk/test/ELF/ppc64-local-exec-tls.s
Modified:
lld/trunk/ELF/Arch/PPC64.cpp
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/Target.h
Modified: lld/trunk/ELF/Arch/PPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC64.cpp?rev=334304&r1=334303&r2=334304&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Fri Jun 8 10:04:09 2018
@@ -79,6 +79,8 @@ PPC64::PPC64() {
GotPltHeaderEntriesNum = 2;
PltHeaderSize = 60;
NeedsThunks = true;
+ TcbSize = 8;
+ TlsTpOffset = 0x7000;
TlsModuleIndexRel = R_PPC64_DTPMOD64;
TlsOffsetRel = R_PPC64_DTPREL64;
@@ -187,6 +189,17 @@ RelExpr PPC64::getRelExpr(RelType Type,
case R_PPC64_GOT_TPREL16_DS:
case R_PPC64_GOT_TPREL16_HI:
return R_GOT_OFF;
+ case R_PPC64_TPREL16:
+ case R_PPC64_TPREL16_HA:
+ case R_PPC64_TPREL16_LO:
+ case R_PPC64_TPREL16_HI:
+ case R_PPC64_TPREL16_DS:
+ case R_PPC64_TPREL16_LO_DS:
+ case R_PPC64_TPREL16_HIGHER:
+ case R_PPC64_TPREL16_HIGHERA:
+ case R_PPC64_TPREL16_HIGHEST:
+ case R_PPC64_TPREL16_HIGHESTA:
+ return R_TLS;
case R_PPC64_TLSGD:
case R_PPC64_TLSLD:
case R_PPC64_TLS:
@@ -277,38 +290,48 @@ void PPC64::relocateOne(uint8_t *Loc, Re
break;
}
case R_PPC64_ADDR16:
+ case R_PPC64_TPREL16:
checkInt(Loc, Val, 16, Type);
write16(Loc, Val);
break;
case R_PPC64_ADDR16_DS:
+ case R_PPC64_TPREL16_DS:
checkInt(Loc, Val, 16, Type);
write16(Loc, (read16(Loc) & 3) | (Val & ~3));
break;
case R_PPC64_ADDR16_HA:
case R_PPC64_REL16_HA:
+ case R_PPC64_TPREL16_HA:
write16(Loc, applyPPCHa(Val));
break;
case R_PPC64_ADDR16_HI:
case R_PPC64_REL16_HI:
+ case R_PPC64_TPREL16_HI:
write16(Loc, applyPPCHi(Val));
break;
case R_PPC64_ADDR16_HIGHER:
+ case R_PPC64_TPREL16_HIGHER:
write16(Loc, applyPPCHigher(Val));
break;
case R_PPC64_ADDR16_HIGHERA:
+ case R_PPC64_TPREL16_HIGHERA:
write16(Loc, applyPPCHighera(Val));
break;
case R_PPC64_ADDR16_HIGHEST:
+ case R_PPC64_TPREL16_HIGHEST:
write16(Loc, applyPPCHighest(Val));
break;
case R_PPC64_ADDR16_HIGHESTA:
+ case R_PPC64_TPREL16_HIGHESTA:
write16(Loc, applyPPCHighesta(Val));
break;
case R_PPC64_ADDR16_LO:
case R_PPC64_REL16_LO:
+ case R_PPC64_TPREL16_LO:
write16(Loc, applyPPCLo(Val));
break;
case R_PPC64_ADDR16_LO_DS:
+ case R_PPC64_TPREL16_LO_DS:
write16(Loc, (read16(Loc) & 3) | (applyPPCLo(Val) & ~3));
break;
case R_PPC64_ADDR32:
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=334304&r1=334303&r2=334304&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Fri Jun 8 10:04:09 2018
@@ -618,8 +618,23 @@ static uint64_t getRelocTargetVA(RelType
// statically to zero.
if (Sym.isTls() && Sym.isUndefWeak())
return 0;
- if (Target->TcbSize)
+
+ // For TLS variant 1 the TCB is a fixed size, whereas for TLS variant 2 the
+ // TCB is on unspecified size and content. Targets that implement variant 1
+ // should set TcbSize.
+ if (Target->TcbSize) {
+ // PPC64 V2 ABI has the thread pointer offset into the middle of the TLS
+ // storage area by TlsTpOffset for efficient addressing TCB and up to
+ // 4KB â 8 B of other thread library information (placed before the TCB).
+ // Subtracting this offset will get the address of the first TLS block.
+ if (Target->TlsTpOffset)
+ return Sym.getVA(A) - Target->TlsTpOffset;
+
+ // If thread pointer is not offset into the middle, the first thing in the
+ // TLS storage area is the TCB. Add the TcbSize to get the address of the
+ // first TLS block.
return Sym.getVA(A) + alignTo(Target->TcbSize, Out::TlsPhdr->p_align);
+ }
return Sym.getVA(A) - Out::TlsPhdr->p_memsz;
case R_RELAX_TLS_GD_TO_LE_NEG:
case R_NEG_TLS:
Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=334304&r1=334303&r2=334304&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Fri Jun 8 10:04:09 2018
@@ -105,9 +105,15 @@ public:
// On PPC ELF V2 abi, the first entry in the .got is the .TOC.
unsigned GotHeaderEntriesNum = 0;
- // Set to 0 for variant 2
+ // For TLS variant 1, the TCB is a fixed size specified by the Target.
+ // For variant 2, the TCB is an unspecified size.
+ // Set to 0 for variant 2.
unsigned TcbSize = 0;
+ // Set to the offset (in bytes) that the thread pointer is initialized to
+ // point to, relative to the start of the thread local storage.
+ unsigned TlsTpOffset = 0;
+
bool NeedsThunks = false;
// A 4-byte field corresponding to one or more trap instructions, used to pad
Added: lld/trunk/test/ELF/ppc64-local-exec-tls.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-local-exec-tls.s?rev=334304&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc64-local-exec-tls.s (added)
+++ lld/trunk/test/ELF/ppc64-local-exec-tls.s Fri Jun 8 10:04:09 2018
@@ -0,0 +1,163 @@
+// REQUIRES: ppc
+// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
+// RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s
+
+ .text
+ .abiversion 2
+ .globl test_local_exec # -- Begin function test_local_exec
+ .p2align 4
+ .type test_local_exec, at function
+test_local_exec: # @test_local_exec
+.Lfunc_begin0:
+# %bb.0: # %entry
+ li 3, 0
+ stw 3, -12(1)
+ addis 3, 13, a at tprel@ha
+ addi 3, 3, a at tprel@l
+ ld 3, 0(3)
+ mr 4, 3
+ extsw 3, 4
+ blr
+ .long 0
+ .quad 0
+.Lfunc_end0:
+ .size test_local_exec, .Lfunc_end0-.Lfunc_begin0
+ # -- End function
+test_tprel:
+.Lfunc_gep1:
+ addis 2, 12, .TOC.-.Lfunc_gep1 at ha
+ addi 2, 2, .TOC.-.Lfunc_gep1 at l
+.Lfunc_lep1:
+ .localentry test_tprel, .Lfunc_lep1-.Lfunc_gep1
+ addi 3, 13, b at tprel
+ blr
+
+
+test_hi:
+.Lfunc_gep2:
+ addis 2, 12, .TOC.-.Lfunc_gep2 at ha
+ addi 2, 2, .TOC.-.Lfunc_gep2 at l
+.Lfunc_lep2:
+ .localentry test_hi, .Lfunc_lep2-.Lfunc_gep2
+ addis 3, 13, b at tprel@h
+ blr
+
+test_ds:
+.Lfunc_gep3:
+ addis 2, 12, .TOC.-.Lfunc_gep3 at ha
+ addi 2, 2, .TOC.-.Lfunc_gep3 at l
+.Lfunc_lep3:
+ .localentry test_ds, .Lfunc_lep3-.Lfunc_gep3
+ ld 3, b at tprel, 13
+ blr
+
+test_lo_ds:
+.Lfunc_gep4:
+ addis 2, 12, .TOC.-.Lfunc_gep4 at ha
+ addi 2, 2, .TOC.-.Lfunc_gep4 at l
+.Lfunc_lep4:
+ .localentry test_lo_ds, .Lfunc_lep4-.Lfunc_gep4
+ ld 3, b at tprel@l, 13
+ blr
+
+test_highest_a:
+.Lfunc_gep5:
+ addis 2, 12, .TOC.-.Lfunc_gep5 at ha
+ addi 2, 2, .TOC.-.Lfunc_gep5 at l
+.Lfunc_lep5:
+ .localentry test_highest_a, .Lfunc_lep5-.Lfunc_gep5
+ lis 4, b at tprel@highesta
+ ori 4, 4, b at tprel@highera
+ lis 5, b at tprel@ha
+ addi 5, 5, b at tprel@l
+ sldi 4, 4, 32
+ or 4, 4, 5
+ add 3, 13, 4
+ blr
+
+test_highest:
+.Lfunc_gep6:
+ addis 2, 12, .TOC.-.Lfunc_gep6 at ha
+ addi 2, 2, .TOC.-.Lfunc_gep6 at l
+.Lfunc_lep6:
+ .localentry test_highest, .Lfunc_lep6-.Lfunc_gep6
+ lis 4, b at tprel@highest
+ ori 4, 4, b at tprel@higher
+ sldi 4, 4, 32
+ oris 4, 4, b at tprel@h
+ ori 4, 4, b at tprel@l
+ add 3, 13, 4
+ blr
+
+ .type a, at object # @a
+ .type b, at object # @b
+ .section .tdata,"awT", at progbits
+ .p2align 3
+a:
+ .quad 55 # 0x37
+ .size a, 8
+
+b:
+ .quad 55 # 0x37
+ .size b, 8
+
+// Verify that the input has every initial-exec tls relocation type.
+// InputRelocs: Relocation section '.rela.text'
+// InputRelocs: R_PPC64_TPREL16_HA {{0+}} a + 0
+// InputRelocs: R_PPC64_TPREL16_LO {{0+}} a + 0
+// InputRelocs: R_PPC64_TPREL16 {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_HI {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_DS {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_LO_DS {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_HIGHESTA {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_HIGHERA {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_HIGHEST {{0+8}} b + 0
+// InputRelocs: R_PPC64_TPREL16_HIGHER {{0+8}} b + 0
+
+// The start of the TLS storage area is 0x7000 bytes before the thread pointer (r13).
+// We are building the address of the first TLS variable, relative to the thread pointer.
+// #ha(a at tprel) --> (0 - 0x7000 + 0x8000) >> 16 = 0
+// #lo(a at tprel)) --> (0 - 0x7000) & 0xFFFF = -0x7000 = -28672
+// Dis: test_local_exec:
+// Dis: addis 3, 13, 0
+// Dis: addi 3, 3, -28672
+
+// We are building the offset for the second TLS variable
+// Offset within tls storage - 0x7000
+// b at tprel = 8 - 0x7000 = 28664
+// Dis: test_tprel:
+// Dis: addi 3, 13, -28664
+
+// #hi(b at tprel) --> (8 - 0x7000) >> 16 = -1
+// Dis: test_hi:
+// Dis: addis 3, 13, -1
+
+// b at tprel = 8 - 0x7000 = -28664
+// Dis: test_ds:
+// Dis: ld 3, -28664(13)
+
+// #lo(b at tprel) --> (8 - 0x7000) & 0xFFFF = -28664
+// Dis: test_lo_ds:
+// Dis: ld 3, -28664(13)
+
+// #highesta(b at tprel) --> ((0x8 - 0x7000 + 0x8000) >> 48) & 0xFFFF = 0
+// #highera(b at tprel) --> ((0x8 - 0x7000 + 0x8000) >> 32) & 0xFFFF = 0
+// #ha(k at dtprel) --> ((0x8 - 0x7000 + 0x8000) >> 16) & 0xFFFF = 0
+// #lo(k at dtprel) --> ((0x8 - 0x7000) & 0xFFFF = -28664
+// Dis: test_highest_a:
+// Dis: lis 4, 0
+// Dis: ori 4, 4, 0
+// Dis: lis 5, 0
+// Dis: addi 5, 5, -28664
+
+// #highest(b at tprel) --> ((0x8 - 0x7000) >> 48) & 0xFFFF = 0xFFFF = -1
+// #higher(b at tprel) --> ((0x8 - 0x7000) >> 32) & 0xFFFF = 0xFFFF = 65535
+// #hi(k at dtprel) --> ((0x8 - 0x7000) >> 16) & 0xFFFF = 0xFFFF = 65535
+// #lo(k at dtprel) --> ((0x8 - 0x7000) & 0xFFFF = 33796
+// Dis: test_highest:
+// Dis: lis 4, -1
+// Dis: ori 4, 4, 65535
+// Dis: oris 4, 4, 65535
+// Dis: ori 4, 4, 36872
More information about the llvm-commits
mailing list