Commit Graph
134 Commits
Author SHA1 Message Date
Dean adbcdcdd58 Merge pull request #11463 from Mherberts/codex/feat-elf-relr-relocations
feat(relinker): support packed ELF64 relative relocations
2026-10-28 17:50:40 +13:00
Dean 77e44989b6 Merge pull request #11561 from javierUDP/docs/rosetta-m5-26-4-evidence
docs(relinker): record SHA, AVX-512 and XSAVE under Rosetta on an M5
2026-10-28 12:06:23 +13:00
Adrià 254240c747 Merge pull request #11045 from roboterspinne/fix/relinker-macos-fixups-writable
fix(relinker): reject macOS fixups outside writable segments
2026-10-27 18:29:51 +01:00
Matheus Herberts 458da3450e feat(relinker): support packed ELF64 relative relocations 2026-10-27 11:58:24 -03:00
Adrià 2635028370 Merge pull request #11061 from roboterspinne/fix/relinker-red-zone-body-pushes
fix(relinker): refuse red-zone leaves without a frame pointer that push or pop
2026-10-27 12:00:25 +01:00
roboterspinne 0326845257 docs(relinker): record measured dyld behaviour for macOS fixups
The debt entry on pointer fixups in executable segments claimed that
dyld refuses them, which no run had shown. It now states what was
measured on an M1 Pro running macOS 27.0.1 under Rosetta 2: dyld_info
reports both cases, the PF_R|PF_W|PF_X case loads and runs, and a
fixup into a PF_R|PF_X segment ends with SIGBUS in dyld. The
interpreter_in_code fixture keeps a read-only data PT_LOAD for the
Windows runs, so PE output still covers a RELATIVE into it.
2026-10-27 08:18:50 +01:00
roboterspinne e5297264e3 fix(relinker): reject macOS fixups outside writable segments
The macOS image writer emitted dyld rebase and bind opcodes for any
target inside a segment, so an R_X86_64_RELATIVE into an R-X PT_LOAD
became a rebase into a read-execute segment. dyld-1378 refuses fixups
in segments without write access (enforceFixupsInWritableSegments), so
Locate now throws when the target segment lacks VM_PROT_WRITE. Such
inputs now fail the macOS conversion instead of writing an output that
dyld would not load.
2026-10-27 08:18:50 +01:00
Adrià bf83eae375 Merge pull request #10947 from roboterspinne/fix/relinker-windows-tls-template-imports
fix(relinker): reject Windows executable imports bound into the TLS template
2026-10-27 07:59:13 +01:00
Dean a8bc4474c4 Merge pull request #11090 from roboterspinne/fix/relinker-windows-gs-trap-entry-roots
fix(relinker): refuse GS traps that overwrite a code entry point in Windows output
2026-10-27 18:32:02 +13:00
roboterspinne de3c2d9536 fix(relinker): refuse red-zone leaves without a frame pointer that push or pop
In a leaf without a frame pointer, --frame-red-zone lowers RSP after
the prologue and adds the shift to every RSP operand in the body,
assuming RSP does not move between the prologue and the exits. It
refused explicit RSP arithmetic but not opcode-encoded pushes and pops,
so after "push rax" in the body the read of the pushed slot at [rsp]
became [rsp+0x10], a red-zone slot, and "pushfq; and qword [rsp], -2;
popfq" changed that slot instead of the saved flags. Such a leaf now
keeps its red zone and is reported as "push or pop inside the body":
push and pop of a register, push imm, push r/m, pop r/m, pushf, popf
and push or pop of fs or gs outside the exits. The pops of an exit
still frame, and leaves with a frame pointer, whose RSP operands are
already refused, still frame when they push and pop.
2026-10-27 02:36:47 +01:00
Dean 5566e1e097 Merge pull request #10971 from roboterspinne/fix/relinker-linux-nonzero-import-addends
fix(relinker): reject nonzero GLOB_DAT and JUMP_SLOT addends in Linux output
2026-10-27 10:58:17 +13:00
Dean 1748d26517 Merge pull request #10871 from Chronyyx/feat/relinker-frame-short-exits
feat(relinker): frame red-zone leaves whose prologue or exit is shorter than a jump
2026-10-27 10:55:26 +13:00
Dean 357b586723 Merge pull request #11067 from slopgobblercobbler/fix/relinker-unwind-narrow-unsigned-overflow
fix(relinker): reject unsigned address overflow for narrow unwind encodings
2026-10-27 10:36:42 +13:00
javierUDP 5a9631df3b docs(relinker): record SHA, AVX-512 and XSAVE under Rosetta on an M5
The entry for the M5 running macOS 26.4 did not say what Rosetta does
with SHA or AVX-512, and the XSAVE entry was measured only on macOS
27.0.1. On that host sha1rnds4 and a 256-bit-wide vpaddd on zmm raise an
illegal instruction alongside RDSEED, CLWB, RDPID, ADCX and ADOX, while
XSAVE writes an XSTATE_BV of 0x7 and XGETBV returns the same x87, SSE
and AVX mask although CPUID leaf 1 still reports neither XSAVE nor
OSXSAVE.

