code wiki / _hdl_build / nx_gdbstub_gate.nx

nx_gdbstub_gate.nx

buildroot/runtime/_hdl_build/nx_gdbstub_gate.nx

26859 B490 linesdepth 6pulls 21 transitivereach 0 importersview sourcekind gate/proof
docsdependenciesstructsconstsfunctions

about

nx_gdbstub_gate.nx -- the VERDICT gate for NO1 (nx_gdbstub, watch symbol gdbstub_serve). NO mocks. THE ACCEPT RULE (nishios.plan NO1, verbatim): a STOCK gdb attaches to a running guest, breaks at an address the disassembler independently resolved, steps, reads a register whose value a separate path derived, and detaches leaving the guest running -- plus a NEG-CONTROL that a breakpoint at an address never executed does NOT stop. The oracle is a third-party debugger, so this rung cannot be self-graded. HOW EACH EXPECTATION IS DERIVED INDEPENDENTLY OF THE STUB (the stub is never its own oracle): bp address = the pc of the FIRST store-kind instruction the K-R0 boot image executes, found by running a SECOND, stub-free sim in this process and DECODING each fetched word with rv64im_min_decoder (nx_rv64im_decode_kind == NX_RV64IM_OP_STORE). register = that store's rs2 (decoded) read from the reference sim's regfile at that pc. next pc = bp + 4, after asserting the word is a 32-bit encoding ((w & 3) == 3) and a store never branches. memory words = the first two little-endian words of the IMAGE FILE, not of any sim. never-addr = the lowest 4-aligned RAM address at/after the image end that the reference run NEVER fetched (a bitmap of every executed pc over the WHOLE boot, not a guess). golden = <image>.gold, the transcript the boot rulers already certify. SESSIONS (each on a FRESH stub process, port 0 = kernel-chosen, read back from the stub's ready file): A stock gdb: attach, break *bp, continue, p/x $xN, stepi, x/2xw mem_base, detach -> T1..T7 B stock gdb: break *never-addr, continue -> the guest must run to EXIT, never a breakpoint stop -> T8 C sovereign RSP client (no gdb): a frame with a WRONG checksum must be NAK'd; a good '?' must be ACK'd and answered S05; 'D' must be answered OK; the stub must count the bad frame -> T9..T12 If no stock gdb is on this host, sessions A/B are a MISSING PRECONDITION (gv_need -> SKIP), never a pass and never a RED: the oracle leg is reported UNWITNESSED, C still runs. (NAS: no gdb; laptop WSL: gdb-multiarch 15.1 installed 2026-08-23 as a third-party ORACLE only.) Fixtures live in /tmp/nx_gdbstub_gate/ (created at setup; a crashed run cannot leave a fixture beside a production beat). Every tooth prints the values it compared, not only PASS/FAIL. license_tier: ORIGINAL (the debugger is an oracle; nothing of it ships)

dependencies 6 imports · 0 importers

nx_syscalls.nx nx_gate_verdict.nx nx_gatekit_lib.nx nx_http_server.nx nx_bootcap.nx rv64im_min_decoder.nx nx_gdbstub_gate.nx

imports: nx_syscalls.nxnx_gate_verdict.nxnx_gatekit_lib.nxnx_http_server.nxnx_bootcap.nxrv64im_min_decoder.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main gv_head gv_puts sys_write gv_ctr sys_mmap nxa_die sys_write ↻ sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ gk_mkdir sys_mkdir sys_mmap ↻ gg_resolve gk_exists sys_openat_rd sys_close gk_cat gk_len gg_p gv_puts ↻ bootcap_load gg_n gv_num sys_mmap ↻ sys_write ↻ sys_munmap gk_cat ↻ sys_read_file sys_openat_rd ↻

structs

none

consts

38const GG_DIR: *u8 = "/tmp/nx_gdbstub_gate"
39const GG_IMG: *u8 = "runtime/_hdl_build/_boot_nishi_virt.bin"
40const GG_IMG_ALT: *u8 = "_boot_nishi_virt.bin"
41const GG_OUT_CAP: i64 = 1048576 // gdb's batch output for a 1,164-step boot is a few KB; 1 MiB = the gatekit capture bound
44const GG_READY_MS: i64 = 5000
45const GG_READY_POLL_MS: i64 = 50
48const GG_GDB_MS: i64 = 60000
49const GG_IO_MS: i64 = 5000 // session C: one reply should arrive within this; a stub that answers nothing fails the tooth
50const GG_RV_INSTR_BYTES: i64 = 4
51const GG_EXIT_CODE_RD: i64 = 0

functions

53func gg_p(s: *u8) -> i64 { return gv_puts(s) }
called by 2: gg_reapmain calls 1: gv_puts
54func gg_n(v: i64) -> i64 { return gv_num(v) }
called by 1: main calls 1: gv_num
55func gg_hex(v: i64) -> i64
called by 1: main calls 3: sys_mmapsys_writesys_munmap
68func gg_find(buf: *u8, n: i64, from: i64, needle: *u8) -> i64
called by 2: gg_value_aftermain calls 1: gk_len
81func gg_hexval(c: i64) -> i64
called by 1: gg_parse_hex
88func gg_parse_hex(buf: *u8, n: i64, i: i64, ndig: *i64) -> i64
called by 2: gg_value_aftermain calls 1: gg_hexval
105func gg_value_after(buf: *u8, n: i64, needle: *u8, k: i64, found: *i64) -> i64
129func gg_resolve(out: *u8, a: *u8, b: *u8, c: *u8) -> i64
called by 1: main calls 3: gk_existsgk_catgk_len
138func gg_spawn(elf: *u8, a1: *u8, a2: *u8, a3: *u8, logpath: *u8) -> i64
158func gg_wait_port(readyfile: *u8) -> i64
called by 1: main calls 3: sys_mmapgk_readsys_sleep_ms
176func gg_reap(pid: i64, budget_ms: i64) -> i64
193func gg_rsp_connect(port: i64) -> i64
203func gg_rsp_read(fd: i64, buf: *u8, cap: i64, want: i64) -> i64
221func main() -> i64