namespace jitlink {
namespace riscv {
-/// Represets riscv fixups
+/// Represents riscv fixups. Ordered in the same way as the relocations in
+/// include/llvm/BinaryFormat/ELFRelocs/RISCV.def.
enum EdgeKind_riscv : Edge::Kind {
// TODO: Capture and replace to generic fixups
///
R_RISCV_JAL,
- /// High 20 bits of 32-bit pointer value relocation
+ /// PC relative call
///
- /// Fixup expression
- /// Fixup <- (Target + Addend + 0x800) >> 12
- R_RISCV_HI20,
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend)
+ R_RISCV_CALL,
- /// Low 12 bits of 32-bit pointer value relocation, used by S type instruction
- /// format
+ /// PC relative call by PLT
///
- /// Fixup expression
- /// Fixup <- (Target + Addend) & 0xFFF
- R_RISCV_LO12_S,
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend)
+ R_RISCV_CALL_PLT,
- /// Low 12 bits of 32-bit pointer value relocation
+ /// PC relative GOT offset
///
- /// Fixup expression
- /// Fixup <- (Target + Addend) & 0xFFF
- R_RISCV_LO12_I,
+ /// Fixup expression:
+ /// Fixup <- (GOT - Fixup + Addend) >> 12
+ R_RISCV_GOT_HI20,
+
/// High 20 bits of PC relative relocation
///
/// Fixup expression:
/// Fixup <- (Target - Fixup + Addend) & 0xFFF
R_RISCV_PCREL_LO12_S,
- /// PC relative call
+ /// High 20 bits of 32-bit pointer value relocation
///
- /// Fixup expression:
- /// Fixup <- (Target - Fixup + Addend)
- R_RISCV_CALL,
+ /// Fixup expression
+ /// Fixup <- (Target + Addend + 0x800) >> 12
+ R_RISCV_HI20,
- /// 32 bits PC relative relocation
+ /// Low 12 bits of 32-bit pointer value relocation
///
- /// Fixup expression:
- /// Fixup <- (Target - Fixup + Addend)
- R_RISCV_32_PCREL,
+ /// Fixup expression
+ /// Fixup <- (Target + Addend) & 0xFFF
+ R_RISCV_LO12_I,
- /// PC relative GOT offset
+ /// Low 12 bits of 32-bit pointer value relocation, used by S type instruction
+ /// format
///
- /// Fixup expression:
- /// Fixup <- (GOT - Fixup + Addend) >> 12
- R_RISCV_GOT_HI20,
+ /// Fixup expression
+ /// Fixup <- (Target + Addend) & 0xFFF
+ R_RISCV_LO12_S,
- /// PC relative call by PLT
+ /// 8 bits label addition
///
- /// Fixup expression:
- /// Fixup <- (Target - Fixup + Addend)
- R_RISCV_CALL_PLT,
+ /// Fixup expression
+ /// Fixup <- (Target - *{1}Fixup + Addend)
+ R_RISCV_ADD8,
- /// 64 bits label addition
+ /// 16 bits label addition
///
- /// Fixup expression:
- /// Fixup <- (Target - *{8}Fixup + Addend)
- R_RISCV_ADD64,
+ /// Fixup expression
+ /// Fixup <- (Target - *{2}Fixup + Addend)
+ R_RISCV_ADD16,
/// 32 bits label addition
///
/// Fixup <- (Target - *{4}Fixup + Addend)
R_RISCV_ADD32,
- /// 16 bits label addition
+ /// 64 bits label addition
///
- /// Fixup expression
- /// Fixup <- (Target - *{2}Fixup + Addend)
- R_RISCV_ADD16,
+ /// Fixup expression:
+ /// Fixup <- (Target - *{8}Fixup + Addend)
+ R_RISCV_ADD64,
- /// 8 bits label addition
+ /// 8 bits label subtraction
///
/// Fixup expression
- /// Fixup <- (Target - *{1}Fixup + Addend)
- R_RISCV_ADD8,
+ /// Fixup <- (Target - *{1}Fixup - Addend)
+ R_RISCV_SUB8,
- /// 64 bits label subtraction
+ /// 16 bits label subtraction
///
/// Fixup expression
- /// Fixup <- (Target - *{8}Fixup - Addend)
- R_RISCV_SUB64,
+ /// Fixup <- (Target - *{2}Fixup - Addend)
+ R_RISCV_SUB16,
/// 32 bits label subtraction
///
/// Fixup <- (Target - *{4}Fixup - Addend)
R_RISCV_SUB32,
- /// 16 bits label subtraction
- ///
- /// Fixup expression
- /// Fixup <- (Target - *{2}Fixup - Addend)
- R_RISCV_SUB16,
-
- /// 8 bits label subtraction
+ /// 64 bits label subtraction
///
/// Fixup expression
- /// Fixup <- (Target - *{1}Fixup - Addend)
- R_RISCV_SUB8,
+ /// Fixup <- (Target - *{8}Fixup - Addend)
+ R_RISCV_SUB64,
/// 6 bits label subtraction
///
/// Fixup expression:
/// Fixup <- (Target + Addend)
R_RISCV_SET32,
+
+ /// 32 bits PC relative relocation
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend)
+ R_RISCV_32_PCREL,
};
/// Returns a string name for the given riscv edge. For debugging purposes
*(little32_t *)FixupPtr = RawInstr | Imm20 | Imm10_1 | Imm11 | Imm19_12;
break;
}
- case R_RISCV_HI20: {
- int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
- int64_t Hi = Value + 0x800;
- if (LLVM_UNLIKELY(!isInRangeForImm(Hi, 32)))
- return makeTargetOutOfRangeError(G, B, E);
- uint32_t RawInstr = *(little32_t *)FixupPtr;
- *(little32_t *)FixupPtr =
- (RawInstr & 0xFFF) | (static_cast<uint32_t>(Hi & 0xFFFFF000));
- break;
- }
- case R_RISCV_LO12_I: {
- // FIXME: We assume that R_RISCV_HI20 is present in object code and pairs
- // with current relocation R_RISCV_LO12_I. So here may need a check.
- int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
- int32_t Lo = Value & 0xFFF;
- uint32_t RawInstr = *(little32_t *)FixupPtr;
- *(little32_t *)FixupPtr =
- (RawInstr & 0xFFFFF) | (static_cast<uint32_t>(Lo & 0xFFF) << 20);
- break;
- }
- case R_RISCV_LO12_S: {
- // FIXME: We assume that R_RISCV_HI20 is present in object code and pairs
- // with current relocation R_RISCV_LO12_S. So here may need a check.
- int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
- int64_t Lo = Value & 0xFFF;
- uint32_t Imm31_25 = extractBits(Lo, 5, 7) << 25;
- uint32_t Imm11_7 = extractBits(Lo, 0, 5) << 7;
- uint32_t RawInstr = *(little32_t *)FixupPtr;
- *(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm31_25 | Imm11_7;
- break;
- }
case R_RISCV_CALL: {
int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
int64_t Hi = Value + 0x800;
RawInstrJalr | (static_cast<uint32_t>(Lo) << 20);
break;
}
+ // The relocations R_RISCV_CALL_PLT and R_RISCV_GOT_HI20 are handled by
+ // PerGraphGOTAndPLTStubsBuilder_ELF_riscv and are transformed into
+ // R_RISCV_CALL and R_RISCV_PCREL_HI20.
case R_RISCV_PCREL_HI20: {
int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
int64_t Hi = Value + 0x800;
*(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm31_25 | Imm11_7;
break;
}
- case R_RISCV_ADD64: {
+ case R_RISCV_HI20: {
+ int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
+ int64_t Hi = Value + 0x800;
+ if (LLVM_UNLIKELY(!isInRangeForImm(Hi, 32)))
+ return makeTargetOutOfRangeError(G, B, E);
+ uint32_t RawInstr = *(little32_t *)FixupPtr;
+ *(little32_t *)FixupPtr =
+ (RawInstr & 0xFFF) | (static_cast<uint32_t>(Hi & 0xFFFFF000));
+ break;
+ }
+ case R_RISCV_LO12_I: {
+ // FIXME: We assume that R_RISCV_HI20 is present in object code and pairs
+ // with current relocation R_RISCV_LO12_I. So here may need a check.
+ int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
+ int32_t Lo = Value & 0xFFF;
+ uint32_t RawInstr = *(little32_t *)FixupPtr;
+ *(little32_t *)FixupPtr =
+ (RawInstr & 0xFFFFF) | (static_cast<uint32_t>(Lo & 0xFFF) << 20);
+ break;
+ }
+ case R_RISCV_LO12_S: {
+ // FIXME: We assume that R_RISCV_HI20 is present in object code and pairs
+ // with current relocation R_RISCV_LO12_S. So here may need a check.
+ int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue();
+ int64_t Lo = Value & 0xFFF;
+ uint32_t Imm31_25 = extractBits(Lo, 5, 7) << 25;
+ uint32_t Imm11_7 = extractBits(Lo, 0, 5) << 7;
+ uint32_t RawInstr = *(little32_t *)FixupPtr;
+ *(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm31_25 | Imm11_7;
+ break;
+ }
+ case R_RISCV_ADD8: {
+ int64_t Value =
+ (E.getTarget().getAddress() +
+ *(reinterpret_cast<const uint8_t *>(FixupAddress.getValue())) +
+ E.getAddend())
+ .getValue();
+ *FixupPtr = static_cast<uint8_t>(Value);
+ break;
+ }
+ case R_RISCV_ADD16: {
int64_t Value = (E.getTarget().getAddress() +
- support::endian::read64le(reinterpret_cast<const void *>(
+ support::endian::read16le(reinterpret_cast<const void *>(
FixupAddress.getValue())) +
E.getAddend())
.getValue();
- *(little64_t *)FixupPtr = static_cast<uint64_t>(Value);
+ *(little16_t *)FixupPtr = static_cast<uint16_t>(Value);
break;
}
case R_RISCV_ADD32: {
*(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
break;
}
- case R_RISCV_ADD16: {
+ case R_RISCV_ADD64: {
int64_t Value = (E.getTarget().getAddress() +
- support::endian::read16le(reinterpret_cast<const void *>(
+ support::endian::read64le(reinterpret_cast<const void *>(
FixupAddress.getValue())) +
E.getAddend())
.getValue();
- *(little16_t *)FixupPtr = static_cast<uint16_t>(Value);
+ *(little64_t *)FixupPtr = static_cast<uint64_t>(Value);
break;
}
- case R_RISCV_ADD8: {
+ case R_RISCV_SUB8: {
int64_t Value =
- (E.getTarget().getAddress() +
- *(reinterpret_cast<const uint8_t *>(FixupAddress.getValue())) +
- E.getAddend())
- .getValue();
+ *(reinterpret_cast<const uint8_t *>(FixupAddress.getValue())) -
+ E.getTarget().getAddress().getValue() - E.getAddend();
*FixupPtr = static_cast<uint8_t>(Value);
break;
}
- case R_RISCV_SUB64: {
- int64_t Value = support::endian::read64le(reinterpret_cast<const void *>(
+ case R_RISCV_SUB16: {
+ int64_t Value = support::endian::read16le(reinterpret_cast<const void *>(
FixupAddress.getValue())) -
E.getTarget().getAddress().getValue() - E.getAddend();
- *(little64_t *)FixupPtr = static_cast<uint64_t>(Value);
+ *(little16_t *)FixupPtr = static_cast<uint32_t>(Value);
break;
}
case R_RISCV_SUB32: {
*(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
break;
}
- case R_RISCV_SUB16: {
- int64_t Value = support::endian::read16le(reinterpret_cast<const void *>(
+ case R_RISCV_SUB64: {
+ int64_t Value = support::endian::read64le(reinterpret_cast<const void *>(
FixupAddress.getValue())) -
E.getTarget().getAddress().getValue() - E.getAddend();
- *(little16_t *)FixupPtr = static_cast<uint32_t>(Value);
- break;
- }
- case R_RISCV_SUB8: {
- int64_t Value =
- *(reinterpret_cast<const uint8_t *>(FixupAddress.getValue())) -
- E.getTarget().getAddress().getValue() - E.getAddend();
- *FixupPtr = static_cast<uint8_t>(Value);
+ *(little64_t *)FixupPtr = static_cast<uint64_t>(Value);
break;
}
case R_RISCV_SUB6: {
return EdgeKind_riscv::R_RISCV_BRANCH;
case ELF::R_RISCV_JAL:
return EdgeKind_riscv::R_RISCV_JAL;
- case ELF::R_RISCV_HI20:
- return EdgeKind_riscv::R_RISCV_HI20;
- case ELF::R_RISCV_LO12_I:
- return EdgeKind_riscv::R_RISCV_LO12_I;
- case ELF::R_RISCV_LO12_S:
- return EdgeKind_riscv::R_RISCV_LO12_S;
case ELF::R_RISCV_CALL:
return EdgeKind_riscv::R_RISCV_CALL;
+ case ELF::R_RISCV_CALL_PLT:
+ return EdgeKind_riscv::R_RISCV_CALL_PLT;
+ case ELF::R_RISCV_GOT_HI20:
+ return EdgeKind_riscv::R_RISCV_GOT_HI20;
case ELF::R_RISCV_PCREL_HI20:
return EdgeKind_riscv::R_RISCV_PCREL_HI20;
case ELF::R_RISCV_PCREL_LO12_I:
return EdgeKind_riscv::R_RISCV_PCREL_LO12_I;
case ELF::R_RISCV_PCREL_LO12_S:
return EdgeKind_riscv::R_RISCV_PCREL_LO12_S;
- case ELF::R_RISCV_GOT_HI20:
- return EdgeKind_riscv::R_RISCV_GOT_HI20;
- case ELF::R_RISCV_CALL_PLT:
- return EdgeKind_riscv::R_RISCV_CALL_PLT;
- case ELF::R_RISCV_ADD64:
- return EdgeKind_riscv::R_RISCV_ADD64;
- case ELF::R_RISCV_ADD32:
- return EdgeKind_riscv::R_RISCV_ADD32;
- case ELF::R_RISCV_ADD16:
- return EdgeKind_riscv::R_RISCV_ADD16;
+ case ELF::R_RISCV_HI20:
+ return EdgeKind_riscv::R_RISCV_HI20;
+ case ELF::R_RISCV_LO12_I:
+ return EdgeKind_riscv::R_RISCV_LO12_I;
+ case ELF::R_RISCV_LO12_S:
+ return EdgeKind_riscv::R_RISCV_LO12_S;
case ELF::R_RISCV_ADD8:
return EdgeKind_riscv::R_RISCV_ADD8;
- case ELF::R_RISCV_SUB64:
- return EdgeKind_riscv::R_RISCV_SUB64;
- case ELF::R_RISCV_SUB32:
- return EdgeKind_riscv::R_RISCV_SUB32;
- case ELF::R_RISCV_SUB16:
- return EdgeKind_riscv::R_RISCV_SUB16;
+ case ELF::R_RISCV_ADD16:
+ return EdgeKind_riscv::R_RISCV_ADD16;
+ case ELF::R_RISCV_ADD32:
+ return EdgeKind_riscv::R_RISCV_ADD32;
+ case ELF::R_RISCV_ADD64:
+ return EdgeKind_riscv::R_RISCV_ADD64;
case ELF::R_RISCV_SUB8:
return EdgeKind_riscv::R_RISCV_SUB8;
+ case ELF::R_RISCV_SUB16:
+ return EdgeKind_riscv::R_RISCV_SUB16;
+ case ELF::R_RISCV_SUB32:
+ return EdgeKind_riscv::R_RISCV_SUB32;
+ case ELF::R_RISCV_SUB64:
+ return EdgeKind_riscv::R_RISCV_SUB64;
case ELF::R_RISCV_SUB6:
return EdgeKind_riscv::R_RISCV_SUB6;
case ELF::R_RISCV_SET6: