2026-09-03 - (/loop) The guest runs its own code
tests 1984 -> 1991
PPSA02664 now executes Il2CppUserAssemblies. It has
never done that before, and getting there took undoing three separate
reasons why placing the module had achieved nothing.
It started with the fault address, and the decision log had it
0x7fff0001 is GuestError::Unimplemented -
orbistoun's own placeholder - recorded in D128, D154,
D186, D187, D190, D281 and D299. Grepping the decision log first is this
tick's own rule after D488, and it turned a wall into a one-line
answer.
So the report's header was wrong:
>> EMULATOR BUG: the fault is in orbistoun's OWN code, not the guest's
And the findings section of the same report was right:
instruction fetch from 0x7fff0001 is one of our own placeholder codes, used as an address
One report, two opposite diagnoses, and the loud one at the
top was the wrong one. The test for "our code" is "the
instruction pointer is outside every placed region", which cannot tell
our code from our own return values.
placeholder_named now recognises the family; the header
defers to it.
A negative test earned itself immediately:
>= 0x7FFF_0000 alone also claims every vendor code, and
0x8002_0016 is a value a console answered. Naming that as
orbistoun's own would report a measurement as an invention. Bounded
above.
Then the report answered the actual question
! Il2CppUserAssemblies::0x6f8b9da539afc9af was called 222 times and has no name
arg0 = "il2cpp_init" arg2 = 0x7fff0001
That is the NID D482 exists to answer - a
symbol-lookup function, called 222 times with names like
il2cpp_init, answering a placeholder every time while the
code implementing it sat relocated a few gigabytes away.
Three things were missing, each making the others inert (D489)
The binding was never implemented.
PlacedTitleModules::resolve - the whole of D483's rule -
was called from nowhere, and the worker relocated the executable against
the stub table. TitleResolver puts the title's modules in
front of the stubs, for the imports D483 selects.
That alone moved the fault to an instruction fetch inside a module, because -
The modules were never protected. Placement leaves pages writable and none executable, since relocation writes into text. The executable has always been re-protected afterwards; the modules never were. Same ordering now: place, relocate, then protect.
Which got the guest running, and then -
The reporter could not see them. A fault inside a
module was outside every registered region, which is the exact test for
"our code faulted", so the guest's own crash was announced as an
emulator bug. Module spans are now registered with both the fault
reporter and sceKernelVirtualQuery - the latter would
otherwise refuse an address the guest is running from.
guest fault: read of 0x8 while executing at 0x4800013dca44 (the title's own modules+0x13dca44)
from 0x4800013d5f00 (the title's own modules+0x13d5f00)
The score, which is not flattering
| before | after | |
|---|---|---|
| distinct imports | 69 | 46 |
| calls | 10884 | 2080 |
| died | using a placeholder as an address | reading 0x8 inside
Il2CppUserAssemblies |
The verdict is BACK, and it is not
wrong. The guest reaches less of the platform interface than it
did - it reaches it from inside its own code, which it had never
entered, and the wall is now a null field read in the title's il2cpp
rather than a jump through one of our refusals.
Writing the number down rather than explaining it away, because it is the one the next run compares against. D487's point again: distinct imports measure breadth and this was depth.
Also
The ±3 call oscillation survives (44/46 distinct, 2077/2080 calls across three runs), on a stable fault address. Still unexplained, still not moving anything that matters.
Four place_and_relocate extractions came out of the line
limit rather than of taste - describe_title_modules,
publish_what_the_guest_reads,
relocate_the_executable. The last one is the better shape
anyway: the resolvers borrow the tables, and building them inside the
function ends the borrow before the report starts moving things
about.
State
cargo test --workspace green - 117 suites, 1991
tests, 0 failures. clippy --tests clean, fmt
clean, identity scan clean.
Nothing committed. The day holds worklogs 292-339 and D466-D489.
Next: the null read at
the title's own modules+0x13dca44. The guest is in its own
il2cpp init and dereferencing a field of a pointer nothing set - so the
question is which call was supposed to have returned it, and the calls
just before the fault are printed.