[ELF] Pass `Relocation` to relaxGot and relaxTls{GdToIe,GdToLe,LdToLe,IeToLe}

These functions call relocateOne(). This patch is a prerequisite for
making relocateOne() aware of `Symbol` (D73254).

Reviewed By: grimar, nickdesaulniers

Differential Revision: https://reviews.llvm.org/D73250
This commit is contained in:
Fangrui Song 2020-01-22 19:42:54 -08:00
parent b81a337be7
commit 1e57038bf2
8 changed files with 132 additions and 90 deletions

View File

@ -48,9 +48,12 @@ public:
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
RelExpr expr) const override;
void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
};
} // namespace
@ -455,7 +458,8 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
}
}
void AArch64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
void AArch64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
// TLSDESC Global-Dynamic relocation are in the form:
// adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21]
// ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12]
@ -467,9 +471,9 @@ void AArch64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
// movk x0, #0x10
// nop
// nop
checkUInt(loc, val, 32, type);
checkUInt(loc, val, 32, rel.type);
switch (type) {
switch (rel.type) {
case R_AARCH64_TLSDESC_ADD_LO12:
case R_AARCH64_TLSDESC_CALL:
write32le(loc, 0xd503201f); // nop
@ -485,7 +489,8 @@ void AArch64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
}
}
void AArch64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
void AArch64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
// TLSDESC Global-Dynamic relocation are in the form:
// adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21]
// ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12]
@ -498,7 +503,7 @@ void AArch64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
// nop
// nop
switch (type) {
switch (rel.type) {
case R_AARCH64_TLSDESC_ADD_LO12:
case R_AARCH64_TLSDESC_CALL:
write32le(loc, 0xd503201f); // nop
@ -516,16 +521,17 @@ void AArch64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
}
}
void AArch64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
checkUInt(loc, val, 32, type);
void AArch64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
checkUInt(loc, val, 32, rel.type);
if (type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) {
if (rel.type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) {
// Generate MOVZ.
uint32_t regNo = read32le(loc) & 0x1f;
write32le(loc, (0xd2a00000 | regNo) | (((val >> 16) & 0xffff) << 5));
return;
}
if (type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) {
if (rel.type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) {
// Generate MOVK.
uint32_t regNo = read32le(loc) & 0x1f;
write32le(loc, (0xf2800000 | regNo) | ((val & 0xffff) << 5));

View File

@ -48,10 +48,14 @@ public:
RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
RelExpr expr) const override;
int getTlsGdRelaxSkip(RelType type) const override;
void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
};
} // namespace
@ -368,8 +372,9 @@ int PPC::getTlsGdRelaxSkip(RelType type) const {
return 1;
}
void PPC::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
switch (type) {
void PPC::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
switch (rel.type) {
case R_PPC_GOT_TLSGD16: {
// addi rT, rA, x@got@tlsgd --> lwz rT, x@got@tprel(rA)
uint32_t insn = readFromHalf16(loc);
@ -386,8 +391,9 @@ void PPC::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
}
}
void PPC::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
switch (type) {
void PPC::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
switch (rel.type) {
case R_PPC_GOT_TLSGD16:
// addi r3, r31, x@got@tlsgd --> addis r3, r2, x@tprel@ha
writeFromHalf16(loc, 0x3c620000 | ha(val));
@ -401,8 +407,9 @@ void PPC::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
}
}
void PPC::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
switch (type) {
void PPC::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
switch (rel.type) {
case R_PPC_GOT_TLSLD16:
// addi r3, rA, x@got@tlsgd --> addis r3, r2, 0
writeFromHalf16(loc, 0x3c620000);
@ -417,15 +424,16 @@ void PPC::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
case R_PPC_DTPREL16_HA:
case R_PPC_DTPREL16_HI:
case R_PPC_DTPREL16_LO:
relocateOne(loc, type, val);
relocateOne(loc, rel.type, val);
break;
default:
llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
}
}
void PPC::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
switch (type) {
void PPC::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
switch (rel.type) {
case R_PPC_GOT_TPREL16: {
// lwz rT, x@got@tprel(rA) --> addis rT, r2, x@tprel@ha
uint32_t rt = readFromHalf16(loc) & 0x03e00000;

View File

@ -155,8 +155,7 @@ getRelaTocSymAndAddend(InputSectionBase *tocSec, uint64_t offset) {
// ld/lwa 3, 0(3) # load the value from the address
//
// Returns true if the relaxation is performed.
bool tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel,
uint8_t *bufLoc) {
bool tryRelaxPPC64TocIndirection(const Relocation &rel, uint8_t *bufLoc) {
assert(config->tocOptimize);
if (rel.addend < 0)
return false;
@ -187,7 +186,7 @@ bool tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel,
return false;
// Add PPC64TocOffset that will be subtracted by relocateOne().
target->relaxGot(bufLoc, type, tocRelative + ppc64TocOffset);
target->relaxGot(bufLoc, rel, tocRelative + ppc64TocOffset);
return true;
}
@ -214,11 +213,16 @@ public:
bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
RelExpr expr) const override;
void relaxGot(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxGot(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
uint8_t stOther) const override;
@ -364,11 +368,11 @@ uint32_t PPC64::calcEFlags() const {
return 2;
}
void PPC64::relaxGot(uint8_t *loc, RelType type, uint64_t val) const {
switch (type) {
void PPC64::relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const {
switch (rel.type) {
case R_PPC64_TOC16_HA:
// Convert "addis reg, 2, .LC0@toc@h" to "addis reg, 2, var@toc@h" or "nop".
relocateOne(loc, type, val);
relocateOne(loc, rel.type, val);
break;
case R_PPC64_TOC16_LO_DS: {
// Convert "ld reg, .LC0@toc@l(reg)" to "addi reg, reg, var@toc@l" or
@ -385,7 +389,8 @@ void PPC64::relaxGot(uint8_t *loc, RelType type, uint64_t val) const {
}
}
void PPC64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
void PPC64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
// Reference: 3.7.4.2 of the 64-bit ELF V2 abi supplement.
// The general dynamic code sequence for a global `x` will look like:
// Instruction Relocation Symbol
@ -401,7 +406,7 @@ void PPC64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
// bl __tls_get_addr(x@tlsgd) into nop
// nop into addi r3, r3, x@tprel@l
switch (type) {
switch (rel.type) {
case R_PPC64_GOT_TLSGD16_HA:
writeFromHalf16(loc, 0x60000000); // nop
break;
@ -424,7 +429,8 @@ void PPC64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
}
}
void PPC64::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
void PPC64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
// Reference: 3.7.4.3 of the 64-bit ELF V2 abi supplement.
// The local dynamic code sequence for a global `x` will look like:
// Instruction Relocation Symbol
@ -440,7 +446,7 @@ void PPC64::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
// bl __tls_get_addr(x@tlsgd) into nop
// nop into addi r3, r3, 4096
switch (type) {
switch (rel.type) {
case R_PPC64_GOT_TLSLD16_HA:
writeFromHalf16(loc, 0x60000000); // nop
break;
@ -457,7 +463,7 @@ void PPC64::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
case R_PPC64_DTPREL16_DS:
case R_PPC64_DTPREL16_LO:
case R_PPC64_DTPREL16_LO_DS:
relocateOne(loc, type, val);
relocateOne(loc, rel.type, val);
break;
default:
llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
@ -489,7 +495,8 @@ unsigned getPPCDFormOp(unsigned secondaryOp) {
}
}
void PPC64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
// The initial exec code sequence for a global `x` will look like:
// Instruction Relocation Symbol
// addis r9, r2, x@got@tprel@ha R_PPC64_GOT_TPREL16_HA x
@ -510,7 +517,7 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
// indexed load or store instructions.
unsigned offset = (config->ekind == ELF64BEKind) ? 2 : 0;
switch (type) {
switch (rel.type) {
case R_PPC64_GOT_TPREL16_HA:
write32(loc - offset, 0x60000000); // nop
break;
@ -971,8 +978,9 @@ RelExpr PPC64::adjustRelaxExpr(RelType type, const uint8_t *data,
// thread pointer.
// Since the nop must directly follow the call, the R_PPC64_TLSGD relocation is
// used as the relaxation hint for both steps 2 and 3.
void PPC64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
switch (type) {
void PPC64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
switch (rel.type) {
case R_PPC64_GOT_TLSGD16_HA:
// This is relaxed from addis rT, r2, sym@got@tlsgd@ha to
// addis rT, r2, sym@got@tprel@ha.

View File

@ -39,10 +39,14 @@ public:
RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
RelExpr expr) const override;
void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
};
} // namespace
@ -320,7 +324,7 @@ void X86::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
}
}
void X86::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
void X86::relaxTlsGdToLe(uint8_t *loc, const Relocation &, uint64_t val) const {
// Convert
// leal x@tlsgd(, %ebx, 1),
// call __tls_get_addr@plt
@ -335,7 +339,7 @@ void X86::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
write32le(loc + 5, val);
}
void X86::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
void X86::relaxTlsGdToIe(uint8_t *loc, const Relocation &, uint64_t val) const {
// Convert
// leal x@tlsgd(, %ebx, 1),
// call __tls_get_addr@plt
@ -352,14 +356,15 @@ void X86::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
// In some conditions, relocations can be optimized to avoid using GOT.
// This function does that for Initial Exec to Local Exec case.
void X86::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
void X86::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
// Ulrich's document section 6.2 says that @gotntpoff can
// be used with MOVL or ADDL instructions.
// @indntpoff is similar to @gotntpoff, but for use in
// position dependent code.
uint8_t reg = (loc[-1] >> 3) & 7;
if (type == R_386_TLS_IE) {
if (rel.type == R_386_TLS_IE) {
if (loc[-1] == 0xa1) {
// "movl foo@indntpoff,%eax" -> "movl $foo,%eax"
// This case is different from the generic case below because
@ -375,7 +380,7 @@ void X86::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
loc[-1] = 0xc0 | reg;
}
} else {
assert(type == R_386_TLS_GOTIE);
assert(rel.type == R_386_TLS_GOTIE);
if (loc[-2] == 0x8b) {
// "movl foo@gottpoff(%rip),%reg" -> "movl $foo,%reg"
loc[-2] = 0xc7;
@ -389,8 +394,9 @@ void X86::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
write32le(loc, val);
}
void X86::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
if (type == R_386_TLS_LDO_32) {
void X86::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
if (rel.type == R_386_TLS_LDO_32) {
write32le(loc, val);
return;
}

View File

@ -39,11 +39,16 @@ public:
RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
RelExpr expr) const override;
void relaxGot(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
void relaxGot(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
uint8_t stOther) const override;
};
@ -177,8 +182,9 @@ RelType X86_64::getDynRel(RelType type) const {
return R_X86_64_NONE;
}
void X86_64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
if (type == R_X86_64_TLSGD) {
void X86_64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
if (rel.type == R_X86_64_TLSGD) {
// Convert
// .byte 0x66
// leaq x@tlsgd(%rip), %rdi
@ -201,7 +207,7 @@ void X86_64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
// lea x@tlsgd(%rip), %rax
// call *(%rax)
// to the following two instructions.
assert(type == R_X86_64_GOTPC32_TLSDESC);
assert(rel.type == R_X86_64_GOTPC32_TLSDESC);
if (memcmp(loc - 3, "\x48\x8d\x05", 3)) {
error(getErrorLocation(loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used "
"in callq *x@tlsdesc(%rip), %rax");
@ -217,8 +223,9 @@ void X86_64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
}
}
void X86_64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
if (type == R_X86_64_TLSGD) {
void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
if (rel.type == R_X86_64_TLSGD) {
// Convert
// .byte 0x66
// leaq x@tlsgd(%rip), %rdi
@ -241,7 +248,7 @@ void X86_64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
// lea x@tlsgd(%rip), %rax
// call *(%rax)
// to the following two instructions.
assert(type == R_X86_64_GOTPC32_TLSDESC);
assert(rel.type == R_X86_64_GOTPC32_TLSDESC);
if (memcmp(loc - 3, "\x48\x8d\x05", 3)) {
error(getErrorLocation(loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used "
"in callq *x@tlsdesc(%rip), %rax");
@ -258,7 +265,8 @@ void X86_64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
// In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
// R_X86_64_TPOFF32 so that it does not use GOT.
void X86_64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
void X86_64::relaxTlsIeToLe(uint8_t *loc, const Relocation &,
uint64_t val) const {
uint8_t *inst = loc - 3;
uint8_t reg = loc[-1] >> 3;
uint8_t *regSlot = loc - 1;
@ -299,12 +307,13 @@ void X86_64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
write32le(loc, val + 4);
}
void X86_64::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
if (type == R_X86_64_DTPOFF64) {
void X86_64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
if (rel.type == R_X86_64_DTPOFF64) {
write64le(loc, val);
return;
}
if (type == R_X86_64_DTPOFF32) {
if (rel.type == R_X86_64_DTPOFF32) {
write32le(loc, val);
return;
}
@ -495,7 +504,7 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
write32le(loc, val);
}
void X86_64::relaxGot(uint8_t *loc, RelType type, uint64_t val) const {
void X86_64::relaxGot(uint8_t *loc, const Relocation &, uint64_t val) const {
const uint8_t op = loc[-2];
const uint8_t modRm = loc[-1];

View File

@ -939,29 +939,29 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) {
switch (expr) {
case R_RELAX_GOT_PC:
case R_RELAX_GOT_PC_NOPIC:
target->relaxGot(bufLoc, type, targetVA);
target->relaxGot(bufLoc, rel, targetVA);
break;
case R_PPC64_RELAX_TOC:
if (!tryRelaxPPC64TocIndirection(type, rel, bufLoc))
if (!tryRelaxPPC64TocIndirection(rel, bufLoc))
target->relocateOne(bufLoc, type, targetVA);
break;
case R_RELAX_TLS_IE_TO_LE:
target->relaxTlsIeToLe(bufLoc, type, targetVA);
target->relaxTlsIeToLe(bufLoc, rel, targetVA);
break;
case R_RELAX_TLS_LD_TO_LE:
case R_RELAX_TLS_LD_TO_LE_ABS:
target->relaxTlsLdToLe(bufLoc, type, targetVA);
target->relaxTlsLdToLe(bufLoc, rel, targetVA);
break;
case R_RELAX_TLS_GD_TO_LE:
case R_RELAX_TLS_GD_TO_LE_NEG:
target->relaxTlsGdToLe(bufLoc, type, targetVA);
target->relaxTlsGdToLe(bufLoc, rel, targetVA);
break;
case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC:
case R_RELAX_TLS_GD_TO_IE:
case R_RELAX_TLS_GD_TO_IE_ABS:
case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
case R_RELAX_TLS_GD_TO_IE_GOTPLT:
target->relaxTlsGdToIe(bufLoc, type, targetVA);
target->relaxTlsGdToIe(bufLoc, rel, targetVA);
break;
case R_PPC64_CALL:
// If this is a call to __tls_get_addr, it may be part of a TLS

View File

@ -155,26 +155,27 @@ RelExpr TargetInfo::adjustRelaxExpr(RelType type, const uint8_t *data,
return expr;
}
void TargetInfo::relaxGot(uint8_t *loc, RelType type, uint64_t val) const {
void TargetInfo::relaxGot(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
llvm_unreachable("Should not have claimed to be relaxable");
}
void TargetInfo::relaxTlsGdToLe(uint8_t *loc, RelType type,
void TargetInfo::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
llvm_unreachable("Should not have claimed to be relaxable");
}
void TargetInfo::relaxTlsGdToIe(uint8_t *loc, RelType type,
void TargetInfo::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
llvm_unreachable("Should not have claimed to be relaxable");
}
void TargetInfo::relaxTlsIeToLe(uint8_t *loc, RelType type,
void TargetInfo::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
llvm_unreachable("Should not have claimed to be relaxable");
}
void TargetInfo::relaxTlsLdToLe(uint8_t *loc, RelType type,
void TargetInfo::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
llvm_unreachable("Should not have claimed to be relaxable");
}

View File

@ -129,11 +129,16 @@ public:
virtual RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
RelExpr expr) const;
virtual void relaxGot(uint8_t *loc, RelType type, uint64_t val) const;
virtual void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const;
virtual void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const;
virtual void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const;
virtual void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const;
virtual void relaxGot(uint8_t *loc, const Relocation &rel,
uint64_t val) const;
virtual void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
uint64_t val) const;
virtual void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const;
virtual void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const;
virtual void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
uint64_t val) const;
protected:
// On FreeBSD x86_64 the first page cannot be mmaped.
@ -171,8 +176,7 @@ static inline std::string getErrorLocation(const uint8_t *loc) {
void writePPC32GlinkSection(uint8_t *buf, size_t numEntries);
bool tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel,
uint8_t *bufLoc);
bool tryRelaxPPC64TocIndirection(const Relocation &rel, uint8_t *bufLoc);
unsigned getPPCDFormOp(unsigned secondaryOp);
// In the PowerPC64 Elf V2 abi a function can have 2 entry points. The first