Commit Graph

152 Commits

Author SHA1 Message Date
Simone ad0d478a81 Merge remote-tracking branch 'origin/main' into fix/relinker-weak-imports
# Conflicts:
#	core/relinker/relinker/src/output/SysVDynamicSectionBuilder.cpp
#	core/relinker/relinker/src/pipeline/RelinkerPipeline.cpp
2026-10-12 23:40:54 +02: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 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
Simone cb1c18d552 fix(relinker): keep weak undefined imports weak
Weak undefined imports in the input ELF became STB_GLOBAL in the relinked
output, so a title that weak-imports a function no module exports stopped
at startup instead of binding the import to null.

Keep STB_WEAK on the relinked dynamic symbols. On Windows, write 0 plus
the addend to the slot of a weak import that no searched module exports.

Fixes #4497

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:48:50 +02: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
ArjenS-LA e2c24cf038 fix(relinker): accept trailing separators on the Windows origin path 2026-10-12 00:01:09 -07: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 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
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
MrMha 3742fa136e test(relinker): cover extra block bounds and header address overflow 2026-10-11 23:11:42 +04:00
MrMha 653eb704c2 fix(relinker): validate complete allocated section ranges 2026-10-11 19:52:18 +04:00
MrMha d85d1c268f fix(relinker): validate program layout ranges before writing 2026-10-11 19:51:17 +04:00
Oguzhan Ozdemir 5ea9ce2e40 fix(relinker): allow identical Windows function export aliases 2026-10-11 16:43:07 +02:00
Scramblrrrr 363d17985e fix(relinker): lower legacy packed reciprocal register instructions 2026-10-11 10:58:14 -03:00
fablevoid 1b865fc3ea fix(relinker): pass module start arguments to macOS guest initializers
The macOS image initializer called a guest module's DT_INIT with no
arguments, so a module started with sceKernelLoadStartModule never saw
its args and argp, and its result was dropped. The Linux writer already
calls DT_INIT through libkernel's pending argument handoff. On the
macOS port, the PSN plugin of PPSA12544 refuses to start without its
argument block ("PSN is an old version that cannot be used by the
current player runtime") and the title then crashes.

A guest module with DT_INIT now gets two slots bound to
__aps5_get_pending_module_args_nid_no_patch and
__aps5_set_module_init_result_nid_no_patch, and its initializer calls
DT_INIT with the args and argp that sceKernelLoadStartModule records,
as on Linux, then hands the result back. The TechnicalDebt sentence
about the missing arguments on macOS is removed.

guest_module_args also relinks its fixture with --macos and checks the
two binds; on x86-64 macOS it loads the module and checks that DT_INIT
receives the arguments and that its result is returned.

AI-assisted: yes
2026-10-11 11:22:38 +00:00
Adrià Franch 33a1ca5d33 fix(relinker): skip the desktop entry for macOS output and use native paths
The Linux desktop entry was written for every non-Windows output, macOS
included since --macos landed. It is now written only for Linux output,
and its paths go through Io::NativePath/Utf8Path like the rest of the
relinker. An end-to-end test relinks for Linux, macOS and Windows.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-11 12:55:22 +02:00
Adrià Franch ca330dfefb fix(relinker): validate the desktop entry before writing the executable
The icon, title and output path are checked before the ELF is written,
so a malformed icon0.png or param.json leaves no output behind. Paths
with control characters are refused instead of producing an invalid
entry.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-11 12:39:14 +02:00
Adrià Franch 1ff7b534fe feat(relinker): write a desktop entry with the game icon for Linux executables
ELF has no icon resource, so when sce_sys/icon0.png sits beside the input
the relinker copies it next to the output and writes <output>.desktop
(freedesktop Desktop Entry) with that icon. Name is the param.json title
without trademark signs or line breaks, or the output name without
param.json. Exec is quoted per the spec and the entry is marked executable
so file managers launch it. A malformed icon0.png or param.json fails the
relink; without icon0.png nothing extra is written.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-11 12:39:14 +02:00
fablevoid 3462427519 fix(relinker): accept absolute symbols in macOS guest modules
#698 taught the reader, the module builder and the Windows writer to
resolve relocations against SHN_ABS symbols and to leave them out of the
exports, but the macOS writer still threw "Unsupported guest export
section" for them. PPSA12544 bundles modules with such an export
(RKDbTdN8TO0), so --macos stopped before writing anything.

The macOS writer now resolves a relocation against an absolute symbol to
its value plus the addend, without a rebase, and skips absolute symbols
when exporting, as the Windows writer does. guest_absolute_symbols covers
the macOS output too.

AI-assisted: yes
2026-10-11 10:16:59 +00:00
MathiasDevelopes 2faa5dd6ed fix(relinker): load needed providers for unscoped Windows imports 2026-10-11 11:33:13 +02:00
Merijn 1c6eac425d feat(relinker): add --module-dir for modules loaded at run time
Relinks the ELF modules of extra directories under the module parent directory. Modules the executable or another module needs start with the executable; the others are initialized when the title loads them with sceKernelLoadStartModule, with its start arguments (Windows: __aps5_guest_initialize export; Linux: left out of DT_NEEDED).

Squashed onto main by the reviewer (history had a merge commit).
2026-10-11 10:11:31 +02:00
Adrià c8facc79ff
Merge pull request #3325 from AchrafReyani/carry/windows-stub-orphan-failed-line
fix(relinker): print the Windows stub's ' -> FAILED' only with dependency diagnostics
2026-10-11 09:58:25 +02:00
Adrià 832c84298e
Merge pull request #2705 from DariusHQ/fix/windows-guest-libc-placeholders
fix(relinker): skip zero-return guest libc exports for internal libc imports
2026-10-11 09:56:33 +02:00
Badr d102e186c9 fix(relinker): print the Windows stub's ' -> FAILED' only with dependency diagnostics 2026-10-11 16:40:50 +09:00
Adrià cfcffebd0f
Merge pull request #3290 from AchrafReyani/carry/relinker-windows-tls-thread-pointer
fix(relinker): place the Windows thread pointer after the TLS size rounded to its own alignment
2026-10-11 09:26:24 +02:00
Adrià 6957bb4ae2
Merge pull request #2785 from tototomate123/fix/hfw-relinker-split
fix(relinker): preserve Linux executable exports and ELF section addresses
2026-10-11 09:20:45 +02:00
DariusHQ e720d3cd61 fix(relinker): skip zero-return guest libc exports for internal libc imports
Since #1454, a libSceLibcInternal import that no native library exports
on Windows falls back to the title's own libc.prx. The loader shim that
ps5-native-app-boilerplate builds into homebrew titles exports 1874
functions at three addresses whose code is `xor eax, eax; ret` or
`pxor xmm0, xmm0; xor eax, eax; ret`. Such an import then binds to a
function that returns 0, and the title starts instead of stopping with
`unresolved ELF import`.

The Windows guest module writer records the exported functions whose
code is one of these two sequences, and the entry stub leaves the guest
libc.prx out of the search for those names. A guest export with code of
its own still provides a missing libSceLibcInternal function, and native
libraries keep their priority.
2026-10-11 09:20:00 +02:00
Adrià bbb9419642
Merge pull request #3129 from CnRJay/fix/windows-start-without-unused-library
fix(relinker): start on Windows without a missing library nothing imports from
2026-10-11 09:11:54 +02:00
Chad 7755e1d05c fix(relinker): leave needed libraries nothing imports from out of the start-up load list
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 20:14:23 -05:00
Adrià abb2f8e4fc
Merge pull request #2986 from MarcZX100/fix/relinker-windows-unicode-2640
fix(relinker): support Unicode Windows startup paths
2026-10-11 01:46:23 +02:00
xXPBSXx 8e03bb0af8 fix(relinker): place the Windows thread pointer after the TLS size rounded to its own alignment
The converted thread pointer was set to the TLS block plus the size rounded to max(p_align, 16), while the guest reads its first variable at tp minus the size rounded to p_align. For a PT_TLS with memsz 0x21 and p_align 8 (Resident Evil 4) that is 0x30 against 0x28, so the first variable was read from the second slot. The thread pointer now uses the size rounded to p_align; the block layout is unchanged. WIP: the test for this is still missing.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 00:56:01 +02:00
Abdulrahman Elkordy 87ca3a2cf1 fix(relinker): count unnamed imports only against the library they declare
An import whose module matches no needed library has no library name,
and the Windows startup stub counted it against every library, so a
missing library with nothing imported from it was still never skipped.
Every such import in the executables of Record of Lodoss War, Resident
Evil 4, PRAGMATA and Returnal declares a module that exists under
another file name (libSceJson for libSceJson2.prx, for example), and
none declares libSceXml or Party.

The relinker now keeps the declared module names of those imports, for
the executable and each guest module, and the stub counts a host
library as imported from when its name up to the first dot matches one
of them, ignoring case. A module declared as libGuest still keeps a
missing libGuest.xyz required, as guest_module_identity checks.
Imports without a module ID declare nothing and count against no
library. The rule and the title data are from xXPBSXx.
2026-10-10 17:49:47 -05:00
Abdulrahman Elkordy 8ebf892849 fix(relinker): start on Windows without a missing library nothing imports from
The Windows startup stub stopped at the first DT_NEEDED library it could
not load, even when no import is searched in that library. Titles list
libraries they import nothing from (Road of Death needs libSceXml.prx,
Resident Evil 4 needs Party.prx), so they stopped with GetLastError 126
before running. A host library that no import's search list contains is
now skipped with a message when it is not found; its handle stays null
and is never read. Missing libraries that something imports from, other
load errors and guest modules still stop the start.
2026-10-10 17:49:47 -05:00
Doston Abdullayev 28b1f1578f fix(relinker): walk Windows dependency diagnostics through the wide API
The --windows-diagnostics walker looked up modules and directories with
GetModuleHandleA, LoadLibraryExA, GetFileAttributesA,
GetModuleFileNameA and GetSystemDirectoryA, so under a directory outside
the ANSI code page it failed with "dependency diagnostics Windows API
failed" instead of naming the missing dependency.

Keep the walker's paths in UTF-8 and convert them at the Windows API
calls, which now use the wide functions. The entry stub passes it, and
prints, its paths as UTF-8 instead of the ANSI code page. The dependency
diagnostics test now builds its fixtures under a non-ASCII directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:42:28 +00:00
Doston Abdullayev 19803c0086 fix(relinker): start Windows executables from directories outside the ANSI code page
The Windows entry stub read its path with GetModuleFileNameA, which
turns every character the ANSI code page cannot represent into '?', and
then used it with SetCurrentDirectoryA and LoadLibraryExA. A converted
executable in such a directory (Japanese on a Western-locale system, an
emoji, a script without an ANSI code page) stopped at start-up with
ERROR_INVALID_NAME.

Read the path with GetModuleFileNameW and enter the directory and load
the libraries with SetCurrentDirectoryW and LoadLibraryExW, with library
paths stored as UTF-16. Messages and the --windows-diagnostics walker
still get the paths in the ANSI code page, as recorded in TechnicalDebt.

Fixes #2640

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:42:28 +00:00
ctj01 b7d5f18c41 fix(relinker): drop the input PT_PHDR and PT_INTERP from Linux output
The Linux patcher writes its own PT_PHDR and PT_INTERP but also copied
the input's. glibc takes the load bias from the last PT_PHDR, which was
the input's entry with the pre-relink address, so such an executable
crashed at start. Both copies also took program header slots, so an
input with PT_PHDR and PT_INTERP and no spare slots failed to relink.
2026-10-10 17:33:59 +00:00
tototomate123 ded8b4df23 fix(relinker): preserve executable exports and dynamic lookup tags 2026-10-10 16:58:39 +02:00
tototomate123 7ea423f78b fix(relinker): map executable section addresses through load segments 2026-10-10 16:57:31 +02:00
Adrià ebe6c180bf
Merge pull request #2594 from morten-holm/pr/macos-clear-pie
fix(relinker): leave MH_PIE clear in the macOS executable
2026-10-10 11:15:15 +02:00
Adrià 3d1a7d90c7
Merge pull request #2619 from oneandonlydean/fix/carry-2525
fix(relinker): skip repeated DT_NEEDED libraries
2026-10-10 11:01:22 +02:00
Yassine 6158444f71 fix(relinker): leave zero-filled PT_LOAD memory out of Windows files
WindowsPeWriter stored every PE section with SizeOfRawData equal to its
virtual size, so the zero-filled tail of a PT_LOAD segment (p_memsz above
p_filesz, the .bss) was written to the executable byte for byte. A segment
with 256 MiB of .bss produced a 269 MB .exe, while the Linux output of the
same image is under 5 KB.

Each section is now stored up to its last non-zero byte, aligned to the file
alignment, and VirtualSize keeps the full size. The PE loader zero-fills the
part of a section beyond SizeOfRawData (Microsoft PE format, section table:
SizeOfRawData). A section with no non-zero byte gets no raw data and a zero
PointerToRawData.

windows_bss relinks an image with 64 MiB of .bss, checks the section table
and the mapped image, and on Windows runs the executable, which reads the
last word of the .bss.
2026-10-10 21:23:19 +13:00
Hannah Lyons 0e03ad0f95 fix(relinker): skip repeated DT_NEEDED libraries 2026-10-10 21:23:19 +13:00
Dean edbf36ad4c
Merge pull request #2574 from oneandonlydean/fix/carry-2464
fix(relinker): start Windows executables in their own directory
2026-10-10 20:07:53 +13:00
Morten Holm 31b6af028f fix(relinker): leave MH_PIE clear in the macOS executable
The executable is linked at a fixed base with a __PAGEZERO that fills the space below it, and
the guest assumes 16 KB pages. With MH_PIE set dyld slides the image by a multiple of 4 KB,
which breaks that assumption and ends in a SIGBUS (KERN_PROTECTION_FAILURE) in about half of
the launches under Rosetta 2. Clearing the flag keeps the image at its linked address.

test_macos_output.py now reads the header flags and checks that MH_PIE is clear.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 09:07:14 +02:00
Adrià 653e3d04d7
Merge pull request #2097 from treuenten/fix/relinker-entry-stub-rel32
fix(relinker): reject a Linux entry stub whose call cannot reach the entry
2026-10-10 08:49:35 +02:00
Get-fix 975475929e fix(relinker): start Windows executables in their own directory
The guest filesystem root and the save data directory are taken from the
current directory, so an executable started from another directory does
not find its title files and keeps saves elsewhere. Make the executable
directory the current directory in the Windows entry stub before the
system libraries are loaded.
2026-10-10 19:44:06 +13:00
Adrià 8f693fc82c
Merge pull request #2274 from jweidenh/codex/fix-linux-program-header-count
fix(relinker): count all synthetic Linux program headers
2026-10-10 08:32:53 +02:00
simonbbby fcb0b962a7 fix(relinker): collect init and fini array roots through the containing load segment
The unused-filter=1 entry point collector translated DT_INIT_ARRAY and
DT_FINI_ARRAY through PT_DYNAMIC and skipped arrays placed before it, which is
the usual linker layout, so constructors and destructors were not roots and
imports used only by them were dropped. Arrays are now translated through the
PT_LOAD that holds them, slot targets come from RELATIVE relocations when
present, and DT_PREINIT_ARRAY is collected as in the strict filter.
2026-10-10 08:25:50 +02:00
Adrià 019ca236fb
Merge pull request #1958 from arcwiser/fix/windows-pe-relocs-stripped
fix(relinker): keep Windows images without relocations loadable
2026-10-10 08:06:20 +02:00