Files
chimera-gfx-Public/docs/retroarch/phase-1.0b-runtime-and-exit-contract.md
T
Chimera GFX release export a6037502d7
phase0-ci / build-and-audit (push) Successful in 2m14s
Publish Chimera GFX source
2026-09-03 03:27:14 +02:00

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 libSceSysmodule before entering RetroArch;
  • firmware-9.60 libc _Exit behavior 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.