The BMI1 and BMI2 results were compared with the Intel SDM definitions
over 200,000 random inputs each for PDEP, PEXT, BEXTR, BZHI, LZCNT and
TZCNT, so the entry can say they compute the documented result rather
than only that they avoid a fault.
2026-10-26 16:49:15 -03:00
roboterspinne 823251ddf5 docs(relinker): record the Windows GS trap refusals as debt
A Windows conversion now fails when a code entry lies after the first
byte of a guest GS instruction that the TLS builder replaces with UD2.
The new debt entry names both messages, says that no option skips the
checks and that Linux output keeps the instruction, so a user who hits
the refusal knows which target to use.
2026-10-26 20:31:54 +01:00
roboterspinne ca8e16751c Merge remote-tracking branch 'upstream/main' into fix/relinker-windows-tls-template-imports 2026-10-26 19:38:21 +01:00
Adrià cbf76e7a6e Merge pull request #9408 from rursache/feat/macos-trace-imports
feat(relinker): trace function imports on macOS
2026-10-26 11:27:51 +01:00
Dean b744c37f4e Merge pull request #8076 from brainiac91/fix/relinker-embedded-data-tables
fix(relinker): mask embedded data tables in inter-FDE gaps
2026-10-26 20:36:58 +13:00
Brainiac91 56718b3314 fix(relinker): keep non-SCE scans strict while masking gap tables
Read the unwind functions of an image that only has PT_GNU_EH_FRAME so
inter-FDE data tables are still found and masked, but leave the syscall
and call-site scan ranges empty without PT_SCE_DYNLIBDATA as main does.
The fixture now emits standard dynamic tags for its SysV block, and the
debt entry stays within the 1000 character limit.
2026-10-25 23:44:07 +02:00
Brainiac91 dfe24c2e3a fix(relinker): bound embedded data tables and preserve trailing gap code 2026-10-25 23:25:32 +02:00
Brainiac91 2f3e41252d fix(relinker): mask embedded data tables in inter-FDE gaps
In PS5 Prospero PRX binaries, compilers place embedded constant data tables (such as the OpenSSL Whirlpool lookup table in ubiservices.prx) in inter-FDE gaps after function code, referenced via RIP-relative LEA instructions.

- In RelativeJumpTables, detect constant data tables in inter-FDE gaps that begin with padding, contain no direct branch targets, and contain undecodable non-code bytes, distinguishing them from valid unannotated code routines and multi-hop gap branches.
- In GuestModuleBuilder and RelinkerPipeline, extract unwind functions from PT_GNU_EH_FRAME as well as PT_SCE_DYNLIBDATA, and mask embedded data tables with 0x90 in scan buffers before SyscallScanner.
- In CodeInstructionCollector, populate table boundaries whenever unwind functions are present to prevent addAddressTakenRoot from adding data table addresses to CFG roots on Windows and macOS.
- Update relinker technical debt documentation and add regression tests.

