Repository navigation
fix(relinker): read the PS4 needed-module tag in guest modules - #6381
Conversation
The guest reader took a module's import modules only from 0x61000045, the PS5 needed-module tag. PS4 modules list them in 0x6100000f (DT_SCE_NEEDED_MODULE), so every import of a PS4 module had no library and bound to any guest export with its NID. In the libc.prx and libSceFios2.prx that Until Dawn (CUSA02636) bundles, a libc.prx import then bound to libSceFios2.prx, and the conversion failed with "Cyclic guest initialization dependency: libSceFios2.prx". The reader now also reads 0x6100000f, with the same layout (module ID in bits 48-63, name offset in the low 32 bits). A module that has both tags fails with "Guest module mixes PS4 and PS5 needed-module tags". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@SandstromPL Checked:
AI-assisted: yes (Claude Code). I ran the builds, conversions and samples myself on Windows 11. 🤖 Generated with Claude Code |
|
@Get-fix Thanks for running the samples! I've added your results to the description. That On the bot's note: it couldn't compare
|
jotitadev
left a comment
There was a problem hiding this comment.
Ran this on macOS. The new test converts with the Linux and --windows targets only, so I also checked the --macos output.
Setup: Apple M2 Max, macOS 27.2, head 6f8d9a09d merged without a commit onto main b7cedd900 (clean). Relinker-only Release builds for arm64 and for x86_64 under Rosetta (/usr/bin/python3 3.9.6).
- Full relinker-only suite: arm64 173/173. x86_64 170/173; the 3 failures (
pr_overlap_tools,release_package,linux_fixed_base) fail the same way onmain(Python 3.9 issues unrelated to this PR). guest_symbol_nameswith only the test changes applied tomainfails on both arches (theguest-declared-ps4case still getsshared#guest); with the fix it passes.
--macos, using the test's libc.prx / libSceFios2.prx pair with each tag:
main:0x61000045converts;0x6100000ffails withCyclic guest initialization dependency: .../libSceFios2.prx, the same stop as on Windows.- This PR: both tags convert, and the Mach-O load commands are identical for the two tags.
output.elfloadslibc.prx.guest.prxbeforelibSceFios2.prx.guest.prx, andlibSceFios2.prx.guest.prxhas@loader_path/libc.prx.guest.prx, so dyld initializes libc first.
Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.
|
@jotitadev Thanks for the macOS run, and especially for checking |
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
Second-title data point: Hasbro Family Fun Pack (CUSA03312, my own dump) needs this PR, on Linux and Windows. Relinker-only Release build, Windows 11 Pro 26300, WinLibs GCC 15.2.0 r7. Starting from The other members each stop at their own step, so every one of them is needed for this title; the whole table is on #6977. AI-assisted: yes (Claude Code) |
What
Until Dawn (CUSA02636) bundles
libc.prxandlibSceFios2.prx(01.00). Their conversion stops inGuestModuleBuilderwith:SuperCatElvis reported it on #3093 as stop 8 of the title's
--windowsconversion, onmaind92a8da. He had the open #5138 applied and scratch fixes for his other stops: "these modules list their dependencies in 0x6100000f, not 0x61000045; falling back to it fixes the order".GuestImageReadertakes a guest module's import modules only from0x61000045, the PS5 needed-module tag. PS4 modules use0x6100000f(DT_SCE_NEEDED_MODULE) instead. Both tags have the same layout: module ID in bits 48-63, a version in bits 32-47 (not read here), name offset in the low 32 bits. Sources:Elf.hL86-L87). It decodes them with one function (RuntimeLinker.cppL300-L315, called at L1367-L1368).linker.cppL688-L705).create-fselfwrites one0x6100000Fper imported module (PS4Constants.goL25,OELFGenDynlibData.goL992-L997), in that layout (L882-L888).The reader already accepts both forms of the export tag (
0x6100000dand0x61000043).So no import of a PS4 module had a library, and each bound to any guest export with its NID. A
libc.prximport declared from another module then bound to an export oflibSceFios2.prx, which itself needslibc.prx, and the initialization order became a cycle.The reader now also reads
0x6100000f, so a PS4 module's imports are tied to their declared modules, as a PS5 module's already are. A module that has both tags fails withGuest module mixes PS4 and PS5 needed-module tags. Kyty (RuntimeLinker.cppL1363) and RPCSX (linker.cppL803-L806) reject that too.This changes how PS4 modules are converted, including modules built with OpenOrbis
create-fself. Each change is what PS5 modules already get:DT_NEEDEDis no longer bound by NID across all modules.libc.prxif the program's library list has it, and forlibSceLibcInternal.prxalso in a bundledlibc.prx(WindowsEntryStubBuilder.cppL155-L165). Before, every loaded library was searched.Failed to load module, where before it was skipped.unresolved ELF import.libSceDiscMap.prxfunctions thatlibSceFios2.prximports. A separate PR will add that library.DT_NEEDEDstill binds by NID alone, as before. On Windows, a host library with that module's name (up to the first dot, ignoring case) becomes a required load.Unknown import module ID: the ID has no needed-module entry.Invalid qualified import,Invalid import module ID,Invalid import module nameorDuplicate import module ID.Ambiguous import module dependency: the declared module matches twoDT_NEEDEDnames.Not changed: executables.
RelinkerPipelinestill reads only0x61000045, so the imports of a PS4 executable keep binding by NID alone; no title needs that yet.Tested
Ubuntu 24.04, GCC 13.3, Release with
BUILD_TESTING=ON, onmain97aac62. Locally the libusb submodule isn't checked out, so I removed its two lines fromCMakeLists.txt.libSceUsbdthen fails to compile, andninja -k 0built everything that does not depend on it.guest_symbol_names(relinker/tests/test_guest_symbol_names.py) gains these cases:libSceLibcInternal.prxthrough0x6100000f, next to a guest module exporting the same NID0x61000045sce_module/libc.prxexports X and imports Y fromlibkernel.prx;libSceFios2.prxexports Y and imports X fromlibc.prx(the shape of stop 8), with0x6100000f, Linux and Windowslibc.prx's import of Y stays a host import,libSceFios2.prx's import of X binds tolibc.prx, andlibc.prxcomes beforelibSceFios2.prxin the executable'sDT_NEEDED0x61000045(control)mainGuest module mixes PS4 and PS5 needed-module tags#A#C(module ID 2, not listed) through0x6100000fUnknown import module IDlibFoo) is not in itsDT_NEEDED(libFoo2.prx), through0x6100000fshared#guest), as onmaintest_windows_import_modules.py'sconsumer()gains aneeded_module_tagparameter (default0x61000045), so existing callers are unchanged.On
main:shared#guestinstead ofshared.Cyclic guest initialization dependency: .../sce_module/libSceFios2.prx, the line in the report.With the change all cases pass, and so do
windows_import_modules,guest_module_identityandguest_registry(which useconsumer()), 5 runs out of 5. The Windows required-load behaviour comes from the existing code path for PS5 modules (WindowsEntryStubBuilder.cpp); no new test checks the load order.Other checks:
cteston the RTX 3050 Ti: 1,253 of 1,257 pass, and all relinker tests pass.agc_driver_stencil_ref_exporton this GPU, and the VideoOut flip and frame-dump tests, which need a display.patched_librariesandguest_usbdare Not Run, because the libusb submodule isn't checked out.agc_pending_key_storesfails onmainsince perf(agc): clear a register fast clear without waiting for a known key store #6247, as reported there.agc_driver_store_over_untrackedfails intermittently when run alone here.mainf633042 with fix(relinker): search libc.prx for libkernel-only Windows executables #5990 to fix(relinker): stop module syscall scans at the PLT and skip the PS4 loader path #5994, fix(relinker): accept section-relative guest module relocations #5138 and feat(libSceFreeType): implement the six FreeType functions OpenOrbis samples use #6376.using_librarystill starts and calls intolibExample.prx, acreate-fselfmodule withDT_NEEDED libkernel.prxand one0x6100000fentry. Its import stubs now namelibkernel.prx.__error, which AnyPS5 exports fromlibc.prx, still resolves through thelibc.prxstep.sce_module.mainb7cedd9, relinker-only builds for arm64 and for x86_64 under Rosetta.main.guest_symbol_namesfails onmainwith only the test changes, and passes with the fix.--macos, which the new test doesn't cover,mainstops the0x6100000fpair with the same cycle. With this PR both tags convert, the Mach-O load commands are identical for the two, and dyld initializeslibc.prxfirst.main4186f06. Six open PRs touch these files (fix(windows): enter guest startup on an arena-backed main stack #3965, fix(relinker): accept section-relative guest module relocations #5138, fix(relinker): preserve DF_SYMBOLIC on guest modules #5981, fix(relinker): run guest preinit arrays before the module initializer #6112, refactor(relinker): remove functions nothing calls #6325, fix(relinker): accept matching defined relative symbols #6357), and none of them gets a new conflict.main, incore/relinker/CMakeLists.txtanddocs/dev/debt/relinker.md, and has the same two conflicts with this PR merged. ItsGuestImageReader.cppline is in the lifecycle-array block, apart from this PR's hunks.main4186f06, this PR and fix(relinker): run guest preinit arrays before the module initializer #6112 passes all 182 relinker tests, including fix(relinker): run guest preinit arrays before the module initializer #6112'sguest_preinit.tools/check_conventions.pyfrommainpasses with this title and body.@Get-fix, thanks for running the OpenOrbis samples. @SuperCatElvis, could you check that this gets
libc.prxandlibSceFios2.prxpast stop 8, and say whichlibc.prximport resolved tolibSceFios2.prx?Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)libc.prxandlibSceFios2.prx); CUSA03312 Hasbro Family Fun Pack (CUSA03312) #7198 (Hasbro Family Fun Pack: stop 7 in savvaniss's conversion); CUSA02636 (no Game bring-up discussion): stop 8 of SuperCatElvis's--windowsconversion on Relinker rejects PS4 executables: SCE dynamic tables and data in the code segment (two ready branches) + remaining PS4 work #3093, in the bundledlibc.prxandlibSceFios2.prx.main. A full conversion scans the eboot first, and stop 1 (its jump tables) still stops it there.cteston NVIDIA GeForce RTX 3050 Ti Laptop GPU, driver 580.178.04, Ubuntu 24.04🤖 Generated with Claude Code