Commit Graph
84 Commits
Author SHA1 Message Date
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
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
Adrià 3a2ca40dab Merge pull request #9234 from mossyanwar/fix/relinker-linux-named-imports
fix(relinker): resolve symbol-name imports through NIDs on Linux
2026-10-22 20:54:22 +02:00
Rookie 123ba70839 fix(relinker): load Linux executables at 0x400000 by default 2026-10-21 19:25:33 +01:00
wail-arch 03fae5dfcb fix(relinker): bind SDK guest module imports on Linux
A bundled module that names a console file dependency (.sprx, .suprx,
.debug_prx) imports by symbol name, as homebrew built with the
ps5-payload-dev SDK does. Bind those imports to the NID of the name,
except names another bundled module or the executable exports, and name
the module's host dependencies with the .prx library of the same stem.
2026-10-21 18:06:47 +00:00
mossyanwar be51ab7bae fix(relinker): resolve symbol-name imports through NIDs on Linux
Homebrew built with the ps5-payload-dev SDK names its system
libraries with .sprx and imports by symbol name, while the libraries
in libs/ are .prx files that export NIDs. On Linux such an executable
converted but stopped at load time on the first .sprx dependency and,
once that was found, on the first symbol name.

The Linux patcher now loads a dependency named with .sprx, .suprx or
.debug_prx as the .prx library of the same stem. In an executable that
names such a dependency, an import without a module that is named by
symbol gets the NID of that name. A name that a bundled module exports
still binds to that module. There is no lookup by the name as written,
because the host loader also searches the host C library. Other
executables keep their unqualified imports as written.
2026-10-21 18:43:42 +01:00
Dean 27bcd6a29e Merge pull request #8162 from savvaniss/fix/windows-runtime-module-start
fix(relinker): start Windows runtime modules the executable needs when the title loads them
2026-10-22 02:10:11 +13:00
Savvanis SpyrosandClaude Opus 5.5 1d0451f659 docs(relinker): note that a deferred module the title never loads gets no module_start
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 14:12:12 +03:00
Dean fbba6e8208 Merge pull request #8845 from rooklz/fix/refs-file-identity
fix(relinker): compare Windows file identities by their 128-bit file ID
2026-10-21 20:57:16 +13:00
Rookie 5748d7ce81 fix(relinker): compare Windows file identities by their 128-bit file ID 2026-10-21 06:09:46 +01:00
Dean 46bfbe4e25 Merge pull request #8063 from AasishDairelSahayaGrinspan/fix/relinker-gs-memory-only-traps
fix(relinker): trap only GS memory accesses in Windows and macOS output
2026-10-21 16:35:25 +13:00
mpratsakiandClaude Opus 5.5 763702c5ce fix(relinker): use the Windows file identity in module and executable checks
Guest module discovery skipped the input executable and the
--executable check rejected an executable converted twice through
std::filesystem::equivalent, which MinGW reports as false for hard links
whose names give different permissions, such as .bin and .exe. Move the
GetFileInformationByHandle comparison to Io::SameFile and use it for
these checks and for SameOutputFile.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 02:19:01 +03:00
Dean Galvin 143ed02750 Merge branch 'main' into #7417
Resolve docs/dev/debt/libc.md: keep main's _Throw_Cpp_error entry and this branch's call tracing entry.
2026-10-21 06:33:59 +13:00
Dean bdc33a556c Merge pull request #7995 from mpratsaki/fix/relinker-windows-file-identity
fix(relinker): compare Windows file identities by handle
2026-10-21 06:25:35 +13:00
Savvanis SpyrosandClaude Opus 5.5 e0095e5b49 fix(relinker): find more constant syscall numbers before a gap syscall
The raw-byte check that runs before a syscall pattern between PS4 unwind
functions is skipped now also accepts mov rax, imm64, merges a following
mov al, imm8 or mov ax, imm16 into the earlier constant, and walks back
over any number of register moves or zeroings that leave rax alone
instead of at most seven. Visited states keep the walk linear in the
bytes it covers.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 18:10:59 +03:00
Savvanis SpyrosandClaude Opus 5.5 58a2a4962f fix(relinker): follow fs loads and report pointers taken as data between PS4 unwind functions
A relocation or lea target outside the unwind functions of a PS4 image
is now decoded up to its first jump, return or trap, or to the start of
the next unwind function, which also bounds the transfer check of the
tail rule. A target whose run holds an fs:[disp32] access, the form the
linear TLS sweep roots, is followed as code. The other targets taken as
data are counted in one message and kept as entry points that the
Windows TLS rewrite may not overwrite. The analysis merges nested
unwind ranges like the scans.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 15:48:42 +03:00
Savvanis SpyrosandClaude Opus 5.5 1ea49c741f fix(relinker): tighten the syscall skip between PS4 unwind functions
The skip of syscall patterns outside the unwind functions let some real
syscalls through. The scan now merges nested and overlapping unwind
ranges with the instruction scanner's MergeCodeRanges, so a pattern
inside an outer function is refused. A constant syscall number is also
looked for in the bytes in front of the pattern, whatever alignment the
decoding took: a mov eax, mov rax or xor eax, eax that ends at the
pattern or before register moves and zeroings that leave rax alone. The
decoded lookback requires each instruction to end where the next one
starts. Guest modules without PT_SCE_DYNLIBDATA get no unwind ranges,
so their scan stays strict even when their unwind table is read.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 15:48:42 +03:00
Savvanis Spyros 079e6ca316 Merge remote-tracking branch 'origin/main' into fix/windows-runtime-module-start 2026-10-20 15:27:06 +03:00
Savvanis SpyrosandClaude Opus 5.5 f154e132bc fix(relinker): take pointers into data between PS4 unwind functions as data
The code analysis of the Windows and macOS outputs followed every
relocation and lea target inside the code range as code. PS4 images keep
read-only data between unwind functions, and strings and tables there
decoded into garbage, failing the conversion. Outside the unwind functions
such a target is now code only when it is 16-byte aligned, starts less
than 256 bytes after an unwind function and decodes to a jump, return or
trap; lea targets go through the same rule instead of the graph's own.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 15:19:45 +03:00
Adrià 8afd6ea478 Merge pull request #7660 from savvaniss/fix/sce-code-gaps
fix(relinker): resume scans after undecodable bytes between PS4 unwind functions
2026-10-20 13:17:15 +02:00
aasishdairel 570c3297d3 fix(relinker): trap only GS memory accesses in Windows and macOS output 2026-10-20 10:13:34 +05:30
Dean d85b7c759a Merge pull request #2780 from SuarezPM/ai/relinker-hardening
feat(relinker): lower MCOMMIT and RDPRU for Intel with execution tests
2026-10-20 16:22:49 +13:00
Savvanis SpyrosandClaude Opus 5.5 45cc02c49c fix(relinker): start Windows runtime modules the executable needs when the title loads them
A --module-dir module that only the executable needs was initialized by
the Windows entry stub with no start arguments, so a later
sceKernelLoadStartModule with arguments found it started and its
module_start never saw them. Unity's mono-ps4.sprx keeps those
arguments for the plugins it loads. Such a module is now deferred like
any other runtime module: mapped at startup and started, with its
arguments, when the title loads it. Modules another guest module needs
are still started at startup, and Linux and macOS are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 03:57:24 +03:00
Adrià 34b1b77abf Merge pull request #7651 from DavidSamir/fix/relinker-amd-only-branch-targets
fix(relinker): ignore direct branch targets inside an instruction past its prefixes
2026-10-20 02:13:47 +02:00
Karim Masmoudi 3cae921a66 fix(relinker): probe masked store elements before the store under --to-rosetta
Rosetta ends the process instead of raising SIGSEGV or SIGBUS when a
VMASKMOVPS, VMASKMOVPD, VPMASKMOVD or VPMASKMOVQ store faults on any
element other than an active first element ("rosetta error: unexpectedly
need to EmulateForward on a synchronous exception"). Measured on an M5
with macOS 27.0.1 for all eight 128- and 256-bit store forms. A masked
store into a page the macOS write watch keeps read-only therefore ends
the title.

--to-rosetta now moves each masked store to a stub that saves RAX, RCX
and RFLAGS below the red zone, computes the operand address with LEA,
reads the mask sign bits with VMOVMSKPS or VMOVMSKPD, and writes to the
first and last byte of every active element with LOCK OR of 0. Those
writes fault normally, so the write watch sees the page and unprotects
it, and they leave memory unchanged. The stub then restores the
registers and runs the original store. Segment and address-size
prefixes are kept on the probes, RSP-based operands skip the spill
frame, and RIP-relative operands are relocated. Masked loads, the
Intel target and a plain relink are unchanged.

masked_store_lowering decodes every form, register and extension,
checks the stub bytes, and on x86-64 Linux and macOS runs 1728 stubs
across all forms, six addressing modes, six offsets around a read-only
page and six mask patterns. It checks the stored bytes, that exactly one
fault reaches the handler when an active element touches the page,
that no register, flag or red-zone byte changes, and that RSP is
restored. Without the probes the x86-64 build aborts under Rosetta.
test_to_rosetta.py checks that only --to-rosetta lowers a VMASKMOVPS.
2026-10-20 01:12:24 +01:00
SuarezPM bf47697ec0 feat(relinker): lower MCOMMIT and RDPRU for Intel with execution tests
MCOMMIT becomes STC plus NOP padding and RDPRU goes through a
runtime-checked stub returning the host TSC for MPERF/APERF while
other selectors yield zero, with converter and execution tests.

docs/dev/debt/relinker.md records the new lowering and its unverified
assumptions.
2026-10-19 19:19:31 -03:00
Ishmam Ahmed 78634fb0a9 feat(relinker): support --trace-imports for Linux output
The Linux entry stub now passes each traced import through libc.prx's
TraceImport_nid_no_patch before it calls the guest entry, and stores the
returned thunk in the import's slot. The same imports are traced as on
Windows: functions bound through a PLT slot or a GOT slot, without an
addend, and not weak. TraceImport_nid_no_patch is bound eagerly through
an added GLOB_DAT relocation, so a libc.prx without it fails at load.
Each slot's page is made writable with mprotect first, so slots inside a
PT_GNU_RELRO range can be replaced.

--trace-imports now requires libc.prx among the libraries on Linux too,
and is refused with --macos.
2026-10-19 22:56:03 +01:00
mpratsakiandClaude Opus 5.5 c9731df4c9 fix(relinker): compare Windows file identities by handle
MinGW's std::filesystem::equivalent returns false for hard links whose
names give different permissions, such as .elf and .exe. The temporary
hard-link probe that worked around it failed on read-only files and on
directories that refuse the link. Compare the volume serial number and
file index from GetFileInformationByHandle instead.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 19:54:53 +03:00
Savvanis SpyrosandClaude Opus 5.5 c92f09d1d5 docs(debt): name no title in the SCE code gap entry
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 14:53:58 +03:00
muteburrito 3dc2ecba0b test(relinker): characterize embedded code data scanning 2026-10-19 16:39:04 +05:30
Adrià e0adc075a2 Merge pull request #6697 from karimibrahim07/feat/relinker-named-host-imports
fix(relinker): resolve symbol-name imports through NIDs on Windows
2026-10-19 10:49:05 +02:00
Savvanis Spyros 504c41a9ad Merge branch 'main' of https://github.com/boykopovar/AnyPS5 into fix/sce-code-gaps
# Conflicts:
#	core/relinker/relinker/src/pipeline/RelinkerPipeline.cpp
2026-10-19 10:06:58 +03:00
Adrià Franch da5b7e3334 docs(debt): note that macOS output traps GS-prefixed instructions without a memory operand too 2026-10-19 02:06:49 +02:00
David 414c1f96a6 docs(debt): record that guest GS accesses trap in macOS output 2026-10-19 02:06:44 +02:00
Savvanis Spyros c3d1363df3 Merge branch 'main' of https://github.com/boykopovar/AnyPS5 into fix/sce-code-gaps
# Conflicts:
#	docs/dev/debt/relinker.md
2026-10-19 02:35:44 +03:00
Adrià 2c2abc453b Merge pull request #6354 from SandstromPL/fix/relinker-plt-before-code
fix(relinker): find the PLT before the code in PS4 modules
2026-10-19 01:32:36 +02:00
Adrià 64b57d1b02 Merge pull request #6328 from aaro56/fix/relinker-preserve-input-hardlinks
fix(relinker): preserve inputs behind Windows executable hard links
2026-10-19 01:17:35 +02:00
Adrià 9121a9e455 Merge pull request #6327 from HilalElusive/patch-1
docs(debt): correct Windows GUI logging description
2026-10-19 01:08:04 +02:00
Savvanis SpyrosandClaude Opus 5.5 45a2e3dd4a fix(relinker): resume scans after undecodable bytes between PS4 unwind functions
In PS4 executables and modules the bytes between unwind functions are
16-byte slots of function tails and padding, and a tail can begin inside
an instruction, such as a lone REX byte before a 15-byte NOP. The
syscall and call-site scans decode the executable segment linearly, so
such a slot failed the relink with "Cannot decode instruction".

For images with a PT_SCE_DYNLIBDATA segment the scans now receive the
unwind function ranges. Outside every range an undecodable byte is
skipped and decoding resumes at the next byte, and a decoding that would
cross into a range ends at its start, so gap bytes cannot change how a
function is decoded. Inside a range a decode failure still fails the
relink, and images without unwind ranges are scanned as before.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 23:45:49 +03:00
Dean Galvin c3b9001592 revert(relinker): run guest preinit arrays before the module initializer (#6112)
This reverts commit 376c040294.
2026-10-19 09:38:31 +13:00
David 2f406862a8 docs(debt): note the branch targets the AMD-only converter ignores 2026-10-19 00:10:07 +04:00
SandstromPLandClaude Opus 5.5 81561867fc Merge upstream/main into fix/relinker-plt-before-code
Resolve the docs/dev/debt/relinker.md conflict with #5994: keep its
sce_module syscall-scan entry, which now also stops at the end of the
last unwind function when the PLT comes before the code (it calls the
same FindSceCodeEnd), and its /libexec/ld-elf.so.1 start in the code
analysis entry, with this PR's end for a PLT before the code.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 22:51:57 +05:30
Ayamullah Khan 9c43211664 fix(relinker): run guest preinit arrays before the module initializer
Converted guest modules never ran their DT_PREINIT_ARRAY entries: the
reader validated the array and the unused-NID filter kept its targets,
but no writer emitted or ran it. ld.so runs a shared object's preinit
array only for the main executable, so the Linux output runs the
entries from the DT_INIT stub before the module initializer; the macOS
and Windows outputs run them before the initializer in their startup
stubs, and the deferred Windows output exports a thunk that runs them
before the initializer for runtime-loaded modules. A module with a
preinit array and no initializer is still rejected, since the Linux
stub exists only with one.
2026-10-18 19:09:46 +02:00
Adrià f890e21a81 Merge pull request #6111 from Kernel-Hunter/fix/rosetta-rdtscp-processor
fix(relinker): report processor 0 from RDTSCP under --to-rosetta
2026-10-18 19:00:12 +02:00
Adrià aff1f7190d Merge pull request #6102 from DavidSamir/fix/relinker-trap-windows-guest-gs
fix(relinker): trap guest GS accesses in Windows output instead of refusing the module
2026-10-18 18:29:03 +02:00