nx_backtrace.nx
buildroot/runtime/nx_backtrace.nx
about
nx_backtrace.nx -- frame-pointer-based stack walker.
Walks the saved-frame-pointer chain to recover return addresses
for a backtrace. Used by:
- Panic handler (print stack on assertion / SIGSEGV)
- Sampling profilers
- Memory-leak attribution (allocate-site tracking)
Convention (RV64 ABI):
- s0 / fp = current frame pointer
- At each call, the prologue stores ra and previous-fp on the
stack and sets fp = sp + frame_size.
- The slot at [fp - 8] holds the previous frame's ra.
- The slot at [fp - 16] holds the previous frame's saved-fp.
Limitations:
- Functions compiled WITHOUT a frame pointer (e.g. -fomit-frame-pointer
leaf functions) are invisible to this walker. For full coverage
we need DWARF .eh_frame / nx_dwarf_cfi-driven unwinding -- that
belongs in a future nx_unwind module.
- We bound the walk at 64 frames to avoid runaway loops on
corrupted stacks.
API:
n = nx_bt_capture(start_fp, frames, max) -> count of frames captured
nx_bt_print(io, frames, n) -> print to fd
ra = nx_bt_self_fp() -> read fp register
nx_bt_self_fp is a stub today (NishiLang doesn't expose inline
asm yet); callers pass in a frame pointer they captured via the
host runtime. Once asm-block syntax lands the stub becomes a
real read of x8.
dependencies 1 imports · 0 importers
imports: syscalls.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 NxBtFrame |
consts
| 48 | const NX_BT_FRAME_BYTES: i64 = 16 |
| 49 | const NX_BT_MAX_FRAMES: i64 = 64 |
functions
| 57 | func nx_bt_capture(start_fp: i64, frames: *NxBtFrame, max: i64) -> i64 called by 1: main |
| 90 | func nx_bt_print_pc(fd: i64, pc: i64) -> i64 called by 1: nx_bt_print |
| 129 | func nx_bt_print(fd: i64, frames: *NxBtFrame, n: i64) -> i64 calls 1: nx_bt_print_pc |
| 142 | func main() -> i64 calls 1: nx_bt_capture |