forked from OSchip/llvm-project
[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:
parent
b81a337be7
commit
1e57038bf2
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue