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

@@ -142,6 +142,18 @@ poke32(u8 *buf, u64 off, u32 v)
int
l_emit_dyn_elf(Lnk *l, FILE *f, u64 base, u64 entry)
{
/* Writable globals on the dynamic-link path need their own R+W
* segment, and the existing R+W segment (gotplt + dynamic) has a
* fixed layout that l_relocate's data_va guess wouldn't match.
* Rather than ship a silently-miscompiled binary, refuse and
* leave the feature for a follow-up. */
if (l->datalen > 0) {
fprintf(stderr, "w6l: top-level mutable globals (.data) are "
"not yet supported with -l/-L; link without shared "
"libraries to use them.\n");
return 1;
}
const int N = l->dyn_n;
/* ---- Pass 1: collect dynamic symbol names + .dynstr layout ---- */