nx_addr2line.nx
buildroot/runtime/nx_addr2line.nx
about
nx_addr2line.nx -- sovereign addr2line.
Given an ELF + a code address, walk the DWARF .debug_line program
and return the source (file_idx, line) at that address. Foundation
for the future nx_dbg.nx debugger ("show me the source line at PC")
+ sovereign nx_panic backtraces with file:line locations.
What we do (DWARF v5 ยง6.2 line-program VM):
1. Locate .debug_line section via nx_elf_read.
2. Decode the line-program header (file table + dir table).
3. Run the line-program VM until address >= target_addr or end.
4. Return the (file_idx, line) of the most recent committed row
whose address <= target.
Pairs with nx_dwarf_line.nx which BUILDS the section; together,
produce + consume the same byte format with our own code only.
v0.0.1 scope:
* Decode the standard opcodes our nx_dwarf_line emits:
DW_LNS_copy, DW_LNS_advance_pc, DW_LNS_advance_line,
DW_LNS_set_file
* Decode extended ops:
DW_LNE_end_sequence, DW_LNE_set_address
Special opcodes (the compact bias-encoded form) NOT yet decoded;
our emitter doesn't use them today. Add when the emitter does.
dependencies 3 imports · 1 importers
imports: syscalls.nxnx_elf_read.nxnx_dwarf_line.nx
imported by: nx_dbg.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 49 | struct NxA2LResult |
consts
| 42 | const NX_A2L_DW_LNS_copy: i64 = 0x01 |
| 43 | const NX_A2L_DW_LNS_advance_pc: i64 = 0x02 |
| 44 | const NX_A2L_DW_LNS_advance_line: i64 = 0x03 |
| 45 | const NX_A2L_DW_LNS_set_file: i64 = 0x04 |
| 46 | const NX_A2L_DW_LNE_end_sequence: i64 = 0x01 |
| 47 | const NX_A2L_DW_LNE_set_address: i64 = 0x02 |
| 56 | const NX_A2L_RESULT_BYTES: i64 = 32 |
functions
| 59 | func nx_a2l_uleb(buf: *u8, off: i64, consumed: *i64) -> i64 called by 1: nx_a2l_run |
| 76 | func nx_a2l_sleb(buf: *u8, off: i64, consumed: *i64) -> i64 called by 1: nx_a2l_run |
| 108 | func nx_a2l_run(buf: *u8, len: i64, target_addr: i64) -> *NxA2LResult |
| 217 | func main() -> i64 calls 1: nx_a2l_run |