summaryrefslogtreecommitdiffstats
path: root/lld/ELF/InputSection.cpp
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2019-05-30 10:00:20 +0000
committerFangrui Song <maskray@google.com>2019-05-30 10:00:20 +0000
commit0526c0cd8e73317ddef71b81b78631b16f4e9cd0 (patch)
tree5917968d4b095704674af6abb731d0a1a8378fe5 /lld/ELF/InputSection.cpp
parent3475a46ec23d170d086e98a470f3a3f5492845bd (diff)
downloadbcm5719-llvm-0526c0cd8e73317ddef71b81b78631b16f4e9cd0.tar.gz
bcm5719-llvm-0526c0cd8e73317ddef71b81b78631b16f4e9cd0.zip
[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
Diffstat (limited to 'lld/ELF/InputSection.cpp')
-rw-r--r--lld/ELF/InputSection.cpp16
1 files changed, 10 insertions, 6 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 2ff6b4800b7..45bafd321de 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -584,24 +584,28 @@ static Relocation *getRISCVPCRelHi20(const Symbol *Sym, uint64_t Addend) {
// A TLS symbol's virtual address is relative to the TLS segment. Add a
// target-specific adjustment to produce a thread-pointer-relative offset.
-static int64_t getTlsTpOffset() {
+static int64_t getTlsTpOffset(const Symbol &S) {
+ // On targets that support TLSDESC, _TLS_MODULE_BASE_@tpoff = 0.
+ if (&S == ElfSym::TlsModuleBase)
+ return 0;
+
switch (Config->EMachine) {
case EM_ARM:
case EM_AARCH64:
// Variant 1. The thread pointer points to a TCB with a fixed 2-word size,
// followed by a variable amount of alignment padding, followed by the TLS
// segment.
- return alignTo(Config->Wordsize * 2, Out::TlsPhdr->p_align);
+ return S.getVA(0) + alignTo(Config->Wordsize * 2, Out::TlsPhdr->p_align);
case EM_386:
case EM_X86_64:
// Variant 2. The TLS segment is located just before the thread pointer.
- return -alignTo(Out::TlsPhdr->p_memsz, Out::TlsPhdr->p_align);
+ return S.getVA(0) - alignTo(Out::TlsPhdr->p_memsz, Out::TlsPhdr->p_align);
case EM_PPC64:
// The thread pointer points to a fixed offset from the start of the
// executable's TLS segment. An offset of 0x7000 allows a signed 16-bit
// offset to reach 0x1000 of TCB/thread-library data and 0xf000 of the
// program's TLS segment.
- return -0x7000;
+ return S.getVA(0) - 0x7000;
default:
llvm_unreachable("unhandled Config->EMachine");
}
@@ -745,12 +749,12 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,
// loaders.
if (Sym.isUndefined())
return A;
- return Sym.getVA(A) + getTlsTpOffset();
+ return getTlsTpOffset(Sym) + A;
case R_RELAX_TLS_GD_TO_LE_NEG:
case R_NEG_TLS:
if (Sym.isUndefined())
return A;
- return -Sym.getVA(0) - getTlsTpOffset() + A;
+ return -getTlsTpOffset(Sym) + A;
case R_SIZE:
return Sym.getSize() + A;
case R_TLSDESC:
OpenPOWER on IntegriCloud