mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-09 09:32:20 +00:00
[ELF] Rename relocateOne() to relocate() and pass Relocation
to it
Symbol information can be used to improve out-of-range/misalignment diagnostics. It also helps R_ARM_CALL/R_ARM_THM_CALL which has different behaviors with different symbol types. There are many (67) relocateOne() call sites used in thunks, {Arm,AArch64}errata, PLT, etc. Rename them to `relocateNoSym()` to be clearer that there is no symbol information. Reviewed By: grimar, peter.smith Differential Revision: https://reviews.llvm.org/D73254
This commit is contained in:
parent
481b79668c
commit
deb5819d62
@ -421,7 +421,7 @@ void Patch843419Section::writeTo(uint8_t *buf) {
|
||||
// Return address is the next instruction after the one we have just copied.
|
||||
uint64_t s = getLDSTAddr() + 4;
|
||||
uint64_t p = patchSym->getVA() + 4;
|
||||
target->relocateOne(buf + 4, R_AARCH64_JUMP26, s - p);
|
||||
target->relocateNoSym(buf + 4, R_AARCH64_JUMP26, s - p);
|
||||
}
|
||||
|
||||
void AArch64Err843419Patcher::init() {
|
||||
|
@ -189,7 +189,7 @@ void Patch657417Section::writeTo(uint8_t *buf) {
|
||||
// been altered to point to us!
|
||||
uint64_t s = getThumbDestAddr(getBranchAddr(), instr);
|
||||
uint64_t p = getVA(4);
|
||||
target->relocateOne(buf, isARM ? R_ARM_JUMP24 : R_ARM_THM_JUMP24, s - p);
|
||||
target->relocateNoSym(buf, isARM ? R_ARM_JUMP24 : R_ARM_THM_JUMP24, s - p);
|
||||
}
|
||||
|
||||
// Given a branch instruction spanning two 4KiB regions, at offset off from the
|
||||
|
@ -45,7 +45,8 @@ public:
|
||||
uint32_t getThunkSectionSpacing() const override;
|
||||
bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
|
||||
bool usesOnlyLowPageBits(RelType type) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
|
||||
RelExpr expr) const override;
|
||||
void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
|
||||
@ -211,10 +212,10 @@ void AArch64::writePltHeader(uint8_t *buf) const {
|
||||
|
||||
uint64_t got = in.gotPlt->getVA();
|
||||
uint64_t plt = in.plt->getVA();
|
||||
relocateOne(buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
|
||||
getAArch64Page(got + 16) - getAArch64Page(plt + 4));
|
||||
relocateOne(buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, got + 16);
|
||||
relocateOne(buf + 12, R_AARCH64_ADD_ABS_LO12_NC, got + 16);
|
||||
relocateNoSym(buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
|
||||
getAArch64Page(got + 16) - getAArch64Page(plt + 4));
|
||||
relocateNoSym(buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, got + 16);
|
||||
relocateNoSym(buf + 12, R_AARCH64_ADD_ABS_LO12_NC, got + 16);
|
||||
}
|
||||
|
||||
void AArch64::writePlt(uint8_t *buf, const Symbol &sym,
|
||||
@ -228,10 +229,10 @@ void AArch64::writePlt(uint8_t *buf, const Symbol &sym,
|
||||
memcpy(buf, inst, sizeof(inst));
|
||||
|
||||
uint64_t gotPltEntryAddr = sym.getGotPltVA();
|
||||
relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21,
|
||||
getAArch64Page(gotPltEntryAddr) - getAArch64Page(pltEntryAddr));
|
||||
relocateOne(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr);
|
||||
relocateOne(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr);
|
||||
relocateNoSym(buf, R_AARCH64_ADR_PREL_PG_HI21,
|
||||
getAArch64Page(gotPltEntryAddr) - getAArch64Page(pltEntryAddr));
|
||||
relocateNoSym(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr);
|
||||
relocateNoSym(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr);
|
||||
}
|
||||
|
||||
bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file,
|
||||
@ -312,16 +313,17 @@ static void writeSMovWImm(uint8_t *loc, uint32_t imm) {
|
||||
write32le(loc, inst | ((imm & 0xFFFF) << 5));
|
||||
}
|
||||
|
||||
void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
switch (type) {
|
||||
void AArch64::relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const {
|
||||
switch (rel.type) {
|
||||
case R_AARCH64_ABS16:
|
||||
case R_AARCH64_PREL16:
|
||||
checkIntUInt(loc, val, 16, type);
|
||||
checkIntUInt(loc, val, 16, rel);
|
||||
write16le(loc, val);
|
||||
break;
|
||||
case R_AARCH64_ABS32:
|
||||
case R_AARCH64_PREL32:
|
||||
checkIntUInt(loc, val, 32, type);
|
||||
checkIntUInt(loc, val, 32, rel);
|
||||
write32le(loc, val);
|
||||
break;
|
||||
case R_AARCH64_ABS64:
|
||||
@ -335,13 +337,13 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
||||
case R_AARCH64_TLSDESC_ADR_PAGE21:
|
||||
checkInt(loc, val, 33, type);
|
||||
checkInt(loc, val, 33, rel);
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_AARCH64_ADR_PREL_PG_HI21_NC:
|
||||
write32AArch64Addr(loc, val >> 12);
|
||||
break;
|
||||
case R_AARCH64_ADR_PREL_LO21:
|
||||
checkInt(loc, val, 21, type);
|
||||
checkInt(loc, val, 21, rel);
|
||||
write32AArch64Addr(loc, val);
|
||||
break;
|
||||
case R_AARCH64_JUMP26:
|
||||
@ -355,13 +357,13 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
write32le(loc, 0x14000000);
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_AARCH64_CALL26:
|
||||
checkInt(loc, val, 28, type);
|
||||
checkInt(loc, val, 28, rel);
|
||||
or32le(loc, (val & 0x0FFFFFFC) >> 2);
|
||||
break;
|
||||
case R_AARCH64_CONDBR19:
|
||||
case R_AARCH64_LD_PREL_LO19:
|
||||
checkAlignment(loc, val, 4, type);
|
||||
checkInt(loc, val, 21, type);
|
||||
checkAlignment(loc, val, 4, rel);
|
||||
checkInt(loc, val, 21, rel);
|
||||
or32le(loc, (val & 0x1FFFFC) << 3);
|
||||
break;
|
||||
case R_AARCH64_LDST8_ABS_LO12_NC:
|
||||
@ -370,12 +372,12 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
break;
|
||||
case R_AARCH64_LDST16_ABS_LO12_NC:
|
||||
case R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
|
||||
checkAlignment(loc, val, 2, type);
|
||||
checkAlignment(loc, val, 2, rel);
|
||||
or32AArch64Imm(loc, getBits(val, 1, 11));
|
||||
break;
|
||||
case R_AARCH64_LDST32_ABS_LO12_NC:
|
||||
case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
|
||||
checkAlignment(loc, val, 4, type);
|
||||
checkAlignment(loc, val, 4, rel);
|
||||
or32AArch64Imm(loc, getBits(val, 2, 11));
|
||||
break;
|
||||
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||
@ -383,28 +385,28 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
||||
case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
|
||||
case R_AARCH64_TLSDESC_LD64_LO12:
|
||||
checkAlignment(loc, val, 8, type);
|
||||
checkAlignment(loc, val, 8, rel);
|
||||
or32AArch64Imm(loc, getBits(val, 3, 11));
|
||||
break;
|
||||
case R_AARCH64_LDST128_ABS_LO12_NC:
|
||||
case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC:
|
||||
checkAlignment(loc, val, 16, type);
|
||||
checkAlignment(loc, val, 16, rel);
|
||||
or32AArch64Imm(loc, getBits(val, 4, 11));
|
||||
break;
|
||||
case R_AARCH64_MOVW_UABS_G0:
|
||||
checkUInt(loc, val, 16, type);
|
||||
checkUInt(loc, val, 16, rel);
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_AARCH64_MOVW_UABS_G0_NC:
|
||||
or32le(loc, (val & 0xFFFF) << 5);
|
||||
break;
|
||||
case R_AARCH64_MOVW_UABS_G1:
|
||||
checkUInt(loc, val, 32, type);
|
||||
checkUInt(loc, val, 32, rel);
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_AARCH64_MOVW_UABS_G1_NC:
|
||||
or32le(loc, (val & 0xFFFF0000) >> 11);
|
||||
break;
|
||||
case R_AARCH64_MOVW_UABS_G2:
|
||||
checkUInt(loc, val, 48, type);
|
||||
checkUInt(loc, val, 48, rel);
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_AARCH64_MOVW_UABS_G2_NC:
|
||||
or32le(loc, (val & 0xFFFF00000000) >> 27);
|
||||
@ -415,7 +417,7 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_AARCH64_MOVW_PREL_G0:
|
||||
case R_AARCH64_MOVW_SABS_G0:
|
||||
case R_AARCH64_TLSLE_MOVW_TPREL_G0:
|
||||
checkInt(loc, val, 17, type);
|
||||
checkInt(loc, val, 17, rel);
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_AARCH64_MOVW_PREL_G0_NC:
|
||||
case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
|
||||
@ -424,7 +426,7 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_AARCH64_MOVW_PREL_G1:
|
||||
case R_AARCH64_MOVW_SABS_G1:
|
||||
case R_AARCH64_TLSLE_MOVW_TPREL_G1:
|
||||
checkInt(loc, val, 33, type);
|
||||
checkInt(loc, val, 33, rel);
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_AARCH64_MOVW_PREL_G1_NC:
|
||||
case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
|
||||
@ -433,7 +435,7 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_AARCH64_MOVW_PREL_G2:
|
||||
case R_AARCH64_MOVW_SABS_G2:
|
||||
case R_AARCH64_TLSLE_MOVW_TPREL_G2:
|
||||
checkInt(loc, val, 49, type);
|
||||
checkInt(loc, val, 49, rel);
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_AARCH64_MOVW_PREL_G2_NC:
|
||||
writeSMovWImm(loc, val >> 32);
|
||||
@ -442,11 +444,11 @@ void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
writeSMovWImm(loc, val >> 48);
|
||||
break;
|
||||
case R_AARCH64_TSTBR14:
|
||||
checkInt(loc, val, 16, type);
|
||||
checkInt(loc, val, 16, rel);
|
||||
or32le(loc, (val & 0xFFFC) << 3);
|
||||
break;
|
||||
case R_AARCH64_TLSLE_ADD_TPREL_HI12:
|
||||
checkUInt(loc, val, 24, type);
|
||||
checkUInt(loc, val, 24, rel);
|
||||
or32AArch64Imm(loc, val >> 12);
|
||||
break;
|
||||
case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|
||||
@ -471,7 +473,7 @@ void AArch64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
|
||||
// movk x0, #0x10
|
||||
// nop
|
||||
// nop
|
||||
checkUInt(loc, val, 32, rel.type);
|
||||
checkUInt(loc, val, 32, rel);
|
||||
|
||||
switch (rel.type) {
|
||||
case R_AARCH64_TLSDESC_ADD_LO12:
|
||||
@ -510,11 +512,11 @@ void AArch64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
|
||||
break;
|
||||
case R_AARCH64_TLSDESC_ADR_PAGE21:
|
||||
write32le(loc, 0x90000000); // adrp
|
||||
relocateOne(loc, R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, val);
|
||||
relocateNoSym(loc, R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, val);
|
||||
break;
|
||||
case R_AARCH64_TLSDESC_LD64_LO12:
|
||||
write32le(loc, 0xf9400000); // ldr
|
||||
relocateOne(loc, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, val);
|
||||
relocateNoSym(loc, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, val);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
|
||||
@ -523,7 +525,7 @@ void AArch64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
|
||||
|
||||
void AArch64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const {
|
||||
checkUInt(loc, val, 32, rel.type);
|
||||
checkUInt(loc, val, 32, rel);
|
||||
|
||||
if (rel.type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) {
|
||||
// Generate MOVZ.
|
||||
@ -633,10 +635,10 @@ void AArch64BtiPac::writePltHeader(uint8_t *buf) const {
|
||||
}
|
||||
memcpy(buf, pltData, sizeof(pltData));
|
||||
|
||||
relocateOne(buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
|
||||
getAArch64Page(got + 16) - getAArch64Page(plt + 8));
|
||||
relocateOne(buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, got + 16);
|
||||
relocateOne(buf + 12, R_AARCH64_ADD_ABS_LO12_NC, got + 16);
|
||||
relocateNoSym(buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
|
||||
getAArch64Page(got + 16) - getAArch64Page(plt + 8));
|
||||
relocateNoSym(buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, got + 16);
|
||||
relocateNoSym(buf + 12, R_AARCH64_ADD_ABS_LO12_NC, got + 16);
|
||||
if (!btiHeader)
|
||||
// We didn't add the BTI c instruction so round out size with NOP.
|
||||
memcpy(buf + sizeof(pltData), nopData, sizeof(nopData));
|
||||
@ -670,11 +672,10 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
|
||||
|
||||
uint64_t gotPltEntryAddr = sym.getGotPltVA();
|
||||
memcpy(buf, addrInst, sizeof(addrInst));
|
||||
relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21,
|
||||
getAArch64Page(gotPltEntryAddr) -
|
||||
getAArch64Page(pltEntryAddr));
|
||||
relocateOne(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr);
|
||||
relocateOne(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr);
|
||||
relocateNoSym(buf, R_AARCH64_ADR_PREL_PG_HI21,
|
||||
getAArch64Page(gotPltEntryAddr) - getAArch64Page(pltEntryAddr));
|
||||
relocateNoSym(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr);
|
||||
relocateNoSym(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr);
|
||||
|
||||
if (pacEntry)
|
||||
memcpy(buf + sizeof(addrInst), pacBr, sizeof(pacBr));
|
||||
|
@ -26,7 +26,8 @@ class AMDGPU final : public TargetInfo {
|
||||
public:
|
||||
AMDGPU();
|
||||
uint32_t calcEFlags() const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
RelExpr getRelExpr(RelType type, const Symbol &s,
|
||||
const uint8_t *loc) const override;
|
||||
RelType getDynRel(RelType type) const override;
|
||||
@ -58,8 +59,8 @@ uint32_t AMDGPU::calcEFlags() const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AMDGPU::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
switch (type) {
|
||||
void AMDGPU::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
|
||||
switch (rel.type) {
|
||||
case R_AMDGPU_ABS32:
|
||||
case R_AMDGPU_GOTPCREL:
|
||||
case R_AMDGPU_GOTPCREL32_LO:
|
||||
|
@ -43,7 +43,8 @@ public:
|
||||
int64_t a) const override;
|
||||
uint32_t getThunkSectionSpacing() const override;
|
||||
bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@ -375,8 +376,8 @@ bool ARM::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
|
||||
return distance <= range;
|
||||
}
|
||||
|
||||
void ARM::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
switch (type) {
|
||||
void ARM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
|
||||
switch (rel.type) {
|
||||
case R_ARM_ABS32:
|
||||
case R_ARM_BASE_PREL:
|
||||
case R_ARM_GOTOFF32:
|
||||
@ -397,7 +398,7 @@ void ARM::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
write32le(loc, val);
|
||||
break;
|
||||
case R_ARM_PREL31:
|
||||
checkInt(loc, val, 31, type);
|
||||
checkInt(loc, val, 31, rel);
|
||||
write32le(loc, (read32le(loc) & 0x80000000) | (val & ~0x80000000));
|
||||
break;
|
||||
case R_ARM_CALL:
|
||||
@ -406,7 +407,7 @@ void ARM::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
if (val & 1) {
|
||||
// If bit 0 of Val is 1 the target is Thumb, we must select a BLX.
|
||||
// The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1'
|
||||
checkInt(loc, val, 26, type);
|
||||
checkInt(loc, val, 26, rel);
|
||||
write32le(loc, 0xfa000000 | // opcode
|
||||
((val & 2) << 23) | // H
|
||||
((val >> 2) & 0x00ffffff)); // imm24
|
||||
@ -421,16 +422,16 @@ void ARM::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_ARM_JUMP24:
|
||||
case R_ARM_PC24:
|
||||
case R_ARM_PLT32:
|
||||
checkInt(loc, val, 26, type);
|
||||
checkInt(loc, val, 26, rel);
|
||||
write32le(loc, (read32le(loc) & ~0x00ffffff) | ((val >> 2) & 0x00ffffff));
|
||||
break;
|
||||
case R_ARM_THM_JUMP11:
|
||||
checkInt(loc, val, 12, type);
|
||||
checkInt(loc, val, 12, rel);
|
||||
write16le(loc, (read32le(loc) & 0xf800) | ((val >> 1) & 0x07ff));
|
||||
break;
|
||||
case R_ARM_THM_JUMP19:
|
||||
// Encoding T3: Val = S:J2:J1:imm6:imm11:0
|
||||
checkInt(loc, val, 21, type);
|
||||
checkInt(loc, val, 21, rel);
|
||||
write16le(loc,
|
||||
(read16le(loc) & 0xfbc0) | // opcode cond
|
||||
((val >> 10) & 0x0400) | // S
|
||||
@ -454,7 +455,7 @@ void ARM::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
if (!config->armJ1J2BranchEncoding) {
|
||||
// Older Arm architectures do not support R_ARM_THM_JUMP24 and have
|
||||
// different encoding rules and range due to J1 and J2 always being 1.
|
||||
checkInt(loc, val, 23, type);
|
||||
checkInt(loc, val, 23, rel);
|
||||
write16le(loc,
|
||||
0xf000 | // opcode
|
||||
((val >> 12) & 0x07ff)); // imm11
|
||||
@ -468,7 +469,7 @@ void ARM::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_ARM_THM_JUMP24:
|
||||
// Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0
|
||||
checkInt(loc, val, 25, type);
|
||||
checkInt(loc, val, 25, rel);
|
||||
write16le(loc,
|
||||
0xf000 | // opcode
|
||||
((val >> 14) & 0x0400) | // S
|
||||
@ -514,7 +515,8 @@ void ARM::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
(val & 0x00ff)); // imm8
|
||||
break;
|
||||
default:
|
||||
error(getErrorLocation(loc) + "unrecognized relocation " + toString(type));
|
||||
error(getErrorLocation(loc) + "unrecognized relocation " +
|
||||
toString(rel.type));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,8 @@ public:
|
||||
AVR();
|
||||
RelExpr getRelExpr(RelType type, const Symbol &s,
|
||||
const uint8_t *loc) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@ -57,8 +58,8 @@ RelExpr AVR::getRelExpr(RelType type, const Symbol &s,
|
||||
return R_ABS;
|
||||
}
|
||||
|
||||
void AVR::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
switch (type) {
|
||||
void AVR::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
|
||||
switch (rel.type) {
|
||||
case R_AVR_CALL: {
|
||||
uint16_t hi = val >> 17;
|
||||
uint16_t lo = val >> 1;
|
||||
@ -67,7 +68,8 @@ void AVR::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error(getErrorLocation(loc) + "unrecognized relocation " + toString(type));
|
||||
error(getErrorLocation(loc) + "unrecognized relocation " +
|
||||
toString(rel.type));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,8 @@ public:
|
||||
RelExpr getRelExpr(RelType type, const Symbol &s,
|
||||
const uint8_t *loc) const override;
|
||||
RelType getDynRel(RelType type) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
void writePltHeader(uint8_t *buf) const override;
|
||||
void writePlt(uint8_t *buf, const Symbol &sym,
|
||||
uint64_t pltEntryAddr) const override;
|
||||
@ -229,8 +230,9 @@ static uint32_t findMaskR16(uint32_t insn) {
|
||||
|
||||
static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); }
|
||||
|
||||
void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
switch (type) {
|
||||
void Hexagon::relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const {
|
||||
switch (rel.type) {
|
||||
case R_HEX_NONE:
|
||||
break;
|
||||
case R_HEX_6_PCREL_X:
|
||||
@ -284,18 +286,18 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
or32le(loc, applyMask(0x0fff3fff, val >> 6));
|
||||
break;
|
||||
case R_HEX_B9_PCREL:
|
||||
checkInt(loc, val, 11, type);
|
||||
checkInt(loc, val, 11, rel);
|
||||
or32le(loc, applyMask(0x003000fe, val >> 2));
|
||||
break;
|
||||
case R_HEX_B9_PCREL_X:
|
||||
or32le(loc, applyMask(0x003000fe, val & 0x3f));
|
||||
break;
|
||||
case R_HEX_B13_PCREL:
|
||||
checkInt(loc, val, 15, type);
|
||||
checkInt(loc, val, 15, rel);
|
||||
or32le(loc, applyMask(0x00202ffe, val >> 2));
|
||||
break;
|
||||
case R_HEX_B15_PCREL:
|
||||
checkInt(loc, val, 17, type);
|
||||
checkInt(loc, val, 17, rel);
|
||||
or32le(loc, applyMask(0x00df20fe, val >> 2));
|
||||
break;
|
||||
case R_HEX_B15_PCREL_X:
|
||||
@ -303,7 +305,7 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
break;
|
||||
case R_HEX_B22_PCREL:
|
||||
case R_HEX_PLT_B22_PCREL:
|
||||
checkInt(loc, val, 22, type);
|
||||
checkInt(loc, val, 22, rel);
|
||||
or32le(loc, applyMask(0x1ff3ffe, val >> 2));
|
||||
break;
|
||||
case R_HEX_B22_PCREL_X:
|
||||
@ -346,8 +348,8 @@ void Hexagon::writePltHeader(uint8_t *buf) const {
|
||||
|
||||
// Offset from PLT0 to the GOT.
|
||||
uint64_t off = in.gotPlt->getVA() - in.plt->getVA();
|
||||
relocateOne(buf, R_HEX_B32_PCREL_X, off);
|
||||
relocateOne(buf + 4, R_HEX_6_PCREL_X, off);
|
||||
relocateNoSym(buf, R_HEX_B32_PCREL_X, off);
|
||||
relocateNoSym(buf + 4, R_HEX_6_PCREL_X, off);
|
||||
}
|
||||
|
||||
void Hexagon::writePlt(uint8_t *buf, const Symbol &sym,
|
||||
@ -361,8 +363,8 @@ void Hexagon::writePlt(uint8_t *buf, const Symbol &sym,
|
||||
memcpy(buf, inst, sizeof(inst));
|
||||
|
||||
uint64_t gotPltEntryAddr = sym.getGotPltVA();
|
||||
relocateOne(buf, R_HEX_B32_PCREL_X, gotPltEntryAddr - pltEntryAddr);
|
||||
relocateOne(buf + 4, R_HEX_6_PCREL_X, gotPltEntryAddr - pltEntryAddr);
|
||||
relocateNoSym(buf, R_HEX_B32_PCREL_X, gotPltEntryAddr - pltEntryAddr);
|
||||
relocateNoSym(buf + 4, R_HEX_6_PCREL_X, gotPltEntryAddr - pltEntryAddr);
|
||||
}
|
||||
|
||||
RelType Hexagon::getDynRel(RelType type) const {
|
||||
|
@ -36,7 +36,8 @@ public:
|
||||
MSP430();
|
||||
RelExpr getRelExpr(RelType type, const Symbol &s,
|
||||
const uint8_t *loc) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@ -60,31 +61,32 @@ RelExpr MSP430::getRelExpr(RelType type, const Symbol &s,
|
||||
}
|
||||
}
|
||||
|
||||
void MSP430::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
switch (type) {
|
||||
void MSP430::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
|
||||
switch (rel.type) {
|
||||
case R_MSP430_8:
|
||||
checkIntUInt(loc, val, 8, type);
|
||||
checkIntUInt(loc, val, 8, rel);
|
||||
*loc = val;
|
||||
break;
|
||||
case R_MSP430_16:
|
||||
case R_MSP430_16_PCREL:
|
||||
case R_MSP430_16_BYTE:
|
||||
case R_MSP430_16_PCREL_BYTE:
|
||||
checkIntUInt(loc, val, 16, type);
|
||||
checkIntUInt(loc, val, 16, rel);
|
||||
write16le(loc, val);
|
||||
break;
|
||||
case R_MSP430_32:
|
||||
checkIntUInt(loc, val, 32, type);
|
||||
checkIntUInt(loc, val, 32, rel);
|
||||
write32le(loc, val);
|
||||
break;
|
||||
case R_MSP430_10_PCREL: {
|
||||
int16_t offset = ((int16_t)val >> 1) - 1;
|
||||
checkInt(loc, offset, 10, type);
|
||||
checkInt(loc, offset, 10, rel);
|
||||
write16le(loc, (read16le(loc) & 0xFC00) | (offset & 0x3FF));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error(getErrorLocation(loc) + "unrecognized relocation " + toString(type));
|
||||
error(getErrorLocation(loc) + "unrecognized relocation " +
|
||||
toString(rel.type));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,8 @@ public:
|
||||
bool needsThunk(RelExpr expr, RelType type, const InputFile *file,
|
||||
uint64_t branchAddr, const Symbol &s,
|
||||
int64_t a) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
bool usesOnlyLowPageBits(RelType type) const override;
|
||||
};
|
||||
} // namespace
|
||||
@ -274,12 +275,12 @@ template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *buf) const {
|
||||
write16(buf + 18, 0x0f83); // move $28, $3
|
||||
write16(buf + 20, 0x472b); // jalrc $25
|
||||
write16(buf + 22, 0x0c00); // nop
|
||||
relocateOne(buf, R_MICROMIPS_PC19_S2, gotPlt - plt);
|
||||
relocateNoSym(buf, R_MICROMIPS_PC19_S2, gotPlt - plt);
|
||||
} else {
|
||||
write16(buf + 18, 0x45f9); // jalrc $25
|
||||
write16(buf + 20, 0x0f83); // move $28, $3
|
||||
write16(buf + 22, 0x0c00); // nop
|
||||
relocateOne(buf, R_MICROMIPS_PC23_S2, gotPlt - plt);
|
||||
relocateNoSym(buf, R_MICROMIPS_PC23_S2, gotPlt - plt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -330,13 +331,13 @@ void MIPS<ELFT>::writePlt(uint8_t *buf, const Symbol &sym,
|
||||
write16(buf + 4, 0xff22); // lw $25, 0($2)
|
||||
write16(buf + 8, 0x0f02); // move $24, $2
|
||||
write16(buf + 10, 0x4723); // jrc $25 / jr16 $25
|
||||
relocateOne(buf, R_MICROMIPS_PC19_S2, gotPltEntryAddr - pltEntryAddr);
|
||||
relocateNoSym(buf, R_MICROMIPS_PC19_S2, gotPltEntryAddr - pltEntryAddr);
|
||||
} else {
|
||||
write16(buf, 0x7900); // addiupc $2, (GOTPLT) - .
|
||||
write16(buf + 4, 0xff22); // lw $25, 0($2)
|
||||
write16(buf + 8, 0x4599); // jrc $25 / jr16 $25
|
||||
write16(buf + 10, 0x0f02); // move $24, $2
|
||||
relocateOne(buf, R_MICROMIPS_PC23_S2, gotPltEntryAddr - pltEntryAddr);
|
||||
relocateNoSym(buf, R_MICROMIPS_PC23_S2, gotPltEntryAddr - pltEntryAddr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -537,8 +538,10 @@ static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) {
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
void MIPS<ELFT>::relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const {
|
||||
const endianness e = ELFT::TargetEndianness;
|
||||
RelType type = rel.type;
|
||||
|
||||
if (ELFT::Is64Bits || config->mipsN32Abi)
|
||||
std::tie(type, val) = calculateMipsRelChain(loc, type, val);
|
||||
@ -577,7 +580,7 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
if (config->relocatable) {
|
||||
writeValue(loc, val + 0x8000, 16, 16);
|
||||
} else {
|
||||
checkInt(loc, val, 16, type);
|
||||
checkInt(loc, val, 16, rel);
|
||||
writeValue(loc, val, 16, 0);
|
||||
}
|
||||
break;
|
||||
@ -585,7 +588,7 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
if (config->relocatable) {
|
||||
writeShuffleValue<e>(loc, val + 0x8000, 16, 16);
|
||||
} else {
|
||||
checkInt(loc, val, 16, type);
|
||||
checkInt(loc, val, 16, rel);
|
||||
writeShuffleValue<e>(loc, val, 16, 0);
|
||||
}
|
||||
break;
|
||||
@ -596,7 +599,7 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_MIPS_TLS_GD:
|
||||
case R_MIPS_TLS_GOTTPREL:
|
||||
case R_MIPS_TLS_LDM:
|
||||
checkInt(loc, val, 16, type);
|
||||
checkInt(loc, val, 16, rel);
|
||||
LLVM_FALLTHROUGH;
|
||||
case R_MIPS_CALL_LO16:
|
||||
case R_MIPS_GOT_LO16:
|
||||
@ -610,7 +613,7 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_MICROMIPS_GPREL16:
|
||||
case R_MICROMIPS_TLS_GD:
|
||||
case R_MICROMIPS_TLS_LDM:
|
||||
checkInt(loc, val, 16, type);
|
||||
checkInt(loc, val, 16, rel);
|
||||
writeShuffleValue<e>(loc, val, 16, 0);
|
||||
break;
|
||||
case R_MICROMIPS_CALL16:
|
||||
@ -622,7 +625,7 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
writeShuffleValue<e>(loc, val, 16, 0);
|
||||
break;
|
||||
case R_MICROMIPS_GPREL7_S2:
|
||||
checkInt(loc, val, 7, type);
|
||||
checkInt(loc, val, 7, rel);
|
||||
writeShuffleValue<e>(loc, val, 7, 2);
|
||||
break;
|
||||
case R_MIPS_CALL_HI16:
|
||||
@ -665,23 +668,23 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
// Ignore this optimization relocation for now
|
||||
break;
|
||||
case R_MIPS_PC16:
|
||||
checkAlignment(loc, val, 4, type);
|
||||
checkInt(loc, val, 18, type);
|
||||
checkAlignment(loc, val, 4, rel);
|
||||
checkInt(loc, val, 18, rel);
|
||||
writeValue(loc, val, 16, 2);
|
||||
break;
|
||||
case R_MIPS_PC19_S2:
|
||||
checkAlignment(loc, val, 4, type);
|
||||
checkInt(loc, val, 21, type);
|
||||
checkAlignment(loc, val, 4, rel);
|
||||
checkInt(loc, val, 21, rel);
|
||||
writeValue(loc, val, 19, 2);
|
||||
break;
|
||||
case R_MIPS_PC21_S2:
|
||||
checkAlignment(loc, val, 4, type);
|
||||
checkInt(loc, val, 23, type);
|
||||
checkAlignment(loc, val, 4, rel);
|
||||
checkInt(loc, val, 23, rel);
|
||||
writeValue(loc, val, 21, 2);
|
||||
break;
|
||||
case R_MIPS_PC26_S2:
|
||||
checkAlignment(loc, val, 4, type);
|
||||
checkInt(loc, val, 28, type);
|
||||
checkAlignment(loc, val, 4, rel);
|
||||
checkInt(loc, val, 28, rel);
|
||||
writeValue(loc, val, 26, 2);
|
||||
break;
|
||||
case R_MIPS_PC32:
|
||||
@ -689,35 +692,35 @@ void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
break;
|
||||
case R_MICROMIPS_26_S1:
|
||||
case R_MICROMIPS_PC26_S1:
|
||||
checkInt(loc, val, 27, type);
|
||||
checkInt(loc, val, 27, rel);
|
||||
writeShuffleValue<e>(loc, val, 26, 1);
|
||||
break;
|
||||
case R_MICROMIPS_PC7_S1:
|
||||
checkInt(loc, val, 8, type);
|
||||
checkInt(loc, val, 8, rel);
|
||||
writeMicroRelocation16<e>(loc, val, 7, 1);
|
||||
break;
|
||||
case R_MICROMIPS_PC10_S1:
|
||||
checkInt(loc, val, 11, type);
|
||||
checkInt(loc, val, 11, rel);
|
||||
writeMicroRelocation16<e>(loc, val, 10, 1);
|
||||
break;
|
||||
case R_MICROMIPS_PC16_S1:
|
||||
checkInt(loc, val, 17, type);
|
||||
checkInt(loc, val, 17, rel);
|
||||
writeShuffleValue<e>(loc, val, 16, 1);
|
||||
break;
|
||||
case R_MICROMIPS_PC18_S3:
|
||||
checkInt(loc, val, 21, type);
|
||||
checkInt(loc, val, 21, rel);
|
||||
writeShuffleValue<e>(loc, val, 18, 3);
|
||||
break;
|
||||
case R_MICROMIPS_PC19_S2:
|
||||
checkInt(loc, val, 21, type);
|
||||
checkInt(loc, val, 21, rel);
|
||||
writeShuffleValue<e>(loc, val, 19, 2);
|
||||
break;
|
||||
case R_MICROMIPS_PC21_S1:
|
||||
checkInt(loc, val, 22, type);
|
||||
checkInt(loc, val, 22, rel);
|
||||
writeShuffleValue<e>(loc, val, 21, 1);
|
||||
break;
|
||||
case R_MICROMIPS_PC23_S2:
|
||||
checkInt(loc, val, 25, type);
|
||||
checkInt(loc, val, 25, rel);
|
||||
writeShuffleValue<e>(loc, val, 23, 2);
|
||||
break;
|
||||
default:
|
||||
|
@ -44,7 +44,8 @@ public:
|
||||
int64_t a) const override;
|
||||
uint32_t getThunkSectionSpacing() const override;
|
||||
bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
|
||||
RelExpr expr) const override;
|
||||
int getTlsGdRelaxSkip(RelType type) const override;
|
||||
@ -282,12 +283,12 @@ static std::pair<RelType, uint64_t> fromDTPREL(RelType type, uint64_t val) {
|
||||
}
|
||||
}
|
||||
|
||||
void PPC::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
void PPC::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
|
||||
RelType newType;
|
||||
std::tie(newType, val) = fromDTPREL(type, val);
|
||||
std::tie(newType, val) = fromDTPREL(rel.type, val);
|
||||
switch (newType) {
|
||||
case R_PPC_ADDR16:
|
||||
checkIntUInt(loc, val, 16, type);
|
||||
checkIntUInt(loc, val, 16, rel);
|
||||
write16(loc, val);
|
||||
break;
|
||||
case R_PPC_GOT16:
|
||||
@ -295,7 +296,7 @@ void PPC::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_PPC_GOT_TLSLD16:
|
||||
case R_PPC_GOT_TPREL16:
|
||||
case R_PPC_TPREL16:
|
||||
checkInt(loc, val, 16, type);
|
||||
checkInt(loc, val, 16, rel);
|
||||
write16(loc, val);
|
||||
break;
|
||||
case R_PPC_ADDR16_HA:
|
||||
@ -331,8 +332,8 @@ void PPC::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
break;
|
||||
case R_PPC_REL14: {
|
||||
uint32_t mask = 0x0000FFFC;
|
||||
checkInt(loc, val, 16, type);
|
||||
checkAlignment(loc, val, 4, type);
|
||||
checkInt(loc, val, 16, rel);
|
||||
checkAlignment(loc, val, 4, rel);
|
||||
write32(loc, (read32(loc) & ~mask) | (val & mask));
|
||||
break;
|
||||
}
|
||||
@ -340,8 +341,8 @@ void PPC::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_PPC_LOCAL24PC:
|
||||
case R_PPC_PLTREL24: {
|
||||
uint32_t mask = 0x03FFFFFC;
|
||||
checkInt(loc, val, 26, type);
|
||||
checkAlignment(loc, val, 4, type);
|
||||
checkInt(loc, val, 26, rel);
|
||||
checkAlignment(loc, val, 4, rel);
|
||||
write32(loc, (read32(loc) & ~mask) | (val & mask));
|
||||
break;
|
||||
}
|
||||
@ -380,7 +381,7 @@ void PPC::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
|
||||
// addi rT, rA, x@got@tlsgd --> lwz rT, x@got@tprel(rA)
|
||||
uint32_t insn = readFromHalf16(loc);
|
||||
writeFromHalf16(loc, 0x80000000 | (insn & 0x03ff0000));
|
||||
relocateOne(loc, R_PPC_GOT_TPREL16, val);
|
||||
relocateNoSym(loc, R_PPC_GOT_TPREL16, val);
|
||||
break;
|
||||
}
|
||||
case R_PPC_TLSGD:
|
||||
@ -425,7 +426,7 @@ void PPC::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
|
||||
case R_PPC_DTPREL16_HA:
|
||||
case R_PPC_DTPREL16_HI:
|
||||
case R_PPC_DTPREL16_LO:
|
||||
relocateOne(loc, rel.type, val);
|
||||
relocate(loc, rel, val);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
|
||||
|
@ -185,7 +185,7 @@ bool tryRelaxPPC64TocIndirection(const Relocation &rel, uint8_t *bufLoc) {
|
||||
if (!isInt<32>(tocRelative))
|
||||
return false;
|
||||
|
||||
// Add PPC64TocOffset that will be subtracted by relocateOne().
|
||||
// Add PPC64TocOffset that will be subtracted by PPC64::relocate().
|
||||
target->relaxGot(bufLoc, rel, tocRelative + ppc64TocOffset);
|
||||
return true;
|
||||
}
|
||||
@ -204,7 +204,8 @@ public:
|
||||
uint64_t pltEntryAddr) const override;
|
||||
void writeIplt(uint8_t *buf, const Symbol &sym,
|
||||
uint64_t pltEntryAddr) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
void writeGotHeader(uint8_t *buf) const override;
|
||||
bool needsThunk(RelExpr expr, RelType type, const InputFile *file,
|
||||
uint64_t branchAddr, const Symbol &s,
|
||||
@ -373,7 +374,7 @@ 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, rel.type, val);
|
||||
relocate(loc, rel, val);
|
||||
break;
|
||||
case R_PPC64_TOC16_LO_DS: {
|
||||
// Convert "ld reg, .LC0@toc@l(reg)" to "addi reg, reg, var@toc@l" or
|
||||
@ -382,7 +383,7 @@ void PPC64::relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const {
|
||||
if (getPrimaryOpCode(insn) != LD)
|
||||
error("expected a 'ld' for got-indirect to toc-relative relaxing");
|
||||
writeFromHalf16(loc, (insn & 0x03ffffff) | 0x38000000);
|
||||
relocateOne(loc, R_PPC64_TOC16_LO, val);
|
||||
relocateNoSym(loc, R_PPC64_TOC16_LO, val);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -414,7 +415,7 @@ void PPC64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
|
||||
case R_PPC64_GOT_TLSGD16:
|
||||
case R_PPC64_GOT_TLSGD16_LO:
|
||||
writeFromHalf16(loc, 0x3c6d0000); // addis r3, r13
|
||||
relocateOne(loc, R_PPC64_TPREL16_HA, val);
|
||||
relocateNoSym(loc, R_PPC64_TPREL16_HA, val);
|
||||
break;
|
||||
case R_PPC64_TLSGD:
|
||||
write32(loc, 0x60000000); // nop
|
||||
@ -422,8 +423,8 @@ void PPC64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
|
||||
// Since we are relocating a half16 type relocation and Loc + 4 points to
|
||||
// the start of an instruction we need to advance the buffer by an extra
|
||||
// 2 bytes on BE.
|
||||
relocateOne(loc + 4 + (config->ekind == ELF64BEKind ? 2 : 0),
|
||||
R_PPC64_TPREL16_LO, val);
|
||||
relocateNoSym(loc + 4 + (config->ekind == ELF64BEKind ? 2 : 0),
|
||||
R_PPC64_TPREL16_LO, val);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
|
||||
@ -464,7 +465,7 @@ void PPC64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
|
||||
case R_PPC64_DTPREL16_DS:
|
||||
case R_PPC64_DTPREL16_LO:
|
||||
case R_PPC64_DTPREL16_LO_DS:
|
||||
relocateOne(loc, rel.type, val);
|
||||
relocate(loc, rel, val);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
|
||||
@ -526,7 +527,7 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
|
||||
case R_PPC64_GOT_TPREL16_DS: {
|
||||
uint32_t regNo = read32(loc - offset) & 0x03E00000; // bits 6-10
|
||||
write32(loc - offset, 0x3C0D0000 | regNo); // addis RegNo, r13
|
||||
relocateOne(loc, R_PPC64_TPREL16_HA, val);
|
||||
relocateNoSym(loc, R_PPC64_TPREL16_HA, val);
|
||||
break;
|
||||
}
|
||||
case R_PPC64_TLS: {
|
||||
@ -538,7 +539,7 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
|
||||
if (dFormOp == 0)
|
||||
error("unrecognized instruction for IE to LE R_PPC64_TLS");
|
||||
write32(loc, ((dFormOp << 26) | (read32(loc) & 0x03FFFFFF)));
|
||||
relocateOne(loc + offset, R_PPC64_TPREL16_LO, val);
|
||||
relocateNoSym(loc + offset, R_PPC64_TPREL16_LO, val);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -777,11 +778,8 @@ static bool isTocOptType(RelType type) {
|
||||
}
|
||||
}
|
||||
|
||||
void PPC64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
// We need to save the original relocation type to use in diagnostics, and
|
||||
// use the original type to determine if we should toc-optimize the
|
||||
// instructions being relocated.
|
||||
RelType originalType = type;
|
||||
void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
|
||||
RelType type = rel.type;
|
||||
bool shouldTocOptimize = isTocOptType(type);
|
||||
// For dynamic thread pointer relative, toc-relative, and got-indirect
|
||||
// relocations, proceed in terms of the corresponding ADDR16 relocation type.
|
||||
@ -789,27 +787,27 @@ void PPC64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
|
||||
switch (type) {
|
||||
case R_PPC64_ADDR14: {
|
||||
checkAlignment(loc, val, 4, type);
|
||||
checkAlignment(loc, val, 4, rel);
|
||||
// Preserve the AA/LK bits in the branch instruction
|
||||
uint8_t aalk = loc[3];
|
||||
write16(loc + 2, (aalk & 3) | (val & 0xfffc));
|
||||
break;
|
||||
}
|
||||
case R_PPC64_ADDR16:
|
||||
checkIntUInt(loc, val, 16, originalType);
|
||||
checkIntUInt(loc, val, 16, rel);
|
||||
write16(loc, val);
|
||||
break;
|
||||
case R_PPC64_ADDR32:
|
||||
checkIntUInt(loc, val, 32, originalType);
|
||||
checkIntUInt(loc, val, 32, rel);
|
||||
write32(loc, val);
|
||||
break;
|
||||
case R_PPC64_ADDR16_DS:
|
||||
case R_PPC64_TPREL16_DS: {
|
||||
checkInt(loc, val, 16, originalType);
|
||||
checkInt(loc, val, 16, rel);
|
||||
// DQ-form instructions use bits 28-31 as part of the instruction encoding
|
||||
// DS-form instructions only use bits 30-31.
|
||||
uint16_t mask = isDQFormInstruction(readFromHalf16(loc)) ? 0xf : 0x3;
|
||||
checkAlignment(loc, lo(val), mask + 1, originalType);
|
||||
checkAlignment(loc, lo(val), mask + 1, rel);
|
||||
write16(loc, (read16(loc) & mask) | lo(val));
|
||||
} break;
|
||||
case R_PPC64_ADDR16_HA:
|
||||
@ -864,7 +862,7 @@ void PPC64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
// DS-form instructions only use bits 30-31.
|
||||
uint32_t insn = readFromHalf16(loc);
|
||||
uint16_t mask = isDQFormInstruction(insn) ? 0xf : 0x3;
|
||||
checkAlignment(loc, lo(val), mask + 1, originalType);
|
||||
checkAlignment(loc, lo(val), mask + 1, rel);
|
||||
if (config->tocOptimize && shouldTocOptimize && ha(val) == 0) {
|
||||
// When the high-adjusted part of a toc relocation evaluates to 0, it is
|
||||
// changed into a nop. The lo part then needs to be updated to use the toc
|
||||
@ -880,11 +878,11 @@ void PPC64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
}
|
||||
} break;
|
||||
case R_PPC64_TPREL16:
|
||||
checkInt(loc, val, 16, originalType);
|
||||
checkInt(loc, val, 16, rel);
|
||||
write16(loc, val);
|
||||
break;
|
||||
case R_PPC64_REL32:
|
||||
checkInt(loc, val, 32, type);
|
||||
checkInt(loc, val, 32, rel);
|
||||
write32(loc, val);
|
||||
break;
|
||||
case R_PPC64_ADDR64:
|
||||
@ -894,15 +892,15 @@ void PPC64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
break;
|
||||
case R_PPC64_REL14: {
|
||||
uint32_t mask = 0x0000FFFC;
|
||||
checkInt(loc, val, 16, type);
|
||||
checkAlignment(loc, val, 4, type);
|
||||
checkInt(loc, val, 16, rel);
|
||||
checkAlignment(loc, val, 4, rel);
|
||||
write32(loc, (read32(loc) & ~mask) | (val & mask));
|
||||
break;
|
||||
}
|
||||
case R_PPC64_REL24: {
|
||||
uint32_t mask = 0x03FFFFFC;
|
||||
checkInt(loc, val, 26, type);
|
||||
checkAlignment(loc, val, 4, type);
|
||||
checkInt(loc, val, 26, rel);
|
||||
checkAlignment(loc, val, 4, rel);
|
||||
write32(loc, (read32(loc) & ~mask) | (val & mask));
|
||||
break;
|
||||
}
|
||||
@ -985,7 +983,7 @@ void PPC64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
|
||||
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.
|
||||
relocateOne(loc, R_PPC64_GOT_TPREL16_HA, val);
|
||||
relocateNoSym(loc, R_PPC64_GOT_TPREL16_HA, val);
|
||||
return;
|
||||
case R_PPC64_GOT_TLSGD16:
|
||||
case R_PPC64_GOT_TLSGD16_LO: {
|
||||
@ -993,7 +991,7 @@ void PPC64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
|
||||
// ld r3, sym@got@tprel@l(rA)
|
||||
uint32_t ra = (readFromHalf16(loc) & (0x1f << 16));
|
||||
writeFromHalf16(loc, 0xe8600000 | ra);
|
||||
relocateOne(loc, R_PPC64_GOT_TPREL16_LO_DS, val);
|
||||
relocateNoSym(loc, R_PPC64_GOT_TPREL16_LO_DS, val);
|
||||
return;
|
||||
}
|
||||
case R_PPC64_TLSGD:
|
||||
|
@ -33,7 +33,8 @@ public:
|
||||
RelType getDynRel(RelType type) const override;
|
||||
RelExpr getRelExpr(RelType type, const Symbol &s,
|
||||
const uint8_t *loc) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
@ -257,11 +258,10 @@ static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
|
||||
return (v & ((1ULL << (begin + 1)) - 1)) >> end;
|
||||
}
|
||||
|
||||
void RISCV::relocateOne(uint8_t *loc, const RelType type,
|
||||
const uint64_t val) const {
|
||||
void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
|
||||
const unsigned bits = config->wordsize * 8;
|
||||
|
||||
switch (type) {
|
||||
switch (rel.type) {
|
||||
case R_RISCV_32:
|
||||
write32le(loc, val);
|
||||
return;
|
||||
@ -270,8 +270,8 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type,
|
||||
return;
|
||||
|
||||
case R_RISCV_RVC_BRANCH: {
|
||||
checkInt(loc, static_cast<int64_t>(val) >> 1, 8, type);
|
||||
checkAlignment(loc, val, 2, type);
|
||||
checkInt(loc, static_cast<int64_t>(val) >> 1, 8, rel);
|
||||
checkAlignment(loc, val, 2, rel);
|
||||
uint16_t insn = read16le(loc) & 0xE383;
|
||||
uint16_t imm8 = extractBits(val, 8, 8) << 12;
|
||||
uint16_t imm4_3 = extractBits(val, 4, 3) << 10;
|
||||
@ -285,8 +285,8 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type,
|
||||
}
|
||||
|
||||
case R_RISCV_RVC_JUMP: {
|
||||
checkInt(loc, static_cast<int64_t>(val) >> 1, 11, type);
|
||||
checkAlignment(loc, val, 2, type);
|
||||
checkInt(loc, static_cast<int64_t>(val) >> 1, 11, rel);
|
||||
checkAlignment(loc, val, 2, rel);
|
||||
uint16_t insn = read16le(loc) & 0xE003;
|
||||
uint16_t imm11 = extractBits(val, 11, 11) << 12;
|
||||
uint16_t imm4 = extractBits(val, 4, 4) << 11;
|
||||
@ -304,7 +304,7 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type,
|
||||
|
||||
case R_RISCV_RVC_LUI: {
|
||||
int64_t imm = SignExtend64(val + 0x800, bits) >> 12;
|
||||
checkInt(loc, imm, 6, type);
|
||||
checkInt(loc, imm, 6, rel);
|
||||
if (imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0`
|
||||
write16le(loc, (read16le(loc) & 0x0F83) | 0x4000);
|
||||
} else {
|
||||
@ -316,8 +316,8 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type,
|
||||
}
|
||||
|
||||
case R_RISCV_JAL: {
|
||||
checkInt(loc, static_cast<int64_t>(val) >> 1, 20, type);
|
||||
checkAlignment(loc, val, 2, type);
|
||||
checkInt(loc, static_cast<int64_t>(val) >> 1, 20, rel);
|
||||
checkAlignment(loc, val, 2, rel);
|
||||
|
||||
uint32_t insn = read32le(loc) & 0xFFF;
|
||||
uint32_t imm20 = extractBits(val, 20, 20) << 31;
|
||||
@ -331,8 +331,8 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type,
|
||||
}
|
||||
|
||||
case R_RISCV_BRANCH: {
|
||||
checkInt(loc, static_cast<int64_t>(val) >> 1, 12, type);
|
||||
checkAlignment(loc, val, 2, type);
|
||||
checkInt(loc, static_cast<int64_t>(val) >> 1, 12, rel);
|
||||
checkAlignment(loc, val, 2, rel);
|
||||
|
||||
uint32_t insn = read32le(loc) & 0x1FFF07F;
|
||||
uint32_t imm12 = extractBits(val, 12, 12) << 31;
|
||||
@ -349,10 +349,10 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type,
|
||||
case R_RISCV_CALL:
|
||||
case R_RISCV_CALL_PLT: {
|
||||
int64_t hi = SignExtend64(val + 0x800, bits) >> 12;
|
||||
checkInt(loc, hi, 20, type);
|
||||
checkInt(loc, hi, 20, rel);
|
||||
if (isInt<20>(hi)) {
|
||||
relocateOne(loc, R_RISCV_PCREL_HI20, val);
|
||||
relocateOne(loc + 4, R_RISCV_PCREL_LO12_I, val);
|
||||
relocateNoSym(loc, R_RISCV_PCREL_HI20, val);
|
||||
relocateNoSym(loc + 4, R_RISCV_PCREL_LO12_I, val);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -364,7 +364,7 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type,
|
||||
case R_RISCV_TPREL_HI20:
|
||||
case R_RISCV_HI20: {
|
||||
uint64_t hi = val + 0x800;
|
||||
checkInt(loc, SignExtend64(hi, bits) >> 12, 20, type);
|
||||
checkInt(loc, SignExtend64(hi, bits) >> 12, 20, rel);
|
||||
write32le(loc, (read32le(loc) & 0xFFF) | (hi & 0xFFFFF000));
|
||||
return;
|
||||
}
|
||||
|
@ -28,7 +28,8 @@ public:
|
||||
const uint8_t *loc) const override;
|
||||
void writePlt(uint8_t *buf, const Symbol &sym,
|
||||
uint64_t pltEntryAddr) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@ -75,28 +76,29 @@ RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s,
|
||||
}
|
||||
}
|
||||
|
||||
void SPARCV9::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
switch (type) {
|
||||
void SPARCV9::relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const {
|
||||
switch (rel.type) {
|
||||
case R_SPARC_32:
|
||||
case R_SPARC_UA32:
|
||||
// V-word32
|
||||
checkUInt(loc, val, 32, type);
|
||||
checkUInt(loc, val, 32, rel);
|
||||
write32be(loc, val);
|
||||
break;
|
||||
case R_SPARC_DISP32:
|
||||
// V-disp32
|
||||
checkInt(loc, val, 32, type);
|
||||
checkInt(loc, val, 32, rel);
|
||||
write32be(loc, val);
|
||||
break;
|
||||
case R_SPARC_WDISP30:
|
||||
case R_SPARC_WPLT30:
|
||||
// V-disp30
|
||||
checkInt(loc, val, 32, type);
|
||||
checkInt(loc, val, 32, rel);
|
||||
write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff));
|
||||
break;
|
||||
case R_SPARC_22:
|
||||
// V-imm22
|
||||
checkUInt(loc, val, 22, type);
|
||||
checkUInt(loc, val, 22, rel);
|
||||
write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff));
|
||||
break;
|
||||
case R_SPARC_GOT22:
|
||||
@ -106,7 +108,7 @@ void SPARCV9::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
break;
|
||||
case R_SPARC_WDISP19:
|
||||
// V-disp19
|
||||
checkInt(loc, val, 21, type);
|
||||
checkInt(loc, val, 21, rel);
|
||||
write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff));
|
||||
break;
|
||||
case R_SPARC_GOT10:
|
||||
@ -139,8 +141,8 @@ void SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/,
|
||||
memcpy(buf, pltData, sizeof(pltData));
|
||||
|
||||
uint64_t off = pltEntryAddr - in.plt->getVA();
|
||||
relocateOne(buf, R_SPARC_22, off);
|
||||
relocateOne(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize));
|
||||
relocateNoSym(buf, R_SPARC_22, off);
|
||||
relocateNoSym(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize));
|
||||
}
|
||||
|
||||
TargetInfo *getSPARCV9TargetInfo() {
|
||||
|
@ -35,7 +35,8 @@ public:
|
||||
void writePltHeader(uint8_t *buf) const override;
|
||||
void writePlt(uint8_t *buf, const Symbol &sym,
|
||||
uint64_t pltEntryAddr) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
|
||||
RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
|
||||
RelExpr expr) const override;
|
||||
@ -266,21 +267,21 @@ int64_t X86::getImplicitAddend(const uint8_t *buf, RelType type) const {
|
||||
}
|
||||
}
|
||||
|
||||
void X86::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
switch (type) {
|
||||
void X86::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
|
||||
switch (rel.type) {
|
||||
case R_386_8:
|
||||
// R_386_{PC,}{8,16} are not part of the i386 psABI, but they are
|
||||
// being used for some 16-bit programs such as boot loaders, so
|
||||
// we want to support them.
|
||||
checkIntUInt(loc, val, 8, type);
|
||||
checkIntUInt(loc, val, 8, rel);
|
||||
*loc = val;
|
||||
break;
|
||||
case R_386_PC8:
|
||||
checkInt(loc, val, 8, type);
|
||||
checkInt(loc, val, 8, rel);
|
||||
*loc = val;
|
||||
break;
|
||||
case R_386_16:
|
||||
checkIntUInt(loc, val, 16, type);
|
||||
checkIntUInt(loc, val, 16, rel);
|
||||
write16le(loc, val);
|
||||
break;
|
||||
case R_386_PC16:
|
||||
@ -294,7 +295,7 @@ void X86::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
// current location subtracted from it.
|
||||
// We just check that Val fits in 17 bits. This misses some cases, but
|
||||
// should have no false positives.
|
||||
checkInt(loc, val, 17, type);
|
||||
checkInt(loc, val, 17, rel);
|
||||
write16le(loc, val);
|
||||
break;
|
||||
case R_386_32:
|
||||
@ -316,7 +317,7 @@ void X86::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_386_TLS_LE_32:
|
||||
case R_386_TLS_TPOFF:
|
||||
case R_386_TLS_TPOFF32:
|
||||
checkInt(loc, val, 32, type);
|
||||
checkInt(loc, val, 32, rel);
|
||||
write32le(loc, val);
|
||||
break;
|
||||
default:
|
||||
|
@ -35,7 +35,8 @@ public:
|
||||
void writePltHeader(uint8_t *buf) const override;
|
||||
void writePlt(uint8_t *buf, const Symbol &sym,
|
||||
uint64_t pltEntryAddr) const override;
|
||||
void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
|
||||
void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const override;
|
||||
|
||||
RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
|
||||
RelExpr expr) const override;
|
||||
@ -356,26 +357,26 @@ void X86_64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
|
||||
"expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD");
|
||||
}
|
||||
|
||||
void X86_64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
switch (type) {
|
||||
void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
|
||||
switch (rel.type) {
|
||||
case R_X86_64_8:
|
||||
checkIntUInt(loc, val, 8, type);
|
||||
checkIntUInt(loc, val, 8, rel);
|
||||
*loc = val;
|
||||
break;
|
||||
case R_X86_64_PC8:
|
||||
checkInt(loc, val, 8, type);
|
||||
checkInt(loc, val, 8, rel);
|
||||
*loc = val;
|
||||
break;
|
||||
case R_X86_64_16:
|
||||
checkIntUInt(loc, val, 16, type);
|
||||
checkIntUInt(loc, val, 16, rel);
|
||||
write16le(loc, val);
|
||||
break;
|
||||
case R_X86_64_PC16:
|
||||
checkInt(loc, val, 16, type);
|
||||
checkInt(loc, val, 16, rel);
|
||||
write16le(loc, val);
|
||||
break;
|
||||
case R_X86_64_32:
|
||||
checkUInt(loc, val, 32, type);
|
||||
checkUInt(loc, val, 32, rel);
|
||||
write32le(loc, val);
|
||||
break;
|
||||
case R_X86_64_32S:
|
||||
@ -393,7 +394,7 @@ void X86_64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
case R_X86_64_TLSLD:
|
||||
case R_X86_64_DTPOFF32:
|
||||
case R_X86_64_SIZE32:
|
||||
checkInt(loc, val, 32, type);
|
||||
checkInt(loc, val, 32, rel);
|
||||
write32le(loc, val);
|
||||
break;
|
||||
case R_X86_64_64:
|
||||
|
@ -871,15 +871,16 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
|
||||
// address 0. For bug-compatibilty, we accept them with warnings. We
|
||||
// know Steel Bank Common Lisp as of 2018 have this bug.
|
||||
warn(msg);
|
||||
target->relocateOne(bufLoc, type,
|
||||
SignExtend64<bits>(sym.getVA(addend - offset)));
|
||||
target->relocateNoSym(bufLoc, type,
|
||||
SignExtend64<bits>(sym.getVA(addend - offset)));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sym.isTls() && !Out::tlsPhdr)
|
||||
target->relocateOne(bufLoc, type, 0);
|
||||
target->relocateNoSym(bufLoc, type, 0);
|
||||
else
|
||||
target->relocateOne(bufLoc, type, SignExtend64<bits>(sym.getVA(addend)));
|
||||
target->relocateNoSym(bufLoc, type,
|
||||
SignExtend64<bits>(sym.getVA(addend)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -896,7 +897,7 @@ static void relocateNonAllocForRelocatable(InputSection *sec, uint8_t *buf) {
|
||||
assert(rel.expr == R_ABS);
|
||||
uint8_t *bufLoc = buf + rel.offset + sec->outSecOff;
|
||||
uint64_t targetVA = SignExtend64(rel.sym->getVA(rel.addend), bits);
|
||||
target->relocateOne(bufLoc, rel.type, targetVA);
|
||||
target->relocate(bufLoc, rel, targetVA);
|
||||
}
|
||||
}
|
||||
|
||||
@ -943,7 +944,7 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) {
|
||||
break;
|
||||
case R_PPC64_RELAX_TOC:
|
||||
if (!tryRelaxPPC64TocIndirection(rel, bufLoc))
|
||||
target->relocateOne(bufLoc, type, targetVA);
|
||||
target->relocate(bufLoc, rel, targetVA);
|
||||
break;
|
||||
case R_RELAX_TLS_IE_TO_LE:
|
||||
target->relaxTlsIeToLe(bufLoc, rel, targetVA);
|
||||
@ -986,10 +987,10 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) {
|
||||
}
|
||||
write32(bufLoc + 4, 0xe8410018); // ld %r2, 24(%r1)
|
||||
}
|
||||
target->relocateOne(bufLoc, type, targetVA);
|
||||
target->relocate(bufLoc, rel, targetVA);
|
||||
break;
|
||||
default:
|
||||
target->relocateOne(bufLoc, type, targetVA);
|
||||
target->relocate(bufLoc, rel, targetVA);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ static uint64_t getSymVA(const Symbol &sym, int64_t &addend) {
|
||||
// MIPS relocatable files can mix regular and microMIPS code.
|
||||
// Linker needs to distinguish such code. To do so microMIPS
|
||||
// symbols has the `STO_MIPS_MICROMIPS` flag in the `st_other`
|
||||
// field. Unfortunately, the `MIPS::relocateOne()` method has
|
||||
// field. Unfortunately, the `MIPS::relocate()` method has
|
||||
// a symbol value only. To pass type of the symbol (regular/microMIPS)
|
||||
// to that routine as well as other places where we write
|
||||
// a symbol value as-is (.dynamic section, `Elf_Ehdr::e_entry`
|
||||
|
@ -2176,7 +2176,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
|
||||
// We already set the less-significant bit for symbols
|
||||
// marked by the `STO_MIPS_MICROMIPS` flag and for microMIPS PLT
|
||||
// records. That allows us to distinguish such symbols in
|
||||
// the `MIPS<ELFT>::relocateOne()` routine. Now we should
|
||||
// the `MIPS<ELFT>::relocate()` routine. Now we should
|
||||
// clear that bit for non-dynamic symbol table, so tools
|
||||
// like `objdump` will be able to deal with a correct
|
||||
// symbol position.
|
||||
@ -3428,7 +3428,7 @@ void ARMExidxSyntheticSection::writeTo(uint8_t *buf) {
|
||||
memcpy(buf + offset, cantUnwindData, sizeof(cantUnwindData));
|
||||
uint64_t s = isec->getVA();
|
||||
uint64_t p = getVA() + offset;
|
||||
target->relocateOne(buf + offset, R_ARM_PREL31, s - p);
|
||||
target->relocateNoSym(buf + offset, R_ARM_PREL31, s - p);
|
||||
offset += 8;
|
||||
}
|
||||
}
|
||||
@ -3436,7 +3436,7 @@ void ARMExidxSyntheticSection::writeTo(uint8_t *buf) {
|
||||
memcpy(buf + offset, cantUnwindData, sizeof(cantUnwindData));
|
||||
uint64_t s = sentinel->getVA(sentinel->getSize());
|
||||
uint64_t p = getVA() + offset;
|
||||
target->relocateOne(buf + offset, R_ARM_PREL31, s - p);
|
||||
target->relocateNoSym(buf + offset, R_ARM_PREL31, s - p);
|
||||
assert(size == offset + 8);
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,11 @@ public:
|
||||
virtual bool inBranchRange(RelType type, uint64_t src,
|
||||
uint64_t dst) const;
|
||||
|
||||
virtual void relocateOne(uint8_t *loc, RelType type, uint64_t val) const = 0;
|
||||
virtual void relocate(uint8_t *loc, const Relocation &rel,
|
||||
uint64_t val) const = 0;
|
||||
void relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const {
|
||||
relocate(loc, Relocation{R_NONE, type, 0, 0, nullptr}, val);
|
||||
}
|
||||
|
||||
virtual ~TargetInfo();
|
||||
|
||||
@ -200,44 +204,46 @@ TargetInfo *getTarget();
|
||||
|
||||
template <class ELFT> bool isMipsPIC(const Defined *sym);
|
||||
|
||||
static inline void reportRangeError(uint8_t *loc, RelType type, const Twine &v,
|
||||
int64_t min, uint64_t max) {
|
||||
static inline void reportRangeError(uint8_t *loc, const Relocation &rel,
|
||||
const Twine &v, int64_t min, uint64_t max) {
|
||||
ErrorPlace errPlace = getErrorPlace(loc);
|
||||
StringRef hint;
|
||||
if (errPlace.isec && errPlace.isec->name.startswith(".debug"))
|
||||
hint = "; consider recompiling with -fdebug-types-section to reduce size "
|
||||
"of debug sections";
|
||||
|
||||
errorOrWarn(errPlace.loc + "relocation " + lld::toString(type) +
|
||||
errorOrWarn(errPlace.loc + "relocation " + lld::toString(rel.type) +
|
||||
" out of range: " + v.str() + " is not in [" + Twine(min).str() +
|
||||
", " + Twine(max).str() + "]" + hint);
|
||||
}
|
||||
|
||||
// Make sure that V can be represented as an N bit signed integer.
|
||||
inline void checkInt(uint8_t *loc, int64_t v, int n, RelType type) {
|
||||
inline void checkInt(uint8_t *loc, int64_t v, int n, const Relocation &rel) {
|
||||
if (v != llvm::SignExtend64(v, n))
|
||||
reportRangeError(loc, type, Twine(v), llvm::minIntN(n), llvm::maxIntN(n));
|
||||
reportRangeError(loc, rel, Twine(v), llvm::minIntN(n), llvm::maxIntN(n));
|
||||
}
|
||||
|
||||
// Make sure that V can be represented as an N bit unsigned integer.
|
||||
inline void checkUInt(uint8_t *loc, uint64_t v, int n, RelType type) {
|
||||
inline void checkUInt(uint8_t *loc, uint64_t v, int n, const Relocation &rel) {
|
||||
if ((v >> n) != 0)
|
||||
reportRangeError(loc, type, Twine(v), 0, llvm::maxUIntN(n));
|
||||
reportRangeError(loc, rel, Twine(v), 0, llvm::maxUIntN(n));
|
||||
}
|
||||
|
||||
// Make sure that V can be represented as an N bit signed or unsigned integer.
|
||||
inline void checkIntUInt(uint8_t *loc, uint64_t v, int n, RelType type) {
|
||||
inline void checkIntUInt(uint8_t *loc, uint64_t v, int n,
|
||||
const Relocation &rel) {
|
||||
// For the error message we should cast V to a signed integer so that error
|
||||
// messages show a small negative value rather than an extremely large one
|
||||
if (v != (uint64_t)llvm::SignExtend64(v, n) && (v >> n) != 0)
|
||||
reportRangeError(loc, type, Twine((int64_t)v), llvm::minIntN(n),
|
||||
reportRangeError(loc, rel, Twine((int64_t)v), llvm::minIntN(n),
|
||||
llvm::maxUIntN(n));
|
||||
}
|
||||
|
||||
inline void checkAlignment(uint8_t *loc, uint64_t v, int n, RelType type) {
|
||||
inline void checkAlignment(uint8_t *loc, uint64_t v, int n,
|
||||
const Relocation &rel) {
|
||||
if ((v & (n - 1)) != 0)
|
||||
error(getErrorLocation(loc) + "improper alignment for relocation " +
|
||||
lld::toString(type) + ": 0x" + llvm::utohexstr(v) +
|
||||
lld::toString(rel.type) + ": 0x" + llvm::utohexstr(v) +
|
||||
" is not aligned to " + Twine(n) + " bytes");
|
||||
}
|
||||
|
||||
|
@ -345,7 +345,7 @@ void AArch64ABSLongThunk::writeTo(uint8_t *buf) {
|
||||
};
|
||||
uint64_t s = getAArch64ThunkDestVA(destination, addend);
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf + 8, R_AARCH64_ABS64, s);
|
||||
target->relocateNoSym(buf + 8, R_AARCH64_ABS64, s);
|
||||
}
|
||||
|
||||
void AArch64ABSLongThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -369,9 +369,9 @@ void AArch64ADRPThunk::writeTo(uint8_t *buf) {
|
||||
uint64_t s = getAArch64ThunkDestVA(destination, addend);
|
||||
uint64_t p = getThunkTargetSym()->getVA();
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21,
|
||||
getAArch64Page(s) - getAArch64Page(p));
|
||||
target->relocateOne(buf + 4, R_AARCH64_ADD_ABS_LO12_NC, s);
|
||||
target->relocateNoSym(buf, R_AARCH64_ADR_PREL_PG_HI21,
|
||||
getAArch64Page(s) - getAArch64Page(p));
|
||||
target->relocateNoSym(buf + 4, R_AARCH64_ADD_ABS_LO12_NC, s);
|
||||
}
|
||||
|
||||
void AArch64ADRPThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -415,7 +415,7 @@ void ARMThunk::writeTo(uint8_t *buf) {
|
||||
0x00, 0x00, 0x00, 0xea, // b S
|
||||
};
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf, R_ARM_JUMP24, offset);
|
||||
target->relocateNoSym(buf, R_ARM_JUMP24, offset);
|
||||
}
|
||||
|
||||
bool ARMThunk::isCompatibleWith(const InputSection &isec,
|
||||
@ -453,7 +453,7 @@ void ThumbThunk::writeTo(uint8_t *buf) {
|
||||
0x00, 0xf0, 0x00, 0xb0, // b.w S
|
||||
};
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf, R_ARM_THM_JUMP24, offset);
|
||||
target->relocateNoSym(buf, R_ARM_THM_JUMP24, offset);
|
||||
}
|
||||
|
||||
bool ThumbThunk::isCompatibleWith(const InputSection &isec,
|
||||
@ -470,8 +470,8 @@ void ARMV7ABSLongThunk::writeLong(uint8_t *buf) {
|
||||
};
|
||||
uint64_t s = getARMThunkDestVA(destination);
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf, R_ARM_MOVW_ABS_NC, s);
|
||||
target->relocateOne(buf + 4, R_ARM_MOVT_ABS, s);
|
||||
target->relocateNoSym(buf, R_ARM_MOVW_ABS_NC, s);
|
||||
target->relocateNoSym(buf + 4, R_ARM_MOVT_ABS, s);
|
||||
}
|
||||
|
||||
void ARMV7ABSLongThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -488,8 +488,8 @@ void ThumbV7ABSLongThunk::writeLong(uint8_t *buf) {
|
||||
};
|
||||
uint64_t s = getARMThunkDestVA(destination);
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf, R_ARM_THM_MOVW_ABS_NC, s);
|
||||
target->relocateOne(buf + 4, R_ARM_THM_MOVT_ABS, s);
|
||||
target->relocateNoSym(buf, R_ARM_THM_MOVW_ABS_NC, s);
|
||||
target->relocateNoSym(buf + 4, R_ARM_THM_MOVT_ABS, s);
|
||||
}
|
||||
|
||||
void ThumbV7ABSLongThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -509,8 +509,8 @@ void ARMV7PILongThunk::writeLong(uint8_t *buf) {
|
||||
uint64_t p = getThunkTargetSym()->getVA();
|
||||
int64_t offset = s - p - 16;
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf, R_ARM_MOVW_PREL_NC, offset);
|
||||
target->relocateOne(buf + 4, R_ARM_MOVT_PREL, offset);
|
||||
target->relocateNoSym(buf, R_ARM_MOVW_PREL_NC, offset);
|
||||
target->relocateNoSym(buf + 4, R_ARM_MOVT_PREL, offset);
|
||||
}
|
||||
|
||||
void ARMV7PILongThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -530,8 +530,8 @@ void ThumbV7PILongThunk::writeLong(uint8_t *buf) {
|
||||
uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
|
||||
int64_t offset = s - p - 12;
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf, R_ARM_THM_MOVW_PREL_NC, offset);
|
||||
target->relocateOne(buf + 4, R_ARM_THM_MOVT_PREL, offset);
|
||||
target->relocateNoSym(buf, R_ARM_THM_MOVW_PREL_NC, offset);
|
||||
target->relocateNoSym(buf + 4, R_ARM_THM_MOVT_PREL, offset);
|
||||
}
|
||||
|
||||
void ThumbV7PILongThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -546,7 +546,7 @@ void ARMV5ABSLongThunk::writeLong(uint8_t *buf) {
|
||||
0x00, 0x00, 0x00, 0x00, // L1: .word S
|
||||
};
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf + 4, R_ARM_ABS32, getARMThunkDestVA(destination));
|
||||
target->relocateNoSym(buf + 4, R_ARM_ABS32, getARMThunkDestVA(destination));
|
||||
}
|
||||
|
||||
void ARMV5ABSLongThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -572,7 +572,7 @@ void ARMV5PILongThunk::writeLong(uint8_t *buf) {
|
||||
uint64_t s = getARMThunkDestVA(destination);
|
||||
uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf + 12, R_ARM_REL32, s - p - 12);
|
||||
target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12);
|
||||
}
|
||||
|
||||
void ARMV5PILongThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -602,7 +602,7 @@ void ThumbV6MABSLongThunk::writeLong(uint8_t *buf) {
|
||||
};
|
||||
uint64_t s = getARMThunkDestVA(destination);
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf + 8, R_ARM_ABS32, s);
|
||||
target->relocateNoSym(buf + 8, R_ARM_ABS32, s);
|
||||
}
|
||||
|
||||
void ThumbV6MABSLongThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -628,7 +628,7 @@ void ThumbV6MPILongThunk::writeLong(uint8_t *buf) {
|
||||
uint64_t s = getARMThunkDestVA(destination);
|
||||
uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
|
||||
memcpy(buf, data, sizeof(data));
|
||||
target->relocateOne(buf + 12, R_ARM_REL32, s - p - 12);
|
||||
target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12);
|
||||
}
|
||||
|
||||
void ThumbV6MPILongThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -645,8 +645,8 @@ void MipsThunk::writeTo(uint8_t *buf) {
|
||||
write32(buf + 4, 0x08000000 | (s >> 2)); // j func
|
||||
write32(buf + 8, 0x27390000); // addiu $25, $25, %lo(func)
|
||||
write32(buf + 12, 0x00000000); // nop
|
||||
target->relocateOne(buf, R_MIPS_HI16, s);
|
||||
target->relocateOne(buf + 8, R_MIPS_LO16, s);
|
||||
target->relocateNoSym(buf, R_MIPS_HI16, s);
|
||||
target->relocateNoSym(buf + 8, R_MIPS_LO16, s);
|
||||
}
|
||||
|
||||
void MipsThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -667,9 +667,9 @@ void MicroMipsThunk::writeTo(uint8_t *buf) {
|
||||
write16(buf + 4, 0xd400); // j func
|
||||
write16(buf + 8, 0x3339); // addiu $25, $25, %lo(func)
|
||||
write16(buf + 12, 0x0c00); // nop
|
||||
target->relocateOne(buf, R_MICROMIPS_HI16, s);
|
||||
target->relocateOne(buf + 4, R_MICROMIPS_26_S1, s);
|
||||
target->relocateOne(buf + 8, R_MICROMIPS_LO16, s);
|
||||
target->relocateNoSym(buf, R_MICROMIPS_HI16, s);
|
||||
target->relocateNoSym(buf + 4, R_MICROMIPS_26_S1, s);
|
||||
target->relocateNoSym(buf + 8, R_MICROMIPS_LO16, s);
|
||||
}
|
||||
|
||||
void MicroMipsThunk::addSymbols(ThunkSection &isec) {
|
||||
@ -691,9 +691,9 @@ void MicroMipsR6Thunk::writeTo(uint8_t *buf) {
|
||||
write16(buf, 0x1320); // lui $25, %hi(func)
|
||||
write16(buf + 4, 0x3339); // addiu $25, $25, %lo(func)
|
||||
write16(buf + 8, 0x9400); // bc func
|
||||
target->relocateOne(buf, R_MICROMIPS_HI16, s);
|
||||
target->relocateOne(buf + 4, R_MICROMIPS_LO16, s);
|
||||
target->relocateOne(buf + 8, R_MICROMIPS_PC26_S1, s - p - 12);
|
||||
target->relocateNoSym(buf, R_MICROMIPS_HI16, s);
|
||||
target->relocateNoSym(buf + 4, R_MICROMIPS_LO16, s);
|
||||
target->relocateNoSym(buf + 8, R_MICROMIPS_PC26_S1, s - p - 12);
|
||||
}
|
||||
|
||||
void MicroMipsR6Thunk::addSymbols(ThunkSection &isec) {
|
||||
|
Loading…
Reference in New Issue
Block a user