[lld] r270243 - Make tp offset computation target independent.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Fri May 20 10:41:16 PDT 2016
Author: rafael
Date: Fri May 20 12:41:09 2016
New Revision: 270243
URL: http://llvm.org/viewvc/llvm-project?rev=270243&view=rev
Log:
Make tp offset computation target independent.
This adds direct support for computing offsets from the thread pointer
for both variants. Of the architectures we support, variant 1 is used
only by aarch64 (but that doesn't seem to be documented anywhere.)
Modified:
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/Target.cpp
lld/trunk/ELF/Target.h
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=270243&r1=270242&r2=270243&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Fri May 20 12:41:09 2016
@@ -180,14 +180,17 @@ getSymVA(uint32_t Type, typename ELFT::u
return Body.getGotVA<ELFT>() + A - P;
case R_GOTONLY_PC:
return Out<ELFT>::Got->getVA() + A - P;
+ case R_RELAX_TLS_GD_TO_LE:
+ case R_RELAX_TLS_IE_TO_LE:
+ case R_RELAX_TLS_LD_TO_LE:
case R_TLS:
+ if (Target->TcbSize)
+ return Body.getVA<ELFT>(A) +
+ alignTo(Target->TcbSize, Out<ELFT>::TlsPhdr->p_align);
return Body.getVA<ELFT>(A) - Out<ELFT>::TlsPhdr->p_memsz;
case R_NEG_TLS:
return Out<ELF32LE>::TlsPhdr->p_memsz - Body.getVA<ELFT>(A);
case R_ABS:
- case R_RELAX_TLS_GD_TO_LE:
- case R_RELAX_TLS_IE_TO_LE:
- case R_RELAX_TLS_LD_TO_LE:
return Body.getVA<ELFT>(A);
case R_GOT_OFF:
return Body.getGotOffset<ELFT>() + A;
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=270243&r1=270242&r2=270243&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Fri May 20 12:41:09 2016
@@ -150,9 +150,6 @@ public:
void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
-
-private:
- static const uint64_t TcbSize = 16;
};
class AMDGPUTargetInfo final : public TargetInfo {
@@ -403,7 +400,7 @@ void X86TargetInfo::relaxTlsGdToLe(uint8
0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 // subl 0(%ebx), %eax
};
memcpy(Loc - 3, Inst, sizeof(Inst));
- relocateOne(Loc + 5, R_386_32, Out<ELF32LE>::TlsPhdr->p_memsz - Val);
+ relocateOne(Loc + 5, R_386_32, -Val);
}
void X86TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type,
@@ -460,13 +457,13 @@ void X86TargetInfo::relaxTlsIeToLe(uint8
else
*Op = 0x80 | Reg | (Reg << 3);
}
- relocateOne(Loc, R_386_TLS_LE, Val - Out<ELF32LE>::TlsPhdr->p_memsz);
+ relocateOne(Loc, R_386_TLS_LE, Val);
}
void X86TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type,
uint64_t Val) const {
if (Type == R_386_TLS_LDO_32) {
- relocateOne(Loc, R_386_TLS_LE, Val - Out<ELF32LE>::TlsPhdr->p_memsz);
+ relocateOne(Loc, R_386_TLS_LE, Val);
return;
}
@@ -605,8 +602,7 @@ void X86_64TargetInfo::relaxTlsGdToLe(ui
0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x at tpoff,%rax
};
memcpy(Loc - 4, Inst, sizeof(Inst));
- relocateOne(Loc + 8, R_X86_64_TPOFF32,
- Val + 4 - Out<ELF64LE>::TlsPhdr->p_memsz);
+ relocateOne(Loc + 8, R_X86_64_TPOFF32, Val + 4);
}
void X86_64TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type,
@@ -658,7 +654,7 @@ void X86_64TargetInfo::relaxTlsIeToLe(ui
if (*Prefix == 0x4c)
*Prefix = (IsMov || RspAdd) ? 0x49 : 0x4d;
*RegSlot = (IsMov || RspAdd) ? (0xc0 | Reg) : (0x80 | Reg | (Reg << 3));
- relocateOne(Loc, R_X86_64_TPOFF32, Val + 4 - Out<ELF64LE>::TlsPhdr->p_memsz);
+ relocateOne(Loc, R_X86_64_TPOFF32, Val + 4);
}
void X86_64TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type,
@@ -673,11 +669,11 @@ void X86_64TargetInfo::relaxTlsLdToLe(ui
// mov %fs:0,%rax
// leaq bar at tpoff(%rax), %rcx
if (Type == R_X86_64_DTPOFF64) {
- write64le(Loc, Val - Out<ELF64LE>::TlsPhdr->p_memsz);
+ write64le(Loc, Val);
return;
}
if (Type == R_X86_64_DTPOFF32) {
- relocateOne(Loc, R_X86_64_TPOFF32, Val - Out<ELF64LE>::TlsPhdr->p_memsz);
+ relocateOne(Loc, R_X86_64_TPOFF32, Val);
return;
}
@@ -936,6 +932,10 @@ AArch64TargetInfo::AArch64TargetInfo() {
TlsOffsetRel = R_AARCH64_TLS_DTPREL64;
PltEntrySize = 16;
PltZeroSize = 32;
+
+ // 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;
}
RelExpr AArch64TargetInfo::getRelExpr(uint32_t Type,
@@ -943,6 +943,11 @@ RelExpr AArch64TargetInfo::getRelExpr(ui
switch (Type) {
default:
return R_ABS;
+
+ case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+ case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ return R_TLS;
+
case R_AARCH64_CALL26:
case R_AARCH64_CONDBR19:
case R_AARCH64_JUMP26:
@@ -1138,17 +1143,13 @@ void AArch64TargetInfo::relocateOne(uint
checkInt<16>(Val, Type);
or32le(Loc, (Val & 0xFFFC) << 3);
break;
- case R_AARCH64_TLSLE_ADD_TPREL_HI12: {
- uint64_t V = llvm::alignTo(TcbSize, Out<ELF64LE>::TlsPhdr->p_align) + Val;
- checkInt<24>(V, Type);
- updateAArch64Add(Loc, (V & 0xFFF000) >> 12);
+ case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+ checkInt<24>(Val, Type);
+ updateAArch64Add(Loc, (Val & 0xFFF000) >> 12);
break;
- }
- case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: {
- uint64_t V = llvm::alignTo(TcbSize, Out<ELF64LE>::TlsPhdr->p_align) + Val;
- updateAArch64Add(Loc, V & 0xFFF);
+ case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ updateAArch64Add(Loc, Val & 0xFFF);
break;
- }
default:
fatal("unrecognized reloc " + Twine(Type));
}
@@ -1166,9 +1167,7 @@ void AArch64TargetInfo::relaxTlsGdToLe(u
// movk x0, #0x10
// nop
// nop
- uint64_t TPOff = llvm::alignTo(TcbSize, Out<ELF64LE>::TlsPhdr->p_align);
- uint64_t X = Val + TPOff;
- checkUInt<32>(X, Type);
+ checkUInt<32>(Val, Type);
uint32_t NewInst;
switch (Type) {
@@ -1179,11 +1178,11 @@ void AArch64TargetInfo::relaxTlsGdToLe(u
break;
case R_AARCH64_TLSDESC_ADR_PAGE21:
// movz
- NewInst = 0xd2a00000 | (((X >> 16) & 0xffff) << 5);
+ NewInst = 0xd2a00000 | (((Val >> 16) & 0xffff) << 5);
break;
case R_AARCH64_TLSDESC_LD64_LO12_NC:
// movk
- NewInst = 0xf2800000 | ((X & 0xffff) << 5);
+ NewInst = 0xf2800000 | ((Val & 0xffff) << 5);
break;
default:
llvm_unreachable("unsupported Relocation for TLS GD to LE relax");
@@ -1193,20 +1192,18 @@ void AArch64TargetInfo::relaxTlsGdToLe(u
void AArch64TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type,
uint64_t Val) const {
- uint64_t TPOff = llvm::alignTo(TcbSize, Out<ELF64LE>::TlsPhdr->p_align);
- uint64_t X = Val + TPOff;
- checkUInt<32>(X, Type);
+ checkUInt<32>(Val, Type);
uint32_t Inst = read32le(Loc);
uint32_t NewInst;
if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) {
// Generate movz.
unsigned RegNo = (Inst & 0x1f);
- NewInst = (0xd2a00000 | RegNo) | (((X >> 16) & 0xffff) << 5);
+ NewInst = (0xd2a00000 | RegNo) | (((Val >> 16) & 0xffff) << 5);
} else if (Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) {
// Generate movk
unsigned RegNo = (Inst & 0x1f);
- NewInst = (0xf2800000 | RegNo) | ((X & 0xffff) << 5);
+ NewInst = (0xf2800000 | RegNo) | ((Val & 0xffff) << 5);
} else {
llvm_unreachable("invalid Relocation for TLS IE to LE Relax");
}
Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=270243&r1=270242&r2=270243&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Fri May 20 12:41:09 2016
@@ -83,6 +83,9 @@ public:
// to support lazy loading.
unsigned GotPltHeaderEntriesNum = 3;
+ // Set to 0 for variant 2
+ unsigned TcbSize = 0;
+
uint32_t ThunkSize = 0;
virtual void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
More information about the llvm-commits
mailing list