Commit Graph
7 Commits
Author SHA1 Message Date
roboterspinne 94e4031147 fix(relinker): keep a moved Linux PT_LOAD's alignment on the header block
Moving a PT_LOAD to the end of the file sets its p_align to
min(p_align, 0x1000), since the copy honours only the page. When that
segment carried the largest p_align, the output's largest PT_LOAD
alignment, which Linux uses to align the ET_DYN load bias, fell with
it. SeparateSharedLoadPages now returns the largest power-of-two
p_align above the page that it lowered, and WriteLayout aligns the
header block PT_LOAD to at least that value, as it already does for
the largest kept p_align.
2026-11-01 09:37:04 +01:00
roboterspinne ffa036cbec Merge remote-tracking branch 'upstream/main' into fix/relinker-linux-congruent-loads
# Conflicts:
#	core/relinker/elfpatcher/tests/LinuxLoadPageTests.cpp
2026-10-30 16:23:11 +01:00
dkdhanda8 cb7ed5672e fix(elfpatcher): reject rel32 distances that only fit after a 64-bit wrap
The five Linux rel32 sites subtracted addresses and range-checked the
signed result, so two addresses more than 2^63 apart wrapped into a
small in-range displacement and was written verbatim. SignedDistance
now classifies both addresses by the 2^63 boundary, takes the
high-minus-low magnitude as a plain subtraction and rejects a distance
whose magnitude exceeds int64. The new linux_load_pages test places a
site at 0x500 and the body near 2^64: main wrote a wrapped rel32, the
change throws.
2026-10-29 00:37:07 +05:30
dkdhanda8 100b3c1c5c fix(relinker): patch Linux displacements without signed overflow
Crafted program headers can map a load segment so its page end sits at
2^63, which places the patcher's extra block above the boundary while
the original code sites stay below it. The trampoline, import trace and
guest module displacement math subtracted addresses as two int64 casts,
which overflows for such pairs before the rel32 range check runs.

Subtract in unsigned arithmetic and cast the true difference once, as
the entry stub builder already does.
2026-10-29 00:27:20 +05:30
roboterspinne 5890fc1820 fix(relinker): align moved Linux PT_LOADs to the page, not to p_align
The move path of SeparateSharedLoadPages padded the output byte by byte
to an offset congruent modulo max(p_align, 0x1000), so a p_align of
0x80000000 grew the output by 2 GiB and 0x8000000000000000 ended in
std::bad_alloc. A moved segment now starts at the next offset congruent
to its address modulo the page and its p_align becomes at most 0x1000,
since Linux maps every PT_LOAD from p_offset - (p_vaddr % 0x1000) and
reads p_align only to align the ET_DYN load bias. At a fixed base every
input PT_LOAD p_align is checked against the base before any segment is
moved, with the message RebaseProgramHeaders uses.
2026-10-26 19:20:39 +01:00
roboterspinne 0e1c23cbd8 fix(relinker): move a Linux PT_LOAD whose file offset is not page-congruent with its address
The Linux patcher kept a PT_LOAD whose p_offset and p_vaddr differ
modulo the 4 KiB page in place, so the output executable could not be
mapped: the kernel's elf_map passes p_offset minus the page offset of
p_vaddr to vm_mmap, which fails with EINVAL when that is not page
aligned. The gABI requires p_offset and p_vaddr to be congruent modulo
the page size. Such a segment is now copied to the end of the file at
an offset congruent to p_vaddr modulo max(p_align, 4 KiB), through the
path that already separates shared load pages. Congruent layouts keep
their exact bytes, and the Windows and macOS outputs are unchanged.
2026-10-25 15:17:24 +01:00
milescovielloandClaude Opus 5.5 24ec391c06 fix(relinker): keep a segment's zero-filled tail zero when the next PT_LOAD starts on its page
On Linux the kernel maps each PT_LOAD from the start of its first page.
When a segment begins inside the page that holds the end of the previous
segment's zero-filled memory, that page is mapped again from the file, and
the bss tail reads whatever bytes precede the segment in the file. Nuvio
Max'd 0.5.27 (PPSA99288) keeps a mutex there and crashes at launch.

A segment whose page would read wrong bytes is now appended to the output
with that page prefix rebuilt from the segments below it. Outputs whose
pages already read right are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 18:41:25 +00:00