2026-09-02 - (/loop) The loader's answers were already right; the real gap is exports
hardware claims 15 -> 18 (7 outstanding, 2 opaque)
tests 1955 -> 1957
Went to build the TitleOwn loader. Read first, and found that three of its five measured conditions already pass - and that the work I had scoped was scoped at the wrong layer.
The doc comment described code that is no longer there
sceKernelLoadStartModule opened with:
Refused, and that is the honest answer. orbistoun places one executable at load and has no way to bring another in afterwards, so every request fails.
The function below it does nothing of the sort. It answers
libkernel's well-known handle, refuses a /system path with
the not-found errno, and hands a fresh handle to anything under
/app0. Somebody implemented the measured behaviour and left
the comment saying the opposite.
That comment is why the loader work looked bigger than it is. Both the plan and the outstanding entries carried "orbistoun's loader loads nothing, so it has no module table to answer from" - which described the comment rather than the code. Rewritten to say what the function does, and what it still does not.
Three measurements that were already satisfied
Using the probe's exact paths and call form:
| path | console | orbistoun |
|---|---|---|
libkernel.prx |
0x2001 |
0x2001 |
/system/common/lib/libc.prx |
0x80020002 |
errno::NO_ENTRY |
/system/common/lib/libSceFios2.prx |
0x80020002 |
errno::NO_ENTRY |
All three are now assertions. That is the third tick running where an outstanding entry's stated reason was worse than the truth, so it is no longer a coincidence: a reason written when something is deferred decays, and nothing re-reads it. The three ticks were the mutex type mapping (already in the source), the memory-query "harness" (one call), and this.
The two that can never be asserted, and a third list for them (D481)
The console answered 0x15 and 0x14 for two
/app0 modules. Both captures agree, so the gate calls them
constants - and asserting either would be wrong. A
handle is allocated by the loader; 0x15 says that console
had already placed twenty modules. Orbistoun answers 0x40
upward and its own comment says the value is opaque.
Leaving them in the work queue would say "not done yet" about
something that will never be done. OPAQUE names them
instead, with the reason, and the gate requires every constant to be in
exactly one of three lists. The arithmetic is asserted, not printed -
checked by dropping a category and watching the count come back 25
against 27.
What is asserted is the shape, which is a property of the call: a title's own module must load rather than be refused, and two loads must answer different handles.
The real gap, which is one layer down
Il2CppUserAssemblies.prx and PS5Util.prx
are not in sce_module/ - they are in
Media/Modules/, which is why looking for
them beside the vendor libraries found nothing.
And the corpus survey settles how the title reaches them: 8
imports from Il2CppUserAssemblies, 2 from
PS5Util - plus 4 more under a case-variant
spelling, Il2cppUserAssemblies, which is worth knowing
before anything matches library names. Those are import-table
entries, resolved at relocation time, not runtime
sceKernelDlsym calls.
So the wall is not in sceKernelLoadStartModule at all.
It is that the main executable's imports have nothing to bind to, which
means:
orbistoun-elfreads imports and has no notion of exports. There isRawImportand noRawExport; the dynamic symbol table is walked for undefined symbols only. This is the piece that does not exist at all.- The loader must place and relocate the title's own modules before relocating the main executable, and feed their exports into the resolver.
Neither is a guess: the import counts are measured off the title's own bytes, and the absence of export handling is a grep.
Not started this tick, deliberately - it is a design with a load-order question in it (which module places first, how a case-variant library name matches, what happens when a title's module imports from another of its own), and starting it at the end of a long tick is how the last three misleading notes got written.
State
cargo test --workspace green - 117 suites, 1957
tests, 0 failures. clippy --tests clean, fmt
clean, identity scan clean. Hardware: 18 claimed, 7 outstanding, 2
opaque, 27 constants.
Nothing committed. The day holds worklogs 292-326 and D466-D481.
Next: exports in orbistoun-elf -
self-contained, testable against the title's own .prx files
which are on disk, and the thing everything else waits on. Then the
load-order design, which is D482.