ELF and SELF loading
The loader maps decrypted PS5 SELF and bare ELF64 modules, applies relocations, and resolves imports against the HLE registry. The title then receives stable handles for modules it starts itself.
Repository notes through October 10, 2026
Images
A PlayStation 5 executable is usually a SELF container around an ELF64 image. PS5PCEM reads both the container and a bare ELF. The reader collects imports, maps segments into the reserved guest address space, and applies relocations. TLS images are registered with the threads that will run them.
The tooling can inspect a module, dump a relocated dependency graph, or disassemble a shader without starting the title. game-run is the path that loads, initializes HLE, and enters the guest. When the decrypted eboot.bin lives apart from the install, --app0 points the read-only mount at the content directory.
Modules the title starts later
The runtime maps the reachable dependency graph, plus anything named in PS5_PRELOAD, before guest code runs. sceKernelLoadStartModule then returns a stable handle for a module in that set. Loading it again does not create a second relocated copy. sceKernelDlsym hashes the name the title passed and searches only the module the handle selected, so two plugins that export the same callback do not alias.
Path matching ignores slash direction and case. One observed title asks for Il2CppUserAssemblies.prx and ships Il2cppUserAssemblies.prx. An exact match would refuse a file the title installed. The relative path is tried before the bare file name, so two modules that share a file name stay distinct. A module that was not in the published set returns ENOENT. It is not mapped while guest threads are already running.
Unity plugins
Unity plugins can be mapped with their constructors deferred. sceKernelLoadStartModule then starts them once, with the title's real argument block, instead of running those constructors during graph initialization. That ordering is the difference between a plugin that sees its arguments and a plugin that starts too early.
The loader does not decrypt a retail SELF. The input is a decrypted image the user is entitled to load. Encrypted packages are the PKG tool's problem, and retail encryption is outside that tool as well.
What is implemented
- ELF64 and decrypted SELF mapping, relocation, imports and TLS.
- A preloaded dependency graph and stable sceKernelLoadStartModule handles.
- Dlsym limited to the selected module, with case-insensitive path matching.
- Deferred constructors for Unity plugins so they start with the real arguments.
What is still missing
- A module that appears only after startup, and was not preloaded, returns ENOENT.
- Encrypted retail SELF images are not decrypted.
- Inspection builds do not execute the loaded image on non-Windows hosts.
Related mechanisms
What these pages are