diff --git a/selfhost/cmd/w6l/dyn.ww b/selfhost/cmd/w6l/dyn.ww index 34ebf2ef..f04593d1 100644 --- a/selfhost/cmd/w6l/dyn.ww +++ b/selfhost/cmd/w6l/dyn.ww @@ -123,8 +123,8 @@ fn d_basename(p: *u8) *u8 = { // ---- file slurp -------------------------------------------------------- -fn read_all_so(path_cs: *u8) (*u8, u64) = { - let fd: i32 = os.open(path_cs, os.O_RDONLY, 0i32); +fn readallso(path: *u8) (*u8, u64) = { + let fd: i32 = os.open(path, os.O_RDONLY, 0i32); if (fd < 0) { return nil, 0u64; }; let n: i64 = os.filesize(fd); if (n < 0i64) { os.close(fd); return nil, 0u64; }; @@ -137,11 +137,11 @@ fn read_all_so(path_cs: *u8) (*u8, u64) = { // ---- verdef helpers ---------------------------------------------------- -// vd_name_at — walk verdef records and return the name (as *u8 into +// vdnameat — walk verdef records and return the name (as *u8 into // the .so's verstr buffer) for the entry whose vd_ndx == ndx. The name // is the first Verdaux's vda_name (subsequent auxes are predecessor // names). Returns nil if no entry matches. -fn vd_name_at(buf: *u8, verdef_off: u64, verdef_size: u64, +fn vdnameat(buf: *u8, verdef_off: u64, verdef_size: u64, verstr: *u8, ndx: u16) *u8 = { let off: u64 = 0u64; for (off < verdef_size) { @@ -162,10 +162,10 @@ fn vd_name_at(buf: *u8, verdef_off: u64, verdef_size: u64, // ---- entry points ------------------------------------------------------ -export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { +export fn loadso(l: *lnk, path: *u8) i32 = { let buf: *u8; let blen: u64; - buf, blen = read_all_so(path_cs); + buf, blen = readallso(path); if (buf == nil) { os.write(2, "w6l: cannot read .so\n".ptr, 20u64); return -1; @@ -174,22 +174,22 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { os.write(2, "w6l: short ELF\n".ptr, 14u64); return -1; }; - if (buf[0u64] != 127u8) { return so_err("not ELF"); }; - if (buf[1u64] != 69u8) { return so_err("not ELF"); }; - if (buf[2u64] != 76u8) { return so_err("not ELF"); }; - if (buf[3u64] != 70u8) { return so_err("not ELF"); }; - if (buf[4u64] != 2u8) { return so_err("not ELFCLASS64"); }; + if (buf[0u64] != 127u8) { return soerr("not ELF"); }; + if (buf[1u64] != 69u8) { return soerr("not ELF"); }; + if (buf[2u64] != 76u8) { return soerr("not ELF"); }; + if (buf[3u64] != 70u8) { return soerr("not ELF"); }; + if (buf[4u64] != 2u8) { return soerr("not ELFCLASS64"); }; if (d_u16(buf, EH_EMACHINE) != EM_X86_64_SO) { - return so_err("not amd64"); + return soerr("not amd64"); }; if (d_u16(buf, EH_ETYPE) != ET_DYN_SO) { - return so_err("not ET_DYN"); + return soerr("not ET_DYN"); }; let shoff: u64 = d_u64(buf, EH_SHOFF); let shnum: u32 = d_u16(buf, EH_SHNUM): u32; - if (shoff == 0u64) { return so_err("stripped .so unsupported"); }; - if (shnum == 0u32) { return so_err("stripped .so unsupported"); }; + if (shoff == 0u64) { return soerr("stripped .so unsupported"); }; + if (shnum == 0u32) { return soerr("stripped .so unsupported"); }; // Locate the four sections we care about. let idx_dynsym: i32 = -1; @@ -207,7 +207,7 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { i += 1u32; }; if (idx_dynsym < 0) { - return so_err("no .dynsym"); + return soerr("no .dynsym"); }; let dynsym_sh: u64 = shoff + (idx_dynsym: u64) * SH_SIZE; @@ -250,7 +250,7 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { }; }; if (soname_cs == nil) { - soname_cs = d_basename(path_cs); + soname_cs = d_basename(path); }; // Versym is one u16 per dynsym entry. @@ -277,9 +277,9 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { }; // Build the lso. Exports are appended in dynsym order so - // l_so_provides_v's first-match semantics match the C version. + // soprovides_v's first-match semantics match the C version. let so: *lso = amalloc(l.a, 64u64): *lso; - so.path = d_cstr_to_str(l.a, path_cs); + so.path = d_cstr_to_str(l.a, path); so.soname = d_cstr_to_str(l.a, soname_cs); so.exports = nil; let tail: *lexport = nil; @@ -325,7 +325,7 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { vername_cs = nil; } else { if (verstr != nil) { - let nm: *u8 = vd_name_at(buf, verdef_off, verdef_size, verstr, vidx); + let nm: *u8 = vdnameat(buf, verdef_off, verdef_size, verstr, vidx); vername_cs = nm; }; }; }; }; @@ -358,34 +358,34 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { return 0; }; -fn so_err(msg: str) i32 = { +fn soerr(msg: str) i32 = { os.write(2, "w6l: ".ptr, 4u64); os.write(2, msg.ptr, msg.len: u64); os.write(2, "\n".ptr, 1u64); return -1; }; -// l_so_provides — 1 if so exports name, 0 otherwise. -export fn l_so_provides(so: *lso, name: str) i32 = { +// soprovides — 1 if so exports name, 0 otherwise. +export fn soprovides(so: *lso, name: str) i32 = { if (so == nil) { return 0; }; let e: *lexport = so.exports; for (e != nil) { - if (s_eq(e.name, name)) { return 1; }; + if (streq(e.name, name)) { return 1; }; e = e.enext; }; return 0; }; -// l_so_version — the version of so's export named `name`, or an empty +// soversion — the version of so's export named `name`, or an empty // str (ptr=nil, len=0) if the export is unversioned or not present. -export fn l_so_version(so: *lso, name: str) str = { +export fn soversion(so: *lso, name: str) str = { let result: str; result.ptr = nil; result.len = 0i32; if (so == nil) { return result; }; let e: *lexport = so.exports; for (e != nil) { - if (s_eq(e.name, name)) { + if (streq(e.name, name)) { result.ptr = e.version.ptr; result.len = e.version.len; return result; @@ -395,12 +395,4 @@ export fn l_so_version(so: *lso, name: str) str = { return result; }; -fn s_eq(a: str, b: str) bool = { - if (a.len != b.len) { return false; }; - let i: i32 = 0; - for (i < a.len) { - if (a[i] != b[i]) { return false; }; - i += 1; - }; - return true; -}; +// `streq` lives in sym.ww — same bundle, single definition. diff --git a/selfhost/cmd/w6l/dynout.ww b/selfhost/cmd/w6l/dynout.ww index a952f706..5d5ddee1 100644 --- a/selfhost/cmd/w6l/dynout.ww +++ b/selfhost/cmd/w6l/dynout.ww @@ -23,10 +23,10 @@ // [dynamic_off] .dynamic (writable; covered by PT_DYNAMIC) // // cgen workaround notes: -// - Two-level field assignments through pointers (e.g. r.sym.is_dyn = 1) +// - Two-level field assignments through pointers (e.g. r.sym.isdyn = 1) // silently fail in the current wwstage cgen. We bind the inner -// pointer to a local first: `let sym = r.sym; sym.is_dyn = 1;` -// - Tuple returns of (i32, str) drop the str payload. l_so_version +// pointer to a local first: `let sym = r.sym; sym.isdyn = 1;` +// - Tuple returns of (i32, str) drop the str payload. soversion // returns a plain str instead. // - `def NAME: str = "...";` produces a bogus str (len ends up adding // to an offset accumulator). We use a fn returning the literal. @@ -175,19 +175,19 @@ fn str_eq_d(a: str, b: str) bool = { // ---- main entry -------------------------------------------------------- -export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { +export fn emitdynelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { let a: *arena = l.a; - let n: i32 = l.dyn_n; + let n: i32 = l.dynn; let nu: u64 = n: u64; // ---- collect dyn syms into a plt_idx-indexed array ---- let dynsyms: **lsym = amalloc(a, nu * 8u64): **lsym; let s: *lsym = l.syms; for (s != nil) { - if (s.is_dyn != 0) { - if (s.plt_idx >= 0) { - if (s.plt_idx < n) { - dynsyms[s.plt_idx] = s; + if (s.isdyn != 0) { + if (s.pltidx >= 0) { + if (s.pltidx < n) { + dynsyms[s.pltidx] = s; }; }; }; @@ -214,7 +214,7 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { let j: i32 = 0; for (j < n) { let dsm: *lsym = dynsyms[j]; - let dl: *lso = dsm.dyn_lib; + let dl: *lso = dsm.dynlib; if (dl == so) { used = 1; j = n; } else { j += 1; }; }; @@ -254,10 +254,10 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { let j: i32 = 0; for (j < n) { let dsm: *lsym = dynsyms[j]; - let dl: *lso = dsm.dyn_lib; + let dl: *lso = dsm.dynlib; if (dl == cur_so) { let nm0: str = dsm.name; - let dv: str = l_so_version(cur_so, nm0); + let dv: str = soversion(cur_so, nm0); if (dv.len > 0) { has = 1; j = n; } else { j += 1; }; @@ -270,10 +270,10 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { let jj: i32 = 0; for (jj < n) { let dsm2: *lsym = dynsyms[jj]; - let dl2: *lso = dsm2.dyn_lib; + let dl2: *lso = dsm2.dynlib; if (dl2 == cur_so) { let nm2: str = dsm2.name; - let vname: str = l_so_version(cur_so, nm2); + let vname: str = soversion(cur_so, nm2); if (vname.len > 0) { let seen: i32 = 0; let k: i32 = 0; @@ -387,9 +387,9 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { pi = 0; for (pi < n) { let dsm3: *lsym = dynsyms[pi]; - let dl3: *lso = dsm3.dyn_lib; + let dl3: *lso = dsm3.dynlib; let nm3: str = dsm3.name; - let vname: str = l_so_version(dl3, nm3); + let vname: str = soversion(dl3, nm3); if (vname.len == 0) { d_wr16(versym_for, (pi: u64) * 2u64, VER_NDX_GLOBAL_D); } else { @@ -630,7 +630,7 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { for (r != nil) { if (r.sym != nil) { let rsym: *lsym = r.sym; - if (rsym.is_dyn != 0) { + if (rsym.isdyn != 0) { if (r.kind != R_X86_64_PC32_D) { if (r.kind != R_X86_64_PLT32_D) { os.write(2, "w6l: dynamic reloc kind unsupported\n".ptr, 35u64); @@ -638,7 +638,7 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { }; }; let site: u64 = text_va + r.off; - let stub: u64 = plt_va + (rsym.plt_idx: u64) * PLT_STUB_BYTES_D; + let stub: u64 = plt_va + (rsym.pltidx: u64) * PLT_STUB_BYTES_D; let disp: i64 = (stub: i64) - (site: i64) + r.addend; d_wr32(l.text, r.off, (disp: i32): u32); }; diff --git a/selfhost/cmd/w6l/main.combined.ww b/selfhost/cmd/w6l/main.combined.ww index 25569435..15e551f2 100644 --- a/selfhost/cmd/w6l/main.combined.ww +++ b/selfhost/cmd/w6l/main.combined.ww @@ -322,20 +322,20 @@ export fn freearena(a: *arena) void = { use mem; type lsym = struct { - name: str, - val: u64, // offset within combined .text once linked - defined: i32, // 1 if some lobj defines this symbol - owner: *lobj, - idx_in_owner: i32, - // Dynamic-linking fields. Set by l_resolve when an undefined sym - // is provided by some loaded lso. plt_idx and dynsym_idx default - // to -1 (set explicitly by l_resolve, not by amalloc-zeroing). - is_dyn: i32, - dyn_lib: *lso, - dyn_version: str, // matched export's version; len 0 if none - plt_idx: i32, - dynsym_idx: i32, - snext: *lsym, + name: str, + val: u64, // offset within combined .text once linked + defined: i32, // 1 if some lobj defines this symbol + owner: *lobj, + idxinowner: i32, + // Dynamic-linking fields. Set by resolve when an undefined sym + // is provided by some loaded lso. pltidx and dynsymidx default + // to -1 (set explicitly by resolve, not by amalloc-zeroing). + isdyn: i32, + dynlib: *lso, + dynversion: str, // matched export's version; len 0 if none + pltidx: i32, + dynsymidx: i32, + snext: *lsym, }; type lrel = struct { @@ -347,17 +347,17 @@ type lrel = struct { }; type lobj = struct { - path: str, - buf: *u8, // object bytes - len: u64, - text_off: u64, // offset of .text in combined output - text_size: u64, - onext: *lobj, + path: str, + buf: *u8, // object bytes + len: u64, + textoff: u64, // offset of .text in combined output + textsize: u64, + onext: *lobj, }; // lexport — one entry per GLOBAL/WEAK symbol exported by a loaded .so. // Stored as a chain in the order the .so's dynsym presents them, so -// l_so_provides_v's first-match semantics agree with the C version. +// soprovides_v's first-match semantics agree with the C version. type lexport = struct { name: str, version: str, // len 0 for unversioned globals @@ -381,7 +381,7 @@ type lnk = struct { textcap: u64, textlen: u64, errs: i32, - dyn_n: i32, // number of syms routed through PLT + dynn: i32, // number of syms routed through PLT }; fn streq(a: str, b: str) bool = { @@ -394,7 +394,7 @@ fn streq(a: str, b: str) bool = { return true; }; -export fn l_intern(l: *lnk, name: str) *lsym = { +export fn intern(l: *lnk, name: str) *lsym = { let s: *lsym = l.syms; for (s != nil) { if (streq(s.name, name)) { return s; }; @@ -407,7 +407,7 @@ export fn l_intern(l: *lnk, name: str) *lsym = { return n; }; -export fn l_lookup(l: *lnk, name: str) *lsym = { +export fn lookup(l: *lnk, name: str) *lsym = { let s: *lsym = l.syms; for (s != nil) { if (streq(s.name, name)) { return s; }; @@ -493,8 +493,8 @@ def RELA_ADDEND: u64 = 16u64; // ---- file slurp -------------------------------------------------------- -fn read_all(path_cs: *u8) (*u8, u64) = { - let fd: i32 = os.open(path_cs, os.O_RDONLY, 0i32); +fn readall(path: *u8) (*u8, u64) = { + let fd: i32 = os.open(path, os.O_RDONLY, 0i32); if (fd < 0) { return nil, 0u64; }; let n: i64 = os.filesize(fd); if (n < 0i64) { os.close(fd); return nil, 0u64; }; @@ -507,7 +507,7 @@ fn read_all(path_cs: *u8) (*u8, u64) = { // ---- text buffer growth ------------------------------------------------ -fn emit_text(l: *lnk, src: *u8, n: u64) void = { +fn emittext(l: *lnk, src: *u8, n: u64) void = { if (l.textlen + n > l.textcap) { let nc: u64 = l.textcap; if (nc == 0u64) { nc = 4096u64; }; @@ -540,7 +540,7 @@ fn cstrlen(p: *u8) u64 = { return n; }; -fn cstr_eq(p: *u8, lit: str) bool = { +fn cstreq(p: *u8, lit: str) bool = { let n: u64 = lit.len: u64; let i: u64 = 0u64; for (i < n) { @@ -552,8 +552,8 @@ fn cstr_eq(p: *u8, lit: str) bool = { return true; }; -// Build a ww str from a NUL-terminated *u8 (for passing to l_intern). -fn cstr_to_str(a: *arena, p: *u8) str = { +// Build a ww str from a NUL-terminated *u8 (for passing to intern). +fn cstrtostr(a: *arena, p: *u8) str = { let n: u64 = cstrlen(p); return astrndup(a, p, n); }; @@ -577,7 +577,7 @@ type armember = struct { mnext: *armember, }; -fn is_archive(p: *u8, len: u64) bool = { +fn isarchive(p: *u8, len: u64) bool = { if (len < 8u64) { return false; }; if (p[0u64] != 33u8) { return false; }; // '!' if (p[1u64] != 60u8) { return false; }; // '<' @@ -590,8 +590,8 @@ fn is_archive(p: *u8, len: u64) bool = { return true; }; -// ar_field — parse a space-padded decimal integer of width n. -fn ar_field(p: *u8, n: u64) u64 = { +// arfield — parse a space-padded decimal integer of width n. +fn arfield(p: *u8, n: u64) u64 = { let v: u64 = 0u64; let i: u64 = 0u64; for (i < n) { @@ -604,10 +604,10 @@ fn ar_field(p: *u8, n: u64) u64 = { return v; }; -// elf_globals — return a linked list of names of globally-defined +// elfglobals — return a linked list of names of globally-defined // (STB_GLOBAL) symbols whose section is `.text`. Names are arena // copies, so the source ELF buffer can be freed afterward. -fn elf_globals(a: *arena, buf: *u8, len: u64) *defent = { +fn elfglobals(a: *arena, buf: *u8, len: u64) *defent = { if (len < EHDR_SIZE) { return nil; }; if (buf[0u64] != 127u8) { return nil; }; if (buf[1u64] != 69u8) { return nil; }; @@ -630,7 +630,7 @@ fn elf_globals(a: *arena, buf: *u8, len: u64) *defent = { let sh_name: u32 = rd_u32(buf, sh_off + SHDR_NAME); let nm: *u8 = shstr + (sh_name: u64); if (sh_type == SHT_PROGBITS: u32) { - if (cstr_eq(nm, ".text")) { idx_text = i: i32; }; + if (cstreq(nm, ".text")) { idx_text = i: i32; }; }; if (sh_type == SHT_SYMTAB: u32) { idx_symtab = i: i32; }; i += 1u32; @@ -662,7 +662,7 @@ fn elf_globals(a: *arena, buf: *u8, len: u64) *defent = { if ((st_shndx: i32) == idx_text) { let nm_p: *u8 = strtab + (st_name: u64); if (nm_p[0u64] != 0u8) { - let nm: str = cstr_to_str(a, nm_p); + let nm: str = cstrtostr(a, nm_p); let de: *defent = amalloc(a, 32u64): *defent; de.name = nm; de.dnext = head; @@ -676,13 +676,13 @@ fn elf_globals(a: *arena, buf: *u8, len: u64) *defent = { return head; }; -// member_defines_undef — true if any of m's defined globals matches a +// memberdefinesundef — true if any of m's defined globals matches a // currently-undefined symbol in the linker's symbol table. Names not // already interned are uninteresting (the link doesn't need them yet). -fn member_defines_undef(l: *lnk, m: *armember) bool = { +fn memberdefinesundef(l: *lnk, m: *armember) bool = { let de: *defent = m.defs; for (de != nil) { - let s: *lsym = l_lookup(l, de.name); + let s: *lsym = lookup(l, de.name); if (s != nil) { if (s.defined == 0) { return true; }; }; @@ -691,17 +691,17 @@ fn member_defines_undef(l: *lnk, m: *armember) bool = { return false; }; -// load_archive — port of cmd/w6l/obj.c:load_archive. +// loadarchive — port of cmd/w6l/obj.c:load_archive. // // Pass 1 indexes every regular member. Pass 2 iteratively pulls in any // member that supplies a currently-undefined symbol; each pull may // introduce fresh undefs, so we loop until quiescent. -fn load_archive(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { +fn loadarchive(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { let head: *armember = nil; let tail: *armember = nil; let pos: u64 = 8u64; // past "!\n" for (pos + 60u64 <= len) { - let hdr_size: u64 = ar_field(buf + pos + 48u64, 10u64); + let hdr_size: u64 = arfield(buf + pos + 48u64, 10u64); let hdr_end: u64 = pos + 60u64; if (hdr_end + hdr_size > len) { break; }; let first: u8 = buf[pos]; @@ -717,7 +717,7 @@ fn load_archive(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { i += 1u64; }; m.data = mb; - m.defs = elf_globals(l.a, mb, hdr_size); + m.defs = elfglobals(l.a, mb, hdr_size); m.loaded = 0; m.mnext = nil; if (head == nil) { head = m; } @@ -734,8 +734,8 @@ fn load_archive(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { let m: *armember = head; for (m != nil) { if (m.loaded == 0) { - if (member_defines_undef(l, m)) { - if (load_image(l, path_cs, m.data, m.size) == 0) { + if (memberdefinesundef(l, m)) { + if (loadimage(l, path, m.data, m.size) == 0) { m.loaded = 1; changed = 1; }; @@ -749,21 +749,21 @@ fn load_archive(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { // ---- main loader ------------------------------------------------------- -export fn l_load(l: *lnk, path_cs: *u8) i32 = { +export fn load(l: *lnk, path: *u8) i32 = { let bufp: *u8; let buflen: u64; - bufp, buflen = read_all(path_cs); + bufp, buflen = readall(path); if (bufp == nil) { os.write(2, "w6l: cannot read object\n".ptr, 23u64); return -1; }; - if (is_archive(bufp, buflen)) { - return load_archive(l, path_cs, bufp, buflen); + if (isarchive(bufp, buflen)) { + return loadarchive(l, path, bufp, buflen); }; - return load_image(l, path_cs, bufp, buflen); + return loadimage(l, path, bufp, buflen); }; -fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { +fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { if (len < EHDR_SIZE) { return -1; }; // magic: 0x7f, 'E', 'L', 'F' if (buf[0u64] != 127u8) { return -1; }; @@ -792,11 +792,11 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { let sh_name: u32 = rd_u32(buf, sh_off + SHDR_NAME); let nm: *u8 = shstr + (sh_name: u64); if (sh_type == SHT_PROGBITS: u32) { - if (cstr_eq(nm, ".text")) { idx_text = i: i32; }; + if (cstreq(nm, ".text")) { idx_text = i: i32; }; }; if (sh_type == SHT_SYMTAB: u32) { idx_symtab = i: i32; }; if (sh_type == SHT_RELA: u32) { - if (cstr_eq(nm, ".rela.text")) { idx_rela = i: i32; }; + if (cstreq(nm, ".rela.text")) { idx_rela = i: i32; }; }; i += 1u32; }; @@ -825,16 +825,16 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { // Track this object. let ob: *lobj = amalloc(l.a, 64u64): *lobj; - ob.path = cstr_to_str(l.a, path_cs); + ob.path = cstrtostr(l.a, path); ob.buf = buf; ob.len = len; - ob.text_off = l.textlen; - ob.text_size = text_size; + ob.textoff = l.textlen; + ob.textsize = text_size; ob.onext = l.objs; l.objs = ob; // Append .text bytes to the combined image. - emit_text(l, buf + text_off, text_size); + emittext(l, buf + text_off, text_size); // Walk symbols. We don't keep a per-object map[] of *lsym. Instead // the reloc loop re-walks symtab and re-interns by name. Simpler @@ -847,8 +847,8 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { let st_value: u64 = rd_u64(buf, sym_p + SYM_VALUE); let nm_p: *u8 = strtab + (st_name: u64); if (nm_p[0u64] != 0u8) { - let nm: str = cstr_to_str(l.a, nm_p); - let gs: *lsym = l_intern(l, nm); + let nm: str = cstrtostr(l.a, nm_p); + let gs: *lsym = intern(l, nm); if (st_shndx != 0u16) { if ((st_shndx: i32) == idx_text) { if (gs.defined != 0) { @@ -857,8 +857,8 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { } else { gs.defined = 1; gs.owner = ob; - gs.idx_in_owner = si: i32; - gs.val = ob.text_off + st_value; + gs.idxinowner = si: i32; + gs.val = ob.textoff + st_value; }; }; }; @@ -881,7 +881,7 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { let r_sym_idx: u32 = (r_info >> 32u64): u32; let r_kind: i32 = ((r_info & 4294967295u64): u32): i32; let nr: *lrel = amalloc(l.a, 48u64): *lrel; - nr.off = ob.text_off + r_off; + nr.off = ob.textoff + r_off; nr.kind = r_kind; nr.addend = r_addend: i64; // Look up the referenced sym by name (re-walk symtab). @@ -890,8 +890,8 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { let s_name: u32 = rd_u32(buf, s_p + SYM_NAME); let s_nm: *u8 = strtab + (s_name: u64); if (s_nm[0u64] != 0u8) { - let nm: str = cstr_to_str(l.a, s_nm); - nr.sym = l_intern(l, nm); + let nm: str = cstrtostr(l.a, s_nm); + nr.sym = intern(l, nm); }; }; nr.rnext = l.rels; @@ -1028,8 +1028,8 @@ fn d_basename(p: *u8) *u8 = { // ---- file slurp -------------------------------------------------------- -fn read_all_so(path_cs: *u8) (*u8, u64) = { - let fd: i32 = os.open(path_cs, os.O_RDONLY, 0i32); +fn readallso(path: *u8) (*u8, u64) = { + let fd: i32 = os.open(path, os.O_RDONLY, 0i32); if (fd < 0) { return nil, 0u64; }; let n: i64 = os.filesize(fd); if (n < 0i64) { os.close(fd); return nil, 0u64; }; @@ -1042,11 +1042,11 @@ fn read_all_so(path_cs: *u8) (*u8, u64) = { // ---- verdef helpers ---------------------------------------------------- -// vd_name_at — walk verdef records and return the name (as *u8 into +// vdnameat — walk verdef records and return the name (as *u8 into // the .so's verstr buffer) for the entry whose vd_ndx == ndx. The name // is the first Verdaux's vda_name (subsequent auxes are predecessor // names). Returns nil if no entry matches. -fn vd_name_at(buf: *u8, verdef_off: u64, verdef_size: u64, +fn vdnameat(buf: *u8, verdef_off: u64, verdef_size: u64, verstr: *u8, ndx: u16) *u8 = { let off: u64 = 0u64; for (off < verdef_size) { @@ -1067,10 +1067,10 @@ fn vd_name_at(buf: *u8, verdef_off: u64, verdef_size: u64, // ---- entry points ------------------------------------------------------ -export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { +export fn loadso(l: *lnk, path: *u8) i32 = { let buf: *u8; let blen: u64; - buf, blen = read_all_so(path_cs); + buf, blen = readallso(path); if (buf == nil) { os.write(2, "w6l: cannot read .so\n".ptr, 20u64); return -1; @@ -1079,22 +1079,22 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { os.write(2, "w6l: short ELF\n".ptr, 14u64); return -1; }; - if (buf[0u64] != 127u8) { return so_err("not ELF"); }; - if (buf[1u64] != 69u8) { return so_err("not ELF"); }; - if (buf[2u64] != 76u8) { return so_err("not ELF"); }; - if (buf[3u64] != 70u8) { return so_err("not ELF"); }; - if (buf[4u64] != 2u8) { return so_err("not ELFCLASS64"); }; + if (buf[0u64] != 127u8) { return soerr("not ELF"); }; + if (buf[1u64] != 69u8) { return soerr("not ELF"); }; + if (buf[2u64] != 76u8) { return soerr("not ELF"); }; + if (buf[3u64] != 70u8) { return soerr("not ELF"); }; + if (buf[4u64] != 2u8) { return soerr("not ELFCLASS64"); }; if (d_u16(buf, EH_EMACHINE) != EM_X86_64_SO) { - return so_err("not amd64"); + return soerr("not amd64"); }; if (d_u16(buf, EH_ETYPE) != ET_DYN_SO) { - return so_err("not ET_DYN"); + return soerr("not ET_DYN"); }; let shoff: u64 = d_u64(buf, EH_SHOFF); let shnum: u32 = d_u16(buf, EH_SHNUM): u32; - if (shoff == 0u64) { return so_err("stripped .so unsupported"); }; - if (shnum == 0u32) { return so_err("stripped .so unsupported"); }; + if (shoff == 0u64) { return soerr("stripped .so unsupported"); }; + if (shnum == 0u32) { return soerr("stripped .so unsupported"); }; // Locate the four sections we care about. let idx_dynsym: i32 = -1; @@ -1112,7 +1112,7 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { i += 1u32; }; if (idx_dynsym < 0) { - return so_err("no .dynsym"); + return soerr("no .dynsym"); }; let dynsym_sh: u64 = shoff + (idx_dynsym: u64) * SH_SIZE; @@ -1155,7 +1155,7 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { }; }; if (soname_cs == nil) { - soname_cs = d_basename(path_cs); + soname_cs = d_basename(path); }; // Versym is one u16 per dynsym entry. @@ -1182,9 +1182,9 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { }; // Build the lso. Exports are appended in dynsym order so - // l_so_provides_v's first-match semantics match the C version. + // soprovides_v's first-match semantics match the C version. let so: *lso = amalloc(l.a, 64u64): *lso; - so.path = d_cstr_to_str(l.a, path_cs); + so.path = d_cstr_to_str(l.a, path); so.soname = d_cstr_to_str(l.a, soname_cs); so.exports = nil; let tail: *lexport = nil; @@ -1230,7 +1230,7 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { vername_cs = nil; } else { if (verstr != nil) { - let nm: *u8 = vd_name_at(buf, verdef_off, verdef_size, verstr, vidx); + let nm: *u8 = vdnameat(buf, verdef_off, verdef_size, verstr, vidx); vername_cs = nm; }; }; }; }; @@ -1263,34 +1263,34 @@ export fn l_load_so(l: *lnk, path_cs: *u8) i32 = { return 0; }; -fn so_err(msg: str) i32 = { +fn soerr(msg: str) i32 = { os.write(2, "w6l: ".ptr, 4u64); os.write(2, msg.ptr, msg.len: u64); os.write(2, "\n".ptr, 1u64); return -1; }; -// l_so_provides — 1 if so exports name, 0 otherwise. -export fn l_so_provides(so: *lso, name: str) i32 = { +// soprovides — 1 if so exports name, 0 otherwise. +export fn soprovides(so: *lso, name: str) i32 = { if (so == nil) { return 0; }; let e: *lexport = so.exports; for (e != nil) { - if (s_eq(e.name, name)) { return 1; }; + if (streq(e.name, name)) { return 1; }; e = e.enext; }; return 0; }; -// l_so_version — the version of so's export named `name`, or an empty +// soversion — the version of so's export named `name`, or an empty // str (ptr=nil, len=0) if the export is unversioned or not present. -export fn l_so_version(so: *lso, name: str) str = { +export fn soversion(so: *lso, name: str) str = { let result: str; result.ptr = nil; result.len = 0i32; if (so == nil) { return result; }; let e: *lexport = so.exports; for (e != nil) { - if (s_eq(e.name, name)) { + if (streq(e.name, name)) { result.ptr = e.version.ptr; result.len = e.version.len; return result; @@ -1300,15 +1300,7 @@ export fn l_so_version(so: *lso, name: str) str = { return result; }; -fn s_eq(a: str, b: str) bool = { - if (a.len != b.len) { return false; }; - let i: i32 = 0; - for (i < a.len) { - if (a[i] != b[i]) { return false; }; - i += 1; - }; - return true; -}; +// `streq` lives in sym.ww — same bundle, single definition. // selfhost/cmd/w6l/pass.ww — port of cmd/w6l/pass.c. // @@ -1329,14 +1321,14 @@ use dyn; def R_X86_64_PC32: i32 = 2; def R_X86_64_PLT32: i32 = 4; -export fn l_resolve(l: *lnk) i32 = { +export fn resolve(l: *lnk) i32 = { // Initialise dynamic-linking sentinels. amalloc zeroes, so - // is_dyn/dyn_lib start clean — but plt_idx and dynsym_idx + // isdyn/dynlib start clean — but pltidx and dynsymidx // must be -1, not 0. let si: *lsym = l.syms; for (si != nil) { - si.plt_idx = -1; - si.dynsym_idx = -1; + si.pltidx = -1; + si.dynsymidx = -1; si = si.snext; }; @@ -1348,14 +1340,14 @@ export fn l_resolve(l: *lnk) i32 = { if (r.sym != nil) { if (r.sym.defined == 0) { let sym: *lsym = r.sym; - if (sym.is_dyn == 0) { + if (sym.isdyn == 0) { let so: *lso = l.sos; for (so != nil) { - if (l_so_provides(so, sym.name) != 0) { - sym.is_dyn = 1; - sym.dyn_lib = so; - sym.plt_idx = l.dyn_n; - l.dyn_n += 1; + if (soprovides(so, sym.name) != 0) { + sym.isdyn = 1; + sym.dynlib = so; + sym.pltidx = l.dynn; + l.dynn += 1; so = nil; // break } else { so = so.sonext; @@ -1372,7 +1364,7 @@ export fn l_resolve(l: *lnk) i32 = { for (r2 != nil) { if (r2.sym != nil) { if (r2.sym.defined == 0) { - if (r2.sym.is_dyn == 0) { + if (r2.sym.isdyn == 0) { os.write(2, "w6l: undefined reference to '".ptr, 28u64); let nm: str = r2.sym.name; os.write(2, nm.ptr, nm.len: u64); @@ -1386,20 +1378,20 @@ export fn l_resolve(l: *lnk) i32 = { return l.errs; }; -fn patch_u32(p: *u8, v: u32) void = { +fn patchu32(p: *u8, v: u32) void = { p[0] = (v & 255u32): u8; p[1] = ((v >> 8u32) & 255u32): u8; p[2] = ((v >> 16u32) & 255u32): u8; p[3] = ((v >> 24u32) & 255u32): u8; }; -export fn l_relocate(l: *lnk, base: u64) i32 = { +export fn relocate(l: *lnk, base: u64) i32 = { let r: *lrel = l.rels; for (r != nil) { if (r.sym != nil) { // Dynamic refs are patched later in dynout once the // PLT vaddr is known. - if (r.sym.is_dyn != 0) { + if (r.sym.isdyn != 0) { r = r.rnext; continue; }; @@ -1409,12 +1401,12 @@ export fn l_relocate(l: *lnk, base: u64) i32 = { let site: u64 = base + r.off; let target: i64 = (base + r.sym.val): i64; let rel: i64 = (target - site: i64) + r.addend; - patch_u32(l.text + r.off, rel: u32); + patchu32(l.text + r.off, rel: u32); } else { if (k == R_X86_64_PLT32) { let site: u64 = base + r.off; let target: i64 = (base + r.sym.val): i64; let rel: i64 = (target - site: i64) + r.addend; - patch_u32(l.text + r.off, rel: u32); + patchu32(l.text + r.off, rel: u32); } else { os.write(2, "w6l: unsupported reloc kind\n".ptr, 27u64); l.errs += 1; @@ -1451,10 +1443,10 @@ export fn l_relocate(l: *lnk, base: u64) i32 = { // [dynamic_off] .dynamic (writable; covered by PT_DYNAMIC) // // cgen workaround notes: -// - Two-level field assignments through pointers (e.g. r.sym.is_dyn = 1) +// - Two-level field assignments through pointers (e.g. r.sym.isdyn = 1) // silently fail in the current wwstage cgen. We bind the inner -// pointer to a local first: `let sym = r.sym; sym.is_dyn = 1;` -// - Tuple returns of (i32, str) drop the str payload. l_so_version +// pointer to a local first: `let sym = r.sym; sym.isdyn = 1;` +// - Tuple returns of (i32, str) drop the str payload. soversion // returns a plain str instead. // - `def NAME: str = "...";` produces a bogus str (len ends up adding // to an offset accumulator). We use a fn returning the literal. @@ -1603,19 +1595,19 @@ fn str_eq_d(a: str, b: str) bool = { // ---- main entry -------------------------------------------------------- -export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { +export fn emitdynelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { let a: *arena = l.a; - let n: i32 = l.dyn_n; + let n: i32 = l.dynn; let nu: u64 = n: u64; // ---- collect dyn syms into a plt_idx-indexed array ---- let dynsyms: **lsym = amalloc(a, nu * 8u64): **lsym; let s: *lsym = l.syms; for (s != nil) { - if (s.is_dyn != 0) { - if (s.plt_idx >= 0) { - if (s.plt_idx < n) { - dynsyms[s.plt_idx] = s; + if (s.isdyn != 0) { + if (s.pltidx >= 0) { + if (s.pltidx < n) { + dynsyms[s.pltidx] = s; }; }; }; @@ -1642,7 +1634,7 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { let j: i32 = 0; for (j < n) { let dsm: *lsym = dynsyms[j]; - let dl: *lso = dsm.dyn_lib; + let dl: *lso = dsm.dynlib; if (dl == so) { used = 1; j = n; } else { j += 1; }; }; @@ -1682,10 +1674,10 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { let j: i32 = 0; for (j < n) { let dsm: *lsym = dynsyms[j]; - let dl: *lso = dsm.dyn_lib; + let dl: *lso = dsm.dynlib; if (dl == cur_so) { let nm0: str = dsm.name; - let dv: str = l_so_version(cur_so, nm0); + let dv: str = soversion(cur_so, nm0); if (dv.len > 0) { has = 1; j = n; } else { j += 1; }; @@ -1698,10 +1690,10 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { let jj: i32 = 0; for (jj < n) { let dsm2: *lsym = dynsyms[jj]; - let dl2: *lso = dsm2.dyn_lib; + let dl2: *lso = dsm2.dynlib; if (dl2 == cur_so) { let nm2: str = dsm2.name; - let vname: str = l_so_version(cur_so, nm2); + let vname: str = soversion(cur_so, nm2); if (vname.len > 0) { let seen: i32 = 0; let k: i32 = 0; @@ -1815,9 +1807,9 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { pi = 0; for (pi < n) { let dsm3: *lsym = dynsyms[pi]; - let dl3: *lso = dsm3.dyn_lib; + let dl3: *lso = dsm3.dynlib; let nm3: str = dsm3.name; - let vname: str = l_so_version(dl3, nm3); + let vname: str = soversion(dl3, nm3); if (vname.len == 0) { d_wr16(versym_for, (pi: u64) * 2u64, VER_NDX_GLOBAL_D); } else { @@ -2058,7 +2050,7 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { for (r != nil) { if (r.sym != nil) { let rsym: *lsym = r.sym; - if (rsym.is_dyn != 0) { + if (rsym.isdyn != 0) { if (r.kind != R_X86_64_PC32_D) { if (r.kind != R_X86_64_PLT32_D) { os.write(2, "w6l: dynamic reloc kind unsupported\n".ptr, 35u64); @@ -2066,7 +2058,7 @@ export fn l_emit_dyn_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { }; }; let site: u64 = text_va + r.off; - let stub: u64 = plt_va + (rsym.plt_idx: u64) * PLT_STUB_BYTES_D; + let stub: u64 = plt_va + (rsym.pltidx: u64) * PLT_STUB_BYTES_D; let disp: i64 = (stub: i64) - (site: i64) + r.addend; d_wr32(l.text, r.off, (disp: i32): u32); }; @@ -2196,31 +2188,31 @@ def TEXT_OFF: u64 = 4096u64; // 0x1000 // ---- little-endian byte writers ---------------------------------------- -fn wr_u16(buf: *u8, off: u64, v: u16) void = { +fn wru16(buf: *u8, off: u64, v: u16) void = { buf[off] = (v & 255u16): u8; buf[off + 1u64] = ((v >> 8u16) & 255u16): u8; }; -fn wr_u32(buf: *u8, off: u64, v: u32) void = { +fn wru32(buf: *u8, off: u64, v: u32) void = { buf[off] = (v & 255u32): u8; buf[off + 1u64] = ((v >> 8u32) & 255u32): u8; buf[off + 2u64] = ((v >> 16u32) & 255u32): u8; buf[off + 3u64] = ((v >> 24u32) & 255u32): u8; }; -fn wr_u64(buf: *u8, off: u64, v: u64) void = { - wr_u32(buf, off, (v & 4294967295u64): u32); - wr_u32(buf, off + 4u64, ((v >> 32u64) & 4294967295u64): u32); +fn wru64(buf: *u8, off: u64, v: u64) void = { + wru32(buf, off, (v & 4294967295u64): u32); + wru32(buf, off + 4u64, ((v >> 32u64) & 4294967295u64): u32); }; // ---- emit --------------------------------------------------------------- -export fn l_emit_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { +export fn emitelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { // Dispatch: any loaded shared object plus any dynamic ref means // we owe the loader a real PT_INTERP/PT_DYNAMIC binary. if (l.sos != nil) { - if (l.dyn_n > 0) { - return l_emit_dyn_elf(l, fd, base, entry); + if (l.dynn > 0) { + return emitdynelf(l, fd, base, entry); }; }; @@ -2237,29 +2229,29 @@ export fn l_emit_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { hdr[4u64] = ELFCLASS64; hdr[5u64] = ELFDATA2LSB; hdr[6u64] = EV_CURRENT: u8; - wr_u16(hdr, 16u64, ET_EXEC); // e_type - wr_u16(hdr, 18u64, EM_X86_64_W); // e_machine - wr_u32(hdr, 20u64, EV_CURRENT); // e_version - wr_u64(hdr, 24u64, entry); // e_entry - wr_u64(hdr, 32u64, 64u64); // e_phoff = sizeof(Ehdr) - wr_u64(hdr, 40u64, 0u64); // e_shoff - wr_u32(hdr, 48u64, 0u32); // e_flags - wr_u16(hdr, 52u64, 64u16); // e_ehsize - wr_u16(hdr, 54u64, 56u16); // e_phentsize - wr_u16(hdr, 56u64, 1u16); // e_phnum - wr_u16(hdr, 58u64, 0u16); // e_shentsize - wr_u16(hdr, 60u64, 0u16); // e_shnum - wr_u16(hdr, 62u64, 0u16); // e_shstrndx + wru16(hdr, 16u64, ET_EXEC); // e_type + wru16(hdr, 18u64, EM_X86_64_W); // e_machine + wru32(hdr, 20u64, EV_CURRENT); // e_version + wru64(hdr, 24u64, entry); // e_entry + wru64(hdr, 32u64, 64u64); // e_phoff = sizeof(Ehdr) + wru64(hdr, 40u64, 0u64); // e_shoff + wru32(hdr, 48u64, 0u32); // e_flags + wru16(hdr, 52u64, 64u16); // e_ehsize + wru16(hdr, 54u64, 56u16); // e_phentsize + wru16(hdr, 56u64, 1u16); // e_phnum + wru16(hdr, 58u64, 0u16); // e_shentsize + wru16(hdr, 60u64, 0u16); // e_shnum + wru16(hdr, 62u64, 0u16); // e_shstrndx // --- Phdr (56 bytes) at offset 64 --- - wr_u32(hdr, 64u64, PT_LOAD); // p_type - wr_u32(hdr, 68u64, PF_R | PF_X); // p_flags - wr_u64(hdr, 72u64, 0u64); // p_offset - wr_u64(hdr, 80u64, base); // p_vaddr - wr_u64(hdr, 88u64, base); // p_paddr - wr_u64(hdr, 96u64, filesz); // p_filesz - wr_u64(hdr, 104u64, filesz); // p_memsz - wr_u64(hdr, 112u64, TEXT_OFF); // p_align + wru32(hdr, 64u64, PT_LOAD); // p_type + wru32(hdr, 68u64, PF_R | PF_X); // p_flags + wru64(hdr, 72u64, 0u64); // p_offset + wru64(hdr, 80u64, base); // p_vaddr + wru64(hdr, 88u64, base); // p_paddr + wru64(hdr, 96u64, filesz); // p_filesz + wru64(hdr, 104u64, filesz); // p_memsz + wru64(hdr, 112u64, TEXT_OFF); // p_align // Write [0..0x1000) then .text. let n1: i64 = os.writefull(fd, hdr, TEXT_OFF); @@ -2296,17 +2288,7 @@ fn mklnk(a: *arena) *lnk = { return l; }; -fn cstreq(a: *u8, lit: str) bool = { - let n: u64 = lit.len: u64; - let i: u64 = 0u64; - for (i < n) { - let li: i32 = i: i32; - if (a[i] != lit[li]) { return false; }; - i += 1u64; - }; - if (a[i] != 0u8) { return false; }; - return true; -}; +// `cstreq` lives in obj.ww — same bundle, single definition. // `cstrlen` lives in obj.ww — same bundle, single definition. @@ -2549,12 +2531,12 @@ export fn main(argc: i32, argv: **u8) i32 = { let l: *lnk = mklnk(a); // Seed _start so libwwrt-style start.o is recognised as wanted. - l_intern(l, "_start"); + intern(l, "_start"); // Load positional inputs first (preserving order). let k: i32 = 0; for (k < ninputs) { - if (l_load(l, inputs[k]) != 0) { + if (load(l, inputs[k]) != 0) { return 1; }; k += 1; @@ -2573,19 +2555,19 @@ export fn main(argc: i32, argv: **u8) i32 = { return 1; }; if (isso(p) != 0) { - if (l_load_so(l, p) != 0) { return 1; }; + if (loadso(l, p) != 0) { return 1; }; } else { - if (l_load(l, p) != 0) { return 1; }; + if (load(l, p) != 0) { return 1; }; }; lf += 1; }; - if (l_resolve(l) != 0) { return 1; }; - if (l_relocate(l, BASE + CODE_VA_OFF) != 0) { return 1; }; + if (resolve(l) != 0) { return 1; }; + if (relocate(l, BASE + CODE_VA_OFF) != 0) { return 1; }; - let entrysym: *lsym = l_lookup(l, "_start"); - if (entrysym == nil) { entrysym = l_lookup(l, "main"); } - else { if (entrysym.defined == 0) { entrysym = l_lookup(l, "main"); }; }; + let entrysym: *lsym = lookup(l, "_start"); + if (entrysym == nil) { entrysym = lookup(l, "main"); } + else { if (entrysym.defined == 0) { entrysym = lookup(l, "main"); }; }; if (entrysym == nil) { os.write(2, "w6l: no _start or main symbol\n".ptr, 29u64); return 1; @@ -2603,7 +2585,7 @@ export fn main(argc: i32, argv: **u8) i32 = { }; let entryva: u64 = BASE + CODE_VA_OFF + entrysym.val; - let rc: i32 = l_emit_elf(l, fd, BASE, entryva); + let rc: i32 = emitelf(l, fd, BASE, entryva); os.close(fd); return rc; }; diff --git a/selfhost/cmd/w6l/main.ww b/selfhost/cmd/w6l/main.ww index 32685ea5..57ac898d 100644 --- a/selfhost/cmd/w6l/main.ww +++ b/selfhost/cmd/w6l/main.ww @@ -23,17 +23,7 @@ fn mklnk(a: *arena) *lnk = { return l; }; -fn cstreq(a: *u8, lit: str) bool = { - let n: u64 = lit.len: u64; - let i: u64 = 0u64; - for (i < n) { - let li: i32 = i: i32; - if (a[i] != lit[li]) { return false; }; - i += 1u64; - }; - if (a[i] != 0u8) { return false; }; - return true; -}; +// `cstreq` lives in obj.ww — same bundle, single definition. // `cstrlen` lives in obj.ww — same bundle, single definition. @@ -276,12 +266,12 @@ export fn main(argc: i32, argv: **u8) i32 = { let l: *lnk = mklnk(a); // Seed _start so libwwrt-style start.o is recognised as wanted. - l_intern(l, "_start"); + intern(l, "_start"); // Load positional inputs first (preserving order). let k: i32 = 0; for (k < ninputs) { - if (l_load(l, inputs[k]) != 0) { + if (load(l, inputs[k]) != 0) { return 1; }; k += 1; @@ -300,19 +290,19 @@ export fn main(argc: i32, argv: **u8) i32 = { return 1; }; if (isso(p) != 0) { - if (l_load_so(l, p) != 0) { return 1; }; + if (loadso(l, p) != 0) { return 1; }; } else { - if (l_load(l, p) != 0) { return 1; }; + if (load(l, p) != 0) { return 1; }; }; lf += 1; }; - if (l_resolve(l) != 0) { return 1; }; - if (l_relocate(l, BASE + CODE_VA_OFF) != 0) { return 1; }; + if (resolve(l) != 0) { return 1; }; + if (relocate(l, BASE + CODE_VA_OFF) != 0) { return 1; }; - let entrysym: *lsym = l_lookup(l, "_start"); - if (entrysym == nil) { entrysym = l_lookup(l, "main"); } - else { if (entrysym.defined == 0) { entrysym = l_lookup(l, "main"); }; }; + let entrysym: *lsym = lookup(l, "_start"); + if (entrysym == nil) { entrysym = lookup(l, "main"); } + else { if (entrysym.defined == 0) { entrysym = lookup(l, "main"); }; }; if (entrysym == nil) { os.write(2, "w6l: no _start or main symbol\n".ptr, 29u64); return 1; @@ -330,7 +320,7 @@ export fn main(argc: i32, argv: **u8) i32 = { }; let entryva: u64 = BASE + CODE_VA_OFF + entrysym.val; - let rc: i32 = l_emit_elf(l, fd, BASE, entryva); + let rc: i32 = emitelf(l, fd, BASE, entryva); os.close(fd); return rc; }; diff --git a/selfhost/cmd/w6l/obj.ww b/selfhost/cmd/w6l/obj.ww index 13915f3f..b65bd43c 100644 --- a/selfhost/cmd/w6l/obj.ww +++ b/selfhost/cmd/w6l/obj.ww @@ -75,8 +75,8 @@ def RELA_ADDEND: u64 = 16u64; // ---- file slurp -------------------------------------------------------- -fn read_all(path_cs: *u8) (*u8, u64) = { - let fd: i32 = os.open(path_cs, os.O_RDONLY, 0i32); +fn readall(path: *u8) (*u8, u64) = { + let fd: i32 = os.open(path, os.O_RDONLY, 0i32); if (fd < 0) { return nil, 0u64; }; let n: i64 = os.filesize(fd); if (n < 0i64) { os.close(fd); return nil, 0u64; }; @@ -89,7 +89,7 @@ fn read_all(path_cs: *u8) (*u8, u64) = { // ---- text buffer growth ------------------------------------------------ -fn emit_text(l: *lnk, src: *u8, n: u64) void = { +fn emittext(l: *lnk, src: *u8, n: u64) void = { if (l.textlen + n > l.textcap) { let nc: u64 = l.textcap; if (nc == 0u64) { nc = 4096u64; }; @@ -122,7 +122,7 @@ fn cstrlen(p: *u8) u64 = { return n; }; -fn cstr_eq(p: *u8, lit: str) bool = { +fn cstreq(p: *u8, lit: str) bool = { let n: u64 = lit.len: u64; let i: u64 = 0u64; for (i < n) { @@ -134,8 +134,8 @@ fn cstr_eq(p: *u8, lit: str) bool = { return true; }; -// Build a ww str from a NUL-terminated *u8 (for passing to l_intern). -fn cstr_to_str(a: *arena, p: *u8) str = { +// Build a ww str from a NUL-terminated *u8 (for passing to intern). +fn cstrtostr(a: *arena, p: *u8) str = { let n: u64 = cstrlen(p); return astrndup(a, p, n); }; @@ -159,7 +159,7 @@ type armember = struct { mnext: *armember, }; -fn is_archive(p: *u8, len: u64) bool = { +fn isarchive(p: *u8, len: u64) bool = { if (len < 8u64) { return false; }; if (p[0u64] != 33u8) { return false; }; // '!' if (p[1u64] != 60u8) { return false; }; // '<' @@ -172,8 +172,8 @@ fn is_archive(p: *u8, len: u64) bool = { return true; }; -// ar_field — parse a space-padded decimal integer of width n. -fn ar_field(p: *u8, n: u64) u64 = { +// arfield — parse a space-padded decimal integer of width n. +fn arfield(p: *u8, n: u64) u64 = { let v: u64 = 0u64; let i: u64 = 0u64; for (i < n) { @@ -186,10 +186,10 @@ fn ar_field(p: *u8, n: u64) u64 = { return v; }; -// elf_globals — return a linked list of names of globally-defined +// elfglobals — return a linked list of names of globally-defined // (STB_GLOBAL) symbols whose section is `.text`. Names are arena // copies, so the source ELF buffer can be freed afterward. -fn elf_globals(a: *arena, buf: *u8, len: u64) *defent = { +fn elfglobals(a: *arena, buf: *u8, len: u64) *defent = { if (len < EHDR_SIZE) { return nil; }; if (buf[0u64] != 127u8) { return nil; }; if (buf[1u64] != 69u8) { return nil; }; @@ -212,7 +212,7 @@ fn elf_globals(a: *arena, buf: *u8, len: u64) *defent = { let sh_name: u32 = rd_u32(buf, sh_off + SHDR_NAME); let nm: *u8 = shstr + (sh_name: u64); if (sh_type == SHT_PROGBITS: u32) { - if (cstr_eq(nm, ".text")) { idx_text = i: i32; }; + if (cstreq(nm, ".text")) { idx_text = i: i32; }; }; if (sh_type == SHT_SYMTAB: u32) { idx_symtab = i: i32; }; i += 1u32; @@ -244,7 +244,7 @@ fn elf_globals(a: *arena, buf: *u8, len: u64) *defent = { if ((st_shndx: i32) == idx_text) { let nm_p: *u8 = strtab + (st_name: u64); if (nm_p[0u64] != 0u8) { - let nm: str = cstr_to_str(a, nm_p); + let nm: str = cstrtostr(a, nm_p); let de: *defent = amalloc(a, 32u64): *defent; de.name = nm; de.dnext = head; @@ -258,13 +258,13 @@ fn elf_globals(a: *arena, buf: *u8, len: u64) *defent = { return head; }; -// member_defines_undef — true if any of m's defined globals matches a +// memberdefinesundef — true if any of m's defined globals matches a // currently-undefined symbol in the linker's symbol table. Names not // already interned are uninteresting (the link doesn't need them yet). -fn member_defines_undef(l: *lnk, m: *armember) bool = { +fn memberdefinesundef(l: *lnk, m: *armember) bool = { let de: *defent = m.defs; for (de != nil) { - let s: *lsym = l_lookup(l, de.name); + let s: *lsym = lookup(l, de.name); if (s != nil) { if (s.defined == 0) { return true; }; }; @@ -273,17 +273,17 @@ fn member_defines_undef(l: *lnk, m: *armember) bool = { return false; }; -// load_archive — port of cmd/w6l/obj.c:load_archive. +// loadarchive — port of cmd/w6l/obj.c:load_archive. // // Pass 1 indexes every regular member. Pass 2 iteratively pulls in any // member that supplies a currently-undefined symbol; each pull may // introduce fresh undefs, so we loop until quiescent. -fn load_archive(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { +fn loadarchive(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { let head: *armember = nil; let tail: *armember = nil; let pos: u64 = 8u64; // past "!\n" for (pos + 60u64 <= len) { - let hdr_size: u64 = ar_field(buf + pos + 48u64, 10u64); + let hdr_size: u64 = arfield(buf + pos + 48u64, 10u64); let hdr_end: u64 = pos + 60u64; if (hdr_end + hdr_size > len) { break; }; let first: u8 = buf[pos]; @@ -299,7 +299,7 @@ fn load_archive(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { i += 1u64; }; m.data = mb; - m.defs = elf_globals(l.a, mb, hdr_size); + m.defs = elfglobals(l.a, mb, hdr_size); m.loaded = 0; m.mnext = nil; if (head == nil) { head = m; } @@ -316,8 +316,8 @@ fn load_archive(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { let m: *armember = head; for (m != nil) { if (m.loaded == 0) { - if (member_defines_undef(l, m)) { - if (load_image(l, path_cs, m.data, m.size) == 0) { + if (memberdefinesundef(l, m)) { + if (loadimage(l, path, m.data, m.size) == 0) { m.loaded = 1; changed = 1; }; @@ -331,21 +331,21 @@ fn load_archive(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { // ---- main loader ------------------------------------------------------- -export fn l_load(l: *lnk, path_cs: *u8) i32 = { +export fn load(l: *lnk, path: *u8) i32 = { let bufp: *u8; let buflen: u64; - bufp, buflen = read_all(path_cs); + bufp, buflen = readall(path); if (bufp == nil) { os.write(2, "w6l: cannot read object\n".ptr, 23u64); return -1; }; - if (is_archive(bufp, buflen)) { - return load_archive(l, path_cs, bufp, buflen); + if (isarchive(bufp, buflen)) { + return loadarchive(l, path, bufp, buflen); }; - return load_image(l, path_cs, bufp, buflen); + return loadimage(l, path, bufp, buflen); }; -fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { +fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { if (len < EHDR_SIZE) { return -1; }; // magic: 0x7f, 'E', 'L', 'F' if (buf[0u64] != 127u8) { return -1; }; @@ -374,11 +374,11 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { let sh_name: u32 = rd_u32(buf, sh_off + SHDR_NAME); let nm: *u8 = shstr + (sh_name: u64); if (sh_type == SHT_PROGBITS: u32) { - if (cstr_eq(nm, ".text")) { idx_text = i: i32; }; + if (cstreq(nm, ".text")) { idx_text = i: i32; }; }; if (sh_type == SHT_SYMTAB: u32) { idx_symtab = i: i32; }; if (sh_type == SHT_RELA: u32) { - if (cstr_eq(nm, ".rela.text")) { idx_rela = i: i32; }; + if (cstreq(nm, ".rela.text")) { idx_rela = i: i32; }; }; i += 1u32; }; @@ -407,16 +407,16 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { // Track this object. let ob: *lobj = amalloc(l.a, 64u64): *lobj; - ob.path = cstr_to_str(l.a, path_cs); + ob.path = cstrtostr(l.a, path); ob.buf = buf; ob.len = len; - ob.text_off = l.textlen; - ob.text_size = text_size; + ob.textoff = l.textlen; + ob.textsize = text_size; ob.onext = l.objs; l.objs = ob; // Append .text bytes to the combined image. - emit_text(l, buf + text_off, text_size); + emittext(l, buf + text_off, text_size); // Walk symbols. We don't keep a per-object map[] of *lsym. Instead // the reloc loop re-walks symtab and re-interns by name. Simpler @@ -429,8 +429,8 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { let st_value: u64 = rd_u64(buf, sym_p + SYM_VALUE); let nm_p: *u8 = strtab + (st_name: u64); if (nm_p[0u64] != 0u8) { - let nm: str = cstr_to_str(l.a, nm_p); - let gs: *lsym = l_intern(l, nm); + let nm: str = cstrtostr(l.a, nm_p); + let gs: *lsym = intern(l, nm); if (st_shndx != 0u16) { if ((st_shndx: i32) == idx_text) { if (gs.defined != 0) { @@ -439,8 +439,8 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { } else { gs.defined = 1; gs.owner = ob; - gs.idx_in_owner = si: i32; - gs.val = ob.text_off + st_value; + gs.idxinowner = si: i32; + gs.val = ob.textoff + st_value; }; }; }; @@ -463,7 +463,7 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { let r_sym_idx: u32 = (r_info >> 32u64): u32; let r_kind: i32 = ((r_info & 4294967295u64): u32): i32; let nr: *lrel = amalloc(l.a, 48u64): *lrel; - nr.off = ob.text_off + r_off; + nr.off = ob.textoff + r_off; nr.kind = r_kind; nr.addend = r_addend: i64; // Look up the referenced sym by name (re-walk symtab). @@ -472,8 +472,8 @@ fn load_image(l: *lnk, path_cs: *u8, buf: *u8, len: u64) i32 = { let s_name: u32 = rd_u32(buf, s_p + SYM_NAME); let s_nm: *u8 = strtab + (s_name: u64); if (s_nm[0u64] != 0u8) { - let nm: str = cstr_to_str(l.a, s_nm); - nr.sym = l_intern(l, nm); + let nm: str = cstrtostr(l.a, s_nm); + nr.sym = intern(l, nm); }; }; nr.rnext = l.rels; diff --git a/selfhost/cmd/w6l/out.ww b/selfhost/cmd/w6l/out.ww index 22c056f0..16c61750 100644 --- a/selfhost/cmd/w6l/out.ww +++ b/selfhost/cmd/w6l/out.ww @@ -24,31 +24,31 @@ def TEXT_OFF: u64 = 4096u64; // 0x1000 // ---- little-endian byte writers ---------------------------------------- -fn wr_u16(buf: *u8, off: u64, v: u16) void = { +fn wru16(buf: *u8, off: u64, v: u16) void = { buf[off] = (v & 255u16): u8; buf[off + 1u64] = ((v >> 8u16) & 255u16): u8; }; -fn wr_u32(buf: *u8, off: u64, v: u32) void = { +fn wru32(buf: *u8, off: u64, v: u32) void = { buf[off] = (v & 255u32): u8; buf[off + 1u64] = ((v >> 8u32) & 255u32): u8; buf[off + 2u64] = ((v >> 16u32) & 255u32): u8; buf[off + 3u64] = ((v >> 24u32) & 255u32): u8; }; -fn wr_u64(buf: *u8, off: u64, v: u64) void = { - wr_u32(buf, off, (v & 4294967295u64): u32); - wr_u32(buf, off + 4u64, ((v >> 32u64) & 4294967295u64): u32); +fn wru64(buf: *u8, off: u64, v: u64) void = { + wru32(buf, off, (v & 4294967295u64): u32); + wru32(buf, off + 4u64, ((v >> 32u64) & 4294967295u64): u32); }; // ---- emit --------------------------------------------------------------- -export fn l_emit_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { +export fn emitelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { // Dispatch: any loaded shared object plus any dynamic ref means // we owe the loader a real PT_INTERP/PT_DYNAMIC binary. if (l.sos != nil) { - if (l.dyn_n > 0) { - return l_emit_dyn_elf(l, fd, base, entry); + if (l.dynn > 0) { + return emitdynelf(l, fd, base, entry); }; }; @@ -65,29 +65,29 @@ export fn l_emit_elf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { hdr[4u64] = ELFCLASS64; hdr[5u64] = ELFDATA2LSB; hdr[6u64] = EV_CURRENT: u8; - wr_u16(hdr, 16u64, ET_EXEC); // e_type - wr_u16(hdr, 18u64, EM_X86_64_W); // e_machine - wr_u32(hdr, 20u64, EV_CURRENT); // e_version - wr_u64(hdr, 24u64, entry); // e_entry - wr_u64(hdr, 32u64, 64u64); // e_phoff = sizeof(Ehdr) - wr_u64(hdr, 40u64, 0u64); // e_shoff - wr_u32(hdr, 48u64, 0u32); // e_flags - wr_u16(hdr, 52u64, 64u16); // e_ehsize - wr_u16(hdr, 54u64, 56u16); // e_phentsize - wr_u16(hdr, 56u64, 1u16); // e_phnum - wr_u16(hdr, 58u64, 0u16); // e_shentsize - wr_u16(hdr, 60u64, 0u16); // e_shnum - wr_u16(hdr, 62u64, 0u16); // e_shstrndx + wru16(hdr, 16u64, ET_EXEC); // e_type + wru16(hdr, 18u64, EM_X86_64_W); // e_machine + wru32(hdr, 20u64, EV_CURRENT); // e_version + wru64(hdr, 24u64, entry); // e_entry + wru64(hdr, 32u64, 64u64); // e_phoff = sizeof(Ehdr) + wru64(hdr, 40u64, 0u64); // e_shoff + wru32(hdr, 48u64, 0u32); // e_flags + wru16(hdr, 52u64, 64u16); // e_ehsize + wru16(hdr, 54u64, 56u16); // e_phentsize + wru16(hdr, 56u64, 1u16); // e_phnum + wru16(hdr, 58u64, 0u16); // e_shentsize + wru16(hdr, 60u64, 0u16); // e_shnum + wru16(hdr, 62u64, 0u16); // e_shstrndx // --- Phdr (56 bytes) at offset 64 --- - wr_u32(hdr, 64u64, PT_LOAD); // p_type - wr_u32(hdr, 68u64, PF_R | PF_X); // p_flags - wr_u64(hdr, 72u64, 0u64); // p_offset - wr_u64(hdr, 80u64, base); // p_vaddr - wr_u64(hdr, 88u64, base); // p_paddr - wr_u64(hdr, 96u64, filesz); // p_filesz - wr_u64(hdr, 104u64, filesz); // p_memsz - wr_u64(hdr, 112u64, TEXT_OFF); // p_align + wru32(hdr, 64u64, PT_LOAD); // p_type + wru32(hdr, 68u64, PF_R | PF_X); // p_flags + wru64(hdr, 72u64, 0u64); // p_offset + wru64(hdr, 80u64, base); // p_vaddr + wru64(hdr, 88u64, base); // p_paddr + wru64(hdr, 96u64, filesz); // p_filesz + wru64(hdr, 104u64, filesz); // p_memsz + wru64(hdr, 112u64, TEXT_OFF); // p_align // Write [0..0x1000) then .text. let n1: i64 = os.writefull(fd, hdr, TEXT_OFF); diff --git a/selfhost/cmd/w6l/pass.ww b/selfhost/cmd/w6l/pass.ww index 94f90c9e..6126de3d 100644 --- a/selfhost/cmd/w6l/pass.ww +++ b/selfhost/cmd/w6l/pass.ww @@ -17,14 +17,14 @@ use dyn; def R_X86_64_PC32: i32 = 2; def R_X86_64_PLT32: i32 = 4; -export fn l_resolve(l: *lnk) i32 = { +export fn resolve(l: *lnk) i32 = { // Initialise dynamic-linking sentinels. amalloc zeroes, so - // is_dyn/dyn_lib start clean — but plt_idx and dynsym_idx + // isdyn/dynlib start clean — but pltidx and dynsymidx // must be -1, not 0. let si: *lsym = l.syms; for (si != nil) { - si.plt_idx = -1; - si.dynsym_idx = -1; + si.pltidx = -1; + si.dynsymidx = -1; si = si.snext; }; @@ -36,14 +36,14 @@ export fn l_resolve(l: *lnk) i32 = { if (r.sym != nil) { if (r.sym.defined == 0) { let sym: *lsym = r.sym; - if (sym.is_dyn == 0) { + if (sym.isdyn == 0) { let so: *lso = l.sos; for (so != nil) { - if (l_so_provides(so, sym.name) != 0) { - sym.is_dyn = 1; - sym.dyn_lib = so; - sym.plt_idx = l.dyn_n; - l.dyn_n += 1; + if (soprovides(so, sym.name) != 0) { + sym.isdyn = 1; + sym.dynlib = so; + sym.pltidx = l.dynn; + l.dynn += 1; so = nil; // break } else { so = so.sonext; @@ -60,7 +60,7 @@ export fn l_resolve(l: *lnk) i32 = { for (r2 != nil) { if (r2.sym != nil) { if (r2.sym.defined == 0) { - if (r2.sym.is_dyn == 0) { + if (r2.sym.isdyn == 0) { os.write(2, "w6l: undefined reference to '".ptr, 28u64); let nm: str = r2.sym.name; os.write(2, nm.ptr, nm.len: u64); @@ -74,20 +74,20 @@ export fn l_resolve(l: *lnk) i32 = { return l.errs; }; -fn patch_u32(p: *u8, v: u32) void = { +fn patchu32(p: *u8, v: u32) void = { p[0] = (v & 255u32): u8; p[1] = ((v >> 8u32) & 255u32): u8; p[2] = ((v >> 16u32) & 255u32): u8; p[3] = ((v >> 24u32) & 255u32): u8; }; -export fn l_relocate(l: *lnk, base: u64) i32 = { +export fn relocate(l: *lnk, base: u64) i32 = { let r: *lrel = l.rels; for (r != nil) { if (r.sym != nil) { // Dynamic refs are patched later in dynout once the // PLT vaddr is known. - if (r.sym.is_dyn != 0) { + if (r.sym.isdyn != 0) { r = r.rnext; continue; }; @@ -97,12 +97,12 @@ export fn l_relocate(l: *lnk, base: u64) i32 = { let site: u64 = base + r.off; let target: i64 = (base + r.sym.val): i64; let rel: i64 = (target - site: i64) + r.addend; - patch_u32(l.text + r.off, rel: u32); + patchu32(l.text + r.off, rel: u32); } else { if (k == R_X86_64_PLT32) { let site: u64 = base + r.off; let target: i64 = (base + r.sym.val): i64; let rel: i64 = (target - site: i64) + r.addend; - patch_u32(l.text + r.off, rel: u32); + patchu32(l.text + r.off, rel: u32); } else { os.write(2, "w6l: unsupported reloc kind\n".ptr, 27u64); l.errs += 1; diff --git a/selfhost/cmd/w6l/sym.ww b/selfhost/cmd/w6l/sym.ww index fd0ba195..d048297d 100644 --- a/selfhost/cmd/w6l/sym.ww +++ b/selfhost/cmd/w6l/sym.ww @@ -6,20 +6,20 @@ use mem; type lsym = struct { - name: str, - val: u64, // offset within combined .text once linked - defined: i32, // 1 if some lobj defines this symbol - owner: *lobj, - idx_in_owner: i32, - // Dynamic-linking fields. Set by l_resolve when an undefined sym - // is provided by some loaded lso. plt_idx and dynsym_idx default - // to -1 (set explicitly by l_resolve, not by amalloc-zeroing). - is_dyn: i32, - dyn_lib: *lso, - dyn_version: str, // matched export's version; len 0 if none - plt_idx: i32, - dynsym_idx: i32, - snext: *lsym, + name: str, + val: u64, // offset within combined .text once linked + defined: i32, // 1 if some lobj defines this symbol + owner: *lobj, + idxinowner: i32, + // Dynamic-linking fields. Set by resolve when an undefined sym + // is provided by some loaded lso. pltidx and dynsymidx default + // to -1 (set explicitly by resolve, not by amalloc-zeroing). + isdyn: i32, + dynlib: *lso, + dynversion: str, // matched export's version; len 0 if none + pltidx: i32, + dynsymidx: i32, + snext: *lsym, }; type lrel = struct { @@ -31,17 +31,17 @@ type lrel = struct { }; type lobj = struct { - path: str, - buf: *u8, // object bytes - len: u64, - text_off: u64, // offset of .text in combined output - text_size: u64, - onext: *lobj, + path: str, + buf: *u8, // object bytes + len: u64, + textoff: u64, // offset of .text in combined output + textsize: u64, + onext: *lobj, }; // lexport — one entry per GLOBAL/WEAK symbol exported by a loaded .so. // Stored as a chain in the order the .so's dynsym presents them, so -// l_so_provides_v's first-match semantics agree with the C version. +// soprovides_v's first-match semantics agree with the C version. type lexport = struct { name: str, version: str, // len 0 for unversioned globals @@ -65,7 +65,7 @@ type lnk = struct { textcap: u64, textlen: u64, errs: i32, - dyn_n: i32, // number of syms routed through PLT + dynn: i32, // number of syms routed through PLT }; fn streq(a: str, b: str) bool = { @@ -78,7 +78,7 @@ fn streq(a: str, b: str) bool = { return true; }; -export fn l_intern(l: *lnk, name: str) *lsym = { +export fn intern(l: *lnk, name: str) *lsym = { let s: *lsym = l.syms; for (s != nil) { if (streq(s.name, name)) { return s; }; @@ -91,7 +91,7 @@ export fn l_intern(l: *lnk, name: str) *lsym = { return n; }; -export fn l_lookup(l: *lnk, name: str) *lsym = { +export fn lookup(l: *lnk, name: str) *lsym = { let s: *lsym = l.syms; for (s != nil) { if (streq(s.name, name)) { return s; };