D248 - Every import was weak, and a loader took that at its word

status: measured

The defect. This program declares its platform functions OBS_WEAK, so a symbol the platform does not have is null rather than a link error. That is a compile-time need and a sound one. What it left behind was a dynamic symbol table in which all 203 imports were STB_WEAK, undefined - and to a loader that means exactly "if resolving this costs anything, do not bother."

It does not bother. Measured, before:

ours   WEAK   FUNC   x203
real   GLOBAL FUNC   x126   GLOBAL OBJECT x13     (a title that launches: no weak imports)

libkernel and libSceLibcInternal bound every import because they are resident in the process already and resolving against them is free. Every other declared library was mapped

The fix, in selfish: rebuild the binding as STB_GLOBAL when re-encoding an import, for the same reason the type is already rebuilt as STT_FUNC. The weak binding belongs in the C, where the reason for it is, and it does not travel into the module.

The result, same console, one flag of difference:

before after
imports bound 127 141
the platform has it and we did not bind it 14 0
the platform does not offer it 6 6
checks skipped for an unresolved symbol 24 10
tally 220/75/192/41 232/75/192/29

Whole sections came back: 100-input, 090-audio, 165-gnm all pass, 080-video, 070-user and 130-layout run and report. Three behavioural findings became visible that no run had ever reached - the user service refusing to initialise (0x80960003), the main video output refusing to open (0x80290009), and the layout size argument not being validated.

The risk that did not materialise. Six imports are for symbols this platform does not have, and a GLOBAL undefined symbol that cannot resolve is a thing a loader may refuse a module over. It loads. Those six stay null and their ten checks skip, which is the honest outcome and the same one weak was chosen to produce.

How it was found, which is the part worth keeping

Four hypotheses were tested and eliminated first - the import-library attribute, the SDK version, the .prx filename, and whether the tables were malformed - three of them against the oracle and one by A/B on the console.

None of them was the answer, and all four were about fields somebody had chosen. The answer was in a field nobody chose: st_info, written by the compiler, passed through untouched, and never printed by any probe in this repository. The library table was inspected repeatedly and looked flawless every time, because every probe showed the fields it knew how to name.

That is the same shape as D241 one level down. Print the byte, not the interpretation - and when four deliberate choices have all been eliminated, start looking at what was never decided.