nx_dbg.nx
buildroot/runtime/nx_dbg.nx
about
nx_dbg.nx -- sovereign single-step debugger primitive.
Wraps nx_rv64_sim with debugger superpowers:
* step run one instruction, return control
* cont run until breakpoint / halt / illegal
* break_at set a code-address breakpoint
* break_clr clear a code-address breakpoint
* dump_regs print all 32 GPR + pc to fd
* dump_stack print N words above sp
* locate PC -> source (file_idx, line) via nx_addr2line
All operations work without GDB / qemu / docker. When wired with
nxc_native_wrap, this is the sovereign equivalent of:
gdb --batch -ex "break main" -ex "run" -ex "info reg" my.elf
Pairs with our existing primitives:
nx_rv64_sim -- VM
nx_dis -- disassemble PC at current state
nx_addr2line -- map PC -> source line
nx_strfmt -- formatted output
v0.0.1 scope: simple breakpoint set (linear scan, up to 64
breakpoints). Future commits add: watchpoints, conditional
breakpoints, scripted recipes, GDB-stub remote-protocol.
dependencies 5 imports · 0 importers
imports: syscalls.nxnx_rv64_sim.nxnx_dis.nxnx_addr2line.nxnx_strfmt.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 43 | struct NxDbg |
consts
| 39 | const NX_MAGIC_9999: i64 = 9999 |
| 41 | const NX_DBG_MAX_BREAKPOINTS: i64 = 64 |
| 49 | const NX_DBG_BYTES: i64 = 24 |
functions
| 51 | func nx_dbg_new(cpu: *NxRv64Cpu) -> *NxDbg called by 1: main |
| 64 | func nx_dbg_break_at(d: *NxDbg, addr: i64) -> i64 called by 1: main |
| 77 | func nx_dbg_break_clr(d: *NxDbg, addr: i64) -> i64 called by 1: main |
| 92 | func nx_dbg_at_bp(d: *NxDbg) -> i64 called by 1: nx_dbg_cont |
| 105 | func nx_dbg_step(d: *NxDbg) -> i64 |
| 113 | func nx_dbg_cont(d: *NxDbg, max_insns: i64) -> i64 |
| 131 | func nx_dbg_dump_regs(d: *NxDbg, fd: i64) -> i64 |
| 149 | func nx_dbg_dump_disasm(d: *NxDbg, n: i64, fd: i64) -> i64 |
| 167 | func nx_dbg_dump_mem(d: *NxDbg, addr: i64, n: i64, fd: i64) -> i64 |
| 183 | func main() -> i64 |