Repository navigation
feat(libkernel): start runtime-loaded modules with their arguments on Linux - #2323
Closed
hugodearaujo wants to merge 3 commits into
Closed
hugodearaujo wants to merge 3 commits into
hugodearaujo wants to merge 3 commits into
Conversation
Unity titles load native plugins from Media/Plugins with sceKernelLoadStartModule; they are neither in a module directory nor needed by the executable, so they stayed unrelinked and the load failed (PPSA12544: DllNotFoundException for 'PSN', /app0/Media/Plugins/PSN.prx). --module-dir <dir> adds a directory relative to the input whose ELF modules are relinked like the bundled ones, with their outputs at the same relative path. The directory must exist inside the input directory and differ from the others. These modules are not initialized at startup: the writer exports their DT_INIT entry as __aps5_guest_initialize, and sceKernelLoadStartModule calls it with its args and argp and returns the result in *res, as the plugins check that argument (PSN refuses to start without it). On Linux they are left out of DT_NEEDED. AI-assisted: yes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Module
On Linux the host loader runs a module's initializers at dlopen with the
host process arguments, so the args and argp passed to
sceKernelLoadStartModule never reach a module that checks them (Unity's
PSN plugin refuses to start without its {16, 0x200, ...} block), and
*res stays 0. Passing start arguments now throws there until deferred
initialization exists on Linux; Windows is unchanged. TechnicalDebt
records the gap.
AI-assisted: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… Linux Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 tasks done
9 tasks done
|
Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.
|
Contributor
|
Tested on Linux (CachyOS x86_64, Intel RPL-S iGPU / Mesa 26.3.0-devel / Vulkan 1.4.363, GCC 16.2.1) at
LGTM! |
9 tasks done
13 tasks
This was referenced Oct 9, 2026
Collaborator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Depends on #846. This branch contains its two commits. Only the last commit,
feat(libkernel): start runtime-loaded modules with their arguments on Linux, belongs to this PR.#846 starts
--module-dirmodules fromsceKernelLoadStartModulewith the call'sargs/argpon Windows. On Linux, the host loader runs theirDT_INITatdlopenwith zeroed arguments, so #846 throws there when start arguments are given. This PR does on Linux what #846 does on Windows, with the same table:--module-dirgets noDT_INIT,DT_INIT_ARRAY,DT_FINIorDT_FINI_ARRAY. Like the Windows.ginitsection, it exports__aps5_guest_initialize: the initializer's address, the number ofINIT_ARRAYslots, and each slot's address. The symbol is added to the module's dynamic symbol table and hash. Modules fromsce_module/prxare written as before.dlopen,OpenModulelooks up__aps5_guest_initialize. It takes the module's load bias fromdl_iterate_phdrand calls the initializer once with(args, argp, nullptr). It stores the return value in*res, then runs theINIT_ARRAYslots. The table walk and the "only once per module" set are now shared with the Windows path, which keeps its behavior. TheNotImplementedfor start arguments on Linux is removed.Evidence: Hollow Knight: Silksong (PPSA12544) on Linux
Unity loads its plugins from
/app0/Media/PluginswithsceKernelLoadStartModule, andPSN.prxis started with start arguments. All runs below are relinked with--module-dir Media/Plugins, onmaind70b89989+ #1836 + #1431 (the title stops before the plugins without them) + #846:terminate ... what(): sceKernelLoadStartModule with start arguments not implemented.PSN.prxstarts. The next stop is in the title's bundledlibSceNpCppWebApi:CppWebApi::Common::initialize() failed. ret = 0x80553504, then an uncaughtUnity.PSN.PS5.PSNExceptionwith that code.Common::initializemaps flexible memory and passes it to the bundled libc'ssceLibcMspaceCreate, which refuses the address on Linux. That is the address-window problem of fix(guest-arena): place guest address space in the PS5 window on Linux #861, not this change.Tested
ctest464/464 on this branch.guest_module_dirgains a Linux case. A--module-dirmodule withDT_INIT,DT_FINIand oneINIT_ARRAYslot is written without those tags. It exports__aps5_guest_initializeas a 12-byte object holding(0x1000, 1, 0x2380). The same module undersce_modulekeeps its tags and has no such symbol. The test fails on feat(relinker): add --module-dir for modules loaded at run time #846 without this commit.guest_dynamic_loadergains a Linux case with a host fixture module that exports the table.GuestLoadStartModule_nid_no_patchwith 16 bytes of arguments must call its start function once with thoseargs/argp, store its return value (7) in*res, and run theINIT_ARRAYslot once. Loading the module a second time must not run either again. The test aborts on feat(relinker): add --module-dir for modules loaded at run time #846 without this commit, on itsNotImplemented.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)@merwie: you mentioned you can't build the Linux path. If you'd rather carry this in #846, take the commit and I'll close this one.
🤖 Generated with Claude Code