Skip to content

Commit bd8f17d

Browse files
committed
[lldb][RISCV] add JIT relocations resolver
Function calls support in LLDB expressions for RISCV: 2 of 6 Adds required RISCV relocations resolving functionality in lldb ExecutionEngine.
1 parent b7f5123 commit bd8f17d

File tree

2 files changed

+159
-3
lines changed

2 files changed

+159
-3
lines changed

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp

Lines changed: 152 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,135 @@ void RuntimeDyldELF::resolveBPFRelocation(const SectionEntry &Section,
10111011
}
10121012
}
10131013

1014+
static void applyUTypeImmRISCV(uint8_t *InstrAddr, uint32_t Imm) {
1015+
uint32_t UpperImm = (Imm + 0x800) & 0xfffff000;
1016+
auto Instr = support::ulittle32_t::ref(InstrAddr);
1017+
Instr = (Instr & 0xfff) | UpperImm;
1018+
}
1019+
1020+
static void applyITypeImmRISCV(uint8_t *InstrAddr, uint32_t Imm) {
1021+
uint32_t LowerImm = Imm & 0xfff;
1022+
auto Instr = support::ulittle32_t::ref(InstrAddr);
1023+
Instr = (Instr & 0xfffff) | (LowerImm << 20);
1024+
}
1025+
1026+
void RuntimeDyldELF::resolveRISCVRelocation(const SectionEntry &Section,
1027+
uint64_t Offset, uint64_t Value,
1028+
uint32_t Type, int64_t Addend,
1029+
SID SectionID) {
1030+
switch (Type) {
1031+
default: {
1032+
std::string Err = "Unimplemented reloc type: " + std::to_string(Type);
1033+
llvm::report_fatal_error(Err.c_str());
1034+
}
1035+
// 32-bit PC-relative function call, macros call, tail (PIC)
1036+
// Write first 20 bits of 32 bit value to the auipc instruction
1037+
// Last 12 bits to the jalr instruction
1038+
case ELF::R_RISCV_CALL:
1039+
case ELF::R_RISCV_CALL_PLT: {
1040+
uint64_t P = Section.getLoadAddressWithOffset(Offset);
1041+
uint64_t PCOffset = Value + Addend - P;
1042+
applyUTypeImmRISCV(Section.getAddressWithOffset(Offset), PCOffset);
1043+
applyITypeImmRISCV(Section.getAddressWithOffset(Offset + 4), PCOffset);
1044+
break;
1045+
}
1046+
// High 20 bits of 32-bit absolute address, %hi(symbol)
1047+
case ELF::R_RISCV_HI20: {
1048+
uint64_t PCOffset = Value + Addend;
1049+
applyUTypeImmRISCV(Section.getAddressWithOffset(Offset), PCOffset);
1050+
break;
1051+
}
1052+
// Low 12 bits of 32-bit absolute address, %lo(symbol)
1053+
case ELF::R_RISCV_LO12_I: {
1054+
uint64_t PCOffset = Value + Addend;
1055+
applyITypeImmRISCV(Section.getAddressWithOffset(Offset), PCOffset);
1056+
break;
1057+
}
1058+
// High 20 bits of 32-bit PC-relative reference, %pcrel_hi(symbol)
1059+
case ELF::R_RISCV_GOT_HI20:
1060+
case ELF::R_RISCV_PCREL_HI20: {
1061+
uint64_t P = Section.getLoadAddressWithOffset(Offset);
1062+
uint64_t PCOffset = Value + Addend - P;
1063+
applyUTypeImmRISCV(Section.getAddressWithOffset(Offset), PCOffset);
1064+
break;
1065+
}
1066+
1067+
// label:
1068+
// auipc a0, %pcrel_hi(symbol) // R_RISCV_PCREL_HI20
1069+
// addi a0, a0, %pcrel_lo(label) // R_RISCV_PCREL_LO12_I
1070+
//
1071+
// The low 12 bits of relative address between pc and symbol.
1072+
// The symbol is related to the high part instruction which is marked by
1073+
// label.
1074+
case ELF::R_RISCV_PCREL_LO12_I: {
1075+
for (auto &&PendingReloc : PendingRelocs) {
1076+
const RelocationValueRef &MatchingValue = PendingReloc.first;
1077+
RelocationEntry &Reloc = PendingReloc.second;
1078+
uint64_t HIRelocPC =
1079+
getSectionLoadAddress(Reloc.SectionID) + Reloc.Offset;
1080+
if (Value + Addend == HIRelocPC) {
1081+
uint64_t Symbol = getSectionLoadAddress(MatchingValue.SectionID) +
1082+
MatchingValue.Addend;
1083+
auto PCOffset = Symbol - HIRelocPC;
1084+
applyITypeImmRISCV(Section.getAddressWithOffset(Offset), PCOffset);
1085+
return;
1086+
}
1087+
}
1088+
1089+
llvm::report_fatal_error(
1090+
"R_RISCV_PCREL_LO12_I without matching R_RISCV_PCREL_HI20");
1091+
}
1092+
case ELF::R_RISCV_32_PCREL: {
1093+
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
1094+
int64_t RealOffset = Value + Addend - FinalAddress;
1095+
int32_t TruncOffset = Lo_32(RealOffset);
1096+
support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) =
1097+
TruncOffset;
1098+
break;
1099+
}
1100+
case ELF::R_RISCV_32: {
1101+
auto Ref = support::ulittle32_t::ref(Section.getAddressWithOffset(Offset));
1102+
Ref = Value + Addend;
1103+
break;
1104+
}
1105+
case ELF::R_RISCV_64: {
1106+
auto Ref = support::ulittle64_t::ref(Section.getAddressWithOffset(Offset));
1107+
Ref = Value + Addend;
1108+
break;
1109+
}
1110+
case ELF::R_RISCV_ADD16: {
1111+
auto Ref = support::ulittle16_t::ref(Section.getAddressWithOffset(Offset));
1112+
Ref = Ref + Value + Addend;
1113+
break;
1114+
}
1115+
case ELF::R_RISCV_ADD32: {
1116+
auto Ref = support::ulittle32_t::ref(Section.getAddressWithOffset(Offset));
1117+
Ref = Ref + Value + Addend;
1118+
break;
1119+
}
1120+
case ELF::R_RISCV_ADD64: {
1121+
auto Ref = support::ulittle64_t::ref(Section.getAddressWithOffset(Offset));
1122+
Ref = Ref + Value + Addend;
1123+
break;
1124+
}
1125+
case ELF::R_RISCV_SUB16: {
1126+
auto Ref = support::ulittle16_t::ref(Section.getAddressWithOffset(Offset));
1127+
Ref = Ref - Value - Addend;
1128+
break;
1129+
}
1130+
case ELF::R_RISCV_SUB32: {
1131+
auto Ref = support::ulittle32_t::ref(Section.getAddressWithOffset(Offset));
1132+
Ref = Ref - Value - Addend;
1133+
break;
1134+
}
1135+
case ELF::R_RISCV_SUB64: {
1136+
auto Ref = support::ulittle64_t::ref(Section.getAddressWithOffset(Offset));
1137+
Ref = Ref - Value - Addend;
1138+
break;
1139+
}
1140+
}
1141+
}
1142+
10141143
// The target location for the relocation is described by RE.SectionID and
10151144
// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each
10161145
// SectionEntry has three members describing its location.
@@ -1076,12 +1205,17 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
10761205
case Triple::bpfeb:
10771206
resolveBPFRelocation(Section, Offset, Value, Type, Addend);
10781207
break;
1208+
case Triple::riscv32: // Fall through.
1209+
case Triple::riscv64:
1210+
resolveRISCVRelocation(Section, Offset, Value, Type, Addend, SectionID);
1211+
break;
10791212
default:
10801213
llvm_unreachable("Unsupported CPU type!");
10811214
}
10821215
}
10831216

