Repository navigation
fix(relinker): keep Linux imports declared from host modules off guest exports - #1529
Conversation
klosixgaming-arch
left a comment
There was a problem hiding this comment.
Excellent fix for a subtle but important relinker issue. The problem of guest modules incorrectly binding to imports declared from host modules is well-documented and the solution is clean.
Strengths:
- Clear identification of the root cause:
GuestModuleBuilderwas renaming all imports matching exported NIDs regardless of declaring module - Proper use of relocation table scanning to determine import module provenance
- Comprehensive test coverage including real-world DOOM example (PPSA99666)
- Good overlap analysis with other open PRs (#1462, #1403, #1249)
- Thorough testing on both Linux and Windows
Technical notes:
- The
declaresHostlambda is a clean way to encapsulate the host vs. guest module distinction - Building the
executableModulesmapping from relocation tables is the right approach for determining import provenance - Test cases properly cover both executable imports and guest-module imports with qualified NIDs
This will significantly improve compatibility with titles that bundle libc.prx loader shims. Ready to merge.
|
Confirmed on Linux with a display and a discrete GPU, on top of current
AI-assisted: yes (Claude Code); the runs and counts above were checked by hand. |
|
This conflicts with main after today's merges; could you rebase? It's otherwise ready. |
d06fafd to
abb5c46
Compare
|
Merged with current main, Since #1102 every guest module also imports those two |
|
I reproduced the reported current-main failure on |
|
@johnmaia @oneandonlydean the rebase and the test change asked for above are on
TestedmacOS 26.7.1 (Apple silicon M2), Apple clang 21.0.0, relinker-only Release build:
Not tested: Linux and Windows runs (no such host here). AI-assisted: yes |
…t exports On Linux every executable or guest-module import whose NID a guest module exports was renamed to the guest-suffixed name, whatever module the import declares. A title that bundles a module exporting system NIDs then had those imports bound to it: the libc.prx loader shim of ps5-native-app-boilerplate exports placeholder functions under the libSceLibcInternal NIDs, so DOOM PPSA99666's snprintf, vsnprintf, memcpy and malloc (declared from libSceLibcInternal) returned 0 and the title never found its WAD (boykopovar#1497). An import now binds to a guest export only when the module it declares is a guest module, as on Windows. Imports without import-module metadata keep the previous behaviour, and a title's own libc.prx imported from libc still binds to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the module's only import
|
Rebased on current
Checked: relinker build + 89 relinker tests green on the rebased tree; |
abb5c46 to
36ffda9
Compare
What
Fixes #1497.
On Linux,
GuestModuleBuilderrenamed every import whose NID a guest module exports to its guest-suffixed name, whatever module the import declares: the executable's imports (GuestModuleBuilder.cpp:180onmain) and the guest modules' own (:218). A title that bundles a module exporting system NIDs then had those imports bound to it.DOOM PPSA99666 declares
snprintf,vsnprintf,strlen,memcpy,mallocandfopenfromlibSceLibcInternal(#G#H, module 7) and nothing fromlibc. Thelibc.prxloader shim it bundles (ps5-native-app-boilerplate) exports placeholder functions under the same NIDs, so 71 imports became<nid>#guestand returned 0: no notification text, 27 opens of uninitialized paths, no WAD. Windows already binds by the declared module (WindowsEntryStubBuilder) and was not affected.An import now binds to a guest export only when the module it declares is a guest module:
ImportModulesthrough its relocation. A symbol declared from a module that is not a guest keeps its plain name and binds to the host library.GuestSymbol::Library; such an import is not searched among guest exports, renamed, or counted as a guest dependency.libc.prximported fromlibcstill binds to it, as in 7103f39 andtest_guest_host_libc.py), and Windows (declaresHostis false there).test_guest_symbol_namesgets two cases, using the qualified-import fixtures fromtest_windows_import_modules: an executable that declares one NID fromlibc(a guest) and one fromlibSceLibcInternal(a host), both exported by the guestlibc.prx; and a guest module importingsharedfromlibSceLibcInternalwhile another guest exports it. Onmainthe first fails with{'EEEEEEEEEEE#guest', 'AAAAAAAAAAA#guest'}.Overlap: #1462 edits the lines next to the executable import loop, so whichever merges second needs a small rebase. #1403 and #1249 merge cleanly.
Tested
ctest433/433, and the 152 guest/relinker tests again on the final revision;guest_symbol_namesfails onmainwith the new cases and passes with this change.windows_import_modules) again on the final revision.eboot.binandlibc.prx), relinked with its bundledlibc.prxand no--exclude-sce-module, on this branch plus feat(libkernel): implement poll for guest sockets #1278 (poll), fix(libkernel): accept MSG_NOSIGNAL in send and sendto #1279 and fix(libkernel): translate scalar POSIX I/O errors #1307: 0 imports bound to the guest module (71 onmain); the title opens/app0/wads/doom1.wadand stops at window creation on this headless machine, as with--exclude-sce-module libc.prx. Not run to E1M1 here (no display).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)poll)🤖 Generated with Claude Code