2026-09-03 - (/loop) The title's own modules relocate
tests 1980 -> 1984
D482 placed them, D484 gave them a shared stub table, and this links them. All three corpus titles relocate every module they ship, completely:
PPSA02664 Il2CppUserAssemblies 346028 applied, 0 unresolved, 0 tls-deferred, 0 unsupported
PS5Util 11 applied, 0 unresolved
libc 1896 applied, 0 unresolved
PPSA03416 Il2CppUserAssemblies 381319 applied, 0 unresolved
libSceAmpr 247 applied, 0 unresolved
PPSA25872 Il2cppUserAssemblies 96419 applied, 0 unresolved
libc 3028 applied, 0 unresolved
A placed module was bytes; a relocated one is code.
Every internal pointer in Il2CppUserAssemblies now reads as
an address rather than as a link-time offset, which is what had to be
true before an address inside it was worth handing to anybody.
What "0 unresolved" does and does not say
It says every relocation found a target. It does not
say every import is implemented - these modules import from
libc and libkernel, and those resolve to
stubs in the shared table, which is a target like any other. A
stub that reports being called is the right answer there and the count
would look identical if all of it were implemented, so the number is
worth having and worth not over-reading.
The three pieces, each with a caller before it was believed
slot_ranges gained
OffsetResolver. A relocation inside module
M names M's own symbol index, so something has to add
offset(M) before the shared table is consulted. It
refuses rather than wraps on overflow: a wrapped index
answers a different module's slot, binding the relocation to an
implementation written for another symbol - silently, for the whole run.
An unresolved relocation is counted and reported; a wrong one is not.
Watched failing by swapping checked_add for
wrapping_add.
build_data_blocks_for builds one block
across every module with shifted indices, so the named map merges as a
consequence - which is what install_data_symbols needs,
being the last OnceLock on this path. It also
reports a name two modules both import as data: they
get separate storage, as they must, but a lookup by name can only answer
one of them and which is not something that layer can decide.
link_title_modules ties them together
in D482's order - place all, collect all exports, relocate all. None of
the three was written without the next one calling it; an uncalled
abstraction is the thing principle 12 warns about, and two of these
would have been exactly that if the slice had stopped a step
earlier.
What is still not true
Nothing here is wired into run. The
worker still takes the single-module path, so a guest does not yet get
these modules -
orbistoun-cli imports <eboot> --own --linked is the
only caller. That is the next unit and it is a small one now: the
worker's sequence has to place and link the title's modules before it
relocates the executable, and pass the shared table on.
The executable is not relocated here, deliberately. It is module 0 and takes slot zero, but relocating it is part of entering it, which is the worker's sequence rather than this one's.
install_data_symbols is called by a reporting
command, which is harmless in a one-shot CLI and would not be
in a process that later ran a guest. Worth knowing before this is called
twice in one process.
State
cargo test --workspace green - 117 suites, 1984
tests, 0 failures. clippy --tests clean, fmt
clean, identity scan clean.
Nothing committed. The day holds worklogs 292-336 and D466-D486.
Next: wire the link into the worker so a run actually gets the title's modules, then see where PPSA02664 stops. After that the encoder path probes (48 outstanding), which the measured 537-module manifest makes answerable.