w6l: dynamic e_entry rebases with the actual text offset, both stages

When the dynamic section pushed the header past the first page, the
entry point kept its first-page address — every sufficiently large
dynamic binary SIGSEGV'd into the headers. Recompute e_entry as
entry - 0x1000 + text_off in both stages (ELF: the entry must point
into .text wherever it lands). Both stages move in one commit: one
ELF contract; the 989_dynentry gate pins the field and the run.
This commit is contained in:
2026-06-13 10:17:51 +09:00
parent 95da870734
commit 675a0368cd
5 changed files with 222 additions and 3 deletions

View File

@@ -589,7 +589,14 @@ l_emit_dyn_elf(Lnk *l, FILE *f, u64 base, u64 entry)
eh.e_type = ET_EXEC;
eh.e_machine = EM_X86_64;
eh.e_version = EV_CURRENT;
eh.e_entry = entry;
/* #63: main computed `entry` as base + 0x1000 + val assuming .text sits
* at file offset 0x1000, but text_off above is recomputed and overflows
* 0x1000 once the dynamic headers exceed the first page (e.g. ~100 dyn
* syms). Rebase e_entry onto the actual text_off so it points at the
* real _start instead of into the headers. e_entry is a virtual address;
* PT_LOAD #1 maps file offset 0 at `base`, so the entry VA tracks
* text_off. Both stages fixed together (#263). */
eh.e_entry = entry - 0x1000 + text_off;
eh.e_phoff = ehdr_sz;
eh.e_ehsize = sizeof(Ehdr);
eh.e_phentsize = sizeof(Phdr);