Fixes #7547
Unblocks: PPSA28155 #7547
2026-10-25 23:22:06 +02:00
ChronyyxandClaude Opus 5.5 f8a99b6b8a docs(relinker): say why the red-zone framer refuses shrink-wrapped leaves
The debt entry said that shrink-wrapped leaves, which push later and pop in
balance, could be framed. They cannot as the framer works now: lowering RSP on
entry moves their later pushes onto the spills, which keep their addresses.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 16:03:51 -04:00
Radu Ursache 66ca5c0442 feat(relinker): trace function imports on macOS
Walk each macOS function import before the guest entry and pass it through TraceImport_nid_no_patch, as Linux and Windows already do. An x86-64 libc build records the call and prints it on SIGABRT.
2026-10-25 18:37:23 +01:00
slopgobblercobbler 670e57b5f1 fix(relinker): reject unsigned address overflow for narrow unwind encodings 2026-10-25 17:40:51 +01:00
Bram910 c265e51abf Merge main into fix/call-site-hint-prefixes 2026-10-25 13:01:17 +01:00
roboterspinne 2ac9311745 fix(relinker): reject nonzero GLOB_DAT and JUMP_SLOT addends in Linux output
The Linux output copied a nonzero r_addend of GLOB_DAT and JUMP_SLOT
relocations unchanged into DT_RELA and DT_JMPREL, while the Windows,
macOS and guest module paths refuse it. The x86-64 psABI computes both
types as S, but glibc before f8587a61892c applies S+A when binding
eagerly, so the result depended on the host glibc and, for JUMP_SLOT,
on the binding mode. The Linux patcher now refuses such an entry in all
three Linux modes with the Windows message and the unrebased r_offset.
Entries with a zero addend are emitted as before.
2026-10-25 12:32:48 +01:00
roboterspinne a54a939924 fix(relinker): reject Windows executable imports bound into the TLS template
Windows output accepted an executable import relocation whose target
overlaps the PT_TLS initialization image, and every guest thread read 0
there because the .gtls template is copied before the entry stub binds
the import. In ELF, ld.so relocates the image before copying it into a
thread's TLS block. The PE patcher now refuses such a relocation after
the relocation pass, as the Windows guest module writer already does,
and reports its ELF target address. Linux and macOS outputs are
unchanged, and the gap is recorded in docs/dev/debt/relinker.md.
2026-10-25 12:10:24 +01:00
ChronyyxandClaude Opus 5.5 07798774b6 fix(relinker): frame red-zone leaves whose only push is rbp
The check that refuses leaves without pushes that push or pop also refused
`push rbp; mov rbp, rsp` leaves without other pushes, whose `pop rbp` it
counted, since rbp is not in their list of pushes. A unit test and an
execution test now cover such a leaf with a 4-byte prologue and a 2-byte
exit. The debt entry also notes that the check refuses shrink-wrapped leaves
whose later pushes and pops balance.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 03:23:34 -04:00
ChronyyxandClaude Opus 5.5 c697fb0ba9 feat(relinker): frame red-zone leaves whose prologue or exit is shorter than a jump
--frame-red-zone replaces a leaf's prologue and each exit with a 5-byte jump
to a stub, so it skipped leaves whose pushes or pop-and-ret exit were shorter
than that, and leaves with neither pushes nor an allocation. A short prologue
now takes in the straight-line instructions after it and a short exit those
before it, re-encoded in the stub with the moved displacement. Widening stops
at branches, rets, RIP-relative instructions, pushes and pops, and the leaf is
skipped when a branch targets the instructions taken in or the first
instruction of a widened prologue, or when a leaf without pushes pushes or
pops.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 02:47:12 -04:00
Dean c4446bbb09 Merge pull request #9332 from rooklz/fix/windows-console-base
fix(relinker): prefer 0x400000 for Windows executables
2026-10-25 12:57:28 +13:00
Adrià d01070d6c3 Merge pull request #5640 from EagleBearerYS/feat/relinker-frame-frameless-leaves
feat(relinker): frame red-zone leaves without a frame pointer by moving their rsp operands
2026-10-24 18:14:53 +02:00
Bram910 7151c6c090 docs(relinker): clarify call-site analysis limits 2026-10-24 18:08:46 +02:00
Rookie 39df8e081c fix(relinker): prefer 0x400000 for Windows executables 2026-10-24 15:58:35 +01:00
Savvanis SpyrosandClaude Opus 5.5 66ccd46909 Merge remote-tracking branch 'origin/main' into feat/log-deferred-imported-modules
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 16:35:28 +03:00
Adrià b84322da6a Merge pull request #7918 from Kernel-Hunter/fix/rosetta-xsaveopt
fix(relinker): rewrite XSAVEOPT to XSAVE under --to-rosetta
2026-10-24 14:14:59 +02:00
Adrià 3fcacfbc0d Merge pull request #7822 from yash27git/fix/refuse-truncated-branch-rewrites
fix(relinker): guard length-changing rewrites around truncated branches
2026-10-24 14:14:54 +02:00
Dean a011db7048 Merge pull request #8142 from Kernel-Hunter/fix/rosetta-masked-stores
fix(relinker): probe masked store elements before the store under --to-rosetta
2026-10-25 00:56:00 +13:00
Adrià a0a8ef2fd5 Merge pull request #7837 from muteburrito/test/relinker-embedded-code-data
test(relinker): characterize embedded code data scanning
2026-10-24 12:53:05 +02:00
Adrià FranchandClaude Sonnet 5.5 927fe074fe docs(relinker): note the M2 Max macOS 27.2 result
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-24 11:05:43 +02:00
Kiara Maldonado 47ff0109c9 docs(relinker): record Rosetta instruction support on an M2 with macOS 14.8.9 2026-10-24 11:05:35 +02:00
Karim Masmoudi ce6c2a0c66 fix(relinker): rewrite XSAVEOPT to XSAVE under --to-rosetta
XSAVEOPT raises an illegal instruction under Rosetta on an M5 running
macOS 27.0.1, as XSAVEC does, while XSAVE and XRSTOR save and restore
x87, SSE and AVX state in the standard format. The PS5's Zen 2 has
XSAVEOPT, so code built for it can use the instruction without a CPUID
check.

