Repository navigation
fix(relinker): skip zero-return guest libc exports for internal libc imports - #2705
Conversation
|
Thank you for your interest in the project! We are sorry, but we cannot accept more PRs while we work through the existing backlog. This PR has been automatically closed and labeled "intake paused". This is not a judgment of the quality of your changes. |
|
Independent Windows check of the zero-return libc fallback fix on Replayed head ceae49c onto its base
The actual guest libc's flockfile export is at PE RVA 0x10050 with bytes This confirms the rejection behavior on another title; it does not unblock that Follow-up (PPSA99902): a controlled local startup stack now provides an actual executed example of the zero-return fallback problem. The ELF's Recheck after merge: PPSA99902 current-main relinker (2026-10-11)Rechecked the merged protection on Windows 11 / RTX 5080 with the relinker source exactly matching pinned main Fresh default conversion of the original PPSA99902 ELF and original guest libc succeeds. Five launches stop before guest entry at With exactly the same refreshed libraries but the prior conversion/guest module, the title still reaches the DCC multisample refusal in 31.986 s. This supports the intended protection: the older conversion's graphics progress depended on a fallback that is not a working libc implementation. No guest invocation of Full build/122 libraries; 823 full-suite passes and 5 documented display/no-Vulkan skips; 73 affected/new groups ×5 = 365 passes, no skips. Relinker/import tests are included in the full suite; no local relinker modification. Every replay restores the exact 123-library baseline population, guest module and original input hashes. No rendering/gameplay or console/Linux equivalence claim. Missing unlocked I/O is already discussed on #1578 and closed unmerged #1765; this is current validation, not a new PR or duplicate issue. AI-assisted investigation: Codex. |
…imports Since boykopovar#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.
|
This conflicted with Checked on Linux on the rebased tree (core/relinker build + ctest, Merging once CI is green on the rebased head. |
ceae49c to
e720d3c
Compare
What
On Windows, a
libSceLibcInternalimport that no native library exports falls back to the title's ownlibc.prx(#1454). Thelibc.prxloader shim that ps5-native-app-boilerplate builds into homebrew titles (#1497) exports 1874 functions at three addresses: 0x30 and 0x40 holdxor eax, eax; ret, and 0x50, where 1872 of them point, holdspxor xmm0, xmm0; xor eax, eax; ret. A missing function then binds to an export that returns 0, and the title starts instead of stopping withunresolved ELF import. The review of #1454 relied on "an absent symbol still fails startup", which does not hold with this shim.The Windows guest module writer now records the exported functions whose code is one of these two sequences (
GuestRuntime::ZeroReturnExports), and the entry stub leaves the guestlibc.prxout of the search for those names. A guest export with code of its own still provides a missinglibSceLibcInternalfunction, as #1454 intended, and native libraries keep their priority. Guest modules' own imports go through the same search, so they are covered too. On Linux the shim intercepts imports through the guest export renaming that #1497 describes and #1529 fixes; this change is Windows only.The problem stayed hidden while a fake-signed
sce_module/libc.prxwas skipped without a message. Since #2605 the module has to be unwrapped, and then these imports bind to the shim on Windows.Homebrew catalog
ps5-homebrew-catalog at
4db487af: 51 release ZIPs downloaded with a matching sha256,eboot.binandsce_module/libc.prxunwrapped from their fSELF containers, relinked with--windows --registryonmainb5f5362,tools/import_audit.pywith--modulesand the libraries of the same build. 42 titles relink; 7 stop onForbidden syscall instruction(#2136) and 2 ship twoeboot.bin.libc.prxwith code behind its exports.libSceLibcInternalimports thatimport_audit.pyreports as absent: 253 imports in all, for exampleatol,rewindand__isinfin Capy Mobile (PPSA92280) andlocaleconvin SymphonyStation5 (PPSA17641).mainand once with this branch. Each stops in the entry stub before any of its code runs. Onmainthe stop is the first absent import that the shim does not export; with this change it is the first absent import. 20 of the 41 stops change. ProsperoRadio (PPSA99001) stops on its missinglibSceOpusCeltDec.prxeither way, and DOOM (PPSA99666) has no absent import and was not started.main_umtx_op(04AjkP0jO9U)localeconv(0hlfW1O4Aa4)utime(1nTKA7pN1jw)ctime(0uAUs3hYuG4)_fstatfs(17Mfe1B3X6U)nextafterf(3m2ro+Di+Ck)utime(1nTKA7pN1jw)ctime(0uAUs3hYuG4)utime(1nTKA7pN1jw)rewind(3QIPIh-GDjw)dup(iiQjzvfWDq0)__fpclassifyd(qlWiRfOJx1A)utime(1nTKA7pN1jw)atoll(fLcU5G6Qrjs)utime(1nTKA7pN1jw)atoll(fLcU5G6Qrjs)_umtx_op(04AjkP0jO9U)flockfile(hGljHZEfF0U)arc4random_buf(n1KOc0lTUEs)__isinf(V02oFv+-JzA)_umtx_op(04AjkP0jO9U)atol(+my9jdHCMIQ)pthread_set_name_np(oxMp8uPqa+U)atoll(fLcU5G6Qrjs)alarm(DQXJraCc1rA)__isinf(V02oFv+-JzA)sceAudioOutExGetMonitorInfo(PhnNN0UEV6Y)__isinf(V02oFv+-JzA)sceAudioOutExGetMonitorInfo(PhnNN0UEV6Y)__isinf(V02oFv+-JzA)getifaddrs(j-gWL6wDros)localeconv(0hlfW1O4Aa4)dup2(wdUufa9g-D8)llroundf(eQhBFnTOp40)freeifaddrs(N2OjwJJGjeQ)__udivti3(802pFCwC9w0)getifaddrs(j-gWL6wDros)atol(+my9jdHCMIQ)sceAudioOutSysGetHdmiMonitorInfo(Tf9-yOJwF-A)atoll(fLcU5G6Qrjs)19 of these titles are in the Linux table of 2026-10-10 in #1578, and for each of them the new stop is the one listed there.
Tested
Windows 11 Pro (26200), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release, full build with
BUILD_TESTING=ONon b5f5362:ctest706/706.windows_import_modulesgets three cases. A guestlibc.prxwhosesharedexport isxor eax, eax; retorpxor xmm0, xmm0; xor eax, eax; ret, with no native provider, must stop withunresolved ELF import shared. With a nativelibSceLibcInternal.prxexport, the native one still wins. Without the entry stub change, both zero-return cases start and exit with 0, the export's return value. A mutant that drops thepxorsequence and one that treats every export as zero-return both fail the test; the second stops the existing guest-only case.tools/check_conventions.py --base upstream/main,tools/check_test_registration.pyandtools/pr_overlap.py --branchpass.Linux and macOS not run here. The new cases execute only on Windows, like the existing ones in
check_internal_guest_libc.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)