w6l: route writable globals into a second PT_LOAD

Second step toward top-level mutable `let`. The static path now loads
.data PROGBITS sections from input .o files, page-aligns them after
.text, and emits a second PT_LOAD (R+W) covering them. Relocations
targeting data symbols compute against the data VA; text→text
displacements still cancel the absolute VAs and stay correct.

Inputs without any .data keep the original single-PT_LOAD layout
byte-for-byte — 992 (selfhost w6l .o diff) and 995 (self-rebuild)
depend on that invariant.

Dynamic-link path (-l/-L) rejects .data for now with a clear error;
folding writable globals into the existing R+W segment alongside
.got.plt/.dynamic is a follow-up.
This commit is contained in:
2026-05-12 11:42:30 +09:00
parent 1b0955c97b
commit 38e0b6510a
8 changed files with 406 additions and 34 deletions

View File

@@ -68,7 +68,7 @@ patch_u32(u8 *p, u32 v)
}
int
l_relocate(Lnk *l, u64 base)
l_relocate(Lnk *l, u64 text_va, u64 data_va)
{
for (Lrel *r = l->rels; r; r = r->next) {
if (r->sym == NULL) continue;
@@ -79,9 +79,11 @@ l_relocate(Lnk *l, u64 base)
switch (r->kind) {
case R_X86_64_PC32:
case R_X86_64_PLT32: {
u64 site = base + r->off;
i64 target = (i64)(base + r->sym->val);
i64 rel = target - (i64)site + r->addend;
u64 site = text_va + r->off;
u64 sym_va = r->sym->in_data
? data_va + r->sym->val
: text_va + r->sym->val;
i64 rel = (i64)sym_va - (i64)site + r->addend;
patch_u32(l->text + r->off, (u32)(i32)rel);
break;
}