1084-
void *RuntimeDyldELF::computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const {
1217+
void *RuntimeDyldELF::computePlaceholderAddress(unsigned SectionID,
1218+
uint64_t Offset) const {
10851219
return (void *)(Sections[SectionID].getObjAddress() + Offset);
10861220
}
10871221

@@ -1870,7 +2004,8 @@ RuntimeDyldELF::processRelocationRef(
18702004
Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset));
18712005
processSimpleRelocation(SectionID, Offset, RelType, Value);
18722006
} else if (RelType == ELF::R_X86_64_PC64) {
1873-
Value.Addend += support::ulittle64_t::ref(computePlaceholderAddress(SectionID, Offset));
2007+
Value.Addend += support::ulittle64_t::ref(
2008+
computePlaceholderAddress(SectionID, Offset));
18742009
processSimpleRelocation(SectionID, Offset, RelType, Value);
18752010
} else if (RelType == ELF::R_X86_64_GOTTPOFF) {
18762011
processX86_64GOTTPOFFRelocation(SectionID, Offset, Value, Addend);
@@ -1884,9 +2019,23 @@ RuntimeDyldELF::processRelocationRef(
18842019
} else {
18852020
processSimpleRelocation(SectionID, Offset, RelType, Value);
18862021
}
2022+
} else if (Arch == Triple::riscv32 || Arch == Triple::riscv64) {
2023+
// *_LO12 relocation receive information about a symbol from the
2024+
// corresponding *_HI20 relocation, so we have to collect this information
2025+
// before resolving
2026+
if (RelType == ELF::R_RISCV_GOT_HI20 ||
2027+
RelType == ELF::R_RISCV_PCREL_HI20 ||
2028+
RelType == ELF::R_RISCV_TPREL_HI20 ||
2029+
RelType == ELF::R_RISCV_TLS_GD_HI20 ||
2030+
RelType == ELF::R_RISCV_TLS_GOT_HI20) {
2031+
RelocationEntry RE(SectionID, Offset, RelType, Addend);
2032+
PendingRelocs.push_back({Value, RE});
2033+
}
2034+
processSimpleRelocation(SectionID, Offset, RelType, Value);
18872035
} else {
18882036
if (Arch == Triple::x86) {
1889-
Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset));
2037+
Value.Addend += support::ulittle32_t::ref(
2038+
computePlaceholderAddress(SectionID, Offset));
18902039
}
18912040
processSimpleRelocation(SectionID, Offset, RelType, Value);
18922041
}

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
6060
void resolveBPFRelocation(const SectionEntry &Section, uint64_t Offset,
6161
uint64_t Value, uint32_t Type, int64_t Addend);
6262

63+
void resolveRISCVRelocation(const SectionEntry &Section, uint64_t Offset,
64+
uint64_t Value, uint32_t Type, int64_t Addend,
65+
SID SectionID);
66+
6367
unsigned getMaxStubSize() const override {
6468
if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be)
6569
return 20; // movz; movk; movk; movk; br
@@ -148,6 +152,9 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
148152

149153
// *HI16 relocations will be added for resolving when we find matching
150154
// *LO16 part. (Mips specific)
155+
//
156+
// *HI20 relocations will be added for resolving when we find matching
157+
// *LO12 part. (RISC-V specific)
151158
SmallVector<std::pair<RelocationValueRef, RelocationEntry>, 8> PendingRelocs;
152159

153160
// When a module is loaded we save the SectionID of the EH frame section

0 commit comments

Comments
 (0)