code wiki / (root) / nxld.nx

nxld.nx

buildroot/runtime/nxld.nx

27671 B754 linesdepth 3pulls 4 transitivereach 1 importersview sourcekind tooltopic nxld
docsdependenciesstructsconstsfunctions

about

nxld.nx -- Nishi sovereign linker. Replaces gcc-ld in verify.sh. Reads RV64 object files (ELF relocatable), resolves symbols across them, and produces a statically-linked RV64 Linux ELF executable. Scope (v0.0.1): - Single-output static linking (no .so / dynamic linking) - RV64 only (Sv39 virtual memory layout) - ELF relocations: R_RISCV_64, R_RISCV_BRANCH, R_RISCV_JAL, R_RISCV_CALL, R_RISCV_HI20, R_RISCV_LO12_I, R_RISCV_LO12_S, R_RISCV_PCREL_HI20, R_RISCV_PCREL_LO12_I - Single .text section + single .data section + single .bss - Entry point = _start (RV64 Linux convention) - Output base vaddr = 0x10000 (matches elf_writer.nx) Out of scope (v0.0.1): - Section ordering directives - Linker scripts - LTO bytecode handling - Position-independent code - Garbage collection of unreferenced sections - Debug info preservation (DWARF stripped) These are deliberate v0.0.1 limits. v0.1.0 closes them. Pipeline: 1. Open + parse each input ELF (header, sections, symbols, relocs) 2. Group sections by type: .text, .data, .bss 3. Resolve undefined symbols across input objects 4. Lay out output sections (text starts at 0x10000 + 0x1000 header) 5. Apply relocations now that final addresses are known 6. Build output ELF (header + program headers + sections) 7. Write to output file

dependencies 2 imports · 1 importers

syscalls.nx elf_writer.nx nxld.nx nxld_main.nx

imports: syscalls.nxelf_writer.nx

imported by: nxld_main.nx

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main nxld_open read_u16_le read_u64_le read_u32_le sec_name_eq nxld_symbol_count nxld_read_symbol nxld_symbol_count ↻ read_u32_le ↻ read_u16_le ↻ read_u64_le ↻ nxld_reloc_count nxld_read_reloc nxld_reloc_count ↻ read_u64_le ↻ nxld_layout nxld_apply_one patch_b_imm write_u32_le patch_j_imm split_hi20 split_lo12 split_hi20 ↻ patch_u_imm patch_i_imm patch_s_imm

structs

75struct ElfObject {
96struct Symbol {
341struct Reloc {

consts

40const ELF_MAGIC0: i64 = 0x7F
41const ELF_MAGIC1: i64 = 0x45 // 'E'
42const ELF_MAGIC2: i64 = 0x4C // 'L'
43const ELF_MAGIC3: i64 = 0x46 // 'F'
44const EI_CLASS64: i64 = 2
45const EI_DATA2LSB: i64 = 1
46const ET_EXEC: i64 = 2
47const ET_REL: i64 = 1
48const EM_RISCV: i64 = 0xF3
50const SHT_NULL: i64 = 0
51const SHT_PROGBITS: i64 = 1
52const SHT_SYMTAB: i64 = 2
53const SHT_STRTAB: i64 = 3
54const SHT_RELA: i64 = 4
55const SHT_NOBITS: i64 = 8
57const PT_LOAD: i64 = 1
58const PF_R: i64 = 4
59const PF_W: i64 = 2
60const PF_X: i64 = 1
63const R_RISCV_64: i64 = 2
64const R_RISCV_BRANCH: i64 = 16
65const R_RISCV_JAL: i64 = 17
66const R_RISCV_CALL: i64 = 18
67const R_RISCV_PCREL_HI20: i64 = 23
68const R_RISCV_PCREL_LO12_I: i64 = 24
69const R_RISCV_HI20: i64 = 26
70const R_RISCV_LO12_I: i64 = 27
71const R_RISCV_LO12_S: i64 = 28
246const SYMBOL_BYTES: i64 = 24
247const STN_UNDEF: i64 = 0
248const STB_LOCAL: i64 = 0
249const STB_GLOBAL: i64 = 1
250const STB_WEAK: i64 = 2
251const STT_NOTYPE: i64 = 0
252const STT_OBJECT: i64 = 1
253const STT_FUNC: i64 = 2
254const STT_SECTION: i64 = 3
339const RELOC_BYTES: i64 = 24
572const NXLD_BASE_VADDR: i64 = 0x10000
573const NXLD_HEADER_BYTES: i64 = 120 // 64 ELF hdr + 56 phdr

functions

108func read_u16_le(buf: *u8, off: i64) -> i64 {
112func read_u32_le(buf: *u8, off: i64) -> i64 {
122func read_u64_le(buf: *u8, off: i64) -> i64 {
136func sec_name_eq(np: *u8, lit: *u8, lit_len: i64) -> i64 {
called by 1: nxld_open
148func nxld_open(obj: *ElfObject, base: *u8, length: i64) -> i64 {
258func nxld_symbol_count(obj: *ElfObject) -> i64 {
266func nxld_read_symbol(obj: *ElfObject, idx: i64, sym: *Symbol) -> i64 {
298func sym_name_eq(np: *u8, np_len: i64, lit: *u8, lit_len: i64) -> i64 {
called by 1: nxld_find_symbol
310func nxld_find_symbol(obj: *ElfObject, name: *u8, name_len: i64) -> i64 {
350func nxld_reloc_count(obj: *ElfObject) -> i64 {
357func nxld_read_reloc(obj: *ElfObject, idx: i64, r: *Reloc) -> i64 {
400func write_u32_le(buf: *u8, off: i64, v: i64) -> i64 {
called by 1: nxld_apply_one
410func patch_i_imm(word: i64, imm: i64) -> i64 {
called by 1: nxld_apply_one
418func patch_s_imm(word: i64, imm: i64) -> i64 {
called by 1: nxld_apply_one
426func patch_u_imm(word: i64, imm_hi: i64) -> i64 {
called by 1: nxld_apply_one
432func patch_j_imm(word: i64, imm: i64) -> i64 {
called by 1: nxld_apply_one
443func patch_b_imm(word: i64, imm: i64) -> i64 {
called by 1: nxld_apply_one
456func split_hi20(value: i64) -> i64 {
459func split_lo12(value: i64) -> i64 {
called by 1: nxld_apply_one calls 1: split_hi20
466func nxld_apply_one(r: *Reloc, text_buf: *u8, text_vaddr: i64,
575func nxld_layout(obj: *ElfObject, syms_pool: *Symbol, n_syms: i64,
called by 2: nxld_linkmain
669func main() -> i64 {