aboutsummaryrefslogtreecommitdiffstats
path: root/fw/cgnames (follow)
Commit message (Collapse)AuthorAge
* regenerate all 16 modules on one decoder; align the RPC naming so diffs mean ↵user2026-10-01
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | something Finishes the rebuild that was interrupted earlier and leaves the corpus on a single decoder version for the first time since the SVC-opcode work started. All 16 modules rebuilt clean, 16/16 self-port gates PASS, no duplicate names in any of the 99 builds, no address-derived names. The naming fix from the previous commit is now actually in the artifacts: 1,038 SVC stubs use the libdump's sysdrv_rpc_<N> convention instead of my own rpc_<N>. Six names persisted in fw/cgnames from when I wrote them by hand are converted too, otherwise they would have quietly reintroduced the inconsistency on the next rebuild. The 85 remaining bare rpc_ names are of the form gcp_asd_rpc_202 -- ASD's libdump names ported into other modules through shared code, so that is the libdump's own convention and correct to leave. Effect on diffs, which is why this mattered: the 22.0.4.49 -> 22.0.4.50 pair reported 8 functions added and 8 removed with no firmware change behind it, and now reports 4. The remaining 4 are a different and smaller problem, now documented in ta_diff.py: a function can carry a richer name in one build than another, gcp_cmdFE0C against gcp_cmdFE0C_CreateCryptoSession, because the semantic half comes from a pass that only reaches some builds. Corpus-wide the diffs are now usable. Adjacent patch versions average 0.5 changed functions in ras, 2.5 in wspe, 3.3 in merit, 4.6 in opm, up to 26 in xgmi where the builds are genuinely far apart. Added/removed should be read as "look at this" rather than ground truth; changed-function counts are sound. Metrics unchanged by the rebuild at 19,487 meaningful names (67.3%) and 75.8% field share, which is the point -- it confirms the mixed-decoder tree was not inflating anything.
* decode the RPC opcode out of SVC stubs: csu, oc, tmz and dtm reach 100% nameduser2026-10-01
| | | | | | | | | | | | | | | | | | | | | | | | | | | Earlier in this work I recorded that the SVC 0xF2 stubs "carry no semantic information whatsoever", since the operation is chosen by caller-set registers. That holds for the shared thunks and I over-generalised it: in the per-module stubs the opcode is loaded by the stub itself. DTM's three unnamed functions all decompile to the same four lines, "SVC 0xF2; return 2". The bytes say otherwise. MOV.W R0,#0x1C0, MOVW R0,#0x101 and MOV.W R0,#0x100, each stored as the first word of the request frame before R0 is set to the selector and R1 pointed at the frame. So the first stored word is the opcode, and 0x100 independently matches a comment already in this tree reading "Opcode 0x100 - DTM TOPOLOGY_UPDATE", which is the corroboration that makes this more than a plausible decode. Named <ta>_rpc_<hex>, following the existing asd_rpc_NNN convention, and only where exactly one in-range immediate survives -- otherwise the stub stays unnamed rather than guessed. Also named by reading the bodies: oc_memcmp_ct, whose loop accumulates "v3 |= *a1++ ^ *a2++" over a counted range with no early exit and is therefore a constant-time comparison worth labelling; csu_rpc_309 and csu_rpc_305, the same stub shape with the opcode differing across builds; and auc_sysdrv_rpc_101C_fwd, an 8-byte forwarder that adds a2+80 as a fourth argument. csu, oc, tmz and dtm are now 100% named. Corpus 19,126 -> 19,134 meaningful names. What remains in the small modules is an AUC body of several hundred lines, a RAP command handler and five FP functions. That is per-function reverse engineering rather than pattern work, which is the honest characterisation of the rest of the corpus too.
* extend log-string naming to POWERPLAY's bare form; alias short names to ↵user2026-10-01
| | | | | | | | | | | | | | | | | | | | | | | | | | canonical entry points Last commit asserted the log-string lever was GCP-only. That claim rested entirely on the AMD?TA regex, so I re-checked it by dumping every message-like string from all 16 module binaries. POWERPLAY logs "CreateEntry: status = 0x%x" and "InvokeCommand: status = 0x%x" -- a second form with no AMD_TA prefix, naming the function BEFORE the colon rather than after it. The harvester now reads both. POWERPLAY yields 10 agreements and 0 contradictions, independently confirming its entry points. That is a small return, but it is the second time re-checking a ceiling claim found the claim wrong, and the check is cheap compared with the mislabels it prevents. POWERPLAY also showed that a log name is not automatically the best name. Build 34.0.0.9 had 0x402570 unnamed and its log calls it CreateEntry, while the other five builds name the same address TA_CreateEntryPoint. Applying the log spelling verbatim named one function two different things across builds and reduced consistency rather than improving it. Short forms of the five standard entry points are now aliased to the canonical spelling, so build 34.0.0.9 gets TA_CreateEntryPoint and TA_InvokeCommandEntryPoint, matching its siblings. Confirmed in the artifacts: 0x402570 and 0x4026cc in powerplay_34.0.0.9 now read TA_CreateEntryPoint and TA_InvokeCommandEntryPoint. XGMI, OPM, MERIT and FP were checked under the bare form too and yield nothing -- their strings are prose ("GetInfo for NodeId %d") or embedded certificates, not function names.
* name functions from the firmware's own log strings, which corrected two of ↵user2026-10-01
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | my mislabels I had claimed the unnamed residue was thunks and that no naming lever remained. Checking that claim against the artifacts instead of repeating it showed only 43% of ASD's unnamed functions are 4-byte thunks, and that GCP's binary contains strings like AMD_TA_GCP: AllocateDRMSession ENTER AMD_TA_GCP: GetCryptoSessionForDevice The leading identifier is the vendor naming the enclosing function. That outranks everything else here: porting infers from byte similarity, the call graph from position, the dispatcher from a jump table, but a string inside the body is the author's own label. fw/ta_logname.py harvests them from the binary, resolves the referencing function through IDA data xrefs, and applies the name. On GCP's 11 builds: 43 agreements with names already derived, 70 functions named that were unnamed, 193 instances contradicting an existing name. The agreements are as valuable as the corrections. gcp_cmd01_AllocateDRMSession, derived from the dispatcher table, is confirmed verbatim by the firmware's log line -- the first independent check that dispatcher-anchored naming is sound. Two mislabels of mine, both now fixed: 0x403a90 was cmdFE0F_GetCryptoSessionByDecodeHandle; its log says GetCryptoSessionForDevice 0x4038d8 was cmdFE0A_QueryAccessibilityAttributes__h9; its log says GetCryptoSessionByDecodeHandle So the name was on the wrong function, and the function that really is GetCryptoSessionByDecodeHandle had been filed as a fragment of a different command. cmdFE0A is QueryAuthenticatedSession, not QueryAccessibilityAttributes, and nine __hN "fragments" are separate routines with their own names. The wrong FE0F name was seeded from fw/libdumps/gcp.json, so it is corrected through LIB_RENAME, which since the seed-consistency fix rewrites the seed as well as the databases. A command id is carried onto the vendor name only when the old name had no __hN suffix: that suffix means the id was inherited from a neighbour and never established for the address, so carrying it would manufacture a false dispatcher mapping. Ceiling: only GCP (72 distinct) and WSPE (7) carry these strings; the other 14 modules have none, established by scanning every build binary. ASD has 41 printable runs, all property keys. Named 19,352 -> 19,422.
* upgrade 509 hash-placeholder names to the real names ASD already knewuser2026-10-01
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Three correctness audits this pass, and the third produced the work. Duplicate function names: zero across all 99 builds. The fp_cmd04 duplicate fixed last pass was the only one. Contradictory names within a module: zero. 3566 byte-identical bodies were grouped per module and every group agrees on its name, so the porting is self-consistent. Contradictory names ACROSS modules: 32 identical bodies carry different base names, and that is where the value was. Most are not contradictions at all but the same function known two ways -- the TA side knows it only by content hash (lib_52b900d8_88) while ASD's symbol set knows it by name (memcmp_be). Byte identity makes the equivalence a fact rather than an inference, so the placeholder loses: 21 clusters resolve to a real name, including memcpy_aligned, memcmp_be, aeabi_uidiv, udiv10, and the vsnprintf_ family (setup, fill, pad_left, out_str, fmt_hex, fmt_octal). 509 instances across 51 builds, merged into fw/cgnames so they are durable. Names still carrying a content-hash placeholder are reported in the commit body rather than left unstated, and the SHARED_ARG1 fragment list keeps BOTH the old hash fragments and the semantic ones, because the upgrade is applied through the name map and the tee_fmt_state typing must keep matching whichever name a given build ends up with. Eleven clusters were deliberately NOT upgraded because the two names genuinely contradict rather than one being a placeholder: gp_cipher_do_final against sysdrv_rpc_10, gp_cipher_update against sysdrv_rpc_7, entry_trampoline against ta_main_loop. One of each pair is wrong and byte identity cannot say which, so both are left standing rather than picking the one that reads better.
* correct an overclaim: the artifacts are not byte-reproducible, and persist ↵user2026-10-01
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | DISPATCH names An earlier pass reported that all 99 artifacts regenerate byte-identically. That was true of that one run and does not hold in general. A full clean regeneration of all sixteen modules changes 220 files, and the cause is IDA's auto-analysis not being identical across fresh databases: AUC's function count comes back 39 instead of 40, and decompiled text varies cosmetically ("(int)nullsub_3" against "nullsub_3"). The claim is corrected here rather than left standing. Semantically the drift is small -- 4 names of 19,353 -- but all four were tier DISPATCH, which exposed a wrong decision. fw/ta_snapshot_names.py excluded DISPATCH on the grounds that fw/ta_re.py re-derives it every run. It does, but not deterministically: dispatcher recovery depends on which function Hex-Rays decompiles cleanly on a given analysis, so xgmi_cmd00, xgmi_cmd04, xgmi_cmd0B and fp_cmd04 simply did not come back. DISPATCH is now persisted, and the exclusion reasoning in that file is rewritten to say why. Persisting it still cannot mask a regression: the dispatcher step runs regardless, so where recovery works the DISPATCH tier wins and where it fails the restored name appears as tier IDA. The tier difference is itself the signal that recovery failed on that build. 7817 names were recovered from the committed artifacts into fw/cgnames so nothing derived is left depending on a database that may not reproduce. XGMI came back whole. The one name that did NOT come back turned out to be a defect being fixed rather than lost. HEAD had TWO functions called fp_cmd04 -- 0x401334 from the dispatcher and 0x402b4c from byte porting -- and the current dispatcher map routes command 4 to 0x402b4c, agreeing with the ported name. So HEAD carried a duplicate, this run does not, and the allow_overwrite=False guard on the re-apply is what refused to restore the bad one. Worth keeping: a name count going DOWN was the correct outcome, and reading it as a regression would have reintroduced the duplicate. Verified state after the clean regeneration: 16/16 gates PASS, 99 builds, 19,349 of 28,945 named (66.8%), field share 66.4%, 21 decompile failures.
* make derived names durable in the repository instead of only inside the .i64 ↵user2026-10-01
files This pass fixes a fragility that was actively destroying work rather than adding coverage. Four IDA databases have now come back corrupted with "worker exited with status 1", and the only remedy is to delete and rebuild them. Every name derived by fw/ta_cgname.py lived solely in those databases, so a rebuild discarded them -- GCP silently fell from 83% to 74% named when I wiped its databases for the dispatcher fix, and I only noticed because I happened to re-measure per module. Worse, those names cannot be re-derived: once a callee has a name it stops being a sub_* candidate, so re-running the tool on an already-processed build reports nothing to do. Three changes: * fw/ta_cgname.py persists every name it applies to fw/cgnames/<ta>.json, keyed by build and address. * fw/ta_re.py re-applies that map at the start of each build, before anything reads names, so a rebuilt database comes back with its derived names intact. * fw/ta_snapshot_names.py recovers the names applied before the map existed. They are read out of fw/decomp/*.index.json, which records name, address and tier per function, and only the IDA tier is snapshotted. EXACT, MNEM, FUZZY and DISPATCH are deliberately excluded because fw/ta_re.py re-derives them every run; persisting those would bake a derived result into the repository and hide a future regression in the porting itself. 1476 names are now durable across 15 modules, including ASD's 847, which would otherwise have needed a 40-minute wipe-and-rederive to recover. Verified by doing the thing that caused the loss: XGMI's databases were deleted and rebuilt. It came back at 238 of 334 named against 239 before, so a full database loss now costs one function instead of nine percentage points. The single remaining loss is not chased down here, but it is recorded rather than rounded away. GCP is restored to 84% and HDCP re-derived cleanly to 86% with a complete map. Corpus naming stands at 67.0%.