2026-08-30 - The constant was a handle, and the wall was an argument

0x2001 had been the thing elfldr and pldmgr die on for three sessions, established as invariant to every handoff variation and never identified. Two sources settled it within an hour of each other and they agree.

The hardware run said sceKernelLoadStartModule returns small integers for application modules and 0x2001 for a system one - a numbering scheme. The payload's own instructions said the rest: it reads its first argument as a table of function pointers, calls field zero to resolve a name with module handle 1, and falls back to 0x2001 if that misses. The value was never something this project produced. It is a value the payload carries, and it matches what the console returns.

It never got there because the guest was entered with an argument count where it expected a pointer. argc is 1, so call *(%rbx) reads address 1, in the second call of the program.

Handed the resolver table instead: sceKernelDlsym and getpid both resolve, three calls where there had been none, and the fault moves from 0x1 to somewhere with 0x2001 in it - which is the payload finally running its own fallback path.

The part worth remembering

The instrument had been reporting on a structure the guest never received. handoff poisons a field and asks whether the guest used it; it set the poison and nothing else, so every run it made was under whatever entry argument the configuration named - not the handoff. It poisoned fields of a block nobody was handed and said no field was reached.

That is the eighth instrument caught this way, and the shape has never varied: the tool changes one input and assumes the rest of the world is what it has in mind. Worth stating as a check rather than a lesson, because the lesson clearly does not stick - an instrument that varies X must also establish the conditions under which X means anything, and say so if it cannot.

Fixed, it produces the first real structure knowledge for these payloads: field 0 called, 1 and 2 read, 5 written.

The default entry argument is deliberately unchanged. Which one a guest wants is a fact about the guest, and six titles are measured against the current one; choosing per guest needs those six re-measured under it.

A flaky gate, found by accident and worth more than the fix

The gate failed on a loader test reserving pages another test already held. It passed when run alone, which is the tell.

Range::take hands out an address no other caller of that instance will get - the cursor is atomic and concurrent takes are safe. Two tests in relocate.rs each declared static RANGE inside their own function, so each got its own instance, each cursor started at zero, and both handed out the same addresses. Whichever ran second failed to reserve.

The mechanism was correct and the usage defeated it, which is why the comment above each one said the opposite of what was happening: "so two tests running at once cannot reserve the same page". Both tests said that. Both were wrong, in the same file, four lines apart.

Now one static per test module, and take documents the distinction where somebody about to repeat it will read it. The other two crates using this have a single test each and were fine by luck rather than by design.

Worth the space because this project has already written down why an intermittent failure is worse than a plain one: it teaches you to re-run until green. This one would have been re-run until green.