diff --git a/lld/ELF/AArch64ErrataFix.cpp b/lld/ELF/AArch64ErrataFix.cpp --- a/lld/ELF/AArch64ErrataFix.cpp +++ b/lld/ELF/AArch64ErrataFix.cpp @@ -421,7 +421,7 @@ // 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() { diff --git a/lld/ELF/ARMErrataFix.cpp b/lld/ELF/ARMErrataFix.cpp --- a/lld/ELF/ARMErrataFix.cpp +++ b/lld/ELF/ARMErrataFix.cpp @@ -189,7 +189,7 @@ // 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 diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -45,7 +45,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ // 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 @@ 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::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 @@ } 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 @@ 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)); diff --git a/lld/ELF/Arch/AMDGPU.cpp b/lld/ELF/Arch/AMDGPU.cpp --- a/lld/ELF/Arch/AMDGPU.cpp +++ b/lld/ELF/Arch/AMDGPU.cpp @@ -26,7 +26,8 @@ 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 @@ 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: diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp --- a/lld/ELF/Arch/ARM.cpp +++ b/lld/ELF/Arch/ARM.cpp @@ -43,7 +43,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ (val & 0x00ff)); // imm8 break; default: - error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); + error(getErrorLocation(loc) + "unrecognized relocation " + + toString(rel.type)); } } diff --git a/lld/ELF/Arch/AVR.cpp b/lld/ELF/Arch/AVR.cpp --- a/lld/ELF/Arch/AVR.cpp +++ b/lld/ELF/Arch/AVR.cpp @@ -46,7 +46,8 @@ 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 @@ 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 @@ break; } default: - error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); + error(getErrorLocation(loc) + "unrecognized relocation " + + toString(rel.type)); } } diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -31,7 +31,8 @@ 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 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 @@ 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 @@ 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 @@ // 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 @@ 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 { diff --git a/lld/ELF/Arch/MSP430.cpp b/lld/ELF/Arch/MSP430.cpp --- a/lld/ELF/Arch/MSP430.cpp +++ b/lld/ELF/Arch/MSP430.cpp @@ -36,7 +36,8 @@ 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 @@ } } -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)); } } diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp --- a/lld/ELF/Arch/Mips.cpp +++ b/lld/ELF/Arch/Mips.cpp @@ -37,7 +37,8 @@ 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 @@ 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 @@ 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 @@ } template -void MIPS::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { +void MIPS::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 @@ 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 @@ if (config->relocatable) { writeShuffleValue(loc, val + 0x8000, 16, 16); } else { - checkInt(loc, val, 16, type); + checkInt(loc, val, 16, rel); writeShuffleValue(loc, val, 16, 0); } break; @@ -596,7 +599,7 @@ 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 @@ 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(loc, val, 16, 0); break; case R_MICROMIPS_CALL16: @@ -622,7 +625,7 @@ writeShuffleValue(loc, val, 16, 0); break; case R_MICROMIPS_GPREL7_S2: - checkInt(loc, val, 7, type); + checkInt(loc, val, 7, rel); writeShuffleValue(loc, val, 7, 2); break; case R_MIPS_CALL_HI16: @@ -665,23 +668,23 @@ // 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 @@ break; case R_MICROMIPS_26_S1: case R_MICROMIPS_PC26_S1: - checkInt(loc, val, 27, type); + checkInt(loc, val, 27, rel); writeShuffleValue(loc, val, 26, 1); break; case R_MICROMIPS_PC7_S1: - checkInt(loc, val, 8, type); + checkInt(loc, val, 8, rel); writeMicroRelocation16(loc, val, 7, 1); break; case R_MICROMIPS_PC10_S1: - checkInt(loc, val, 11, type); + checkInt(loc, val, 11, rel); writeMicroRelocation16(loc, val, 10, 1); break; case R_MICROMIPS_PC16_S1: - checkInt(loc, val, 17, type); + checkInt(loc, val, 17, rel); writeShuffleValue(loc, val, 16, 1); break; case R_MICROMIPS_PC18_S3: - checkInt(loc, val, 21, type); + checkInt(loc, val, 21, rel); writeShuffleValue(loc, val, 18, 3); break; case R_MICROMIPS_PC19_S2: - checkInt(loc, val, 21, type); + checkInt(loc, val, 21, rel); writeShuffleValue(loc, val, 19, 2); break; case R_MICROMIPS_PC21_S1: - checkInt(loc, val, 22, type); + checkInt(loc, val, 22, rel); writeShuffleValue(loc, val, 21, 1); break; case R_MICROMIPS_PC23_S2: - checkInt(loc, val, 25, type); + checkInt(loc, val, 25, rel); writeShuffleValue(loc, val, 23, 2); break; default: diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp --- a/lld/ELF/Arch/PPC.cpp +++ b/lld/ELF/Arch/PPC.cpp @@ -44,7 +44,8 @@ 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 @@ } } -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 @@ 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 @@ 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 @@ 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 @@ // 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 @@ 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"); diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -185,7 +185,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ // 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 @@ 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 @@ 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 @@ 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 @@ } } -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 @@ 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 @@ // 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 @@ } } 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 @@ 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 @@ 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 @@ // 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: diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -33,7 +33,8 @@ 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 @@ 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 @@ return; case R_RISCV_RVC_BRANCH: { - checkInt(loc, static_cast(val) >> 1, 8, type); - checkAlignment(loc, val, 2, type); + checkInt(loc, static_cast(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 @@ } case R_RISCV_RVC_JUMP: { - checkInt(loc, static_cast(val) >> 1, 11, type); - checkAlignment(loc, val, 2, type); + checkInt(loc, static_cast(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 @@ 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 @@ } case R_RISCV_JAL: { - checkInt(loc, static_cast(val) >> 1, 20, type); - checkAlignment(loc, val, 2, type); + checkInt(loc, static_cast(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 @@ } case R_RISCV_BRANCH: { - checkInt(loc, static_cast(val) >> 1, 12, type); - checkAlignment(loc, val, 2, type); + checkInt(loc, static_cast(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 @@ 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 @@ 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; } diff --git a/lld/ELF/Arch/SPARCV9.cpp b/lld/ELF/Arch/SPARCV9.cpp --- a/lld/ELF/Arch/SPARCV9.cpp +++ b/lld/ELF/Arch/SPARCV9.cpp @@ -28,7 +28,8 @@ 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 @@ } } -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 @@ 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 @@ 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() { diff --git a/lld/ELF/Arch/X86.cpp b/lld/ELF/Arch/X86.cpp --- a/lld/ELF/Arch/X86.cpp +++ b/lld/ELF/Arch/X86.cpp @@ -35,7 +35,8 @@ 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 @@ } } -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 @@ // 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 @@ 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: diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -35,7 +35,8 @@ 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 @@ "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 @@ 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: diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -871,15 +871,16 @@ // 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(sym.getVA(addend - offset))); + target->relocateNoSym(bufLoc, type, + SignExtend64(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(sym.getVA(addend))); + target->relocateNoSym(bufLoc, type, + SignExtend64(sym.getVA(addend))); } } @@ -896,7 +897,7 @@ 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 @@ 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 @@ } 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; } } diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -99,7 +99,7 @@ // 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` diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -2176,7 +2176,7 @@ // 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::relocateOne()` routine. Now we should + // the `MIPS::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 @@ 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 @@ 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); } diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -82,7 +82,11 @@ 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 @@ template 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"); } diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp --- a/lld/ELF/Thunks.cpp +++ b/lld/ELF/Thunks.cpp @@ -345,7 +345,7 @@ }; 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 @@ 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 @@ 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 @@ 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 @@ }; 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 @@ }; 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ }; 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 @@ 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 @@ 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 @@ 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 @@ 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) {