code wiki / _hdl_build / nx_doctor_sov_verify.nx

nx_doctor_sov_verify.nx source

↩ module page · 135 lines · 6792 B

1// nx_doctor_sov_verify.nx -- the NISHI DOCTOR's one-step batch sovereign verifier (operator: "have the 2// nishi doctor get tutored to do this in one step and less than ten seconds"). ONE invocation builds + 3// runs + reports MANY modules through the pure-sovereign path (nx_cc -> nxasm_x86 -> run, NO gcc, NO .sh, 4// NO shell loop -- the loop is NishiLang, so it never hits the wsl $VAR-mangling trap). Each module: 5// compile (stdout->/tmp/<m>.s, stderr muted, recompile-retry), assemble+link with nxasm_x86_main, run, 6// capture the real exit via sys_wait4. Prints one line per module + a PASS/FAIL summary; exits 0 iff all 7// passed (treats the module's own expect_exit==0 convention). Usage: 8// nx_doctor_sov_verify <module1> <module2> ... 9// license_tier: ORIGINAL Reuses the sovereign spine from nx_sov_build_run. 10import "nx_syscalls.nx" 11const DSV_MAGIC_4096: i64 = 4096 12 13const DSV_MIN_ASM_BYTES: i64 = 128 14const DSV_MAX_RETRIES: i64 = 12 15const DSV_RUN_TIMEOUT_MS: i64 = 8000 // the <10s law: a hung module is KILLED + reported, never waited on 16 17func dsv_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 18func dsv_putn(v: i64) -> i64 { let bb: *u8 = sys_mmap(28); var m: i64=v; if m<0 {m=0-m;sys_write(1,"-" as *u8,1)}; let t: *u8 = sys_mmap(28); var k: i64=0; if m==0 {t[0]=48;k=1}; while m>0 {t[k]=48+(m%10); m=m/10; k=k+1}; var i: i64=0; while i<k {bb[i]=t[k-1-i]; i=i+1}; sys_write(1, bb, k); return 0 } 19func dsv_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[off+i] = s[i]; i = i + 1 } return off + i } 20 21// fork + stdout/stderr redirect + execve; parent waits; returns child's WEXITSTATUS. 22func dsv_run(path: *u8, argv: *i64, envp: *i64, redir_out: i64, redir_err: i64) -> i64 { 23 let pid: i64 = sys_fork() 24 if pid == 0 { 25 if redir_out >= 0 { sys_dup3(redir_out, 1, 0) } 26 if redir_err >= 0 { sys_dup3(redir_err, 2, 0) } 27 sys_execve(path, argv, envp) 28 sys_exit(127) 29 } 30 let st: *i64 = sys_mmap(16) as *i64 31 sys_wait4(pid, st, 0) 32 return (st[0] >> 8) & 0xff 33} 34 35func dsv_filesize(path: *u8) -> i64 { 36 let fd: i64 = sys_openat_rd(path) 37 if fd < 0 { return 0 } 38 let buf: *u8 = sys_mmap(DSV_MAGIC_4096) 39 var total: i64 = 0 40 var n: i64 = sys_read(fd, buf, DSV_MAGIC_4096) 41 while n > 0 { total = total + n; n = sys_read(fd, buf, DSV_MAGIC_4096) } 42 sys_close(fd) 43 return total 44} 45 46// build ONE module through the sovereign path; return its run-exit, or a negative code on build failure. 47// -3 = compile-fail (empty .s after retries) ; -4 = nxasm-fail (unencoded instruction) 48func dsv_build_run_one(name: *u8, compiler: *u8, asm_tool: *u8, envp: *i64, devnull: i64) -> i64 { 49 let src: *u8 = sys_mmap(512); var o: i64 = 0 50 o = dsv_cat(src, o, "runtime/_hdl_build/" as *u8); o = dsv_cat(src, o, name); o = dsv_cat(src, o, ".nx" as *u8); src[o] = 0 as u8 51 let chk: i64 = sys_openat_rd(src) 52 if chk < 0 { o = 0; o = dsv_cat(src, o, "runtime/" as *u8); o = dsv_cat(src, o, name); o = dsv_cat(src, o, ".nx" as *u8); src[o] = 0 as u8 } 53 if chk >= 0 { sys_close(chk) } 54 let spath: *u8 = sys_mmap(256); o = 0 55 o = dsv_cat(spath, o, "/tmp/" as *u8); o = dsv_cat(spath, o, name); o = dsv_cat(spath, o, ".s" as *u8); spath[o] = 0 as u8 56 let elfpath: *u8 = sys_mmap(256); o = 0 57 o = dsv_cat(elfpath, o, "/tmp/" as *u8); o = dsv_cat(elfpath, o, name); o = dsv_cat(elfpath, o, ".sov.elf" as *u8); elfpath[o] = 0 as u8 58 59 var asmbytes: i64 = 0 60 var tries: i64 = 0 61 while tries < DSV_MAX_RETRIES { 62 let sfd: i64 = sys_openat_wr(spath, 0x1a4) 63 let cc: *i64 = sys_mmap(8*4) as *i64 64 cc[0] = compiler as i64; cc[1] = src as i64; cc[2] = 0 65 dsv_run(compiler, cc, envp, sfd, devnull) 66 sys_close(sfd) 67 asmbytes = dsv_filesize(spath) 68 if asmbytes > DSV_MIN_ASM_BYTES { tries = DSV_MAX_RETRIES } 69 if tries != DSV_MAX_RETRIES { tries = tries + 1 } 70 } 71 if asmbytes <= DSV_MIN_ASM_BYTES { return 0 - 3 } 72 73 let aa: *i64 = sys_mmap(8*4) as *i64 74 aa[0] = asm_tool as i64; aa[1] = spath as i64; aa[2] = elfpath as i64; aa[3] = 0 75 let rc_a: i64 = dsv_run(asm_tool, aa, envp, 0 - 1, devnull) 76 if rc_a != 0 { return 0 - 4 } 77 78 let rr: *i64 = sys_mmap(8*4) as *i64 79 rr[0] = elfpath as i64; rr[1] = 0 80 return dsv_run_watchdog(elfpath, rr, envp, DSV_RUN_TIMEOUT_MS) // stdout passes through; hung = killed 81} 82 83// run under a SOVEREIGN WATCHDOG: a timer child sleeps then kills the test pid. A module that 84// hangs (the 7-minute jam-check spin) is killed at the deadline and reported as -9, instead of 85// the Doctor inheriting the hang. wait4 on both children -- no zombies. 86func dsv_run_watchdog(path: *u8, argv: *i64, envp: *i64, timeout_ms: i64) -> i64 { 87 let pid: i64 = sys_fork() 88 if pid == 0 { 89 sys_execve(path, argv, envp) 90 sys_exit(127) 91 } 92 let wd: i64 = sys_fork() 93 if wd == 0 { 94 sys_sleep_ms(timeout_ms) 95 nx_kill(pid, 9) 96 sys_exit(0) 97 } 98 let st: *i64 = sys_mmap(16) as *i64 99 sys_wait4(pid, st, 0) 100 nx_kill(wd, 9) 101 let st2: *i64 = sys_mmap(16) as *i64 102 sys_wait4(wd, st2, 0) 103 if (st[0] % 256) != 0 { return 0 - 9 } // signal-killed (timeout watchdog or crash) 104 return (st[0] >> 8) & 0xff 105} 106 107func main(argc: i64, argv: *i64) -> i64 { 108 if argc < 2 { dsv_puts("usage: nx_doctor_sov_verify <module1> <module2> ...\n" as *u8); sys_exit(2); return 2 } 109 let compiler: *u8 = "_offc/nx_cc_known_good.elf" as *u8 110 let asm_tool: *u8 = "_offc/nxasm_x86_main.elf" as *u8 111 let envp: *i64 = sys_mmap(8*4) as *i64 112 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0 113 let devnull: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4) 114 115 dsv_puts("=== NISHI DOCTOR sovereign batch verify (nx_cc->nxasm_x86->run, no gcc/sh) ===\n" as *u8) 116 var pass: i64 = 0 117 var total: i64 = 0 118 var i: i64 = 1 119 while i < argc { 120 let name: *u8 = argv[i] as *u8 121 let rc: i64 = dsv_build_run_one(name, compiler, asm_tool, envp, devnull) 122 total = total + 1 123 dsv_puts(" DOCTOR module=" as *u8); dsv_puts(name); dsv_puts(" exit=" as *u8); dsv_putn(rc) 124 if rc == 0 { dsv_puts(" PASS\n" as *u8); pass = pass + 1 } 125 if rc == 0 - 3 { dsv_puts(" BUILD-FAIL(compile)\n" as *u8) } 126 if rc == 0 - 4 { dsv_puts(" BUILD-FAIL(nxasm-unencoded)\n" as *u8) } 127 if rc == 0 - 9 { dsv_puts(" TIMEOUT/SIGNAL(watchdog-killed)\n" as *u8) } 128 if rc > 0 { dsv_puts(" FAIL(runtime exit)\n" as *u8) } 129 i = i + 1 130 } 131 dsv_puts("DOCTOR SUMMARY pass=" as *u8); dsv_putn(pass); dsv_puts("/" as *u8); dsv_putn(total); dsv_puts("\n" as *u8) 132 if pass == total { sys_exit(0) } 133 sys_exit(1) 134 return 1 135}