RISC-V ret instruction resolution (#3211)

* Fix 'ret' alias of JALR in RISC-V, add test

* lint
pull/3213/head
OBarronCS 4 months ago committed by GitHub
parent 630eac36c8
commit 54099990ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -257,13 +257,19 @@ class RISCVDisassemblyAssistant(pwndbg.aglib.disasm.arch.DisassemblyAssistant):
# Determine the target address of the indirect jump
if instruction.id == RISCV_INS_JALR:
# jalr can be represented as:
# 1. jalr r1, rd, offset
# 2. jalr rd
# 3. jalr rd, offset
# If source is omitted, ra is implied as link register
# To find target, get the LAST
# jalr can be represented in the following ways:
# 1. jalr rd // Jump to rd
# 2. jalr rd, offset // Jump to rd+offset
# 3. jalr rX, rd, offset // Return address stored in rX, jump to rd+offset
# 4. jalr x0, x1, 0 // Disassembles as "ret", jump to ra
# To find target, get the LAST register
reg_op_count = instruction.op_count(CS_OP_REG)
if reg_op_count == 0:
# ra is implied as link register
return self._read_register_name(instruction, "ra", emu)
if (target := instruction.op_find(CS_OP_REG, reg_op_count).before_value) is None:
return None

@ -2,6 +2,7 @@ from __future__ import annotations
import gdb
import pwndbg.aglib.disasm.disassembly
import pwndbg.aglib.symbol
import pwndbg.color
import pwndbg.dbg
@ -76,6 +77,66 @@ def test_riscv64_jalr(qemu_assembly_run):
assert dis == expected
# .option norvc disables compressed instructions
RISCV64_JALR_VARIANTS = f"""
.option norvc
{RISCV64_PREAMBLE}
nop
one:
la ra, two
jalr x0, x1, 0
nop
two:
la x2, three
li x3, 8
sub x2, x2, x3
jalr x1, 8(x2)
nop
three:
la x2, four
jalr x2
nop
four:
la x2, end
li x3, 8
sub x2, x2, x3
jalr x2, 8
nop
end:
{RISCV64_GRACEFUL_EXIT}
"""
def test_riscv64_jalr_variants(qemu_assembly_run):
"""
Ensure targets are resolved correctly for different variants of RISC-V JALR
"""
qemu_assembly_run(RISCV64_JALR_VARIANTS, "riscv64")
gdb.execute("stepuntilasm ret")
ins = pwndbg.aglib.disasm.disassembly.emulate_one()
assert ins.target_string == "two"
gdb.execute("stepuntilasm jalr")
ins = pwndbg.aglib.disasm.disassembly.emulate_one()
assert ins.target_string == "three"
gdb.execute("stepuntilasm jalr")
ins = pwndbg.aglib.disasm.disassembly.emulate_one()
assert ins.target_string == "four"
gdb.execute("stepuntilasm jalr")
ins = pwndbg.aglib.disasm.disassembly.emulate_one()
assert ins.target_string == "end"
RISCV64_COMPRESSED_LOAD_STORE = f"""
{RISCV64_PREAMBLE}
li a0, 0x1234567890ABCDEF

Loading…
Cancel
Save