D483 - Attribution is half of what identifies an import, and libc is the title's

measured - 2026-09-03 (user-directed plan, the TitleOwn loader)

D482 found the title's own modules. This places them, indexes what they export, and matches that against what the executable imports. Three things came out of the first run, and two of them contradicted something already written down.

The match is on the hash and the library

An encoded import carries a library id alongside its hash. The first version of this matched on the hash alone, and on the first title it was pointed at it reported five imports binding into Il2CppUserAssemblies where the executable's own table names four.

Matching on the hash alone lets an import that names one library bind into a different module that happens to export the same name. A NID hashes the symbol name and nothing else (D305), so two modules exporting memcpy collide by construction - and which of them a caller meant is exactly what the library id says.

So: an encoded import binds only into the module its library_id names. A library id the executable's own table does not list matches nothing, rather than falling back to a hash-only search - the fallback is the bug.

A plain name carries no attribution (D305), so for those the hash is all there is. Those are matched across every module, and where more than one answers, the import is left unbound and reported ambiguous. Picking one would be a call into whichever module sorted first.

The fifth was real, and it is setenv

The extra binding was 0xc8275f216d188633, and the mystery is instructive:

executable's table:   library 0 = Il2CppUserAssemblies,  library 35 = libc
the import:           M4YYbSFfJ8g#A#B   ->  library id 0, module id 1
orbistoun's registry: 0xc8275f216d188633 = libc::setenv

Both are right. The eboot imports setenv from the title's own IL2CPP module, which really does export it - a Unity IL2CPP build links a good deal of the C runtime and re-exports it. The import was correctly attributed all along.

What was wrong was the report I checked it against

orbistoun-cli imports lists that symbol under libc, because loader::survey prefers the registry's library name over the executable's own attribution - it answers who would answer this, not who did the guest say. That is the right answer for a resolution report and the wrong one for counting what a title imports from a given library.

Which is what the note saying "four" had done. A report answers the question it was built for, and using it for a neighbouring question is how a fact decays. Sixth instance, and the first with the cause identified rather than just the error.

libc is not a platform module

The measured 537-module manifest of the console's own libraries (worklog 328) contains no libc.sprx. The platform's is libSceLibcInternal.sprx. What answers the libc the executable imports 152 symbols from is sce_module/libc.prx - shipped by the title, in its own tree, found by D482's search.

That reframes the fork this opens up:

binds into changes
the emulator's implementations win orbistoun's measured libc nothing
the title's own modules win sce_module/libc.prx, 152 symbols every libc measurement

Default: the emulator's implementation wins wherever it has one. It strictly increases what resolves - the Il2CppUserAssemblies wall opens, including 0x6f8b9da539afc9af - while changing no measurement the differential and hardware corpora were taken under. It is also one flag away from its opposite.

The second column is what the console actually does, and it is the honest end state. It is not reachable yet for a reason that has nothing to do with preference: these modules are placed and not relocated, so binding into them at all is not yet runnable.

Placed is not linked, and nothing here is wired into a run

A placed module has had its bytes copied and nothing else. Its own RELATIVE relocations are unapplied, so every internal pointer in it still reads as a link-time offset.

An address into that is worse than a stub. A stub reports "unimplemented" and stops; a real address into unrelocated code runs and fails somewhere unrelated - the precise failure mode principle 3 exists to forbid. So this slice reports what would bind, run is untouched, and the binding waits for the relocation pass.

What the report says today

PPSA02664   Il2CppUserAssemblies 5, libc 152          157 of 583   2818 exported
PPSA03416   Il2CppUserAssemblies 5, libSceAmpr 5, libc 152   162 of 583   2936 exported
PPSA25872   Il2cppUserAssemblies 5, PS5Util 2, libSceAmpr 5, libc 186   198 of 662   3330 exported

Zero kind mismatches and zero ambiguities across all three, which is worth stating because both checks exist to fail and neither has yet.