code wiki / (root) / nx_elf_writer.nx

nx_elf_writer.nx source

↩ module page · 159 lines · 5444 B

1// nx_elf_writer.nx -- sovereign ELF64 binary writer. 2// 3// Pure NishiLang. Takes an exit-code integer; writes a complete 4// static-linked x86_64 ELF binary to a file descriptor. No as. No 5// ld. No gcc. No libc. The output is bytes that Linux execve loads 6// and runs. 7// 8// Today: smallest credible binary -- `_start: mov rdi, N; mov rax, 9// 231; syscall` (exit_group with code N). Total ELF size: 134 bytes. 10// 11// Tomorrow (L19b): take an IR snapshot (nxc2 --target ir > foo.ir), 12// read it, emit the corresponding x86_64 bytes. That closes the 13// "nxc2 emits ELF directly" loop without adding more C to nxc2. 14// 15// Cardinal alignment: 16// feedback-nishilang-mission-displace-cuda-directx-via-patent-clean- 17// absorption: every new substrate file is .nx. This file replaces 18// the temptation to add an ELF emitter to x86_64.c. 19// 20// genealogy_id: elf_specification_v1_2 + linux_kernel_load_elf + sysv_abi 21// lineage_id: sovereign_elf_emit_q10 22 23// nx_safety_envelope: 24// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 25// sil_target: SIL1 26// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 27// verdict: NOT_YET_EVALUATED 28 29import "nx_syscalls_x86_64.nx" 30 31// Sealed verdict for "did the write succeed". 32const NX_ELF_VERDICT_UNKNOWN: i64 = 0 33const NX_ELF_VERDICT_OK: i64 = 1 34const NX_ELF_VERDICT_WRITE_FAIL: i64 = 2 35const NX_ELF_VERDICT_N: i64 = 3 36 37const NX_ELF_BASE_VADDR_LO: i64 = 0x400000 38const NX_ELF_TEXT_OFFSET: i64 = 0x78 // sizeof(Ehdr=64) + sizeof(Phdr=56) 39 40// Write one byte to fd. 41func _wb(fd: i64, b: i64) -> i64 { 42 let one: *u8 = sys_mmap(8) 43 one[0] = b 44 return sys_write(fd, one, 1) 45} 46 47// Write `n` bytes from `buf` to fd. 48func _wn(fd: i64, buf: *u8, n: i64) -> i64 { 49 return sys_write(fd, buf, n) 50} 51 52// Little-endian 16-bit write. 53func _w16(fd: i64, v: i64) -> i64 { 54 let two: *u8 = sys_mmap(8) 55 two[0] = v & 0xff 56 two[1] = (v >> 8) & 0xff 57 return sys_write(fd, two, 2) 58} 59 60// Little-endian 32-bit write. 61func _w32(fd: i64, v: i64) -> i64 { 62 let four: *u8 = sys_mmap(8) 63 four[0] = v & 0xff 64 four[1] = (v >> 8) & 0xff 65 four[2] = (v >> 16) & 0xff 66 four[3] = (v >> 24) & 0xff 67 return sys_write(fd, four, 4) 68} 69 70// Little-endian 64-bit write. 71func _w64(fd: i64, v: i64) -> i64 { 72 let eight: *u8 = sys_mmap(8) 73 eight[0] = v & 0xff 74 eight[1] = (v >> 8) & 0xff 75 eight[2] = (v >> 16) & 0xff 76 eight[3] = (v >> 24) & 0xff 77 eight[4] = (v >> 32) & 0xff 78 eight[5] = (v >> 40) & 0xff 79 eight[6] = (v >> 48) & 0xff 80 eight[7] = (v >> 56) & 0xff 81 return sys_write(fd, eight, 8) 82} 83 84// Write the .text bytes for `_start: mov rdi, code; mov rax, 231; 85// syscall` -- 14 bytes that exit_group with the given code. 86// 87// Encoding: 88// 48 c7 c7 NN NN NN NN mov rdi, imm32 (7 bytes) 89// 48 c7 c0 e7 00 00 00 mov rax, 231 (7 bytes) 90// 0f 05 syscall (2 bytes) 91// Total: 16 bytes (NOT 14 -- my earlier count was off). 92func _emit_text(fd: i64, exit_code: i64) -> i64 { 93 let buf: *u8 = sys_mmap(32) 94 buf[0] = 0x48; buf[1] = 0xc7; buf[2] = 0xc7 95 buf[3] = exit_code & 0xff 96 buf[4] = (exit_code >> 8) & 0xff 97 buf[5] = (exit_code >> 16) & 0xff 98 buf[6] = (exit_code >> 24) & 0xff 99 buf[7] = 0x48; buf[8] = 0xc7; buf[9] = 0xc0 100 buf[10] = 0xe7; buf[11] = 0x00; buf[12] = 0x00; buf[13] = 0x00 101 buf[14] = 0x0f; buf[15] = 0x05 102 return sys_write(fd, buf, 16) 103} 104 105// Total binary size = 64 + 56 + 16 = 136 bytes. 106const NX_ELF_TEXT_LEN: i64 = 16 107const NX_ELF_FILE_SIZE: i64 = 136 108 109// Top-level: write the complete ELF to fd. Returns NX_ELF_VERDICT_OK 110// on success. 111func nx_elf_emit_return_n(fd: i64, exit_code: i64) -> i64 { 112 let entry_vaddr: i64 = NX_ELF_BASE_VADDR_LO + NX_ELF_TEXT_OFFSET 113 114 // ---- ELF64 header (64 bytes) ---- 115 _wb(fd, 0x7f); _wb(fd, 0x45); _wb(fd, 0x4c); _wb(fd, 0x46) // \x7fELF 116 _wb(fd, 2) // ELFCLASS64 117 _wb(fd, 1) // ELFDATA2LSB 118 _wb(fd, 1) // EV_CURRENT 119 _wb(fd, 0) // OSABI System V 120 _wb(fd, 0) // ABIVERSION 121 // e_ident padding (7 bytes) 122 _wb(fd, 0); _wb(fd, 0); _wb(fd, 0); _wb(fd, 0) 123 _wb(fd, 0); _wb(fd, 0); _wb(fd, 0) 124 _w16(fd, 2) // e_type = ET_EXEC 125 _w16(fd, 0x3e) // e_machine = EM_X86_64 126 _w32(fd, 1) // e_version 127 _w64(fd, entry_vaddr) // e_entry 128 _w64(fd, 64) // e_phoff 129 _w64(fd, 0) // e_shoff (no sections) 130 _w32(fd, 0) // e_flags 131 _w16(fd, 64) // e_ehsize 132 _w16(fd, 56) // e_phentsize 133 _w16(fd, 1) // e_phnum 134 _w16(fd, 0) // e_shentsize 135 _w16(fd, 0) // e_shnum 136 _w16(fd, 0) // e_shstrndx 137 138 // ---- Program header (56 bytes): PT_LOAD R|X ---- 139 _w32(fd, 1) // PT_LOAD 140 _w32(fd, 5) // PF_R | PF_X 141 _w64(fd, 0) // p_offset 142 _w64(fd, NX_ELF_BASE_VADDR_LO) 143 _w64(fd, NX_ELF_BASE_VADDR_LO) 144 _w64(fd, NX_ELF_FILE_SIZE) // p_filesz 145 _w64(fd, NX_ELF_FILE_SIZE) // p_memsz 146 _w64(fd, 0x1000) // p_align 147 148 // ---- .text ---- 149 _emit_text(fd, exit_code) 150 151 return NX_ELF_VERDICT_OK 152} 153 154// Sealed-enum validity gate. 155func nx_elf_verdict_is_valid(v: i64) -> i64 { 156 if v < 0 { return 0 } 157 if v >= NX_ELF_VERDICT_N { return 0 } 158 return 1 159}