Commit Graph

468 Commits

Author SHA1 Message Date
Dean ee966bb747
Merge pull request #4542 from saxopa/fix/relinker-sce-relro
fix(relinker): load a PT_SCE_RELRO segment that no PT_LOAD covers
2026-10-13 07:32:37 +13:00
Dean acbaa8a16d
Merge pull request #4495 from SibteProf/fix/relinker-sdk-mman-syscalls
fix(relinker): recognize SDK memory syscall trap patterns
2026-10-13 07:29:18 +13:00
Dean 2350fa5353
Merge pull request #4489 from Dripl1x/codex/guest-export-index
perf(relinker): index guest exports for dependency resolution
2026-10-13 07:28:34 +13:00
Dean e305bc4e4a
Merge pull request #4483 from fable-void/pr/relinker-jump-table-targets
fix(relinker): treat jump table targets as branch targets when moving instructions
2026-10-13 07:28:12 +13:00
Dean 91e263824e
Merge pull request #4452 from orishamir/fix/relinker-null-symbol-imports
fix(relinker): resolve relocations against null symbol entries to 0
2026-10-13 07:26:13 +13:00
Dean d3187dff7f
Merge pull request #4346 from SandstromPL/fix/relinker-registry-after-patch
fix(relinker): write registries after the executable
2026-10-13 04:52:40 +13:00
Dean 57f5ec232c
Merge pull request #4338 from ArjenS-LA/fix/diagnostic-input-preservation
fix(relinker): preserve inputs when writing Windows diagnostics
2026-10-13 04:52:18 +13:00
Dean 0a6bb6ac51
Merge pull request #4337 from ArjenS-LA/fix/windows-origin-slash
fix(relinker): accept trailing separators on the Windows origin path
2026-10-13 04:51:57 +13:00
Dean 05f6460165
Merge pull request #4336 from ArjenS-LA/fix/guest-runpath-list
fix(relinker): rebase each origin in guest runpath lists
2026-10-13 04:51:37 +13:00
saxopa d0502b449d fix(relinker): load a PT_SCE_RELRO segment that no PT_LOAD covers
PS4 executables keep their relocated read-only data, GOT and init/fini
arrays in a PT_SCE_RELRO segment outside every PT_LOAD. The segment filter
dropped it, so Windows and macOS output stopped at the first relocation
into it, and Linux output placed the relinker's extra block over its
addresses without an error. The ELF reader now reports such a segment as a
read-write PT_LOAD. A PT_SCE_RELRO inside a PT_LOAD keeps being skipped,
and one that partially overlaps a PT_LOAD throws.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:54:13 +02:00
Dean f1514adea3
Merge pull request #4060 from coltken95/claude/sleepy-dirac-e44kw4
fix(relinker): decode 3DNow! instructions with their ModRM and opcode…
2026-10-13 02:35:21 +13:00
Dean b39b78a5ad
Merge pull request #3809 from aayushmishraaa/fix/relinker-reject-non-x86-64
fix(relinker): reject input executables that are not x86-64
2026-10-13 02:34:37 +13:00
Dean a1a9c3db59
Merge pull request #3860 from excited-raccoon/perf/relinker-linear-control-flow
perf(relinker): walk fallthrough instructions without queueing
2026-10-13 02:31:15 +13:00
SibteProf c0967216bf fix(relinker): recognize SDK memory syscall trap patterns 2026-10-12 18:25:06 +05:00
Evgeniy Kazarin 33c955a8e3 perf(relinker): index guest exports for dependency resolution 2026-10-12 16:15:06 +03:00
fablevoid 1541244b78 fix(relinker): treat jump table targets as branch targets when moving instructions
The AMD-only converter moves the instructions next to a short AMD-only
instruction into its stub, and refuses to move one that a branch
enters. It knew only direct jump and call targets, so a switch case
entered through a jump table could land inside the jump written over
the moved instructions.