XSAVEOPT differs from XSAVE only in the init and modified optimizations:
it may skip writing state that is in its initial configuration or
unchanged since the last XRSTOR from the same area. XRSTOR restores the
same state from the area XSAVE writes, so --to-rosetta rewrites
XSAVEOPT (NP 0F AE /6, memory operand) to XSAVE (/4) in place, keeping
the prefixes and the operand, as RDSEED becomes RDRAND. CLWB (66 0F AE
/6), MFENCE, UMONITOR, UMWAIT and the Intel target are left alone.
XSAVEC is not converted: it writes the compacted format.

The converter tests check the rewrite for the plain, REX.W,
RSP-relative, extended-base, RIP-relative and FS-relative forms, check
that the neighbouring 0F AE encodings are not taken, and execute the
rewritten XSAVEOPT64 followed by XRSTOR on YMM3 in the x86-64 build.
The --to-rosetta integration test now covers XSAVEOPT as well.
2026-10-24 11:01:44 +02:00
Adrià FranchandClaude Sonnet 5.5 e1fea2ebc8 fix(relinker): drop stray blank line and document the moving-branch guard
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-24 10:58:12 +02:00
Yaash Singhh f5fbf2f98d fix(relinker): rebase truncated branch guard onto current main 2026-10-24 10:58:00 +02:00
Dean ec3ea2f558 Merge pull request #6586 from JJenkx/fix/linux-runtime-module-start
fix(loader): defer Linux runtime module starts until requested
2026-10-24 19:54:29 +13:00
Dean 6c52b649e7 Merge pull request #9261 from wail-arch/fix/linux-sdk-homebrew-imports
fix(relinker): bind SDK guest module imports on Linux
2026-10-24 17:11:50 +13:00
JJenkx adf0176d3a fix(loader): preserve SDK startup in browser conversions 2026-10-23 11:15:40 -04:00
Yunus Shaikh a376e37b88 fix(relinker): decode each red-zone leaf over its whole FDE range 2026-10-23 05:22:26 +00:00
Josip Parlov 606fa2ef91 fix(relinker): take red-zone framing's function bounds from .eh_frame FDEs
Function starts were direct call targets plus 16-byte-aligned code after
int3 padding. A function reached only through a pointer and not preceded
by int3 then ended up inside the previous region, and its pop rbp; ret
exit could get the epilogue lea without a matching prologue.

The bounds now come from the executable's .eh_frame FDEs (the existing
EhFrameReader), each function is decoded from its FDE start to its FDE
end, and code outside every FDE is not framed. Conversion stops with an
error when the executable has no FDE. Sites added in one pass also count
as taken for the next function.
2026-10-23 05:19:10 +00:00
Yunus Shaikh 542cb30f70 docs(relinker): describe the operand stubs and refused patches of --frame-red-zone
The debt entry no longer says that a leaf with an rsp operand that
cannot move in place is skipped. A new entry says that such an operand
moves to a stub, when the leaf is still skipped, and that a game patch
over a framed site or a moved displacement is refused. The USAGE row
says the same in short.
2026-10-23 04:50:13 +00:00
Yunus Shaikh a665ef2dfb docs(relinker): describe the per-leaf shift and sub allocations of --frame-red-zone 2026-10-23 03:45:27 +00:00