w6l+selfhost: dynamic-link + .data — shared R+W segment

.data now lives at the end of the dyn-path R+W PT_LOAD, just after
.dynamic. The single segment covers .got.plt + .dynamic + .data; its
filesz drops trailing zeros (BSS) while memsz spans the full extent.

Relocation moves from main.c into each emit function so the static
and dynamic paths use their own data_va — text→data refs land on the
right VA regardless of path. Removes the early-error in dynout.c
that previously refused any .data with -l/-L.

Tests: 810_dyn gains two new dyn+.data fixtures (mutable read+write
of an i32, plus a zero-init i64 verifying the BSS scan still produces
a valid p_filesz<p_memsz under the shared segment).
This commit is contained in:
2026-05-12 13:50:09 +09:00
parent 2480f4c272
commit a9b804935c
8 changed files with 150 additions and 82 deletions

View File

@@ -59,10 +59,17 @@ export fn emitelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = {
// .data lands at the next page boundary so the loader can give
// it fresh R+W permissions without overlapping the R+X mapping.
let dataoff: u64 = 0u64;
let datava: u64 = 0u64;
if (hasdata) {
dataoff = (rxend + PAGE_SZ - 1u64) & ~(PAGE_SZ - 1u64);
datava = base + dataoff;
};
// Apply relocations now that the layout's textva/datava are
// known. Deferred from main.ww so the dyn path uses its own
// datava.
if (relocate(l, base + TEXT_OFF, datava) != 0) { return -1; };
// BSS optimisation: trailing zero bytes in .data can be left
// out of the file. The loader zero-fills the gap between
// p_filesz and p_memsz. Scan after l_relocate has applied any