Standalone eh_frame_hdr row after the existing table overflow case:
encoding 0x31 (uleb128 | datarel) with a ten-byte ULEB128 whose last
byte overflows 64 bits, on segments at 0xFFFFFFFFFFFFF000. The reader
must throw "overflowing LEB128 value" from EhFrameReader::leb.
Co-Authored-By: Claude Haiku 5.5 <[email protected]>
Standalone EH table fixture after the unwind record loop: CIE zPLR with
LSDA encoding 0x4B (sdata4 funcrel), FDE augmentation 0xFFFFEFFF with
functionBase at the FDE begin 0x1000. The signed branch of
EhFrameReader::encoded must reject it with "unwind pointer address
overflowed".
Co-Authored-By: Claude Haiku 5.5 <[email protected]>
Standalone block after the main table overflow case: encoding 0x33
(udata4 + datarel), u32 0xFFFFFFFF displacements at the real table
entry offsets 16 and 20, data base 0xFFFFFFFFFFFFF000 so max - base
is 0xFFF, and an assert on the overflow RelinkerException message.
Co-Authored-By: Claude Haiku 5.5 <[email protected]>
An island or relocation window could start in the int3 or nop padding after a jump or return and run into the next function. A function that only a pointer reaches, such as a virtual method, is not a known branch target, so its first bytes became the middle of a jump to a stub. An instruction that follows a jump, a return, a trap or padding after one of them can now only start a window. An int3 inside a window does not count as such an instruction, so a window that lies entirely in int3 padding is still used, as before; nop padding stays excluded, since a function built with -fpatchable-function-entry can begin with a nop.
macOS assesses each new Mach-O file the first time it is executed or
loaded and caches the verdict per file, not per content. The tests wrote
a byte copy of their shared libraries into every case, so every case
paid the assessment again. A hard link reuses the verdict of the file
that was already assessed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Addresses the #12591 review. Because the Windows image ORs page permissions,
refuse a congruent overlap when one segment is executable and the other
writable and the later segment does not start on a page boundary, which would
otherwise share a read-write-execute page; the rule is applied on both loaders
so their acceptance decision matches. Bound the congruence check to the
file-backed part of the overlap and compare spans rather than walking the
implicit zero bytes of a large bss overlap.
Expand test_executable_segments.py: byte-congruent tail and bss overlaps
accepted with their trimmed sizes and no output overlap; a write-execute
overlap refused at an unaligned boundary and accepted at an aligned one with
the Windows image carrying no write-execute section; differing bytes, an
overlap past the later end, a non-zero file byte over the later segment's bss,
and a shared start address refused; and a no-overlap control. Keep only the
PPSA ids in the relinker.md note.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Some homebrew toolchains emit an eboot whose read-only PT_LOAD runs over the
GNU_RELRO start of the following read-write PT_LOAD, with byte-identical content
over the overlap. The relinker refused every such title with "Overlapping
PT_LOAD memory ranges" on both the Linux and Windows paths (Photo Splat VR
PPSA99770 #12183, FoxHollow PPSA99573, WWE 13 PPSA92013).
When an earlier PT_LOAD's tail overlaps a later one, the overlapping bytes are
identical, and the overlap does not extend past the later segment, trim the
earlier segment to end where the later one starts so the later segment owns the
shared range. On Linux the preserved PT_GNU_RELRO makes that range read-only
after relocation, matching the earlier read-only mapping; the Windows image
builder has no RELRO step, so the shared range stays writable (noted in
docs/dev/debt/relinker.md).
Overlaps whose bytes differ (the #10564 case), that extend past the later
segment, or that share a start address with it are still refused on every
target; the last case would otherwise trim the earlier segment to zero length.
test_executable_segments.py covers the accepted tail overlap and all three
refused cases.
Co-Authored-By: Claude Opus 4.8 <[email protected]>