Skip to content

Commit 0526c0c

Browse files
committedMay 30, 2019
[ELF] Implement Local Dynamic style TLSDESC for x86-64
For the Local Dynamic case of TLSDESC, _TLS_MODULE_BASE_ is defined as a special TLS symbol that makes: 1) Without relaxation: it produces a dynamic TLSDESC relocation that computes 0. Adding @dtpoff to access a TLS symbol. 2) With LD->LE relaxation: _TLS_MODULE_BASE_@tpoff = 0 (lowest address in the TLS block). Adding @tpoff to access a TLS symbol. For 1), this saves dynamic relocations and GOT slots as otherwise (General Dynamic) we would create an R_X86_64_TLSDESC and reserve two GOT slots for each symbol. Add ElfSym::TlsModuleBase and change the signature of getTlsTpOffset() to special case _TLS_MODULE_BASE_. Reviewed By: ruiu Differential Revision: https://reviews.llvm.org/D62577 llvm-svn: 362078
1 parent 3475a46 commit 0526c0c

File tree

5 files changed

+80
-6
lines changed

5 files changed

+80
-6
lines changed
 

Diff for: ‎lld/ELF/InputSection.cpp

+10-6
Original file line numberDiff line numberDiff line change
@@ -584,24 +584,28 @@ static Relocation *getRISCVPCRelHi20(const Symbol *Sym, uint64_t Addend) {
584584

585585
// A TLS symbol's virtual address is relative to the TLS segment. Add a
586586
// target-specific adjustment to produce a thread-pointer-relative offset.
587-
static int64_t getTlsTpOffset() {
587+
static int64_t getTlsTpOffset(const Symbol &S) {
588+
// On targets that support TLSDESC, _TLS_MODULE_BASE_@tpoff = 0.
589+
if (&S == ElfSym::TlsModuleBase)
590+
return 0;
591+
588592
switch (Config->EMachine) {
589593
case EM_ARM:
590594
case EM_AARCH64:
591595
// Variant 1. The thread pointer points to a TCB with a fixed 2-word size,
592596
// followed by a variable amount of alignment padding, followed by the TLS
593597
// segment.
594-
return alignTo(Config->Wordsize * 2, Out::TlsPhdr->p_align);
598+
return S.getVA(0) + alignTo(Config->Wordsize * 2, Out::TlsPhdr->p_align);
595599
case EM_386:
596600
case EM_X86_64:
597601
// Variant 2. The TLS segment is located just before the thread pointer.
598-
return -alignTo(Out::TlsPhdr->p_memsz, Out::TlsPhdr->p_align);
602+
return S.getVA(0) - alignTo(Out::TlsPhdr->p_memsz, Out::TlsPhdr->p_align);
599603
case EM_PPC64:
600604
// The thread pointer points to a fixed offset from the start of the
601605
// executable's TLS segment. An offset of 0x7000 allows a signed 16-bit
602606
// offset to reach 0x1000 of TCB/thread-library data and 0xf000 of the
603607
// program's TLS segment.
604-
return -0x7000;
608+
return S.getVA(0) - 0x7000;
605609
default:
606610
llvm_unreachable("unhandled Config->EMachine");
607611
}
@@ -745,12 +749,12 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,
745749
// loaders.
746750
if (Sym.isUndefined())
747751
return A;
748-
return Sym.getVA(A) + getTlsTpOffset();
752+
return getTlsTpOffset(Sym) + A;
749753
case R_RELAX_TLS_GD_TO_LE_NEG:
750754
case R_NEG_TLS:
751755
if (Sym.isUndefined())
752756
return A;
753-
return -Sym.getVA(0) - getTlsTpOffset() + A;
757+
return -getTlsTpOffset(Sym) + A;
754758
case R_SIZE:
755759
return Sym.getSize() + A;
756760
case R_TLSDESC:

Diff for: ‎lld/ELF/Symbols.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Defined *ElfSym::MipsGpDisp;
3939
Defined *ElfSym::MipsLocalGp;
4040
Defined *ElfSym::RelaIpltStart;
4141
Defined *ElfSym::RelaIpltEnd;
42+
Defined *ElfSym::TlsModuleBase;
4243

4344
static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
4445
switch (Sym.kind()) {

Diff for: ‎lld/ELF/Symbols.h

+3
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,9 @@ struct ElfSym {
436436
// __rel{,a}_iplt_{start,end} symbols.
437437
static Defined *RelaIpltStart;
438438
static Defined *RelaIpltEnd;
439+
440+
// _TLS_MODULE_BASE_ on targets that support TLSDESC.
441+
static Defined *TlsModuleBase;
439442
};
440443

441444
// A buffer class that is large enough to hold any Symbol-derived

Diff for: ‎lld/ELF/Writer.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,27 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
16061606
if (!dyn_cast_or_null<Defined>(Symtab->find("__global_pointer$")))
16071607
addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800);
16081608

1609+
if (Config->EMachine == EM_X86_64) {
1610+
// On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
1611+
// way that:
1612+
//
1613+
// 1) Without relaxation: it produces a dynamic TLSDESC relocation that
1614+
// computes 0.
1615+
// 2) With LD->LE relaxation: _TLS_MODULE_BASE_@tpoff = 0 (lowest address in
1616+
// the TLS block).
1617+
//
1618+
// 2) is special cased in @tpoff computation. To satisfy 1), we define it as
1619+
// an absolute symbol of zero. This is different from GNU linkers which
1620+
// define _TLS_MODULE_BASE_ relative to the first TLS section.
1621+
Symbol *S = Symtab->find("_TLS_MODULE_BASE_");
1622+
if (S && S->isUndefined()) {
1623+
S->resolve(Defined{/*File=*/nullptr, S->getName(), STB_GLOBAL, STV_HIDDEN,
1624+
STT_TLS, /*Value=*/0, 0,
1625+
/*Section=*/nullptr});
1626+
ElfSym::TlsModuleBase = cast<Defined>(S);
1627+
}
1628+
}
1629+
16091630
// This responsible for splitting up .eh_frame section into
16101631
// pieces. The relocation scan uses those pieces, so this has to be
16111632
// earlier.

Diff for: ‎lld/test/ELF/x86-64-tlsdesc-ld.s

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# REQUIRES: x86
2+
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3+
4+
# RUN: ld.lld -shared %t.o -o %t.so
5+
# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=LD-REL %s
6+
# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck --check-prefix=LD %s
7+
8+
# RUN: ld.lld %t.o -o %t
9+
# RUN: llvm-readelf -r %t | FileCheck --check-prefix=NOREL %s
10+
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
11+
12+
## Check _TLS_MODULE_BASE_ used by LD produces a dynamic relocation with a value of 0.
13+
# LD-REL: .rela.dyn {
14+
# LD-REL-NEXT: 0x20A0 R_X86_64_TLSDESC - 0x0
15+
# LD-REL-NEXT: }
16+
17+
## 0x20a0-0x1007 = 4249
18+
## dtpoff(a) = 8, dtpoff(b) = 12
19+
# LD: leaq 4249(%rip), %rax
20+
# LD-NEXT: 1007: callq *(%rax)
21+
# LD-NEXT: movl %fs:8(%rax), %edx
22+
# LD-NEXT: addl %fs:12(%rax), %edx
23+
24+
## When producing an executable, the LD code sequence can be relaxed to LE.
25+
## It is the same as GD->LE.
26+
## tpoff(_TLS_MODULE_BASE_) = 0, tpoff(a) = -8, tpoff(b) = -4
27+
28+
# NOREL: no relocations
29+
30+
# LE: movq $0, %rax
31+
# LE-NEXT: nop
32+
# LE-NEXT: movl %fs:-8(%rax), %edx
33+
# LE-NEXT: addl %fs:-4(%rax), %edx
34+
35+
leaq _TLS_MODULE_BASE_@tlsdesc(%rip), %rax
36+
call *_TLS_MODULE_BASE_@tlscall(%rax)
37+
movl %fs:a@dtpoff(%rax), %edx
38+
addl %fs:b@dtpoff(%rax), %edx
39+
40+
.section .tbss
41+
.zero 8
42+
a:
43+
.zero 4
44+
b:
45+
.zero 4

0 commit comments

Comments
 (0)
Please sign in to comment.