code wiki / _hdl_build / nx_xlate_gap_gate.nx

nx_xlate_gap_gate.nx source

↩ module page · 110 lines · 5582 B

1// nx_xlate_gap_gate.nx -- regression gate for the NXASM-SYSCALL-XLATE-GAP class: every syscall once 2// filed as untranslated (mkdirat-34, renameat2-276 via the 2026-06-06 table rows; fsync-74 and 3// unlinkat-263 via the proven direct-x86 escape hatch) must BEHAVE at runtime under the CURRENT 4// blessed toolchain. Each row is a discriminating pair where possible (valid input succeeds AND 5// invalid input fails with the right errno), so a pass cannot be a silent no-op. 6// Durable: XLATE-ROW + XLATE-GATE lines -> knowledge/status/xlate_gap_gate.log. Exit 0 iff all rows 7// PASS. Owner: Engineer. Resolves sentinel key NXASM-XLATE-GAP. license_tier: ORIGINAL 8import "nx_syscalls.nx" 9const AT_FDCWD: i64 = 0 - 100 10func _p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 11func _fs(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 12func _fn(fd: i64, v: i64) -> i64 { 13 let b: *u8 = sys_mmap(32) 14 var x: i64 = v 15 if x < 0 { _fs(fd, "-" as *u8); x = 0 - x } 16 var i: i64 = 31 17 b[i] = 0 as u8 18 i = i - 1 19 if x == 0 { b[i] = 48 as u8; i = i - 1 } 20 while x > 0 { b[i] = ((x - (x / 10) * 10) + 48) as u8; x = x / 10; i = i - 1 } 21 let base: i64 = b as i64 22 _fs(fd, (base + i + 1) as *u8) 23 return 0 24} 25func xg_unlink(p: *u8) -> i64 { return __syscall(263, AT_FDCWD, p, 0, 0, 0, 0) } 26func xg_rmdir(p: *u8) -> i64 { return __syscall(263, AT_FDCWD, p, 512, 0, 0, 0) } // unlinkat AT_REMOVEDIR(0x200) 27// hermetic fixture reset (rule 10 idempotent): clear any leftover from a crashed/prior run so a stale 28// dir/file can never spuriously RED this gate. Best-effort -- errors ignored (paths may not exist). 29func xg_clean() -> i64 { 30 xg_unlink("/tmp/_xg_dir/f" as *u8) 31 xg_unlink("/tmp/_xg_dir/f.new" as *u8) 32 xg_unlink("/tmp/_xg_dir/f.live" as *u8) 33 xg_rmdir("/tmp/_xg_dir" as *u8) 34 return 0 35} 36func xg_row(lfd: i64, name: *u8, ok: i64, rc1: i64, rc2: i64) -> i64 { 37 _p(" " as *u8); _p(name); _p(": rc1=" as *u8); _fn(1, rc1); _p(" rc2=" as *u8); _fn(1, rc2) 38 _fs(lfd, "XLATE-ROW name=" as *u8); _fs(lfd, name) 39 _fs(lfd, " rc1=" as *u8); _fn(lfd, rc1); _fs(lfd, " rc2=" as *u8); _fn(lfd, rc2) 40 if ok == 1 { _p(" PASS\n" as *u8); _fs(lfd, " verdict=PASS\n" as *u8) } 41 if ok != 1 { _p(" FAIL\n" as *u8); _fs(lfd, " verdict=FAIL\n" as *u8) } 42 return 0 43} 44func main() -> i64 { 45 _p("=== XLATE GAP GATE: every once-gapped syscall behaves under the current blessed toolchain ===\n" as *u8) 46 let lfd: i64 = sys_openat_append("knowledge/status/xlate_gap_gate.log" as *u8, 0x1a4) 47 if lfd < 0 { _p(" gate log open FAILED -- loud fail\n" as *u8); sys_exit(1); return 1 } 48 xg_clean() // hermetic START: a stale fixture (e.g. a root-owned /tmp/_xg_dir from a prior sudo run) must not poison the test 49 var pass: i64 = 0 50 51 // [1] mkdirat (rv64 34 -> x86 258, table row): create ok or already-exists; a bogus nested path fails 52 let d: *u8 = "/tmp/_xg_dir" as *u8 53 let r1a: i64 = sys_mkdir(d, 0x1ed) 54 let r1b: i64 = sys_mkdir("/tmp/_xg_nodir/sub" as *u8, 0x1ed) 55 var ok1: i64 = 0 56 if r1a == 0 { ok1 = 1 } 57 if r1a == (0 - 17) { ok1 = 1 } 58 if r1b >= 0 { ok1 = 0 } 59 xg_row(lfd, "mkdirat-34" as *u8, ok1, r1a, r1b) 60 pass = pass + ok1 61 62 // [2] fsync (direct x86 74): 0 on a valid fd, -9 EBADF on a bad fd (discriminating pair) 63 let f: *u8 = "/tmp/_xg_dir/f" as *u8 64 let wfd: i64 = sys_openat_wr(f, 0x1a4) 65 sys_write(wfd, "xlate-gap-gate\n" as *u8, 15) 66 let r2a: i64 = sys_fsync(wfd) 67 sys_close(wfd) 68 let r2b: i64 = sys_fsync(9999) 69 var ok2: i64 = 0 70 if r2a == 0 { if r2b == (0 - 9) { ok2 = 1 } } 71 xg_row(lfd, "fsync-74" as *u8, ok2, r2a, r2b) 72 pass = pass + ok2 73 74 // [3] renameat2 (rv64 276 -> x86 316, table row): atomic swap then the live path reads back 75 let fn2: *u8 = "/tmp/_xg_dir/f.new" as *u8 76 let fl: *u8 = "/tmp/_xg_dir/f.live" as *u8 77 let nfd: i64 = sys_openat_wr(fn2, 0x1a4) 78 sys_write(nfd, "live\n" as *u8, 5) 79 sys_close(nfd) 80 let r3a: i64 = sys_renameat(fn2, fl) 81 let rfd: i64 = sys_openat_rd(fl) 82 var ok3: i64 = 0 83 if r3a == 0 { if rfd >= 0 { ok3 = 1 } } 84 if rfd >= 0 { sys_close(rfd) } 85 xg_row(lfd, "renameat2-276" as *u8, ok3, r3a, rfd) 86 pass = pass + ok3 87 88 // [4] unlinkat (direct x86 263): removes the live file; a re-open then fails 89 let r4a: i64 = xg_unlink(fl) 90 let gone: i64 = sys_openat_rd(fl) 91 var ok4: i64 = 0 92 if r4a == 0 { if gone < 0 { ok4 = 1 } } 93 if gone >= 0 { sys_close(gone) } 94 xg_row(lfd, "unlinkat-263" as *u8, ok4, r4a, gone) 95 pass = pass + ok4 96 97 xg_unlink(f) 98 xg_unlink(fl) // row 4 already removed it; best-effort 99 xg_rmdir(d) // best-effort; NB unlinkat+AT_REMOVEDIR(512) does NOT remove the dir here (flags-arg 100 // translation gap for syscall 263 -- flags=0 unlink works, =512 rmdir no-ops). Harmless: 101 // the empty USER-OWNED dir is reused + writable, and xg_clean() at START guarantees idempotency. 102 _fs(lfd, "XLATE-GATE rows=4 pass=" as *u8); _fn(lfd, pass) 103 if pass == 4 { _fs(lfd, " verdict=GREEN\n" as *u8) } else { _fs(lfd, " verdict=RED\n" as *u8) } 104 sys_close(lfd) 105 _p(" --- XLATE GATE: " as *u8); _fn(1, pass); _p("/4 rows ---\n" as *u8) 106 if pass == 4 { _p(" XLATE GAP GATE: GREEN (gap class closed under current bless)\n" as *u8); sys_exit(0); return 0 } 107 _p(" XLATE GAP GATE: RED (a gap regressed -- fix the toolchain, never the gate)\n" as *u8) 108 sys_exit(1) 109 return 1 110}