D493 -
The null is .bss, and binding made the answer
invisible
measured - 2026-09-03 (segment arithmetic, then a trace with nothing in it)
Two findings that belong together: the first says exactly what the wall is, and the second says why this build cannot currently see past it.
The null
is .bss, not a .data the loader failed to
copy
The loader already knew, and nothing surfaced it.
PlacedSegment records the file-backed and zeroed halves of
every segment separately, which is the
.data/.bss split. Printed:
segment Il2CppUserAssemblies #4 0x480001d68000 0x194a6c copied 0x26e0dc zeroed flags 0x6
The copied part ends at 0x480001efca6c. The faulting
rsi is 0x480001f0c330 -
0xf8c4 past it, inside the zeroed run.
So orbistoun copied everything the file held. That global is zero
because .bss is zero, and the question is not
"what went wrong in the loader" but "what was supposed to write
it".
That rules out the last hypothesis that would have implicated the placement path, and it took one arithmetic comparison against numbers the loader had all along.
And the caller is one of the four
+0x13d5f00 is 0x70 into the export at
+0x13d5e90, which is 0x9fdbed4fe0989d70 - one
of the five imports the eboot binds into this module. It allocates 48
bytes through operator new, calls +0x13dca44,
and that reads the empty global.
Binding removed the calls that matter from the trace
D489 bound the eboot's imports to real addresses inside the module. It works. The consequence was not thought through:
Il2Cpp entries in the trace: NONE
Before binding, 0x6f8b9da539afc9af appeared as
222 calls with il2cpp_init and
il2cpp_init_utf16 as its first argument - which is how the
resolver was found at all. It now resolves to a real address, so the
guest calls it directly and no thunk sees it.
This is principle 7 working exactly as written. Interception is linking, not hooking - so what is observed is precisely what resolves to a stub. Binding an import to real code is the correct answer and it is also the act of switching the instrument off for that call.
The two are not in tension by accident; they are the same decision seen from two sides. Worth naming before somebody reads a shrinking call count as a regression: the trace measures what orbistoun answers, not what the guest does, and the more of a title's own code runs, the less of the title's behaviour the trace describes.
What this leaves
The question - what writes that .bss global - is now
behind the blind spot. The eboot binds five imports into this module and
the order it calls them in would answer it, and that order is exactly
what stopped being recorded.
So the next instrument is a trace of bound calls,
and it is not optional: from here on, every interesting call is one this
build has deliberately stopped watching. is_implemented
already distinguishes a bound slot from a stubbed one, so the
information exists; what does not exist is anything on the path a bound
call takes, because the whole point of binding is that there is no path
- the relocation slot holds the target and the guest jumps.
That makes it a real design question rather than a small feature, which is why it is recorded here rather than attempted at the end of a session: a thunk that forwards to the module would restore the trace and reintroduce exactly the indirection principle 7 exists to avoid.