D105 - 166,960 names and 1,130,742 unnamed identifiers, from eleven sources across 23 firmware versions

Status: derived - assembled by scripts/mine-nids.py, every claimed identifier normalised to one notation and checked against the hash.

source rows
ps4libdoc firmware JSON, 23 versions 1,473,623 named rows
SharpEMU aerolib catalogue 150,629
ps4_module_loader/aerolib.csv 97,623
fpPS4 ps4libdoc.pas 78,372
ps4libdoc known_names 42,010
shadPS4 LIB_FUNCTION 5,049
PS5PCEM, SharpEMU, craziiEmu, GPCS4, ChonkyStation4 5,100 combined

166,960 unique names, 110,250 corroborated by two or more independent sources, 42,812 carrying a library. obSCEne knows 564, so the surface it could import grows 296-fold.

Separately, data/unnamed-nids.txt: 1,130,742 identifiers observed in firmware modules with no recoverable name, every one of them carrying the library that exports it.

Three things this cost, all of them mistakes worth keeping visible

19,599 real names were nearly discarded. The first filter dropped _Z, __cxa_ and __gxx_ as "C++ mangling, not an interface". The platform's system libraries are C++ and export mangled names; _Z10getIpcPathiiPKciPc is a function and its identifier is the hash of exactly that string. Mangling is what the symbol is, not decoration on it. That filter threw away nearly half of ps4libdoc.

5,094 identifiers looked disputed and none were. Two sources publish hex and four publish the encoded form, so every symbol both kinds knew appeared to disagree. Normalising the notation - a conversion, deliberately not a hash - reduced it to 52.

The 52 that remain are real and are not hash failures. They are the case D128 records: one C function registered under several identifiers. sceHmdDistortionGet2dVrCommand is bound to two, in two libraries, and only one is that name's hash.

Why the library column is the valuable part

A name needs no library to be useful - hash it and ask any library for it. An identifier does: it can only be imported from the library that exports it, and a guess produces a symbol that never resolves and an absence that means nothing.

Which is why the firmware JSON matters more than its name count suggests. It is the only source that carries the library, and it supplies one for every unnamed identifier. That turns 1.13 million numbers from unusable into importable.

On where this came from

Nothing here is derived from vendor source. The identifier scheme is a stripping mechanism: the vendor's toolchain hashes a symbol name at build time and stores only eight bytes, so a shipped module's export table lists identifiers and never names. Reading them is ELF parsing. Recovering a name is the hard direction and is why 87% of the observed surface has none.