aboutsummaryrefslogtreecommitdiffstats
path: root/fw/decomp/oc.summary.json (follow)
Commit message (Collapse)AuthorAge
* name all five GP entry-point slots from the image header: TMZ reaches 100%user2026-10-01
| | | | | | | | | | | | | | | | | | | | | | | | | | | ta_entry_points read the trampoline's +0xA0 (Create) and +0xB0 (Invoke) slots and threw away the three between them. Those are TA_DestroyEntryPoint, TA_OpenSessionEntryPoint and TA_CloseSessionEntryPoint. That is the whole reason TMZ sat at 50% named: it has six functions and three of the unnamed ones were entry stubs the header identifies exactly. The slot order is read off GCP rather than assumed from the GP spec. GCP has all five named independently and its table reads Create, nullsub(destroy), OpenSession, CloseSession, Invoke, with WSPE and HDCP agreeing and the types agreeing too -- slots 0, 2, 4 return a status, slots 1 and 3 are void. Running the new derivation against GCP reproduces GCP's own names exactly, which is the check that makes this evidence rather than convention. Applied to every module, only where porting left the address unnamed. Per-module: tmz 50 -> 100, rap 76 -> 98, csu 70 -> 92, oc 90 -> 97, dtm 75 -> 89. Corpus 19,038 -> 19,126 meaningful names (65.8% -> 66.1%), field share 75.5% -> 75.8%. RAS disagrees and is deliberately left alone. Its libdump names TA_CreateEntryPoint and TA_DestroyEntryPoint at addresses the header assigns to OpenSession and CloseSession, a systematic two-slot shift across all 18 builds. My first run wrote the header names anyway, which left RAS asserting two different Create entry points -- a contradiction I introduced and then caught by checking for duplicated roles. A guard now refuses to add a second holder of a role, so the conflict is reported on every build and nothing is written. No build has a duplicated entry-point role. Which source is right for RAS stays open: the obvious tiebreaker, argument count, is not decisive on functions IDA never prototyped.
* anchor prototypes to command ids, and derive the OC and WSPE request structuresuser2026-10-01
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Matching prototypes to functions by NAME reached only 8 of GCP's 24, and the reason turned out to be a correctness problem rather than a matching one: this tree carries two naming generations that disagree about which command a handler serves. fw/pseudo calls the handler at 0x402f90 gcp_cmdFE0C_CreateCryptoSession; fw/libdumps calls the same function gcp_cmdFE0C_CreateAuthenticatedSession. The hardware findings settle it -- FINDING-GCP-ACQUIRE-GATE-BYPASS records 0xFE0C as CreateCryptoSession and FINDING-GCP-FE0D-REFCOUNT-DESYNC agrees -- so the libdump name is wrong and had propagated into every artifact generated so far. Keying on the command id and resolving the address through the dispatcher avoids the disagreement entirely, because the dispatcher is the only authority on which function serves which command. GCP goes from 5-9 applied prototypes per build to 14-17 and from 28 struct-typed signatures to 172, and the handler at 0x402e94 is relabelled from gcp_cmdFE03_* to gcp_cmdFE07_* on every build -- the single conflict the cross-check had been reporting since it was built. Two more request structures are derived and verified the same way as xgmi_req. OC and WSPE both dispatch with if/else chains rather than a switch, so the switch-based dispatcher recovery finds nothing for them and their invoke entry has to be used directly; both work on the host buffer in place rather than staging a copy, so their offsets are host offsets by construction. oc_req closes at 0x1C (handler blocks at +0x0C and +0x16, the latter running 6 bytes to the end of the validated size) and wspe_req at 0x14 (handler block at +0x10). Both sizes are the ones the dispatchers' own size floors enforce. Applied, OC's entry reads 'v5->cmd_id == 2' and the type propagates outward to 'struct oc_req **a4'. Recorded against this work rather than hidden: applying a pseudo-file prototype by name can introduce a WRONG signature. OC's dispatcher calls oc_cmd01(ctx: v5 + 3, params: (struct ta_params *)7) -- the second argument is the literal 7, so the inherited 'struct ta_params *' misdescribes it, and the cast in the output is the tell. Prototypes should be checked against what their call sites actually pass before being applied. Measured from the artifacts rather than from effort: struct-typed signatures 309/10070 (3.1%) -> 456/10070 (4.5%), modules with a derived request struct 0 -> 3, modules with zero struct-typed signatures 6 -> 4. The rate stays low for a structural reason worth stating plainly: ASD is 6763 of the 10070 functions and has no recorded type information at all, so work on the small components cannot move the global figure. ASD is where the remaining value is.
* apply the prototypes, types and comments the pass had been droppinguser2026-10-01
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The decompiled artifacts were missing almost all type information. Three things were available in the tree and only one was being used: * declare_type was never called, so no type definitions were parsed at all; * set_type ran only for the four handover types, because fw/libdumps records just {ea,hash,name,size} and the twelve Windows TA types therefore had no signatures to port; * the recorded comments were read into a variable and discarded without ever being applied. All three are now applied, in dependency order, and counted per build so the result is measurable instead of something you have to notice by reading the output. Across 99 builds: 7727 prototypes (was 1232, all of them ASD), 6068 comments (was zero), 309 struct-typed signatures (was zero). The reason prototypes were failing was NOT the missing types, which is what I assumed when I reported "202 of 1434 rejected" without diagnosing it. Declaring the types first changed the rejection count by nothing. 205 of the 239 failures were prototypes recorded in the bare shape 'int()', with no __fastcall for the name-insertion to latch onto, so they were emitted as the unparsable 'int();'. The name now goes before the first parenthesis whatever the shape, and prototypes land 100%: 1434/1434 on the ASD reference, 99/99 HDCP, 9/9 DTM. Worth recording so nobody repeats the detour: the 43 'local_types' in each handover symbol set are ARM NEON and SVE vector typedefs plus va_list and BOOL -- compiler boilerplate with no domain structs in it. Declaring them is harmless and buys nothing. The only real PSP structs in this tree are the seven hand-written ones in fw/ta_ida.py (gcp_ctx, ta_params, gcp_drm_session, gcp_auth_session, gcp_crypto_session, merit_slot, merit_table), which were sitting unused and are now applied: GCP command handlers finally read as '(struct gcp_ctx *ctx, struct ta_params *params)' rather than '(int, int)'. So the remaining type gap is a data gap, not a pipeline one. Thirteen of the sixteen components have no struct definitions anywhere in the repo to apply, and ASD's 6800 prototypes are almost entirely primitive-typed, which is why it shows only 30 struct-typed signatures against 1439 named functions. Closing that needs structs to be defined by hand, component by component.
* name TA command handlers from the dispatcher, and extend the run to all ↵user2026-10-01
twelve types Byte and mnemonic similarity cannot name a handler whose code diverged, and that failure landed exactly where it hurts: gcp_cmdFE0C, the function carrying the acquire-gate refcount bypass, was unnamed on six of eleven GCP builds. The dispatch table does not care about similarity -- whatever sits in the 0xFE0C arm is the 0xFE0C handler by construction. So the handler names now come from the image itself: the header's trampoline gives TA_InvokeCommandEntryPoint, Hex-Rays recovers the switch, and each case arm is attributed to the function it calls. Parsing the decompiler's switch output beats hand-rolling Thumb jump-table decoding, and callee tokens resolve through the live function list rather than by assuming they look like sub_<addr>, so it works whether or not names were applied first. Validated against the one authoritative map that already existed: all 14 commands this recovers for GCP 22.0.4.50 match fw/cmdmaps/gcp_ea.json address for address, with none spurious. The three it misses (0x3, 0xFE08, 0xFE0E) are precisely the arms with no callee -- inlined into the dispatcher, and recorded in the old map as loc_ labels that were never function starts. FE0C is now named on all eleven builds. Two bugs the first attempt had, both caught by its own conflict reporting. Walking three levels deep from the invoke entry swept up nested sub-command switches inside individual handlers and invented a GCP command 0x0F that does not exist; the walk is now limited to the invoke entry and its direct callees, with a depth-2 fallback only when depth 1 finds no switch at all. And one handler commonly serves several commands -- GCP routes 0xFE03-0xFE07 to one function -- so commands are grouped by handler address before naming or judging agreement. The self-port gate was measuring the wrong quantity. Dividing EXACT matches by every recorded symbol conflated a broken matcher with IDA simply not defining a function at a recorded address, and failed five sound types on that basis -- TMZ scored 17%. The denominator is now the reference symbols that are function starts in the reference build; all twelve types then gate at 100%. That fix made the gate blind to a different error, so it gained a second check. MERIT ships two distinct 24.0.4.42 builds, the reference was being chosen by version alone, and the libdump had been recorded from 444eceee while bc1706f8 was loaded: 24 of 31 symbols landed on nothing and every MERIT build sat near 30% named. The reference is now pinned by hash from fw/syms/<ta>.meta.json, and an orphan-symbol rate above 10% is reported as a suspected build/symbol mismatch. MERIT went to 58-83% named. 62 builds across twelve types, zero decompile failures. The remaining conflicts are real and worth reading rather than suppressing: GCP's 0xFE07 handler carries the inherited name gcp_cmdFE03_CreateAuthenticatedSession, because the older name-keyed cmdmap collapsed 0xFE03-0xFE07 onto one label while the dispatcher shows only 0xFE07 reaching that function.