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.
135 lines
3.5 KiB
Plaintext
135 lines
3.5 KiB
Plaintext
// selfhost/cmd/w6l/pass.ww — port of cmd/w6l/pass.c.
|
|
//
|
|
// Resolution + relocation. l_resolve flags every undefined symbol
|
|
// referenced by a relocation, and promotes those provided by some
|
|
// loaded .so to "dynamic" with a freshly-assigned PLT slot.
|
|
// l_relocate walks the rel list and patches the .text bytes in place
|
|
// once the final virtual base is known. Dynamic refs are deferred:
|
|
// their site is patched later in dynout, once the PLT vaddr is known.
|
|
//
|
|
// Supported relocation kinds: PC32 (=2), PLT32 (=4); both are 32-bit
|
|
// PC-relative displacements (PLT32 == PC32 for static).
|
|
|
|
package w6l;
|
|
|
|
import os;
|
|
import sym;
|
|
import dyn;
|
|
|
|
def R_X86_64_64: i32 = 1;
|
|
def R_X86_64_PC32: i32 = 2;
|
|
def R_X86_64_PLT32: i32 = 4;
|
|
|
|
export fn resolve(l: *lnk) i32 = {
|
|
// Initialise dynamic-linking sentinels. alloc(T{})! zeroes, so
|
|
// isdyn/dynlib start clean — but pltidx and dynsymidx
|
|
// must be -1, not 0.
|
|
let si: *lsym = l.syms;
|
|
for (si != nil) {
|
|
si.pltidx = -1;
|
|
si.dynsymidx = -1;
|
|
si = si.snext;
|
|
};
|
|
|
|
// Promote each undefined sym that some lso exports to dynamic
|
|
// and hand it a PLT slot. Iteration order over the relocation
|
|
// list determines slot numbering and is stable across runs.
|
|
let r: *lrel = l.rels;
|
|
for (r != nil) {
|
|
if (r.sym != nil) {
|
|
if (r.sym.defined == 0) {
|
|
if (r.sym.isdyn == 0) {
|
|
let so: *lso = l.sos;
|
|
for (so != nil) {
|
|
if (soprovides(so, r.sym.name) != 0) {
|
|
r.sym.isdyn = 1;
|
|
r.sym.dynlib = so;
|
|
r.sym.pltidx = l.dynn;
|
|
l.dynn += 1;
|
|
so = nil; // break
|
|
} else {
|
|
so = so.sonext;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
r = r.rnext;
|
|
};
|
|
|
|
// What remains undefined truly is undefined.
|
|
let r2: *lrel = l.rels;
|
|
for (r2 != nil) {
|
|
if (r2.sym != nil) {
|
|
if (r2.sym.defined == 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);
|
|
os.write(2, "'\n".ptr, 2u64);
|
|
l.errs += 1;
|
|
};
|
|
};
|
|
};
|
|
r2 = r2.rnext;
|
|
};
|
|
return l.errs;
|
|
};
|
|
|
|
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;
|
|
};
|
|
|
|
fn patchu64(p: *u8, v: u64) void = {
|
|
let i: i32 = 0;
|
|
for (i < 8) {
|
|
p[i] = ((v >> (i: u64 * 8u64)) & 255u64): u8;
|
|
i += 1;
|
|
};
|
|
};
|
|
|
|
export fn relocate(l: *lnk, textva: u64, datava: 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.isdyn != 0) {
|
|
r = r.rnext;
|
|
continue;
|
|
};
|
|
if (r.sym.defined != 0) {
|
|
let symva: u64 = textva + r.sym.val;
|
|
if (r.sym.indata != 0) { symva = datava + r.sym.val; };
|
|
let k: i32 = r.kind;
|
|
if (k == R_X86_64_PC32) {
|
|
let site: u64 = textva + r.off;
|
|
let rel: i64 = (symva: i64 - site: i64) + r.addend;
|
|
patchu32(l.text + r.off, rel: u32);
|
|
} else { if (k == R_X86_64_PLT32) {
|
|
let site: u64 = textva + r.off;
|
|
let rel: i64 = (symva: i64 - site: i64) + r.addend;
|
|
patchu32(l.text + r.off, rel: u32);
|
|
} else { if (k == R_X86_64_64) {
|
|
// Absolute 64-bit. Currently used only
|
|
// for DATAR slots in .data.
|
|
let v: u64 = (symva: i64 + r.addend): u64;
|
|
if (r.section == 1) {
|
|
patchu64(l.data + r.off, v);
|
|
} else {
|
|
patchu64(l.text + r.off, v);
|
|
};
|
|
} else {
|
|
os.write(2, "w6l: unsupported reloc kind\n".ptr, 27u64);
|
|
l.errs += 1;
|
|
};};};
|
|
};
|
|
};
|
|
r = r.rnext;
|
|
};
|
|
return l.errs;
|
|
};
|