The converter now also reads relative jump tables: a RIP-relative LEA
whose address lies in a loaded segment starts a table of 32-bit
offsets from that address, read while each target starts an
instruction of the segment being converted. To read them, Convert
takes the program headers and converts their executable load
segments; the relinker passes all headers, and
ElfReader::ReadCodeSegments, now unused, is removed.

The converter test builds a dispatch through such a table whose second
case enters the instruction after a 4-byte 256-bit store, and checks
that the store takes the instruction before it instead. It also checks
that reading stops at an entry that does not start an instruction,
that only a LEA forms a table address, that tables are read only
inside loaded segments, that only executable load segments are
converted, and that a segment past the end of the file fails the
conversion.

PPSA12544: one 256-bit store in Il2cppUserAssemblies moved the
instruction after it, which is case 1 of a switch; it now goes through
an island. The other relinked files are unchanged.

AI-assisted: yes
2026-10-12 13:06:23 +00:00
Dean 71c3dbb722
Merge pull request #4190 from ArchitDewan/fix/relinker-empty-path
fix(relinker): reject empty positional paths
2026-10-13 01:29:30 +13:00
Dean f8dee05957
Merge pull request #4091 from jweidenh/codex/guest-noop-relocations
fix(relinker): ignore no-op relocations in guest modules
2026-10-13 01:27:26 +13:00
Dean 253ec3ffee
Merge pull request #4084 from hawwwwwk/pr/relinker-suprx-guest-alias-current
fix(relinker): resolve .suprx guest module aliases
2026-10-13 01:27:08 +13:00
Dean a46ffb5e75
Merge pull request #4066 from hawwwwwk/pr/relinker-ff-callsite-current
fix(relinker): filter non-reference RIP-relative FF operations
2026-10-13 01:25:57 +13:00
Ori Shamir 1205d03daa fix(relinker): resolve relocations against null symbol entries to 0
A relocation whose dynamic symbol entry is all zero, like the null symbol,
now takes the value 0 plus its addend, as the gABI defines for STN_UNDEF.
The Linux output imports such an entry as an unnamed weak symbol, which the
host loader resolves to 0. The Windows and macOS outputs write the value
into the slot instead of failing with "Empty import symbol name". Such
references are left out of the call registry. An unnamed symbol entry that
is not all zero still fails the relink.

