diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -60,6 +60,9 @@ void resolveBPFRelocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend); + void resolveRISCV64Relocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend); + unsigned getMaxStubSize() const override { if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) return 20; // movz; movk; movk; movk; br diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -1007,6 +1007,60 @@ } } +void RuntimeDyldELF::resolveRISCV64Relocation(const SectionEntry &Section, + uint64_t Offset, uint64_t Value, + uint32_t Type, int64_t Addend) { + uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); + uint32_t *TargetPtr = reinterpret_cast(LocalAddress); + uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset); + + LLVM_DEBUG(dbgs() << "resolveRISCV64Relocation, " + << "LocalAddress: 0x" << format("%llx", LocalAddress) + << " FinalAddress: 0x" << format("%llx", FinalAddress) + << " Value: 0x" << format("%llx", Value) << " Addend: 0x" + << format("%llx", Addend) << " Type: 0x" + << format("%x", Type) << "=" + << getELFRelocationTypeName(ELF::EM_RISCV, Type) << "\n"); + + switch (Type) { + default: + report_fatal_error( + Twine("Relocation type not implemented yet: ") + .concat(getELFRelocationTypeName(ELF::EM_RISCV, Type))); + break; + case ELF::R_RISCV_SET6: { + uint64_t Result = Value + Addend; + uint32_t RawData = read32le(TargetPtr); + write32le(TargetPtr, (RawData & 0xFFFF'FFC0) | (Result & 0x3F)); + break; + } + case ELF::R_RISCV_SUB6: { + uint64_t Result = Value + Addend; + uint32_t RawData = read32le(TargetPtr); + uint32_t Word6 = ((RawData & 0x3F) - Result) & 0x3F; + write32le(TargetPtr, (RawData & 0xFFFF'FFC0) | Word6); + break; + } + case ELF::R_RISCV_32_PCREL: { + uint64_t Result = Value + Addend; + write32le(TargetPtr, Result - FinalAddress); + break; + } + case ELF::R_RISCV_ADD32: { + uint64_t Result = Value + Addend; + uint32_t RawData = read32le(TargetPtr); + write32le(TargetPtr, RawData + Result); + break; + } + case ELF::R_RISCV_SUB32: { + uint64_t Result = Value + Addend; + uint32_t RawData = read32le(TargetPtr); + write32le(TargetPtr, RawData - Result); + break; + } + } +} + // The target location for the relocation is described by RE.SectionID and // RE.Offset. RE.SectionID can be used to find the SectionEntry. Each // SectionEntry has three members describing its location. @@ -1072,6 +1126,9 @@ case Triple::bpfeb: resolveBPFRelocation(Section, Offset, Value, Type, Addend); break; + case Triple::riscv64: + resolveRISCV64Relocation(Section, Offset, Value, Type, Addend); + break; default: llvm_unreachable("Unsupported CPU type!"); }