code wiki / (root) / nx_toolchain.nx

nx_toolchain.nx source

↩ module page · 169 lines · 5498 B

1// nx_toolchain.nx -- unified entry point for the off-C tools. 2// 3// Replaces the binutils + qemu suite with a single binary that 4// dispatches subcommands: 5// 6// nx readelf <path.elf> -- full ELF dump 7// nx nm <path.elf> -- list symbols 8// nx objdump <path.elf> -- section headers 9// nx dis <path.bin> <off> -- disassemble bytes 10// nx run <path.elf> -- load + simulate 11// nx help -- list commands 12// 13// Compile this once into a tiny binary; it covers the entire 14// off-C inspection / debug / run workflow. No more invoking 15// 5+ separate binutils tools per session. 16// 17// Pairs with nxc_native_wrap (the bootstrap-verification binary) 18// as the day-to-day developer-facing tool. 19 20// nx_safety_envelope: 21// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 22// sil_target: SIL1 23// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 24// verdict: NOT_YET_EVALUATED 25 26import "syscalls.nx" 27import "nx_elf_read.nx" 28import "nx_objdump.nx" 29import "nx_nm.nx" 30import "nx_readelf.nx" 31import "nx_dis.nx" 32import "nx_loader.nx" 33import "nx_rv64_sim.nx" 34 35// Read entire file into a fresh mmap'd buffer. 36func nx_tc_read_file(path: *u8, out_len: *i64) -> *u8 { 37 let fd: i64 = sys_openat_rd(path) 38 if fd < 0 { *out_len = 0; return 0 as *u8 } 39 let cap: i64 = 16777216 // 16 MB max 40 let buf: *u8 = sys_mmap(cap) 41 var total: i64 = 0 42 var go: i64 = 1 43 while go == 1 { 44 let base: i64 = buf as i64 45 let tail: *u8 = (base + total) as *u8 46 let n: i64 = sys_read(fd, tail, cap - total) 47 if n <= 0 { go = 0 } 48 if n > 0 { total = total + n } 49 if total >= cap { go = 0 } 50 } 51 sys_close(fd) 52 *out_len = total 53 return buf 54} 55 56// Compare a NUL-terminated C-string against a literal byte sequence. 57// streq canonical in runtime.nx. 58 59func nx_tc_help(fd: i64) -> i64 { 60 sys_write(fd, "nx-toolchain commands:\n" as *u8, 23) 61 sys_write(fd, " nx readelf <elf> -- full ELF dump\n" as *u8, 38) 62 sys_write(fd, " nx nm <elf> -- list symbols\n" as *u8, 37) 63 sys_write(fd, " nx objdump <elf> -- section headers\n" as *u8, 41) 64 sys_write(fd, " nx dis <bin> <bytes> -- disassemble RV64\n" as *u8, 47) 65 sys_write(fd, " nx run <elf> -- simulate ELF (RV64I)\n" as *u8, 46) 66 sys_write(fd, " nx help -- this message\n" as *u8, 37) 67 return 0 68} 69 70func main(argc: i64, argv: *i64) -> i64 { 71 if argc < 2 { 72 nx_tc_help(2) 73 return 1 74 } 75 let cmd: *u8 = (argv[1]) as *u8 76 77 if streq(cmd, "help" as *u8) == 1 { 78 nx_tc_help(1) 79 return 0 80 } 81 82 if streq(cmd, "readelf" as *u8) == 1 { 83 if argc < 3 { 84 sys_write(2, "usage: nx readelf <elf>\n" as *u8, 24) 85 return 1 86 } 87 let len_raw: *u8 = sys_mmap(16) 88 let len: *i64 = len_raw as *i64 89 *len = 0 90 let buf: *u8 = nx_tc_read_file((argv[2]) as *u8, len) 91 if buf == (0 as *u8) { 92 sys_write(2, "open failed\n" as *u8, 12) 93 return 2 94 } 95 nx_readelf_all(buf, *len, 1) 96 return 0 97 } 98 99 if streq(cmd, "nm" as *u8) == 1 { 100 if argc < 3 { 101 sys_write(2, "usage: nx nm <elf>\n" as *u8, 19) 102 return 1 103 } 104 let len_raw: *u8 = sys_mmap(16) 105 let len: *i64 = len_raw as *i64 106 *len = 0 107 let buf: *u8 = nx_tc_read_file((argv[2]) as *u8, len) 108 if buf == (0 as *u8) { return 2 } 109 nx_nm_print(buf, *len, 1) 110 return 0 111 } 112 113 if streq(cmd, "objdump" as *u8) == 1 { 114 if argc < 3 { 115 sys_write(2, "usage: nx objdump <elf>\n" as *u8, 24) 116 return 1 117 } 118 let len_raw: *u8 = sys_mmap(16) 119 let len: *i64 = len_raw as *i64 120 *len = 0 121 let buf: *u8 = nx_tc_read_file((argv[2]) as *u8, len) 122 if buf == (0 as *u8) { return 2 } 123 nx_objdump_section_headers(buf, *len, 1) 124 return 0 125 } 126 127 if streq(cmd, "dis" as *u8) == 1 { 128 if argc < 3 { 129 sys_write(2, "usage: nx dis <bin>\n" as *u8, 20) 130 return 1 131 } 132 let len_raw: *u8 = sys_mmap(16) 133 let len: *i64 = len_raw as *i64 134 *len = 0 135 let buf: *u8 = nx_tc_read_file((argv[2]) as *u8, len) 136 if buf == (0 as *u8) { return 2 } 137 // Disassemble all bytes 0..len in 4-byte steps. 138 nx_dis_range(buf, 0, *len, 1) 139 return 0 140 } 141 142 if streq(cmd, "run" as *u8) == 1 { 143 if argc < 3 { 144 sys_write(2, "usage: nx run <elf>\n" as *u8, 20) 145 return 1 146 } 147 let len_raw: *u8 = sys_mmap(16) 148 let len: *i64 = len_raw as *i64 149 *len = 0 150 let buf: *u8 = nx_tc_read_file((argv[2]) as *u8, len) 151 if buf == (0 as *u8) { return 2 } 152 let mem: *u8 = sys_mmap(16777216) 153 let entry: i64 = nx_loader_load(buf, *len, mem, 16777216) 154 if entry < 0 { 155 sys_write(2, "load failed\n" as *u8, 12) 156 return 3 157 } 158 let cpu: *NxRv64Cpu = nx_rv64_cpu_new(mem, 16777216, entry) 159 nx_rv64_cpu_set_sp(cpu, 16777216 - 64) 160 let r: i64 = nx_rv64_run(cpu, 100000000) 161 if r == 0 { return cpu.exit_code } 162 if r > 0 { return 4 } // budget 163 return 5 // illegal 164 } 165 166 sys_write(2, "unknown command\n" as *u8, 16) 167 nx_tc_help(2) 168 return 1 169}