D402 - A stub that returns from exit turns a clean shutdown into a crash

measured - 2026-08-30

With the landing zone in place (D400), elfldr runs its whole startup and then stops on its own ud2. Reading the strings it resolves says exactly what happened, and none of it is a guess:

what it resolves what it does with it
sceKernelDlsym bootstraps its resolver, through handoff field zero
getpid takes the address, adds ten, and that is its syscall entry
exit calls it with a status, and places ud2 after the call

Between the second and the third it calls syscall 649 to bring up its runtime linker, gets nothing (this implements no such call), prints Unable to initialize rtld, writes the status through handoff field five, and exits.

So the run is not crashing. It is shutting down cleanly, for a reason it states, and then crashing only because exit came back.

Why ud2 after a call is worth recognising generally

A compiler emits an undefined instruction after a call it has proved cannot return. It is the program saying if you are reading this, the thing I just called broke its contract. That makes it one of the few places a guest gives an unambiguous verdict on the emulator rather than on itself - and this project has been reading it as an ordinary fault.

Every stub here returns, because a stub is a function and functions return. For the great majority that is right. For the handful that must not - exit, _exit, abort, a thread's final call - returning does not merely give a wrong answer, it resumes a program that had finished, at an instruction chosen to be invalid.

What this does not do yet

Nothing is implemented here. The finding is that a stub needs a way to be terminal, and the shape of that is not obvious enough to assume: ending the guest thread, unwinding to the worker, and reporting a clean exit are three different behaviours, and the difference between "the guest exited with status 0" and "the guest crashed" is exactly the sort of thing this project must not get casually wrong. elfldr also exits with a non-zero status here, so the first implementation would be reporting a failure - which is correct, and would look like a regression in every report that counts faults.

Recorded so the next person meets the question rather than the ud2.