| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
down to 7
The thunk naming in the previous commits set row["name"] in this script's metadata only, never in the
database. So the emitted banner read j_asd_clear_link_outputs while the signature inside the body
still read j_sub_D07E10_16. Checking for it found 1,018 functions disagreeing with their own banner,
most introduced by the earlier repair pass rather than the newest one. A reader who sees the two
differ cannot tell which to trust, which is worse than leaving the function anonymous -- and I had
claimed in the last commit message that no j_sub_ names remained in any artifact, which was false.
ta_re.py now pushes every derived name into the database and re-decompiles whatever still disagrees.
Two details were needed, both found by measuring the result rather than trusting the step:
Names must be uniquified first. Several distinct thunks branch to the same target, so j_<target> is
not unique and a colliding rename is silently refused -- on the ASD reference only 55 of 786
reconciled until duplicates were suffixed. Those suffixes are honest, unlike the address-derived _N
names dropped earlier: these are genuinely separate functions with a shared destination.
And the resolution has to run after address-derived names are dropped, since before that point the
rows still carry a stale j_sub_<addr> label and look named, so the pass skipped all of them.
Regenerated asd, gcp, powerplay, xgmi, wspe and ras. Mismatches 1,018 -> 7 corpus-wide; the 7 are ASD
functions where the decompiler emits no signature line this check can read. Meaningful names hold at
19,038 (65.8%), address-derived 0, field share 75.5%.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
defaults as names
Four metric-definition errors in four commits, each from re-writing the same predicate at a new use
site and getting it slightly too strict. fw/ta_metrics.py now holds the definitions once -- is_addr_name,
is_meaningful, and a measure() that prints every denominator -- and ta_re.py imports them instead of
carrying its own regexes. All four errors are documented in its docstring with the reported and actual
figures, because the pattern is the useful part.
The root cause was in the pipeline, not just the audit. The decompiler-fallback step accepted any
candidate that did not match ^sub_[0-9A-Fa-f]+$, so sub_D07364_12 was admitted as a real name and
1,852 such entries propagated into the artifacts and into every coverage number I quoted.
ta_re.py now drops them, in an order that matters: a j_sub_* candidate is still kept at the fallback
step, because the re-resolution pass needs its target address to recover a real name from it, and
only what remains address-derived afterwards is dropped. Those rows become anonymous and move to the
.anon.c file rather than inflating the count.
Measured with the shared code: address-derived entries 1,295 -> 0, meaningful names unchanged at
18,129 (62.6%), field share unchanged at 75.6%. The drop removes false coverage without losing a
single real name, which is the point -- the artifacts no longer assert that sub_D07364_12 is a name.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
was 6 points high
Measuring collision suffixes in the artifacts showed names like j_sub_D07364_0 through
j_sub_D07364_20. My address-derived regex anchored on $ immediately after the hex digits, so none of
the suffixed forms matched it -- and j_sub_D07364_12 is exactly as address-derived as j_sub_D07364.
1,852 ASD functions were being counted as meaningful names on that basis. The honest figure was
60.2%, not the 66.6% reported one commit ago. The repair pass added in that same commit skipped them
for the identical reason, so 713 thunks with properly named targets sat fixable and untouched.
Both regexes now accept the suffix. In the artifacts: 713 more names recovered, address-derived
entries 2,008 -> 1,295, meaningful names 17,416 -> 18,129 (60.2% -> 62.6%). The remaining 1,272
thunks point at targets that are not functions in their own build, so j_sub_* stays, which is
correct.
This is the fourth metric-definition error in four commits and the largest, and it is worse than the
others because I made it in code written immediately after describing the problem it repeats. Finding
one instance of a class of error is not evidence the class is clear. A regex that defines a quality
metric needs the same scrutiny as one that drives a rename: an over-strict pattern inflates the
number and hides the work it should have exposed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Correcting the headline count last commit exposed 243 functions whose name field was set to an IDA
address default. Looking at what they actually were, rather than treating them as a rounding error,
found a real defect: 220 were j_sub_<addr> thunk names, and 87 of those pointed at targets that by
now carry a proper name.
The cause is ordering. The j_<target> label comes from whatever Hex-Rays printed in the signature at
the moment that thunk was decompiled, so a thunk decompiled before its target was renamed keeps the
stale address forever. Nothing ever revisited it.
decompile_all now re-resolves them from `assigned` after the naming pass. That keeps it a pure
lookup -- the target name is one the pipeline already decided on, so no new inference enters -- and
thunks whose target is still unnamed keep j_sub_*, which is the honest answer rather than a
cosmetic upgrade.
In the artifacts: 87 names recovered across 5 ASD builds, address-derived entries 243 -> 156,
meaningful names 19,181 -> 19,268 (66.3% -> 66.6%). Names like j_asd_build_link_map_full and
j_asd_clear_link_outputs now appear where j_sub_D06CE4 used to.
Worth recording why this was invisible for so long: these functions were being counted as named, so
every coverage number I looked at said they were fine. The metric correction is what made the defect
visible, which is the one case here where fixing a measurement directly produced real improvement
rather than just a more accurate claim.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two GCP handlers were mislabelled in the libdump symbol set and the mislabels had been
propagating into every artifact. The duplicate name was the tell: FE0B and FE0D were both called
DestroyAuthenticatedSession.
The code settles it without needing the documents. gcp_cmdFE0C iterates ctx->crypto, zero-fills a
0x58 gcp_crypto_session and sets crypto->state and crypto->key, so it creates a CRYPTO session.
gcp_cmdFE0D computes "(char *)ctx + 88 * HIBYTE(arg10)" -- stride 88, the crypto array at
ctx+0x800 -- while gcp_cmdFE0B uses stride 80, the auth array at ctx+0x300. AUDIT-NEW-TAS-RE.md
states exactly that split, and the hardware findings agree: FINDING-GCP-ACQUIRE-GATE-BYPASS
records 0xFE0C as CreateCryptoSession.
Worth distinguishing from the FE07 case: that one claimed the wrong COMMAND and the dispatcher
cross-check caught it automatically. These two claim the right command and the wrong SEMANTICS,
so no command-id check can see them -- only reading what the code touches. The corrections are
applied by name through a RENAME_FIX table so they hold for every build.
While verifying them, the dispatcher kept printing the old callee name in four builds after the
rename had demonstrably succeeded. Hex-Rays caches pseudocode per function and
remote_ops.rename refreshes only the function it renamed, never its callers, so a stale cache was
reading as a failed rename. Every function's cached text is now invalidated before the artifacts
are emitted.
That turned out to matter far beyond the two names. Applied TYPES were also being hidden behind
stale text: GCP's field share goes 59% to 83.4%, its typed field accesses 1716 to 3081 and its raw
dereferences 1193 to 612, with no new structure added -- the types had been applied all along and
the emitted artifacts were showing pre-typing output. WSPE lands at 91%, HDCP 70%, XGMI 69%,
POWERPLAY 67%. Corpus field share 65.9% -> 66.4%, held down by ASD, which dominates the corpus and
barely moved.
This is the sixth consecutive pass whose main finding was that something already done was not
visible in the output. The remaining low scores are now informative rather than suspect: merit at
0% and opm at 19% are low because their structures are mostly opaque body arrays, not because
typing failed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The biggest single typing target in the corpus, asd_program_link_by_signal with 504 raw
pointer-arithmetic dereferences, had been counted as typed since the ASD structures were added.
It was not. Re-running the concentration analysis after the naming work -- which moved many
dereference-heavy functions out of ANON and into named groups -- put it straight back at the top
of the list, which is what prompted looking again.
Cause: the name-keyed arg1 block still carried its own inline copy of the prototype rewrite,
written before retype_arg1 was factored out. The inline copy does not strip comment lines before
locating the signature, and fw/ta_re.py applies recorded comments earlier in the same run, so on
any function carrying a comment the head parse ran across the comment text and produced a
declaration IDA rejected. The failure was invisible because the surrounding counter only counted
successes and the missing ones looked like functions absent from the build -- the reference
reported "12/16" for exactly the number of family members it lacks.
Switching that block to the shared helper takes the reference from 12/16 to 16/16 and converts
ASD from 35% to 59.5% field share on its own. Corpus field share goes 59.5% -> 64.6%, with raw
dereferences 8481 -> 7297.
Two avenues were measured and rejected first, so they are not retried: seeding ASD's weaker
builds from its best-named CORPUS build rather than the handover reference yields 1-4 names per
build at a much worse mismatch rate (15-35 against 0-4), because the handover names have already
propagated; and the structural residue is unchanged.
Note the struct-typed signature figure moves DOWN, 6.5% to 4.1%, purely because the denominator
grew: naming added thousands of previously-ANON functions to the emitted set. It is a ratio
artefact, not a regression, and is the clearest demonstration yet of why the field share is the
measure worth tracking.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
every failure
Byte and mnemonic porting only names a function whose own body still resembles the reference.
A function's position in the CALL GRAPH is independent evidence: if reference function A matches
target A' and both make the same number of calls, the Nth callee of A' is the Nth callee of A.
fw/ta_cgname.py applies that, with three restrictions chosen because positional alignment is
exactly the sort of heuristic that quietly invents names: the call counts must be EQUAL or the
anchor is skipped entirely rather than aligned partially; every anchor reaching a target must
agree on the name, or it is left alone; and the candidate must be within a factor of two of the
size of the function whose name it is taking. Rounds iterate, so a function named in one round
becomes an anchor in the next.
The anchor mismatch rate is reported as its own control, because a high rate means the builds
have diverged too far for position to mean anything. For ASD it is 4-8% (9-17 mismatched against
63-269 aligned), which is why the result is trustworthy. For RAS the same tool finds only 4-12
usable anchors and produces nothing at all -- its reference shares too little with the corpus
builds, and that is reported rather than worked around.
843 names applied across ASD's 17 non-reference builds, taking ASD from 62.5% to 66.0% named and
the corpus overall past two thirds.
Found and fixed while debugging why the first run applied zero: the rename response is
{"func":[...], "summary":{"ok":N,"failed":M}}, and both this tool and fw/ta_re.py were looking
for a "result" list that does not exist. In ta_re.py that meant the rename-error counter reported
zero unconditionally for the entire effort -- it could never have told me about a failed rename.
Both now read the summary. The symptom was visible only because this tool counted successes
rather than failures; the ta_re.py version failed silently in the safe direction, which is why it
went unnoticed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
functions named
The artifacts were full of ANON blocks that did not need to be. This pipeline treated a function
as named only if ITS OWN porting had assigned a name, and threw away the name the decompiler
states in the signature. For ASD that was most of the module: 11,737 of its unnamed functions are
4-byte thunks, and Hex-Rays resolves thunks and prints 'j_<target>' in the signature even where
the stored symbol is still sub_*, so 7,812 perfectly good derived names were being written out as
"ANON size=4".
The fix takes the name from the decompiled signature whenever porting produced none and the name
is not a bare sub_*. This is IDA's own thunk resolution rather than an inference, but it is
recorded as a distinct tier -- THUNK for the j_ names, IDA for the rest -- so it never passes for
a ported identity.
Named functions across all 99 builds: 10,259 of 28,945 (35.4%) -> 18,204 of 28,945 (62.9%). ASD
alone goes from 29% to 62%. Tiers: 7508 EXACT, 7812 THUNK, 2269 MNEM, 303 DISPATCH, 179 FUZZY,
133 IDA.
Two measurements on the way that corrected my earlier reasoning about where the naming gap was:
* the ASD reference has only 46 ambiguous bodies involving 109 functions, not the 677-908 the
per-build logs report. The per-build figure counts ambiguous TARGETS, and ASD's are
overwhelmingly tiny identical thunks -- which is also why disambiguating them by address
order was never worth its 12% error rate. They are now named from their jump targets instead,
which needs no tiebreak at all.
* 70% of ASD's reference names embed an address (asd_hdcp1_sub_1144, asd_svc_sub_273E), so they
carry subsystem information but claim an offset that is wrong in any other build. Worth
knowing before relying on a ported ASD name.
Log-string naming was also measured as an alternative and is small by comparison: only 98 unnamed
functions across the corpus reference a string literal at all (86 in GCP), and ASD logs numeric
codes rather than names, so the firmware's own log lines cannot name it.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two things I proposed last turn turned out to be worth less than claimed, and checking them was
most of this pass.
The first was wrong outright. I said the shared TEE formatting cluster was unnamed in ten modules
and that running the libnames clustering would let one declaration cover them. It would not: the
libnames clusters are ALREADY applied everywhere -- 225 matches across the twelve libdumps with
zero remaining sub_* among them. The formatting cluster simply does not exist outside gcp,
powerplay, wspe, xgmi and ras, so there was nothing to name and nothing to gain.
The second avenue is now measured and exhausted. Of the 55 shared clusters, only three others
dereference a1 at all -- lib_3f07c814_10, lib_78974a43_20, lib_71f66102_20 -- each at a single
offset, 56 dereferences between them. A one-field structure buys no readability, so no more
shared structures are worth declaring.
What did pay was enumerating the ASD link and caps families across all 18 builds rather than
across the reference alone, which found five members the earlier list had missed:
program_link_by_signal_v5, encoder_enable_seq_v2, clear_link_outputs, get_link_caps_full_v4 and
_v5. Each was verified to use only offsets that are a strict SUBSET of the structure it is given,
rather than inferred from its name. asd_topology_update is deliberately excluded: it dereferences
a2 over a different offset set, so neither structure describes it.
Also worth recording from the measurement, because it changes where the remaining work is: ASD's
arg-based dereferences in NAMED functions are now 174, down from 6314. Its remaining 4817 a1
dereferences are in UNNAMED functions, which no structure can reach until the functions
themselves are identified. The residue is a naming problem, not a typing one.
Measured across fw/decomp: typed field accesses 7101 -> 7327, raw dereferences 11849 -> 11753,
field share 37.5% -> 38.4%. Struct-typed signatures unchanged at 5.7%, as expected for a change
that retypes arguments of already-named functions.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Request structures were done for every component, but ASD still held 8446 of the raw
pointer-arithmetic dereferences, and typing its dispatcher had moved only a few hundred. So
rather than guess where the rest lived, it was measured: of those 8446, 6314 go through a1, 86%
of those sit in just 20 functions, and only 54 distinct functions touch a1 at all. The
unreadability is not spread across 6781 functions; it is concentrated in a handful.
A first attempt at clustering by name prefix was a dead end worth recording. The largest
cluster, asd_reg_* with 145 functions, has ZERO a1 structure accesses -- they are register
accessors that take an address and a value, not a context. Clustering by subsystem name says
nothing about whether a context structure exists.
The two families that do matter were found by offset signature instead:
asd_link_cfg the link/encoder descriptor, from asd_program_link_by_signal{,_v2,_v3,_v4}
and asd_encoder_enable_seq{,_v3} -- 1638 dereferences across six functions.
Members are dwords throughout rather than placing a 64-bit field at the
observed 0x14 qword read, which is not 8-aligned and would shift every later
offset.
asd_link_caps the capability/handler block, from asd_get_link_caps_full{,_v2,_v3},
asd_resolve_asic_handlers and asd_dio_read_block; offsets 0x04..0x24
contiguous.
Both are internal structures reached through an argument, so unlike the eight host requests with
enforced floors there is no size check anywhere; both sizes are maxima observed and say so.
They are applied by rewriting only the FIRST PARAMETER of each function's live prototype, so the
rest of the signature -- which came from the recorded handover prototypes -- survives instead of
being replaced by an invented declaration. 9 of 11 land on the reference build.
load_type_decls was only reading <TA>_DECLS, so the internal structures were declared in the
table and silently never parsed; it now picks up <TA>_INTERNAL_DECLS as well.
Measured across fw/decomp: ASD typed field accesses 2311 -> 3729 and raw dereferences
8446 -> 6863, taking ASD's field share from 21.5% to 35.2%. Across all modules, field accesses
3828 -> 5246 and field share 21.1% -> 29.2%. Struct-typed signatures are unchanged at 4.8%,
which is expected: this change retypes arguments of already-named functions rather than adding
new signatures, and is the clearest case yet of why the signature count alone is a poor measure
of readability.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ASD is 6781 of the 10088 decompiled functions and had no domain types at all, so it was the
only place left where work could move the overall figure.
It is driver-class rather than a TA: there is no TA entry trampoline, so the entry resolution
used for every other component does not apply. Its dispatcher hangs off the trampoline's +0x1C
slot, and the resolver verifies the ARM stub shape rather than assuming the offset, so a layout
change returns nothing instead of a confidently wrong address. That resolves to 0xD013B8 in all
17 Windows builds, matching the value psp_emu validated independently across its own 12.
The request layout is read off the dispatcher's own 359 lines: an rpc id at +0x00 switched over
0x180..0x1C0, then arguments at +0x04, +0x08, +0x0C, +0x10 and a byte at +0x14, with the first
two also read as bytes and halfwords.
The size is the one weak point and is labelled as such in the declaration: nothing validates a
request size, so 0x18 is not an enforced bound but the smallest 4-aligned size covering every
observed access. xgmi_req, oc_req and wspe_req all close against a size the firmware itself
checks; this one does not, and no code arrays the structure, so the risk is contained.
Applied, the dispatcher reads 'switch ( req->rpc_id )' and 'asd_hdcp1_init(a1: req->arg1)' in
place of pointer arithmetic, with 99 field accesses across it.
Also adds a body-level readability metric, because counting struct-typed SIGNATURES badly
under-measures this change: typing one dispatcher rewrites hundreds of lines while moving the
signature count by two. Measured across fw/decomp, typed field accesses now stand at 3494
against 8255 remaining raw pointer-arithmetic dereferences, 29.7% of the total. HDCP is now the
worst remaining offender with 1742 raw dereferences, zero typed fields and zero struct-typed
signatures.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
The twelve Windows TA types take their symbols from fw/libdumps; ASD, HDCP, RAS and DTM
have theirs in psp_out/handover, in a different shape that also carries prototypes and
comments. This adds that reference path, so every component the corpus holds is covered by
one pipeline rather than twelve of fifteen.
ASD needed its own ELFs. It is driver-class, not a TA: base 0xD00100, and no TA entry
trampoline, so dispatcher-anchored naming does not apply to it at all -- its RPC dispatcher
hangs off trampoline+0x1C instead. The base is not guessed; it matches
psp_out/handover/elf/asd2.elf, whose LOAD segment contains 1562/1562 of the recorded ASD
symbols. The frame discriminator used for the TAs is inapplicable here for the same reason
the trampoline is: there is none, and it reports "neither" for all 17 builds.
Prototypes are applied where recorded. Without them Hex-Rays guesses argument counts and
types, which is most of the distance between readable C and a wall of _DWORD; 1232 of 1434
land on the ASD reference and the rest are rejected by IDA, reported rather than hidden.
One more false-positive class in the dispatcher cross-check, found by running it on HDCP:
the agreement test assumed a ported name encodes its command number, which is GCP's
convention and not HDCP's, so every one of HDCP's 16 commands was reported as conflicting.
A name can only contradict the dispatcher if it claims a command itself, so the check now
requires the ported name to match <ta>_cmd<hex> before judging it. HDCP drops to zero
conflicts while GCP's single real one -- the 0xFE07 handler carrying the inherited name
gcp_cmdFE03_CreateAuthenticatedSession -- is still reported.
Coverage is honest rather than flattering. ASD lands 162-425 named of ~1100-1400 functions
per build, and the dominant limiter is ambiguity, not similarity: 677-908 functions per
build share a byte signature with a differently-named reference function and are skipped
instead of being assigned arbitrarily. ASD is full of identical small stubs, so this is
expected, but it means the ASD figures are a floor and a smarter tie-break would raise
them. RAS is weaker still at 13-20 named per build.
|