3.7 KiB
Phase 1.0B runtime and exit contract
Status: source-bound offline contract; firmware-9.60 behavior remains unproven until a separately authorized one-shot run.
Stateful lifecycle
The status record tracks platform, frontend, SDL, video, input, audio, core,
threads, buffers, direct memory and device handles. Initialization records
each subsystem once in a bounded stack. Cleanup may touch only an initialized
bit, runs once, and verifies reverse order. An order violation is sticky
E120, duplicate init is E119, duplicate cleanup is E121, and a cleanup
failure is E122. Host fault injection covers every partial-init boundary,
every per-subsystem cleanup failure and an out-of-order cleanup.
Video cleanup stops future flips, destroys the software surface and event queue, closes VideoOut, releases direct memory, then clears handles. Input cleanup closes Pad before its state is cleared. Audio cleanup stops the SDL worker before AudioOut close and records the elapsed cleanup time. The pinned public SDL source exposes release of direct memory but no separately evidenced direct-memory unmap primitive; this remains a declared cleanup uncertainty.
Exit alternatives
| Option | Exact evidence | Destructors/cleanup | Continuation | Decision |
|---|---|---|---|---|
return from main |
SDK crt/crt.c:133-146,153-170,196-220 |
SDK .fini runs |
a hijacked process returns through the synthetic address placed by elfldr | rejected |
payload_exit |
SDK crt/crt.c:174-180, payload.h:45-51 |
long-jumps into CRT | still reaches payload_terminate; hijacked route returns |
rejected |
libc exit |
imported and used by SDK payload_terminate only for a non-hijacked process |
libc exit semantics; would bypass the remaining SDK payload path when called directly | process termination expected | not selected |
libc _Exit |
public libc import in the final ELF; direct call from smoke main |
all RetroArch/SDL cleanup runs first; no process destructors after call | no synthetic return | selected |
The selected method is compile-time
CHIMERA_PS5_EXIT_PROCESS_EXIT=1. After rarch_main completes,
main sets S15 and reaches one smoke-owned _Exit(result) call.
The smoke SDL overlay disables the dynamic API and sets
SDL_ASSERT_LEVEL=0, removing SDL's secondary SDL_ExitProcess callsites.
Disassembly and the undefined-symbol inventory bind this decision. It does
not reboot, launch another process, retry or write a device file. The SDK CRT
still imports exit for its own pre-main initialization-failure
termination; that separate startup path is not represented as the selected
smoke exit.
Loader relationship
Hardened elfldr commit 197623058f509eddde18868dafcb92fdcac66464
spawns a separate child, writes the pre-injection RIP to rsp-8, enters the
payload at _start, and on the controlled route waits under a bounded
watchdog (elfldr.c:381-410,643-768;
socksrv.c:128-157; ps5_controlled.c:186-215). _Exit terminates that
child instead of resuming the synthetic continuation.
This is stronger source evidence than returning, but it is not device evidence. Remaining exit risks are:
- SDK CRT initialization and temporary runtime patches occur before
main; - SDK CRT startup resolves runtime-loader functions and may conditionally
load
libSceSysmodulebefore entering RetroArch; - firmware-9.60 libc
_Exitbehavior in this exact injected child is unobserved; - a blocked AudioOut call or SDL join can prevent reaching
_Exit; - the controlled loader route itself is not authorized or exercised here;
- ending the child can end the current host/jailbreak session, which is a session risk rather than an installation guarantee.
No execution-review bundle has been produced.