Index: ELF/Arch/AArch64.cpp =================================================================== --- ELF/Arch/AArch64.cpp +++ ELF/Arch/AArch64.cpp @@ -72,9 +72,6 @@ // FreeBSD automatically promotes 2 MiB-aligned allocations. DefaultImageBase = 0x200000; - // It doesn't seem to be documented anywhere, but tls on aarch64 uses variant - // 1 of the tls structures and the tcb size is 16. - TcbSize = 16; NeedsThunks = true; } Index: ELF/Arch/ARM.cpp =================================================================== --- ELF/Arch/ARM.cpp +++ ELF/Arch/ARM.cpp @@ -62,8 +62,6 @@ PltEntrySize = 16; PltHeaderSize = 32; TrapInstr = 0xd4d4d4d4; - // ARM uses Variant 1 TLS - TcbSize = 8; NeedsThunks = true; } Index: ELF/Arch/PPC64.cpp =================================================================== --- ELF/Arch/PPC64.cpp +++ ELF/Arch/PPC64.cpp @@ -207,8 +207,6 @@ GotPltHeaderEntriesNum = 2; PltHeaderSize = 60; NeedsThunks = true; - TcbSize = 8; - TlsTpOffset = 0x7000; TlsModuleIndexRel = R_PPC64_DTPMOD64; TlsOffsetRel = R_PPC64_DTPREL64; Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -363,6 +363,8 @@ extern std::vector InputSections; Relocation *getRISCVPCRelHi20(const Symbol *Sym, const uint64_t Addend); + +int64_t getTlsTpOffset(); } // namespace elf std::string toString(const elf::InputSectionBase *); Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -566,6 +566,31 @@ return nullptr; } +// A TLS symbol's virtual address is relative to the TLS segment. Add a +// target-specific adjustment to produce a thread-pointer-relative offset. +int64_t lld::elf::getTlsTpOffset() { + 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); + case EM_386: + case EM_X86_64: + // Variant 2. The TLS segment is located just before the thread pointer. + return -Out::TlsPhdr->p_memsz; + 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; + default: + llvm_unreachable("unhandled Config->EMachine"); + } +} + static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, uint64_t P, const Symbol &Sym, RelExpr Expr) { switch (Expr) { @@ -711,24 +736,7 @@ // statically to zero. if (Sym.isTls() && Sym.isUndefWeak()) return 0; - - // 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; + return Sym.getVA(A) + getTlsTpOffset(); case R_RELAX_TLS_GD_TO_LE_NEG: case R_NEG_TLS: return Out::TlsPhdr->p_memsz - Sym.getVA(A); Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -117,15 +117,6 @@ // On PPC ELF V2 abi, the first entry in the .got is the .TOC. unsigned GotHeaderEntriesNum = 0; - // 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