selfhost/cmd/w6l: strip *arena cascade (γ-4)

amalloc has 0 callers post-γ-2; the *arena threaded through w6l's
mklnk/resolvelib/cstrtostr/elfglobals/dcstrtostr and the lnk.a
field are vestigial.

Drop `import mem;` from sym/main/obj/dyn/dynout, remove lnk.a
struct field, strip *arena from the five signatures, update 13
call sites. Drop a dead `let a: *arena = l.a;` in dynout. Comments
at pass.ww/obj.ww/main.ww retidied to match post-strip reality.
main.combined.ww auto-regenerated.

Verified 132/132 incl. 992_w6l_ww + 996_dyn_ww + 995_self_rebuild
byte-identity.
This commit is contained in:
2026-05-21 12:00:46 +09:00
parent 12e0b4057f
commit 6faf00223e
7 changed files with 48 additions and 158 deletions

View File

@@ -12,7 +12,6 @@ package w6l;
import os; import os;
import rt; import rt;
import mem;
import strings; import strings;
import sym; import sym;
@@ -107,7 +106,7 @@ fn dcstrlen(p: *u8) u64 = {
return n; return n;
}; };
fn dcstrtostr(a: *arena, p: *u8) str = { fn dcstrtostr(p: *u8) str = {
let n: u64 = dcstrlen(p); let n: u64 = dcstrlen(p);
let view: str; let view: str;
view.ptr = p; view.ptr = p;
@@ -295,7 +294,7 @@ export fn loadso(l: *lnk, path: *u8) i32 = {
// Build the lso. Exports are appended in dynsym order so // Build the lso. Exports are appended in dynsym order so
// soprovides_v's first-match semantics match the C version. // soprovides_v's first-match semantics match the C version.
let so: *lso = alloc(lso { path = dcstrtostr(l.a, path), soname = dcstrtostr(l.a, sonamecs) })!; let so: *lso = alloc(lso { path = dcstrtostr(path), soname = dcstrtostr(sonamecs) })!;
let tail: *lexport = nil; let tail: *lexport = nil;
let si: u64 = 1u64; let si: u64 = 1u64;
@@ -347,9 +346,9 @@ export fn loadso(l: *lnk, path: *u8) i32 = {
}; };
if (keep != 0) { if (keep != 0) {
let e: *lexport = alloc(lexport { name = dcstrtostr(l.a, nmp) })!; let e: *lexport = alloc(lexport { name = dcstrtostr(nmp) })!;
if (vernamecs != nil) { if (vernamecs != nil) {
e.version = dcstrtostr(l.a, vernamecs); e.version = dcstrtostr(vernamecs);
}; };
if (tail == nil) { if (tail == nil) {
so.exports = e; so.exports = e;

View File

@@ -26,7 +26,6 @@ package w6l;
import os; import os;
import rt; import rt;
import mem;
import sym; import sym;
// ELF constants // ELF constants
@@ -170,7 +169,6 @@ export fn emitdynelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = {
// Placed after .dynamic so the segment is one contiguous run; // Placed after .dynamic so the segment is one contiguous run;
// relocate runs from here so the dyn layout's datava lands in // relocate runs from here so the dyn layout's datava lands in
// patched offsets. // patched offsets.
let a: *arena = l.a;
let n: i32 = l.dynn; let n: i32 = l.dynn;
let nu: u64 = n: u64; let nu: u64 = n: u64;

View File

@@ -750,98 +750,6 @@ package rt;
// a future task (task #39). ref/hare/rt/malloc.ha:27. // a future task (task #39). ref/hare/rt/malloc.ha:27.
@symbol("rt_malloc") export fn malloc(n: u64) *void; @symbol("rt_malloc") export fn malloc(n: u64) *void;
// selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c.
//
// Bump arena allocator. Backed by the runtime page allocator
// (rt_malloc / rt_free), no libc. Each chunk is mmap'd; when the
// current chunk runs out we link a fresh one. Freeing the arena
// unmaps the chain.
//
// Memory handed out is 16-byte aligned. The C version under
// cmd/wcc/ is retained until the three-stage bootstrap diffs clean.
package wcc;
import os;
import rt;
def ALIGN: u64 = 16u64;
def INIT_CHUNK: u64 = 65536u64;
def MAX_CHUNK: u64 = 4194304u64;
def ARENA_SZ: u64 = 48u64; // sizeof(arena), kept in sync below
type arena = struct {
buf: *u8,
off: u64,
cap: u64,
next: *arena,
total: u64,
};
fn roundup(n: u64, a: u64) u64 = {
return (n + a - 1u64) & ~(a - 1u64);
};
export fn newarena() *arena = {
let a: *arena = rt.malloc(ARENA_SZ): *arena;
a.buf = rt.malloc(INIT_CHUNK): *u8;
a.off = 0u64;
a.cap = INIT_CHUNK;
a.next = nil;
a.total = 0u64;
return a;
};
// Grow: link a fresh chunk in front of the head. We push the old
// chunk into `next` so the head always describes the current bump
// region. Chunk size doubles up to MAX_CHUNK.
fn grow(a: *arena, need: u64) bool = {
let want: u64 = a.cap * 2u64;
if (want < need) { want = need; };
if (want > MAX_CHUNK) { want = MAX_CHUNK; };
if (want < need) { return false; }; // single allocation too big
let old: *arena = rt.malloc(ARENA_SZ): *arena;
old.buf = a.buf;
old.off = a.off;
old.cap = a.cap;
old.next = a.next;
old.total = 0u64;
a.buf = rt.malloc(want): *u8;
a.off = 0u64;
a.cap = want;
a.next = old;
return true;
};
export fn amalloc(a: *arena, n: u64) *void = {
let need: u64 = roundup(n, ALIGN);
if (need > a.cap - a.off) {
if (!grow(a, need)) { return nil; };
};
let p: *u8 = a.buf + a.off;
a.off += need;
a.total += need;
// Zero the region. Plan 9 amalloc zeroes; we mirror that here so
// the checker can assume freshly allocated nodes start at 0.
let i: u64 = 0u64;
for (i < need) {
p[i] = 0u8;
i += 1u64;
};
return p: *void;
};
export fn freearena(a: *arena) void = {
for (a != nil) {
let next: *arena = a.next;
os.free(a.buf: *void, a.cap);
os.free(a: *void, ARENA_SZ);
a = next;
};
};
// selfhost/cmd/w6l/sym.ww — port of cmd/w6l/sym.c. // selfhost/cmd/w6l/sym.ww — port of cmd/w6l/sym.c.
// //
// Linker symbol table. Singly-linked list, usually a few hundred // Linker symbol table. Singly-linked list, usually a few hundred
@@ -849,8 +757,6 @@ export fn freearena(a: *arena) void = {
package w6l; package w6l;
import mem;
type lsym = struct { type lsym = struct {
name: str, name: str,
val: u64, // offset within combined .text (or .data when val: u64, // offset within combined .text (or .data when
@@ -907,7 +813,6 @@ type lso = struct {
}; };
type lnk = struct { type lnk = struct {
a: *arena,
objs: *lobj, objs: *lobj,
sos: *lso, sos: *lso,
syms: *lsym, syms: *lsym,
@@ -2899,7 +2804,6 @@ package w6l;
import os; import os;
import rt; import rt;
import mem;
import strings; import strings;
import sym; import sym;
@@ -3045,7 +2949,7 @@ fn cstrlen(p: *u8) u64 = {
return n; return n;
}; };
// pathstr — view a NUL-terminated *u8 as a str. Bridges argv/arena // pathstr — view a NUL-terminated *u8 as a str. Bridges argv-style
// callers to lib/os entrypoints (str post-task-#23). Shared with // callers to lib/os entrypoints (str post-task-#23). Shared with
// main.ww and dyn.ww via the w6l bundle. // main.ww and dyn.ww via the w6l bundle.
fn pathstr(p: *u8) str = { fn pathstr(p: *u8) str = {
@@ -3068,7 +2972,7 @@ fn cstreq(p: *u8, lit: str) bool = {
}; };
// Build a ww str from a NUL-terminated *u8 (for passing to intern). // Build a ww str from a NUL-terminated *u8 (for passing to intern).
fn cstrtostr(a: *arena, p: *u8) str = { fn cstrtostr(p: *u8) str = {
let n: u64 = cstrlen(p); let n: u64 = cstrlen(p);
let view: str; let view: str;
view.ptr = p; view.ptr = p;
@@ -3088,7 +2992,7 @@ type defent = struct {
}; };
type armember = struct { type armember = struct {
data: *u8, // arena copy of the member's ELF bytes data: *u8, // owned heap copy of the member's ELF bytes
size: u64, size: u64,
defs: *defent, // linked list of defined globals defs: *defent, // linked list of defined globals
loaded: i32, loaded: i32,
@@ -3123,9 +3027,9 @@ fn arfield(p: *u8, n: u64) u64 = {
}; };
// elfglobals — 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 // (STB_GLOBAL) symbols whose section is `.text`. Names are owned
// copies, so the source ELF buffer can be freed afterward. // heap copies, so the source ELF buffer can be freed afterward.
fn elfglobals(a: *arena, buf: *u8, len: u64) *defent = { fn elfglobals(buf: *u8, len: u64) *defent = {
if (len < EHDR_SIZE) { return nil; }; if (len < EHDR_SIZE) { return nil; };
if (buf[0u64] != 127u8) { return nil; }; if (buf[0u64] != 127u8) { return nil; };
if (buf[1u64] != 69u8) { return nil; }; if (buf[1u64] != 69u8) { return nil; };
@@ -3189,7 +3093,7 @@ fn elfglobals(a: *arena, buf: *u8, len: u64) *defent = {
if (intext || indt) { if (intext || indt) {
let nmp: *u8 = strtab + (stname: u64); let nmp: *u8 = strtab + (stname: u64);
if (nmp[0u64] != 0u8) { if (nmp[0u64] != 0u8) {
let nm: str = cstrtostr(a, nmp); let nm: str = cstrtostr(nmp);
let de: *defent = alloc(defent { name = nm, dnext = head })!; let de: *defent = alloc(defent { name = nm, dnext = head })!;
head = de; head = de;
}; };
@@ -3242,7 +3146,7 @@ fn loadarchive(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
i += 1u64; i += 1u64;
}; };
m.data = mb; m.data = mb;
m.defs = elfglobals(l.a, mb, hdrsize); m.defs = elfglobals(mb, hdrsize);
if (head == nil) { head = m; } if (head == nil) { head = m; }
else { tail.mnext = m; }; else { tail.mnext = m; };
tail = m; tail = m;
@@ -3360,7 +3264,7 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
// Track this object. // Track this object.
let ob: *lobj = alloc(lobj { let ob: *lobj = alloc(lobj {
path = cstrtostr(l.a, path), path = cstrtostr(path),
buf = buf, buf = buf,
len = len, len = len,
textoff = l.textlen, textoff = l.textlen,
@@ -3391,7 +3295,7 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
let stvalue: u64 = rdu64(buf, symp + SYM_VALUE); let stvalue: u64 = rdu64(buf, symp + SYM_VALUE);
let nmp: *u8 = strtab + (stname: u64); let nmp: *u8 = strtab + (stname: u64);
if (nmp[0u64] != 0u8) { if (nmp[0u64] != 0u8) {
let nm: str = cstrtostr(l.a, nmp); let nm: str = cstrtostr(nmp);
let gs: *lsym = intern(l, nm); let gs: *lsym = intern(l, nm);
if (stshndx != 0u16) { if (stshndx != 0u16) {
let intext: bool = (stshndx: i32) == idxtext; let intext: bool = (stshndx: i32) == idxtext;
@@ -3455,7 +3359,7 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
let sname: u32 = rdu32(buf, sp + SYM_NAME); let sname: u32 = rdu32(buf, sp + SYM_NAME);
let snm: *u8 = strtab + (sname: u64); let snm: *u8 = strtab + (sname: u64);
if (snm[0u64] != 0u8) { if (snm[0u64] != 0u8) {
let nm: str = cstrtostr(l.a, snm); let nm: str = cstrtostr(snm);
nr.sym = intern(l, nm); nr.sym = intern(l, nm);
}; };
}; };
@@ -3491,7 +3395,7 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
let sname: u32 = rdu32(buf, sp + SYM_NAME); let sname: u32 = rdu32(buf, sp + SYM_NAME);
let snm: *u8 = strtab + (sname: u64); let snm: *u8 = strtab + (sname: u64);
if (snm[0u64] != 0u8) { if (snm[0u64] != 0u8) {
let nm: str = cstrtostr(l.a, snm); let nm: str = cstrtostr(snm);
nr.sym = intern(l, nm); nr.sym = intern(l, nm);
}; };
}; };
@@ -3517,7 +3421,6 @@ package w6l;
import os; import os;
import rt; import rt;
import mem;
import strings; import strings;
import sym; import sym;
@@ -3612,7 +3515,7 @@ fn dcstrlen(p: *u8) u64 = {
return n; return n;
}; };
fn dcstrtostr(a: *arena, p: *u8) str = { fn dcstrtostr(p: *u8) str = {
let n: u64 = dcstrlen(p); let n: u64 = dcstrlen(p);
let view: str; let view: str;
view.ptr = p; view.ptr = p;
@@ -3800,7 +3703,7 @@ export fn loadso(l: *lnk, path: *u8) i32 = {
// Build the lso. Exports are appended in dynsym order so // Build the lso. Exports are appended in dynsym order so
// soprovides_v's first-match semantics match the C version. // soprovides_v's first-match semantics match the C version.
let so: *lso = alloc(lso { path = dcstrtostr(l.a, path), soname = dcstrtostr(l.a, sonamecs) })!; let so: *lso = alloc(lso { path = dcstrtostr(path), soname = dcstrtostr(sonamecs) })!;
let tail: *lexport = nil; let tail: *lexport = nil;
let si: u64 = 1u64; let si: u64 = 1u64;
@@ -3852,9 +3755,9 @@ export fn loadso(l: *lnk, path: *u8) i32 = {
}; };
if (keep != 0) { if (keep != 0) {
let e: *lexport = alloc(lexport { name = dcstrtostr(l.a, nmp) })!; let e: *lexport = alloc(lexport { name = dcstrtostr(nmp) })!;
if (vernamecs != nil) { if (vernamecs != nil) {
e.version = dcstrtostr(l.a, vernamecs); e.version = dcstrtostr(vernamecs);
}; };
if (tail == nil) { if (tail == nil) {
so.exports = e; so.exports = e;
@@ -3934,7 +3837,7 @@ def R_X86_64_PC32: i32 = 2;
def R_X86_64_PLT32: i32 = 4; def R_X86_64_PLT32: i32 = 4;
export fn resolve(l: *lnk) i32 = { export fn resolve(l: *lnk) i32 = {
// Initialise dynamic-linking sentinels. amalloc zeroes, so // Initialise dynamic-linking sentinels. alloc(T{})! zeroes, so
// isdyn/dynlib start clean — but pltidx and dynsymidx // isdyn/dynlib start clean — but pltidx and dynsymidx
// must be -1, not 0. // must be -1, not 0.
let si: *lsym = l.syms; let si: *lsym = l.syms;
@@ -4074,7 +3977,6 @@ package w6l;
import os; import os;
import rt; import rt;
import mem;
import sym; import sym;
// ELF constants // ELF constants
@@ -4218,7 +4120,6 @@ export fn emitdynelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = {
// Placed after .dynamic so the segment is one contiguous run; // Placed after .dynamic so the segment is one contiguous run;
// relocate runs from here so the dyn layout's datava lands in // relocate runs from here so the dyn layout's datava lands in
// patched offsets. // patched offsets.
let a: *arena = l.a;
let n: i32 = l.dynn; let n: i32 = l.dynn;
let nu: u64 = n: u64; let nu: u64 = n: u64;
@@ -4996,7 +4897,6 @@ package main;
import os; import os;
import rt; import rt;
import mem;
import sym; import sym;
import obj; import obj;
import dyn; import dyn;
@@ -5006,8 +4906,8 @@ import out;
def BASE: u64 = 4194304u64; // 0x400000 def BASE: u64 = 4194304u64; // 0x400000
def CODE_VA_OFF: u64 = 4096u64; // .text starts at base + 0x1000 def CODE_VA_OFF: u64 = 4096u64; // .text starts at base + 0x1000
fn mklnk(a: *arena) *lnk = { fn mklnk() *lnk = {
let l: *lnk = alloc(lnk { a = a })!; let l: *lnk = alloc(lnk { })!;
return l; return l;
}; };
@@ -5114,9 +5014,9 @@ fn islinkable(path: *u8) bool = {
}; };
// Walk libdirs[0..n) trying lib<name>.so, then lib<name>.so.{0..8}, // Walk libdirs[0..n) trying lib<name>.so, then lib<name>.so.{0..8},
// then lib<name>.a. Return arena-owned NUL-terminated path on success, // then lib<name>.a. Return a heap-allocated NUL-terminated path on
// nil on miss. // success, nil on miss.
fn resolvelib(a: *arena, name: *u8, libdirs: **u8, nlibdirs: i32) *u8 = { fn resolvelib(name: *u8, libdirs: **u8, nlibdirs: i32) *u8 = {
let bufp: []u8 = alloc([], 1024u64)!; let bufp: []u8 = alloc([], 1024u64)!;
bufp.len = 1024; bufp.len = 1024;
let i: i32 = 0; let i: i32 = 0;
@@ -5254,8 +5154,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
return 2; return 2;
}; };
let a: *arena = newarena(); let l: *lnk = mklnk();
let l: *lnk = mklnk(a);
// Seed _start so libwwrt-style start.o is recognised as wanted. // Seed _start so libwwrt-style start.o is recognised as wanted.
intern(l, "_start"); intern(l, "_start");
@@ -5273,7 +5172,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
// objects register their exports. // objects register their exports.
let lf: i32 = 0; let lf: i32 = 0;
for (lf < nlflags) { for (lf < nlflags) {
let p: *u8 = resolvelib(a, lflags[lf], libdirs.ptr, nlibdirs); let p: *u8 = resolvelib(lflags[lf], libdirs.ptr, nlibdirs);
if (p == nil) { if (p == nil) {
os.write(2, "w6l: cannot find -l".ptr, 18u64); os.write(2, "w6l: cannot find -l".ptr, 18u64);
let nm: *u8 = lflags[lf]; let nm: *u8 = lflags[lf];

View File

@@ -10,7 +10,6 @@ package main;
import os; import os;
import rt; import rt;
import mem;
import sym; import sym;
import obj; import obj;
import dyn; import dyn;
@@ -20,8 +19,8 @@ import out;
def BASE: u64 = 4194304u64; // 0x400000 def BASE: u64 = 4194304u64; // 0x400000
def CODE_VA_OFF: u64 = 4096u64; // .text starts at base + 0x1000 def CODE_VA_OFF: u64 = 4096u64; // .text starts at base + 0x1000
fn mklnk(a: *arena) *lnk = { fn mklnk() *lnk = {
let l: *lnk = alloc(lnk { a = a })!; let l: *lnk = alloc(lnk { })!;
return l; return l;
}; };
@@ -128,9 +127,9 @@ fn islinkable(path: *u8) bool = {
}; };
// Walk libdirs[0..n) trying lib<name>.so, then lib<name>.so.{0..8}, // Walk libdirs[0..n) trying lib<name>.so, then lib<name>.so.{0..8},
// then lib<name>.a. Return arena-owned NUL-terminated path on success, // then lib<name>.a. Return a heap-allocated NUL-terminated path on
// nil on miss. // success, nil on miss.
fn resolvelib(a: *arena, name: *u8, libdirs: **u8, nlibdirs: i32) *u8 = { fn resolvelib(name: *u8, libdirs: **u8, nlibdirs: i32) *u8 = {
let bufp: []u8 = alloc([], 1024u64)!; let bufp: []u8 = alloc([], 1024u64)!;
bufp.len = 1024; bufp.len = 1024;
let i: i32 = 0; let i: i32 = 0;
@@ -268,8 +267,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
return 2; return 2;
}; };
let a: *arena = newarena(); let l: *lnk = mklnk();
let l: *lnk = mklnk(a);
// Seed _start so libwwrt-style start.o is recognised as wanted. // Seed _start so libwwrt-style start.o is recognised as wanted.
intern(l, "_start"); intern(l, "_start");
@@ -287,7 +285,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
// objects register their exports. // objects register their exports.
let lf: i32 = 0; let lf: i32 = 0;
for (lf < nlflags) { for (lf < nlflags) {
let p: *u8 = resolvelib(a, lflags[lf], libdirs.ptr, nlibdirs); let p: *u8 = resolvelib(lflags[lf], libdirs.ptr, nlibdirs);
if (p == nil) { if (p == nil) {
os.write(2, "w6l: cannot find -l".ptr, 18u64); os.write(2, "w6l: cannot find -l".ptr, 18u64);
let nm: *u8 = lflags[lf]; let nm: *u8 = lflags[lf];

View File

@@ -12,7 +12,6 @@ package w6l;
import os; import os;
import rt; import rt;
import mem;
import strings; import strings;
import sym; import sym;
@@ -158,7 +157,7 @@ fn cstrlen(p: *u8) u64 = {
return n; return n;
}; };
// pathstr — view a NUL-terminated *u8 as a str. Bridges argv/arena // pathstr — view a NUL-terminated *u8 as a str. Bridges argv-style
// callers to lib/os entrypoints (str post-task-#23). Shared with // callers to lib/os entrypoints (str post-task-#23). Shared with
// main.ww and dyn.ww via the w6l bundle. // main.ww and dyn.ww via the w6l bundle.
fn pathstr(p: *u8) str = { fn pathstr(p: *u8) str = {
@@ -181,7 +180,7 @@ fn cstreq(p: *u8, lit: str) bool = {
}; };
// Build a ww str from a NUL-terminated *u8 (for passing to intern). // Build a ww str from a NUL-terminated *u8 (for passing to intern).
fn cstrtostr(a: *arena, p: *u8) str = { fn cstrtostr(p: *u8) str = {
let n: u64 = cstrlen(p); let n: u64 = cstrlen(p);
let view: str; let view: str;
view.ptr = p; view.ptr = p;
@@ -201,7 +200,7 @@ type defent = struct {
}; };
type armember = struct { type armember = struct {
data: *u8, // arena copy of the member's ELF bytes data: *u8, // owned heap copy of the member's ELF bytes
size: u64, size: u64,
defs: *defent, // linked list of defined globals defs: *defent, // linked list of defined globals
loaded: i32, loaded: i32,
@@ -236,9 +235,9 @@ fn arfield(p: *u8, n: u64) u64 = {
}; };
// elfglobals — 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 // (STB_GLOBAL) symbols whose section is `.text`. Names are owned
// copies, so the source ELF buffer can be freed afterward. // heap copies, so the source ELF buffer can be freed afterward.
fn elfglobals(a: *arena, buf: *u8, len: u64) *defent = { fn elfglobals(buf: *u8, len: u64) *defent = {
if (len < EHDR_SIZE) { return nil; }; if (len < EHDR_SIZE) { return nil; };
if (buf[0u64] != 127u8) { return nil; }; if (buf[0u64] != 127u8) { return nil; };
if (buf[1u64] != 69u8) { return nil; }; if (buf[1u64] != 69u8) { return nil; };
@@ -302,7 +301,7 @@ fn elfglobals(a: *arena, buf: *u8, len: u64) *defent = {
if (intext || indt) { if (intext || indt) {
let nmp: *u8 = strtab + (stname: u64); let nmp: *u8 = strtab + (stname: u64);
if (nmp[0u64] != 0u8) { if (nmp[0u64] != 0u8) {
let nm: str = cstrtostr(a, nmp); let nm: str = cstrtostr(nmp);
let de: *defent = alloc(defent { name = nm, dnext = head })!; let de: *defent = alloc(defent { name = nm, dnext = head })!;
head = de; head = de;
}; };
@@ -355,7 +354,7 @@ fn loadarchive(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
i += 1u64; i += 1u64;
}; };
m.data = mb; m.data = mb;
m.defs = elfglobals(l.a, mb, hdrsize); m.defs = elfglobals(mb, hdrsize);
if (head == nil) { head = m; } if (head == nil) { head = m; }
else { tail.mnext = m; }; else { tail.mnext = m; };
tail = m; tail = m;
@@ -473,7 +472,7 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
// Track this object. // Track this object.
let ob: *lobj = alloc(lobj { let ob: *lobj = alloc(lobj {
path = cstrtostr(l.a, path), path = cstrtostr(path),
buf = buf, buf = buf,
len = len, len = len,
textoff = l.textlen, textoff = l.textlen,
@@ -504,7 +503,7 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
let stvalue: u64 = rdu64(buf, symp + SYM_VALUE); let stvalue: u64 = rdu64(buf, symp + SYM_VALUE);
let nmp: *u8 = strtab + (stname: u64); let nmp: *u8 = strtab + (stname: u64);
if (nmp[0u64] != 0u8) { if (nmp[0u64] != 0u8) {
let nm: str = cstrtostr(l.a, nmp); let nm: str = cstrtostr(nmp);
let gs: *lsym = intern(l, nm); let gs: *lsym = intern(l, nm);
if (stshndx != 0u16) { if (stshndx != 0u16) {
let intext: bool = (stshndx: i32) == idxtext; let intext: bool = (stshndx: i32) == idxtext;
@@ -568,7 +567,7 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
let sname: u32 = rdu32(buf, sp + SYM_NAME); let sname: u32 = rdu32(buf, sp + SYM_NAME);
let snm: *u8 = strtab + (sname: u64); let snm: *u8 = strtab + (sname: u64);
if (snm[0u64] != 0u8) { if (snm[0u64] != 0u8) {
let nm: str = cstrtostr(l.a, snm); let nm: str = cstrtostr(snm);
nr.sym = intern(l, nm); nr.sym = intern(l, nm);
}; };
}; };
@@ -604,7 +603,7 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
let sname: u32 = rdu32(buf, sp + SYM_NAME); let sname: u32 = rdu32(buf, sp + SYM_NAME);
let snm: *u8 = strtab + (sname: u64); let snm: *u8 = strtab + (sname: u64);
if (snm[0u64] != 0u8) { if (snm[0u64] != 0u8) {
let nm: str = cstrtostr(l.a, snm); let nm: str = cstrtostr(snm);
nr.sym = intern(l, nm); nr.sym = intern(l, nm);
}; };
}; };

View File

@@ -21,7 +21,7 @@ def R_X86_64_PC32: i32 = 2;
def R_X86_64_PLT32: i32 = 4; def R_X86_64_PLT32: i32 = 4;
export fn resolve(l: *lnk) i32 = { export fn resolve(l: *lnk) i32 = {
// Initialise dynamic-linking sentinels. amalloc zeroes, so // Initialise dynamic-linking sentinels. alloc(T{})! zeroes, so
// isdyn/dynlib start clean — but pltidx and dynsymidx // isdyn/dynlib start clean — but pltidx and dynsymidx
// must be -1, not 0. // must be -1, not 0.
let si: *lsym = l.syms; let si: *lsym = l.syms;

View File

@@ -5,8 +5,6 @@
package w6l; package w6l;
import mem;
type lsym = struct { type lsym = struct {
name: str, name: str,
val: u64, // offset within combined .text (or .data when val: u64, // offset within combined .text (or .data when
@@ -63,7 +61,6 @@ type lso = struct {
}; };
type lnk = struct { type lnk = struct {
a: *arena,
objs: *lobj, objs: *lobj,
sos: *lso, sos: *lso,
syms: *lsym, syms: *lsym,