Skip to content

Commit 353a798

Browse files
jnohlgardghidra1
authored andcommitted
Implement handling of relocations R_RISCV_CALL, R_RISCV_HI20,
R_RISCV_LO12, R_RISCV_RVC_BRANCH, R_RISCV_RVC_JUMP, R_RISCV_BRANCH, R_RISCV_JAL
1 parent 4fbb7bf commit 353a798

File tree

1 file changed

+58
-28
lines changed

1 file changed

+58
-28
lines changed

Ghidra/Processors/RISCV/src/main/java/ghidra/app/util/bin/format/elf/relocation/RISCV_ElfRelocationHandler.java

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -186,22 +186,33 @@ public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
186186
return RelocationResult.UNSUPPORTED;
187187

188188
case RISCV_ElfRelocationConstants.R_RISCV_BRANCH:
189-
// PC-relative branch (SB-Type)
190-
markAsWarning(program, relocationAddress, "R_RISCV_BRANCH", symbolName, symbolIndex,
191-
"TODO, needs support ", elfRelocationContext.getLog());
192-
return RelocationResult.UNSUPPORTED;
189+
// PC-relative branch (B-Type)
190+
int target = (int) (addend + symbolValue - offset);
191+
value32 =
192+
((target & 0x01e) << 7) | ((target & 0x0800) >> 4) | ((target & 0x03e0) << 20) |
193+
((target & 0x1000) << 19) | memory.getInt(relocationAddress);
194+
memory.setInt(relocationAddress, value32);
195+
break;
193196

194197
case RISCV_ElfRelocationConstants.R_RISCV_JAL:
195-
// PC-relative jump (UJ-Type)
196-
markAsWarning(program, relocationAddress, "R_RISCV_JAL", symbolName, symbolIndex,
197-
"TODO, needs support ", elfRelocationContext.getLog());
198-
return RelocationResult.UNSUPPORTED;
198+
// PC-relative jump (J-Type)
199+
target = (int) (addend + symbolValue - offset);
200+
value32 =
201+
(target & 0xff000) | ((target & 0x00800) << 9) | ((target & 0x007fe) << 20) |
202+
((target & 0x100000) << 11) | memory.getInt(relocationAddress);
203+
memory.setInt(relocationAddress, value32);
204+
break;
199205

200206
case RISCV_ElfRelocationConstants.R_RISCV_CALL:
201207
// PC-relative call MACRO call,tail (auipc+jalr pair)
202-
markAsWarning(program, relocationAddress, "R_RISCV_CALL", symbolName, symbolIndex,
203-
"TODO, needs support ", elfRelocationContext.getLog());
204-
return RelocationResult.UNSUPPORTED;
208+
target = (int) (addend + symbolValue - offset);
209+
int target_l = target << 20 >> 20;
210+
int target_h = target - target_l;
211+
value32 = (target_h & 0xfffff000) | memory.getInt(relocationAddress);
212+
memory.setInt(relocationAddress, value32);
213+
value32 = ((target_l & 0x00000fff) << 20) | memory.getInt(relocationAddress.add(4));
214+
memory.setInt(relocationAddress.add(4), value32);
215+
break;
205216

206217
case RISCV_ElfRelocationConstants.R_RISCV_CALL_PLT:
207218
// PC-relative call (PLT) MACRO call,tail (auipc+jalr pair) PIC
@@ -254,21 +265,25 @@ public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
254265

255266
case RISCV_ElfRelocationConstants.R_RISCV_HI20:
256267
// Absolute address %hi(symbol) (U-Type)
257-
markAsWarning(program, relocationAddress, "R_RISCV_HI20", symbolName, symbolIndex,
258-
"TODO, needs support ", elfRelocationContext.getLog());
259-
return RelocationResult.UNSUPPORTED;
268+
value32 =
269+
(int) ((symbolValue + 0x800) & 0xfffff000) | memory.getInt(relocationAddress);
270+
memory.setInt(relocationAddress, value32);
271+
break;
260272

