D149 - A censused library is not a load-time dependency, and saying it is stops obSCEne loading on current shadPS4 at all
Status: defect, found by doing what D094 says to do.
shadPS4 built from its own source (be21649) refuses the
corpus build outright:
LoadModule: Provided file /app0/sce_module/libc.prx does not exist
preloadModulesForLibkernel: Assertion Failed!
libc.prx cannot be loaded, but the guest attempted to use it.
The downloaded binary this project has been measuring with does not.
Handed the same module, it prints
Failed to preload libc, expect crashes and carries on into
the suite - 65,665 log lines against 33,044, and a run that reaches
040-file instead of dying in the loader. Current shadPS4
promoted that warning to an assertion.
So every shadPS4 number in COMPATIBILITY.md was
produced by a binary whose behaviour the current source no longer
has. That is exactly the method error D094 names, and it stayed
invisible for as long as the source was only read and the binary only
run.
The cause is ours
A corpus-free module loads on the same emulator with no complaint at
all - 284 records, no assertion, not one missing-.prx line.
The difference is DT_NEEDED.
mkmodule emits one per imported library, which was right
when the imports were the curated surface (D100 - fpPS4 keys its whole
implementation table on DT_NEEDED, and without it every
symbol resolves to a stub). The corpus made it wrong: the module now
names hundreds of libraries, including libSceFios2, which
obSCEne never calls and only ever asks about.
A census asks "is this present?". That is not a dependency. Declaring one for a library you intend to probe is over-claiming in the module's own metadata - the same fault this project refuses in a report - and a loader that takes the claim seriously is entitled to demand the file. Current shadPS4 does exactly that, and firmwareless is the whole premise.
Resolution: the declarations stay
The section above was written emulator-first, and reached the wrong conclusion from the right evidence. It is kept because the evidence is the valuable part and because the reasoning is worth being able to see.
DT_NEEDED is not an over-claim. It is
the tag for declaring the platform libraries a module works with, which
is what a real title does, and on a console every one of those modules
exists - the firmware ships them, the loader loads them, and nothing
fires. What changed is shadPS4's tolerance for not having them, and a
firmwareless loader meeting a dependency it cannot satisfy is a gap in
the loader's deployment, not a defect in the module.
The framing that produced the earlier conclusion had these emulators as the standard obSCEne must satisfy. They are scaffolding: they exist to get this program running before hardware, and the direction of travel is that obSCEne becomes the reference they are measured against. Trimming the module to suit the least tolerant of them would be shaping the oracle to fit the thing it is meant to outrank - and would reduce what obSCEne can reach on the hardware that is the actual target.
So the declarations stay, and COMPATIBILITY.md records
the shadPS4 gap as a firmware gap.
What is still genuinely open, and it is not the emulator's half
A large set of hard dependencies is not obviously right for hardware either, for a reason that has nothing to do with emulators: the corpus spans 23 firmware versions and no single console carries every library in it, so a module declaring all of them could be refused by a real loader for naming one the installed firmware does not have. Same failure, different cause, and not yet measured.
The durable answer is probably that a census should not be a
load-time declaration at all. sceKernelLoadStartModule and
sceKernelDlsym are already declared in
platform.h and 110-modules already exists:
asking the platform at runtime and reading the error code it returns is
strictly stronger evidence than a resolved address, which D140
established is close to worthless on a loader that stubs whatever it
cannot find. That is the shape of the census obSCEne needs to be an
oracle rather than a presence counter, and it is the work this decision
hands forward - not a DT_NEEDED trim.