code wiki / (root) / nx_size.nx

nx_size.nx source

↩ module page · 142 lines · 4772 B

1// nx_size.nx -- sovereign `size` tool (binutils equivalent). 2// 3// Reports section sizes in the standard sysv format: 4// 5// text data bss dec hex filename 6// 1024 256 512 1792 0x700 my_program.elf 7// 8// 'text' = ALLOCATED + EXECUTABLE bytes (.text + .rodata) 9// 'data' = ALLOCATED + WRITABLE bytes (.data) 10// 'bss' = ALLOCATED + NOBITS bytes (.bss) 11// 'dec' = sum 12// 'hex' = same in hex 13// 14// Useful for tracking binary bloat over commits + verifying that 15// stripping or DCE actually shrank what we expected. 16// 17// Pairs with nx_objdump / nx_nm / nx_readelf as the size-focused 18// inspection 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_strfmt.nx" 29const NX_MAGIC_1024: i64 = 1024 30 31// SHF_* (matches nx_shtab constants). 32const NX_SIZE_SHF_WRITE: i64 = 0x1 33const NX_SIZE_SHF_ALLOC: i64 = 0x2 34const NX_SIZE_SHF_EXECINSTR: i64 = 0x4 35// SHT_*. 36const NX_SIZE_SHT_NOBITS: i64 = 8 37 38struct NxSizeReport { 39 text: i64, 40 data: i64, 41 bss: i64, 42} 43 44const NX_SIZE_REPORT_BYTES: i64 = 24 45 46func nx_size_report(buf: *u8, len: i64) -> *NxSizeReport { 47 let raw: *u8 = sys_mmap(NX_SIZE_REPORT_BYTES) 48 let r: *NxSizeReport = raw as *NxSizeReport 49 r.text = 0 50 r.data = 0 51 r.bss = 0 52 53 let h: *NxElfHeader = nx_elf_parse_header(buf, len) 54 if h.valid != 1 { return r } 55 if h.e_shnum == 0 { return r } 56 57 var i: i64 = 0 58 while i < h.e_shnum { 59 let s: *NxElfShdr = nx_elf_read_shdr(buf, h, i) 60 if (s.sh_flags & NX_SIZE_SHF_ALLOC) != 0 { 61 if s.sh_type == NX_SIZE_SHT_NOBITS { 62 r.bss = r.bss + s.sh_size 63 } else { 64 if (s.sh_flags & NX_SIZE_SHF_EXECINSTR) != 0 { 65 r.text = r.text + s.sh_size 66 } else { 67 if (s.sh_flags & NX_SIZE_SHF_WRITE) != 0 { 68 r.data = r.data + s.sh_size 69 } else { 70 // .rodata: counted as text. 71 r.text = r.text + s.sh_size 72 } 73 } 74 } 75 } 76 i = i + 1 77 } 78 return r 79} 80 81// Print sysv-format size to fd. 82func nx_size_print(buf: *u8, len: i64, fname: *u8, fd: i64) -> i64 { 83 let r: *NxSizeReport = nx_size_report(buf, len) 84 let total: i64 = r.text + r.data + r.bss 85 86 sys_write(fd, " text data bss dec hex filename\n" as *u8, 46) 87 88 let argv_raw: *u8 = sys_mmap(64) 89 let argv: *i64 = argv_raw as *i64 90 argv[0] = r.text 91 argv[1] = r.data 92 argv[2] = r.bss 93 argv[3] = total 94 argv[4] = total 95 argv[5] = fname as i64 96 nx_fmt_to_fd(fd, " %d %d %d %d 0x%X %s\n" as *u8, argv, 6) 97 return 0 98} 99 100// ---- self-test --------------------------------------------------- 101 102func main() -> i64 { 103 // Build a fake ELF with section headers describing 1 PROGBITS+ 104 // EXEC + 1 PROGBITS+WRITE + 1 NOBITS section. 105 // Minimal layout: header + 4 section headers (NULL, .text, .data, 106 // .bss) at offset 0x100. 107 let elf: *u8 = sys_mmap(NX_MAGIC_1024) 108 var i: i64 = 0 109 while i < NX_MAGIC_1024 { elf[i] = 0; i = i + 1 } 110 111 // ELF header. 112 elf[0] = 0x7F; elf[1] = 0x45; elf[2] = 0x4C; elf[3] = 0x46 113 elf[4] = 2; elf[5] = 1; elf[6] = 1 114 elf[16] = 2; elf[18] = 0xF3 115 elf[40] = 0; elf[41] = 0x01 // e_shoff = 0x100 116 elf[52] = 64; elf[58] = 64; elf[60] = 4 // shentsize=64, shnum=4 117 118 // Section header table at offset 0x100. 119 // [0] NULL: all zero. 120 // [1] .text: PROGBITS, ALLOC|EXEC, size 256. 121 let off_text: i64 = 0x100 + 64 122 elf[off_text + 4] = 1 // SHT_PROGBITS 123 elf[off_text + 8] = 0x06 // ALLOC|EXEC 124 elf[off_text + 32] = 0; elf[off_text + 33] = 0x01 // size = 256 125 // [2] .data: PROGBITS, ALLOC|WRITE, size 128. 126 let off_data: i64 = 0x100 + 128 127 elf[off_data + 4] = 1 128 elf[off_data + 8] = 0x03 // ALLOC|WRITE 129 elf[off_data + 32] = 128 130 // [3] .bss: NOBITS, ALLOC|WRITE, size 512. 131 let off_bss: i64 = 0x100 + 192 132 elf[off_bss + 4] = 8 // SHT_NOBITS 133 elf[off_bss + 8] = 0x03 // ALLOC|WRITE 134 elf[off_bss + 32] = 0; elf[off_bss + 33] = 2 // size = 512 135 136 let r: *NxSizeReport = nx_size_report(elf, NX_MAGIC_1024) 137 if r.text != 256 { return __syscall(93, 10, 0, 0, 0, 0, 0) } 138 if r.data != 128 { return __syscall(93, 11, 0, 0, 0, 0, 0) } 139 if r.bss != 512 { return __syscall(93, 12, 0, 0, 0, 0, 0) } 140 141 return 0 142}