diff options
Diffstat (limited to 'lld/ELF/InputSection.cpp')
| -rw-r--r-- | lld/ELF/InputSection.cpp | 16 |
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: |