OliSe Player (PPSA01153) has seven of these entries and calls through the
slots only when they are not 0 (#4437).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:24:56 +03:00
Dean c99cc11cf5
Merge pull request #4194 from fable-void/pr/rosetta-store-split
feat(relinker): split unaligned 256-bit stores for Rosetta
2026-10-13 01:22:45 +13:00
Dean 4d5fcef15b
Merge pull request #4203 from saxopa/fix/relinker-relative-section-symbol
fix(relinker): accept RELATIVE relocations against a zero-value section symbol
2026-10-13 01:21:34 +13:00
Dean 8b06e64176
Merge pull request #3854 from aryan0078/fix/relinker-debug-module
fix(relinker): resolve debug PRX dependencies by module identity
2026-10-12 20:27:31 +13:00
Dean 5161070e67
Merge pull request #4273 from poonasor/fix/relinker-move-tls-branch-from-short-access
fix(relinker): move a short guest TLS access's follower branch into its stub
2026-10-12 20:26:47 +13:00
SandstromPL 70f03dc5e5 fix(relinker): write registries after the executable
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:48:01 +05:30
ArjenS-LA 4b6bb2f059 fix(relinker): preserve inputs when writing Windows diagnostics 2026-10-12 00:01:25 -07:00
ArjenS-LA e2c24cf038 fix(relinker): accept trailing separators on the Windows origin path 2026-10-12 00:01:09 -07:00
ArjenS-LA 341dafb7ca fix(relinker): rebase each origin in guest runpath lists 2026-10-12 00:00:52 -07:00
Dean 66ab8753bf
Merge pull request #3780 from MrMha/fix/unwind-record-bounds
fix(relinker): validate file-backed unwind record ranges
2026-10-12 17:35:37 +13:00
poonasor c6f934a3d0 fix(relinker): move a short guest TLS access's follower branch into its stub
A short fs-prefixed TLS access is patched with a 5-byte jump by
relocating the following instructions into the stub, but any branch
there was rejected outright. NHL 27 hits this on every stack-protector
epilogue: fs:xor rax,[rbx] immediately followed by jne __stack_chk_fail.

Allow relative conditional branches and short jumps: re-encode rel8
forms as their rel32 equivalents, rebase the displacement when the
stub is emitted, and keep rejecting loop/jrcxz, calls, returns, and
segment-prefixed followers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 23:44:54 -04:00
Dean 26d87eec20
Merge pull request #3850 from SandstromPL/fix/relinker-module-dir-root
fix(relinker): accept the input's directory as a module directory
2026-10-12 16:07:27 +13:00
fablevoid c763a78b67 feat(relinker): split unaligned 256-bit stores for Rosetta
Rosetta 2 ends the process when an unaligned 256-bit store crosses into
a page the store may not write ("rosetta error: unexpectedly need to
EmulateForward on a synchronous exception") instead of raising the
fault. A store inside such a page, and a 128-bit store across one,
fault normally. The macOS write watch keeps watched pages read-only
between collections, so a guest that stores 32 bytes across the start
of a watched page ends the process.

--to-rosetta now lowers VMOVUPS, VMOVUPD and VMOVDQU with a 256-bit
memory destination to a stub that stores the low half with the same
instruction at VEX.L=0 and the high half with VEXTRACTF128 at the
operand plus 16, so each half faults like any other store. RIP-relative
operands are relocated from the instruction's place in the site. A
store whose upper half has no 32-bit displacement fails the conversion.
Aligned stores (VMOVAPS, VMOVAPD, VMOVDQA and the non-temporal forms)
cannot cross a page and are left alone.

Every store is lowered. A 4-byte store has no room for the jump to its
stub, so its stub also takes one neighbouring instruction. The
following one: a return ends the stub, a call pushes its original
return address and jumps, a jump or conditional branch is re-encoded
with a 32-bit displacement, and another 256-bit store is lowered in the
same stub. Otherwise the preceding one, unless it is a call, a jump, a
return or a trap. Register calls, LOOP, JRCXZ and branches with a
prefix that changes them do not move. When neither neighbour can move,
the store becomes a short jump to an island: a run of movable
instructions within reach is moved to its own stub, and the bytes it
frees hold the jump to the store's stub. A store with neither fails the
conversion.

The converter tests compare the halves with clang's encodings for base,
SIB, disp8 overflowing to disp32, disp32, RSP-relative, FS-absolute,
r13-based and RIP-relative operands, and check that aligned stores,
loads, register forms and masked stores are not split. They check the
stub of a short store followed by a return, a call (direct, with an
address-size prefix, and through a RIP-relative pointer), short, near
and RIP-relative jumps, short and near conditional branches and another
store; that a following register call, LOOP, JRCXZ, prefixed branch or
CLWB makes the store take the instruction before it; islands past
instructions already moved, a store that needs its own stub, a branch
target, a register call and the short-jump reach; and that a store with
no room fails.

PPSA12544: 55295 stores split in the executable, 278 of them in the
stub of the store before them; every module converts with none kept.

AI-assisted: yes
2026-10-12 02:48:33 +00:00
Dean 2263cefe25
Merge pull request #3601 from Scramblrrrr/codex/legacy-sse-reciprocals
fix(relinker): lower legacy packed reciprocal register instructions
2026-10-12 15:43:20 +13:00
saxopa cded9ba8c3 fix(relinker): accept RELATIVE relocations against a zero-value section symbol
OpenOrbis create-fself adds one to the symbol index of every relocation it
copies from .rela.dyn, so each R_X86_64_RELATIVE entry of a homebrew built
with the OpenOrbis toolchain names symbol 1, a local STT_SECTION symbol with
value 0. FreeBSD rtld computes RELATIVE as base + addend without reading the
symbol. The pipeline, the code analysis and the strict filter now accept
index 0 or a STT_SECTION symbol with value 0, and still throw for any other
symbol. The relocation is written with symbol index 0, where the pipeline
previously dropped RELATIVE entries with a nonzero index.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:12:02 +02:00
Archit Dewan 5eb22de16d fix(relinker): reject empty positional paths 2026-10-11 20:28:56 -04:00
jweidenh 72d5b8ce90 fix(relinker): ignore no-op relocations in guest modules 2026-10-11 19:02:06 -04:00
ethan 0a324d8ccb fix(relinker): resolve .suprx guest module aliases 2026-10-11 15:45:27 -07:00
Claude 36c78ba143
fix(relinker): report the ModRM of 3DNow! instructions in decoded instruction info
DecodeInstruction did not treat 0F 0F as having a ModRM byte, so a
RIP-relative 3DNow! operand was not reported to the analyses and the
--to-intel stub relocation that read HasRipRelativeDisp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-11 22:34:39 +00:00
ethan 409f53eaed fix(relinker): filter non-reference RIP-relative FF operations 2026-10-11 15:24:53 -07:00
Claude feb19a844d
fix(relinker): decode 3DNow! instructions with their ModRM and opcode suffix
0F 0F was decoded as a two-byte instruction. 3DNow! instructions are
0F 0F ModRM [SIB] [displacement] imm8, the trailing byte selecting the
operation (AMD64 Architecture Programmer's Manual Volume 3, Appendix A,
3DNow! opcodes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-11 22:21:32 +00:00
MrMha 3687b2e214 perf(relinker): use a flat sorted call-site index 2026-10-12 00:11:00 +02:00
Aryan singh 7c1b64b0ca fix(relinker): share module suffixes between identity and import matching
The guest identity predicate accepted .debug_prx while Domain::ImportModule
did not: a dependency named libGuest.debug_prx normalised to
libGuest_debug_prx, so a qualified import declared in module libGuest was
left unscoped. When another guest module exported the same symbol, the
conversion failed with an ambiguous guest import, while .prx, .sprx and
.suprx resolved to the declaring module.

Module suffixes are now one list in the domain layer, used by the identity
predicate, import module normalisation and the default .prx suffix.
Needed-name stem aliasing keeps its own list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:38:07 +05:30
Aryan singh d3fc14a50c fix(relinker): resolve debug PRX dependencies by module identity 2026-10-12 03:38:07 +05:30
Adrià 66e87807d5
Merge pull request #3804 from MarcZX100/codex/relinker-trap-sdk-syscalls-2136
feat(relinker): trap exact SDK syscall stubs on request
2026-10-12 00:05:38 +02:00
Adrià 3929c21fb9
Merge pull request #3782 from MrMha/fix/rewrite-instruction-boundaries
fix(codegen): reject rewrites inside instructions
2026-10-12 00:01:46 +02:00
Adrià 6566c9c8c6
Merge pull request #3784 from MrMha/fix/param-json-utf8
fix(libkernel): reject malformed UTF-8 in param JSON
2026-10-12 00:01:32 +02:00
Adrià bb48d60fc6
Merge pull request #3774 from MrMha/fix/program-layout-ranges
fix(relinker): validate program layout ranges before writing
2026-10-12 00:00:46 +02:00
Adrià 7ee8992714
Merge pull request #3776 from MrMha/fix/section-header-ranges
fix(relinker): validate complete allocated section ranges
2026-10-12 00:00:39 +02:00
Adrià 05c2509c61
Merge pull request #3678 from Ondra97/codex/relinker-desktop-input-preservation
fix(relinker): preserve inputs when writing desktop assets
2026-10-11 23:49:58 +02:00