Changeset View
Changeset View
Standalone View
Standalone View
lld/trunk/ELF/Arch/X86_64.cpp
Show First 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | void X86_64<ELFT>::relaxTlsIeToLe(uint8_t *Loc, RelType Type, | ||||
// The original code used a PC relative relocation. | // The original code used a PC relative relocation. | ||||
// Need to compensate for the -4 it had in the addend. | // Need to compensate for the -4 it had in the addend. | ||||
write32le(Loc, Val + 4); | write32le(Loc, Val + 4); | ||||
} | } | ||||
template <class ELFT> | template <class ELFT> | ||||
void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type, | void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type, | ||||
uint64_t Val) const { | uint64_t Val) const { | ||||
// Convert | |||||
// leaq bar@tlsld(%rip), %rdi | |||||
// callq __tls_get_addr@PLT | |||||
// leaq bar@dtpoff(%rax), %rcx | |||||
// to | |||||
// .word 0x6666 | |||||
// .byte 0x66 | |||||
// mov %fs:0,%rax | |||||
// leaq bar@tpoff(%rax), %rcx | |||||
if (Type == R_X86_64_DTPOFF64) { | if (Type == R_X86_64_DTPOFF64) { | ||||
write64le(Loc, Val); | write64le(Loc, Val); | ||||
return; | return; | ||||
} | } | ||||
if (Type == R_X86_64_DTPOFF32) { | if (Type == R_X86_64_DTPOFF32) { | ||||
write32le(Loc, Val); | write32le(Loc, Val); | ||||
return; | return; | ||||
} | } | ||||
const uint8_t Inst[] = { | const uint8_t Inst[] = { | ||||
0x66, 0x66, // .word 0x6666 | 0x66, 0x66, // .word 0x6666 | ||||
0x66, // .byte 0x66 | 0x66, // .byte 0x66 | ||||
0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax | 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax | ||||
}; | }; | ||||
if (Loc[4] == 0xe8) { | |||||
// Convert | |||||
// leaq bar@tlsld(%rip), %rdi # 48 8d 3d <Loc> | |||||
// callq __tls_get_addr@PLT # e8 <disp32> | |||||
// leaq bar@dtpoff(%rax), %rcx | |||||
// to | |||||
// .word 0x6666 | |||||
// .byte 0x66 | |||||
// mov %fs:0,%rax | |||||
// leaq bar@tpoff(%rax), %rcx | |||||
memcpy(Loc - 3, Inst, sizeof(Inst)); | memcpy(Loc - 3, Inst, sizeof(Inst)); | ||||
return; | |||||
} | |||||
if (Loc[4] == 0xff && Loc[5] == 0x15) { | |||||
// Convert | |||||
// leaq x@tlsld(%rip),%rdi # 48 8d 3d <Loc> | |||||
// call *__tls_get_addr@GOTPCREL(%rip) # ff 15 <disp32> | |||||
// to | |||||
// .long 0x66666666 | |||||
// movq %fs:0,%rax | |||||
// See "Table 11.9: LD -> LE Code Transition (LP64)" in | |||||
// https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf | |||||
Loc[-3] = 0x66; | |||||
memcpy(Loc - 2, Inst, sizeof(Inst)); | |||||
return; | |||||
} | |||||
error(getErrorLocation(Loc - 3) + | |||||
"expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD"); | |||||
} | } | ||||
template <class ELFT> | template <class ELFT> | ||||
void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { | void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { | ||||
switch (Type) { | switch (Type) { | ||||
case R_X86_64_8: | case R_X86_64_8: | ||||
checkUInt(Loc, Val, 8, Type); | checkUInt(Loc, Val, 8, Type); | ||||
*Loc = Val; | *Loc = Val; | ||||
▲ Show 20 Lines • Show All 358 Lines • Show Last 20 Lines |