nx_pe_compile_win_nishi.nx
buildroot/runtime/nx_pe_compile_win_nishi.nx
about
nx_pe_compile_win_nish.nx -- W-NISH: the SOVEREIGN NISHI BROWSER (nish), native Windows PE.
Keystone-linker: takes nxc2-compiled nish (runtime/_hdl_build/nish.nx -> /tmp/nxwin.s via
nx_compile_x86_native) and emits a NATIVE Windows .exe whose Linux syscalls are redirected to
Win32 (kernel32 + ws2_32) thunks -- no WSL, no gcc, no curl/openssl/zlib. Mirrors the proven
nx_pe_compile_win_uiserve.nx pattern, sized for nish's ~0.8MB position-independent .text.
STAGE 3 (live): real thunks for the whole reached syscall surface so nish performs a live HTTPS
fetch + render natively. WSAStartup is injected into the entry stub (nish never calls it -- it is
a Linux program). Stage 2a (kernel32-only, network neutralized) already proved the PE layout +
1.34MB CA-bundle read + clock + console on the real nish; this stage adds the network layer.
nish's reached syscall surface (measured from its .s, call-site counts):
sys_mmap x471 -> HeapAlloc; sys_write x14 -> WriteFile(fd<=2) | send(socket);
sys_read x7 -> stdin ReadFile(fd==0) | recv(socket); sys_close x12 -> closesocket;
sys_exit x4 -> ExitProcess; sys_socket x3 -> socket(honor args, TCP+UDP);
sys_connect x2 -> connect; sys_sendto/sys_recvfrom -> UDP DNS; sys_openat_rd x2 ->
CreateFileA (/dev/urandom -> fail -> deterministic entropy fallback); sys_read_file -> CA bundle;
sys_now_realtime_sec -> GetSystemTimeAsFileTime; sys_setsockopt x2 -> 0 (blocking sockets).
Everything else compiled-in but never called.
ABI bridge: compiled nish is SysV; Win32 callees are MS-x64. The intersection of registers a SysV
caller assumes survive a call {rbx,rbp,rsp,r12-r15} is preserved by every Win64 callee, so the
thunks just remap args (rdi/rsi/rdx/rcx/r8/r9 -> rcx/rdx/r8/r9/[rsp+20]/[rsp+28]) and return in rax.
Image has no .reloc -> loads at preferred base 0x140000000, so absolute VAs in the url/argv blob
are computable; the compiled code itself is fully RIP-relative (75 leaq .L..(%rip), 0 absolute).
lineage_id: substrate_pe_compile_win_nish_v2 (tutor-scaffold; back-fill = data-driven N-from-spec).
dependencies 3 imports · 0 importers
imports: nx_syscalls.nxnxasm_x86.nxnx_pe_writer.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 34 | const NSH_CODE_CAP: i64 = 0x300000 // 3 MiB assembled-code ceiling |
| 35 | const NSH_STUB_LEN: i64 = 40 // sub/call WSAStartup/call build_argv/mov edi/mov rsi/call main/mov ecx/call exit/int3 |
| 36 | const NSH_THUNK_SLACK: i64 = 0x1000 // reserved after code for thunks + url/argv blob |
| 37 | const NSH_FOFF_TEXT: i64 = 0x200 |
| 38 | const NSH_RVA_TEXT: i64 = 0x1000 |
| 39 | const NSH_IDATA_FSZ: i64 = 0x400 |
| 42 | const NSH_DESC_K: i64 = 0x00 // kernel32 import descriptor (20) |
| 43 | const NSH_DESC_W: i64 = 0x14 // ws2_32 import descriptor (20) |
| 44 | const NSH_DESC_N: i64 = 0x28 // null descriptor (20) |
| 45 | const NSH_INT_K: i64 = 0x3C // kernel32 INT: 11+null (96) |
| 46 | const NSH_INT_W: i64 = 0x9C // ws2_32 INT: 8+null (72) |
| 47 | const NSH_IAT_K: i64 = 0xE4 // kernel32 IAT: 11+null (96) |
| 48 | const NSH_IAT_W: i64 = 0x144 // ws2_32 IAT: 8+null (72) |
| 49 | const NSH_NAMES: i64 = 0x18C // IMAGE_IMPORT_BY_NAME entries, then dll names |
| 52 | const KF_EXIT: i64 = 0 |
| 53 | const KF_GPH: i64 = 1 |
| 54 | const KF_HA: i64 = 2 |
| 55 | const KF_GSH: i64 = 3 |
| 56 | const KF_WF: i64 = 4 |
| 57 | const KF_RF: i64 = 5 |
| 58 | const KF_CFA: i64 = 6 |
| 59 | const KF_GFS: i64 = 7 |
| 60 | const KF_GST: i64 = 8 |
| 61 | const KF_CH: i64 = 9 |
| 62 | const KF_GCL: i64 = 10 // GetCommandLineA |
| 64 | const WF_WSA: i64 = 0 |
| 65 | const WF_SOCK: i64 = 1 |
| 66 | const WF_CONN: i64 = 2 |
| 67 | const WF_SEND: i64 = 3 |
| 68 | const WF_RECV: i64 = 4 |
| 69 | const WF_STO: i64 = 5 |
| 70 | const WF_RFROM: i64 = 6 |
| 71 | const WF_CLOSE: i64 = 7 |
| 73 | const NSH_IMGBASE_LO: i64 = 0x40000000 |
| 74 | const NSH_IMGBASE_HI: i64 = 0x1 |
| 75 | const NSH_IMGBASE: i64 = 5368709120 // 0x1_4000_0000 |
| 78 | const NSH_RAND_SENTINEL: i64 = 0x52414E44 // "RAND" |
functions
| 80 | func _nsh_align(x: i64, a: i64) -> i64 { return ((x + a - 1) / a) * a } called by 1: main |
| 81 | func _nsh_rva(foff: i64) -> i64 { return NSH_RVA_TEXT + (foff - NSH_FOFF_TEXT) } |
| 84 | func _nsh_ec(buf: *u8, foff: i64, iat_rva: i64) -> i64 |
| 91 | func _nsh_redir(buf: *u8, shim_off: i64, thunk_rva: i64) -> i64 |
| 101 | func _nsh_put_name(buf: *u8, foff: i64, s: *u8) -> i64 |
| 111 | func _nsh_put_str(buf: *u8, foff: i64, s: *u8) -> i64 called by 1: nsh_emit_pe |
| 118 | func nsh_lbloff(src: *u8, lo: *i64, ll: *i64, la: *i64, n: i64, nm: *u8) -> i64 |
| 124 | func nsh_assemble(src: *u8, n: i64, out: *u8, out_cap: i64, off: *i64) -> i64 |
| 167 | func nsh_emit_pe(buf: *u8, code: *u8, code_len: i64, off: *i64, |
| 684 | func main() -> i64 |