D567 - A placeholder that names its own source
Status: measured Date: 2026-09-04
The problem, stated by the code itself
Every unimplemented function answers the same
0x7fff_0001. So when one turns up in a guest's argument,
the report knows some unimplemented function produced it and
never which - and error_used_as_pointer's action says so
out loud:
find what answered with that code just before
That is a person's search, and D299 already ruled on it: a finding whose action sends a reader looking must carry what they are to look at. The finding was breaking a rule this repository had written down, in the one place the rule was hardest to keep.
It cost real memory to not have. A work-area sizer answered the
placeholder and PPSA28061 handed it to malloc
twice - four gigabytes - and all the report could offer
was the three calls before it (D564).
The decision
An opt-in diagnostic, ORBISTOUN_TAG_PLACEHOLDERS. Under
it a stub answers 0x7fff_0000 | (0x10 + its stub slot), so
the value is the attribution.
Measured working - each unimplemented function now answers a distinct code:
sceCommonDialogInitialize -> 0x7fff0091
sceAgcDriverRegisterDefaultOwner -> 0x7fff021a
sceAgcCreateShader -> 0x7fff0225
libkernel::0x04df812afad225d7 -> 0x7fffbeac
The trace already indexes every call by the stub it landed on, and that is the same numbering the tag carries, so a value resolves to a name with no new plumbing.
Why opt-in rather than the new default
Sixty-seven documents cite 0x7fff0001,
and several decisions rest on seeing it: D516, D523, D524 and D564 all
fix an arity by spotting orbistoun's own placeholder left in a register.
Changing the value everywhere would make all of that prose stale at a
stroke - the precise failure this project spends most of its discipline
avoiding.
Opt-in costs nothing and invalidates nothing. An ordinary run answers
0x7fff_0001 and every recorded fact stays true; a run that
wants attribution asks for it.
It is Effect::Intervenes, because it changes what the
guest is told - a guest branching on the exact value takes a different
branch, and a verdict under it measures a settings change.
The floor, and why it is 0x10
Tags start at 0x7fff_0010 because
0x7fff_0000..0x7fff_0010 is the fixed range the
GuestError codes occupy. A tag must never be mistaken for
one of those, and - the direction that actually bites - a fixed
code must never be read as a tag: attributing
0x7fff_0001 to whichever import sits at slot 0 would be a
confident, wrong answer, which is worse than the vague one it replaced.
Guarded, and watched failing with the floor removed.
An override still wins
Precedence is overridden.or(tagged).or(declared). A
person who set ORBISTOUN_RETURN for a function gets what
they asked for, tagging on or not. Found by testing: the first attempt
to demonstrate the 4 GiB bug under tagging forced the sizer's return
and enabled tagging, and the override quietly beat the tag. The
precedence is right; the test was wrong.
What this does not establish
That the tag names the right function. The service tags with a global stub index and the trace records the same one, which is true today and is not asserted anywhere - nothing would notice if one of them started counting differently, and the symptom would be a confident finding naming the wrong import. The guard says so.
Nor that it would have caught the four gigabytes.
That is the case it was built for and it can no longer be run: the
sizers are implemented, so no placeholder reaches malloc
any more. The mechanism is proved by unit test and by the tagged returns
above, not by the bug it was too late for.