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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user