summaryrefslogtreecommitdiffstats
path: root/lld/ELF/InputSection.cpp
diff options
context:
space:
mode:
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