Skip to content

Commit

Permalink
support riscv:rv64 without capstone (#1096)
Browse files Browse the repository at this point in the history
* add riscv:rv64 registers

base on #829 by Tobias Faller <faller@endiio.com>

* disassemble without capstone to support other architectures

* ignore gdb.error on context_backtrace
  • Loading branch information
lonnywong committed Aug 30, 2022
1 parent 340dd2d commit e92a45c
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 1 deletion.
3 changes: 2 additions & 1 deletion pwndbg/commands/context.py
Expand Up @@ -720,7 +720,8 @@ def context_backtrace(with_banner=True, target=sys.stdout, width=None):
for i in range(backtrace_lines - 1):
try:
candidate = oldest_frame.older()
except gdb.MemoryError:
# We catch gdb.error in case of a `gdb.error: PC not saved` case
except (gdb.MemoryError, gdb.error):
break

if not candidate:
Expand Down
17 changes: 17 additions & 0 deletions pwndbg/disasm/__init__.py
Expand Up @@ -117,8 +117,25 @@ def get_disassembler(pc):
)


class SimpleInstruction:
def __init__(self, address):
self.address = address
ins = gdb.newest_frame().architecture().disassemble(address)[0]
asm = ins["asm"].split(None, 1)
self.mnemonic = asm[0].strip()
self.op_str = asm[1].strip() if len(asm) > 1 else ""
self.size = ins["length"]
self.next = self.address + self.size
self.target = self.next
self.groups = []
self.symbol = None
self.condition = False


@pwndbg.memoize.reset_on_cont
def get_one_instruction(address):
if pwndbg.arch.current not in CapstoneArch:
return SimpleInstruction(address)
md = get_disassembler(address)
size = VariableInstructionSizeMax.get(pwndbg.arch.current, 4)
data = pwndbg.memory.read(address, size, partial=True)
Expand Down
119 changes: 119 additions & 0 deletions pwndbg/regs.py
Expand Up @@ -473,6 +473,124 @@ def __iter__(self):
retval="v0",
)

# https://riscv.org/technical/specifications/
# Volume 1, Unprivileged Spec v. 20191213
# Chapter 25 - RISC-V Assembly Programmer’s Handbook
# x0 => zero (Hard-wired zero)
# x1 => ra (Return address)
# x2 => sp (Stack pointer)
# x3 => gp (Global pointer)
# x4 => tp (Thread pointer)
# x5 => t0 (Temporary/alternate link register)
# x6–7 => t1–2 (Temporaries)
# x8 => s0/fp (Saved register/frame pointer)
# x9 => s1 (Saved register)
# x10-11 => a0–1 (Function arguments/return values)
# x12–17 => a2–7 (Function arguments)
# x18–27 => s2–11 (Saved registers)
# x28–31 => t3–6 (Temporaries)
# f0–7 => ft0–7 (FP temporaries)
# f8–9 => fs0–1 (FP saved registers)
# f10–11 => fa0–1 (FP arguments/return values)
# f12–17 => fa2–7 (FP arguments)
# f18–27 => fs2–11 (FP saved registers)
# f28–31 => ft8–11 (FP temporaries)
riscv = RegisterSet(
pc="pc",
frame="fp",
stack="sp",
retaddr="ra",
gpr=(
"ra",
"gp",
"tp",
"t0",
"t1",
"t2",
"fp",
"s1",
"a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
"s8",
"s9",
"s10",
"s11",
"t3",
"t4",
"t5",
"t6",
"ft0",
"ft1",
"ft2",
"ft3",
"ft4",
"ft5",
"ft6",
"ft7",
"fs0",
"fs1",
"fa0",
"fa1",
"fa2",
"fa3",
"fa4",
"fa5",
"fa6",
"fa7",
"fs2",
"fs3",
"fs4",
"fs5",
"fs6",
"fs7",
"fs8",
"fs9",
"fs10",
"fs11",
"ft8",
"ft9",
"ft10",
"ft11",
),
retval=(
"a0",
"a1",
"fa0",
"fa1",
),
args=(
"a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"fa0",
"fa1",
"fa2",
"fa3",
"fa4",
"fa5",
"fa6",
"fa7",
),
)


arch_to_regs = {
"i386": i386,
"i8086": i386,
Expand All @@ -483,6 +601,7 @@ def __iter__(self):
"armcm": armcm,
"aarch64": aarch64,
"powerpc": powerpc,
"riscv:rv64": riscv,
}


Expand Down

0 comments on commit e92a45c

Please sign in to comment.