261273
case RISCV_ElfRelocationConstants.R_RISCV_LO12_I:
262274
// Absolute address %lo(symbol) (I-Type)
263-
markAsWarning(program, relocationAddress, "R_RISCV_LO12_I", symbolName, symbolIndex,
264-
"TODO, needs support ", elfRelocationContext.getLog());
265-
return RelocationResult.UNSUPPORTED;
275+
value32 =
276+
((int) (symbolValue & 0x00000fff) << 20) | memory.getInt(relocationAddress);
277+
memory.setInt(relocationAddress, value32);
278+
break;
266279

267280
case RISCV_ElfRelocationConstants.R_RISCV_LO12_S:
268281
// Absolute address %lo(symbol) (S-Type)
269-
markAsWarning(program, relocationAddress, "R_RISCV_LO12_S", symbolName, symbolIndex,
270-
"TODO, needs support ", elfRelocationContext.getLog());
271-
return RelocationResult.UNSUPPORTED;
282+
value32 = (int) (symbolValue & 0x00000fff);
283+
value32 = ((value32 & 0x1f) << 7) | ((value32 & 0xfe0) << 20) |
284+
memory.getInt(relocationAddress);
285+
memory.setInt(relocationAddress, value32);
286+
break;
272287

273288
case RISCV_ElfRelocationConstants.R_RISCV_TPREL_HI20:
274289
// TLS LE thread offset %tprel_hi(symbol) (U-Type)
@@ -406,17 +421,32 @@ public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
406421

407422
case RISCV_ElfRelocationConstants.R_RISCV_RVC_BRANCH:
408423
// PC-relative branch offset (CB-Type)
409-
markAsWarning(program, relocationAddress, "R_RISCV_RVC_BRANCH", symbolName,
410-
symbolIndex,
411-
"TODO, needs support ", elfRelocationContext.getLog());
412-
return RelocationResult.UNSUPPORTED;
424+
target = (short) (addend + symbolValue - offset);
425+
// 15 13 | 12 11 10|9 7| 6 5 4 3 2|1 0
426+
// C.BEQZ offset[8|4:3] src offset[7:6|2:1|5] C1
427+
value16 = (short) (((target & 0x100) << 4) | ((target & 0x18) << 7) |
428+
((target & 0xc0) >> 1) |
429+
((target & 0x06) << 2) | ((target & 0x20) >> 3) |
430+
(memory.getShort(relocationAddress) & 0xe383));
431+
byteLength = 2;
432+
memory.setShort(relocationAddress, value16);
433+
break;
413434

414435
case RISCV_ElfRelocationConstants.R_RISCV_RVC_JUMP:
415436
// PC-relative jump offset (CJ-Type)
416-
markAsWarning(program, relocationAddress, "R_RISCV_RVC_BRANCH", symbolName,
417-
symbolIndex,
418-
"TODO, needs support ", elfRelocationContext.getLog());
419-
return RelocationResult.UNSUPPORTED;
437+
target = (short) (addend + symbolValue - offset);
438+
// Complicated swizzling going on here.
439+
// For details, see The RISC-V Instruction Set Manual Volume I: Unprivileged ISA
440+
// 15 13 | 12 11 10 9 8 7 6 5 3 2|1 0
441+
// C.J offset[11| 4|9:8|10|6|7|3:1|5] C1
442+
value16 = (short) (((target & 0x800) << 1) | ((target & 0x10) << 7) |
443+
((target & 0x300) << 1) |
444+
((target & 0x400) >> 2) | ((target & 0x40) << 1) | ((target & 0x80) >> 1) |
445+
((target & 0x0e) << 2) | ((target & 0x20) >> 3) |
446+
(memory.getShort(relocationAddress) & 0xe003));
447+
byteLength = 2;
448+
memory.setShort(relocationAddress, value16);
449+
break;
420450

421451
case RISCV_ElfRelocationConstants.R_RISCV_RVC_LUI:
422452
// Absolute address (CI-Type)

0 commit comments

Comments
 (0)