Changeset View
Standalone View
ELF/InputSection.cpp
Show First 20 Lines • Show All 578 Lines • ▼ Show 20 Lines | static Relocation *getRISCVPCRelHi20(const Symbol *Sym, uint64_t Addend) { | ||||
error("R_RISCV_PCREL_LO12 relocation points to " + IS->getObjMsg(D->Value) + | error("R_RISCV_PCREL_LO12 relocation points to " + IS->getObjMsg(D->Value) + | ||||
" without an associated R_RISCV_PCREL_HI20 relocation"); | " without an associated R_RISCV_PCREL_HI20 relocation"); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
// A TLS symbol's virtual address is relative to the TLS segment. Add a | // A TLS symbol's virtual address is relative to the TLS segment. Add a | ||||
// target-specific adjustment to produce a thread-pointer-relative offset. | // target-specific adjustment to produce a thread-pointer-relative offset. | ||||
static int64_t getTlsTpOffset() { | static int64_t getTlsTpOffset(const Symbol &S) { | ||||
switch (Config->EMachine) { | switch (Config->EMachine) { | ||||
case EM_ARM: | case EM_ARM: | ||||
case EM_AARCH64: | case EM_AARCH64: | ||||
grimar: I searched for `_TLS_MODULE_BASE_` in LLVM code and found it is mentioned, but only for AARCH64. | |||||
// Variant 1. The thread pointer points to a TCB with a fixed 2-word size, | // 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 | // followed by a variable amount of alignment padding, followed by the TLS | ||||
// segment. | // 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_386: | ||||
case EM_X86_64: | case EM_X86_64: | ||||
// Variant 2. The TLS segment is located just before the thread pointer. | // Variant 2. The TLS segment is located just before the thread pointer. | ||||
return -alignTo(Out::TlsPhdr->p_memsz, Out::TlsPhdr->p_align); | // On targets that support TLSDESC, _TLS_MODULE_BASE_@tpoff = 0. | ||||
if (&S == Symtab->TlsBase) | |||||
This line can be expensive if we have a lot of thread-local local symbols. getName() computes symbol names lazily, so if you call it on a local symbol, the function can be expensive. Maybe you should store TLSModuleBase symbol somewhere and compare S with the pointer? ruiu: This line can be expensive if we have a lot of thread-local local symbols. getName() computes… | |||||
I thought about that too, but supposed that TLS symbols are not that common. Am I wrong? grimar: I thought about that too, but supposed that TLS symbols are not that common. Am I wrong? | |||||
Also we can probably avoid this check if create the symbol with value of alignTo(Out::TlsPhdr->p_memsz, Out::TlsPhdr->p_align) it seems. I.e. I am thinking about using original getTlsTpOffset() helper and creating a symbol with the value of -getTlsTpOffset(). grimar: Also we can probably avoid this check if create the symbol with value of `alignTo(Out::TlsPhdr… | |||||
As a R_X86_64_TLSDESC dynamic relocation, the formula is: Sym->getVA(Addend) (in DynamicReloc::computeAddend()) Both must equal to 0. So there is a conflict. At least one place has to be a special case. I feel the most straightforward approach is to special case the @tpoff computation here. MaskRay: As a R_X86_64_TLSDESC dynamic relocation, the formula is: Sym->getVA(Addend) (in DynamicReloc… | |||||
Maybe it's not a big deal in practice. But identifying a symbol by name always rings a bell, so it'd probably easier to identify by a pointer comparison than explaining why this is not a big deal. ruiu: Maybe it's not a big deal in practice. But identifying a symbol by name always rings a bell, so… | |||||
return 0; | |||||
return S.getVA(0) - alignTo(Out::TlsPhdr->p_memsz, Out::TlsPhdr->p_align); | |||||
case EM_PPC64: | case EM_PPC64: | ||||
// The thread pointer points to a fixed offset from the start of the | // 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 | // 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 | // offset to reach 0x1000 of TCB/thread-library data and 0xf000 of the | ||||
// program's TLS segment. | // program's TLS segment. | ||||
return -0x7000; | return S.getVA(0) - 0x7000; | ||||
default: | default: | ||||
llvm_unreachable("unhandled Config->EMachine"); | llvm_unreachable("unhandled Config->EMachine"); | ||||
} | } | ||||
} | } | ||||
static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, | static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, | ||||
uint64_t P, const Symbol &Sym, RelExpr Expr) { | uint64_t P, const Symbol &Sym, RelExpr Expr) { | ||||
switch (Expr) { | switch (Expr) { | ||||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, | ||||
case R_RELAX_TLS_LD_TO_LE: | case R_RELAX_TLS_LD_TO_LE: | ||||
case R_TLS: | case R_TLS: | ||||
// It is not very clear what to return if the symbol is undefined. With | // It is not very clear what to return if the symbol is undefined. With | ||||
// --noinhibit-exec, even a non-weak undefined reference may reach here. | // --noinhibit-exec, even a non-weak undefined reference may reach here. | ||||
// Just return A, which matches R_ABS, and the behavior of some dynamic | // Just return A, which matches R_ABS, and the behavior of some dynamic | ||||
// loaders. | // loaders. | ||||
if (Sym.isUndefined()) | if (Sym.isUndefined()) | ||||
return A; | return A; | ||||
return Sym.getVA(A) + getTlsTpOffset(); | return getTlsTpOffset(Sym) + A; | ||||
case R_RELAX_TLS_GD_TO_LE_NEG: | case R_RELAX_TLS_GD_TO_LE_NEG: | ||||
case R_NEG_TLS: | case R_NEG_TLS: | ||||
if (Sym.isUndefined()) | if (Sym.isUndefined()) | ||||
return A; | return A; | ||||
return -Sym.getVA(0) - getTlsTpOffset() + A; | return -getTlsTpOffset(Sym) + A; | ||||
case R_SIZE: | case R_SIZE: | ||||
return Sym.getSize() + A; | return Sym.getSize() + A; | ||||
case R_TLSDESC: | case R_TLSDESC: | ||||
return In.Got->getGlobalDynAddr(Sym) + A; | return In.Got->getGlobalDynAddr(Sym) + A; | ||||
case R_TLSDESC_PC: | case R_TLSDESC_PC: | ||||
return In.Got->getGlobalDynAddr(Sym) + A - P; | return In.Got->getGlobalDynAddr(Sym) + A - P; | ||||
case R_AARCH64_TLSDESC_PAGE: | case R_AARCH64_TLSDESC_PAGE: | ||||
return getAArch64Page(In.Got->getGlobalDynAddr(Sym) + A) - | return getAArch64Page(In.Got->getGlobalDynAddr(Sym) + A) - | ||||
▲ Show 20 Lines • Show All 541 Lines • Show Last 20 Lines |
I searched for _TLS_MODULE_BASE_ in LLVM code and found it is mentioned, but only for AARCH64.
Should it be created for this target too?