You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
libSceSystemService: RetroArch (PPSA99169) stops on sceSystemServiceLoadExec("/app0/picker/picker.bin"), a second executable the title ships #4793
Title: RetroArch PS5 (PPSA99169, catalog record v1.0.0-beta.1, release ZIP checked against its sha256). Host: Linux (Fedora 44, kernel 7.2.9), GCC 16.2.1, AMD RX 9060 XT (RADV, Mesa 26.2.4). Run in a rootless Podman container without network. Build:mainee49621 with the logging fix of #4792 applied (without it the stop leaves no message, see there), Release, -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON. eboot.bin and sce_module/ unwrapped from their SELF containers, relinker --registry.
Where it stops
At start-up, every run:
[libc] unhandled exception 'St13runtime_error' thrown from 0x...
terminate called after throwing an instance of 'std::runtime_error'
what(): sceSystemServiceLoadExec: executable replacement not implemented
The title's eboot.bin is a front end. Its trace (app0/trace.txt) shows it choosing the picker:
frontend: mode '', test run 0, picker test 0, picker 1, es-de 1, remembered ask, L1 0 -> picker
and it then calls sceSystemServiceLoadExec (gdb at the call, rdi/rsi):
path: /app0/picker/picker.bin
arguments: two entries, a pointer to an empty string, then NULL
The release ships three executables, all SELF containers whose ELF type is 0xFE10: eboot.bin (38.9 MB), picker/picker.bin (29.6 MB) and es-de/es-de.bin (48.2 MB). (webui/ps5-retroarch-webui.elf is a plain ET_DYN ELF, not passed to LoadExec.)
#1525 implemented sceSystemServiceLoadExec("/app0/eboot.bin", argv) as a restart of the running title (Linux: execv("/proc/self/exe") after LibcRunShutdown; Windows: a new process that waits for the old one) and was closed because no title reached the call. This title reaches it with a different executable, which #1525 left throwing because the relinker converts only the title's executable.
Proposal
Relinker: convert the other executables a title ships, as --module-dir does for modules, for example a repeatable --executable <path> (relative to the module parent) that writes the converted executable next to the converted modules under app0/, with the same libs/ rpath.
Opened #4925 for the narrow diagnostic gap: unsupported sceSystemServiceLoadExec calls now include the requested path in the exception, with a regression check for /app0/picker/picker.bin.
This does not implement conversion or process replacement for secondary executables, so #4793 remains open for that behavior.
Reproduced on Windows 11 (MinGW GCC 15.2.0, main510a218, catalog record v1.0.0-beta.1 checked against its sha256): the first call is sceSystemServiceLoadExec("/app0/picker/picker.bin", {"", NULL}), read with gdb at the call (rdi, rsi). I'd like to take this on; here is what the title needs and a plan, with one question before I write it.
So the argument list holds only arguments (no program name), and both the second executables and the eboot.bin restart with arguments are reached. eboot.bin finds its mode by scanning every argv entry for --ps5-mode=, so whether the console puts the path in argv[0] doesn't decide this title.
Runtime facts that shape the design:/app0, /data and /download0 resolve against the working directory, and on Windows the library path ($ORIGIN becomes .) and the guest module paths are working-directory relative too. A second converted executable started with the same working directory therefore sees the same app0. The Windows entry stub already turns the host command line into the guest argv (CommandLineToArgvW), so LoadExec arguments can be passed as command-line arguments.
Plan
Relinker: a repeatable --executable <path> (relative to the module parent, like --module-dir) runs the pipeline for that ELF too and writes it as app0/<path>.exe on Windows (app0/<path>.elf on Linux), beside the original's directory.
sceSystemServiceLoadExec: "exit" as today; /app0/eboot.bin restarts the main executable; any other /app0/... path starts its converted executable if it exists, else throws with the path (as test(libSceSystemService): retain rejected LoadExec paths in errors #4925 reports it). The arguments go on the new process's command line. The old process runs the guest shutdown and exits without waiting, so its direct memory is released before the new one allocates (Windows: CreateProcessW with the inherited working directory; Linux: execv). feat: convert a title's other executables and start them with sceSystemServiceLoadExec #4786 is the eboot.bin half of this and would become part of it.
Question: a guest module's conversion depends on the executable that needs it: deferred initialization comes from that executable's dynamic section, so picker.bin and eboot.bin can produce different libc.prx.guest.prx files. Should each extra executable get its own converted module tree (for example app0/picker/picker.bin.modules/sce_module/...), or would you rather have one shared tree with initialization decided at run time?
Implemented in #4786. On the module question: libc.prx.guest.prx comes out byte-identical for eboot.bin, picker.bin and es-de.bin, so the executables share one module tree, and the relinker fails if a module ever converts differently. The extra executables go beside the output (picker.picker.bin.exe) rather than under app0/, because the Windows entry stub sets the working directory to the executable's own directory. The RetroArch picker now starts and hands off in both directions; ES-DE also needs tzname (#5009).
Activity
MarcZX10 commentedon Oct 13, 2026
Opened #4925 for the narrow diagnostic gap: unsupported
sceSystemServiceLoadExeccalls now include the requested path in the exception, with a regression check for/app0/picker/picker.bin.This does not implement conversion or process replacement for secondary executables, so #4793 remains open for that behavior.
p3n1cillin commentedon Oct 13, 2026
Reproduced on Windows 11 (MinGW GCC 15.2.0,
main510a218, catalog record v1.0.0-beta.1 checked against its sha256): the first call issceSystemServiceLoadExec("/app0/picker/picker.bin", {"", NULL}), read with gdb at the call (rdi,rsi). I'd like to take this on; here is what the title needs and a plan, with one question before I write it.The whole chain (source at bead807):
eboot.bin→/app0/picker/picker.binor/app0/es-de/es-de.bin(src/frontend_mode_ps5.cpp)LoadExec(next->next, {next->argument, NULL}), e.g./app0/eboot.binwith--ps5-mode=retroarch(frontends/picker/picker.cpp:445)LoadExec("/app0/eboot.bin", {..., "--ps5-mode=quit", NULL})(frontends/es-de/ps5/main_ps5.cpp:180)So the argument list holds only arguments (no program name), and both the second executables and the
eboot.binrestart with arguments are reached.eboot.binfinds its mode by scanning everyargventry for--ps5-mode=, so whether the console puts the path inargv[0]doesn't decide this title.Runtime facts that shape the design:
/app0,/dataand/download0resolve against the working directory, and on Windows the library path ($ORIGINbecomes.) and the guest module paths are working-directory relative too. A second converted executable started with the same working directory therefore sees the sameapp0. The Windows entry stub already turns the host command line into the guestargv(CommandLineToArgvW), soLoadExecarguments can be passed as command-line arguments.Plan
--executable <path>(relative to the module parent, like--module-dir) runs the pipeline for that ELF too and writes it asapp0/<path>.exeon Windows (app0/<path>.elfon Linux), beside the original's directory.sceSystemServiceLoadExec:"exit"as today;/app0/eboot.binrestarts the main executable; any other/app0/...path starts its converted executable if it exists, else throws with the path (as test(libSceSystemService): retain rejected LoadExec paths in errors #4925 reports it). The arguments go on the new process's command line. The old process runs the guest shutdown and exits without waiting, so its direct memory is released before the new one allocates (Windows:CreateProcessWwith the inherited working directory; Linux:execv). feat: convert a title's other executables and start them with sceSystemServiceLoadExec #4786 is theeboot.binhalf of this and would become part of it.Question: a guest module's conversion depends on the executable that needs it: deferred initialization comes from that executable's dynamic section, so
picker.binandeboot.bincan produce differentlibc.prx.guest.prxfiles. Should each extra executable get its own converted module tree (for exampleapp0/picker/picker.bin.modules/sce_module/...), or would you rather have one shared tree with initialization decided at run time?p3n1cillin commentedon Oct 13, 2026
Implemented in #4786. On the module question:
libc.prx.guest.prxcomes out byte-identical foreboot.bin,picker.binandes-de.bin, so the executables share one module tree, and the relinker fails if a module ever converts differently. The extra executables go beside the output (picker.picker.bin.exe) rather than underapp0/, because the Windows entry stub sets the working directory to the executable's own directory. The RetroArch picker now starts and hands off in both directions; ES-DE also needstzname(#5009).