diff options
| author | user <user@clank> | 2026-10-01 15:58:53 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-10-01 15:58:53 +0200 |
| commit | b263d133a992c6b3280516f159c664dae6863b5d (patch) | |
| tree | 2119426cc3556ef8273728ee226a2249d30fce8b /fw/ta_re.py | |
| parent | correct asd_link_cfg, which was a truncated view, and type by offset signature (diff) | |
| download | amd-psp-re-b263d133a992c6b3280516f159c664dae6863b5d.tar.gz amd-psp-re-b263d133a992c6b3280516f159c664dae6863b5d.tar.xz amd-psp-re-b263d133a992c6b3280516f159c664dae6863b5d.zip | |
type the formatting-state helpers the hash-name rule cannot see, using size as a second check
First, a truncation audit of the structures already declared, prompted by asd_link_cfg turning
out to be half its real size. The check looks for a variable that has BOTH field accesses and
leftover raw dereferences, which is what an undersized structure produces. Across every module
and build there are none, so no other declared structure is being overrun in the artifacts. Worth
noting the limit of that check: it could not have caught asd_link_cfg either, because the
functions that overran it were unnamed and therefore untyped, with no field accesses to compare
against.
The gain this pass is 88 functions across gcp, powerplay, wspe and xgmi that dereference a1 over
exactly {0x08, 0x18, 0x1C, 0x20} -- a subset of tee_fmt_state -- but carry no hash-cluster name,
so they appear as sub_*/ANON and the name-keyed rule could not reach them. 802 dereferences.
Four offsets alone are a weak signature and were not trusted on their own. SIZE is required as a
second discriminator: a candidate must be the same byte length as a function that IS a confirmed
cluster member. 86 of the 88 satisfy both conditions, and the four sizes involved -- 112, 178,
606, 758 -- all occur among confirmed members. The contrast with the ASD rule is deliberate: there
a fifteen-offset signature was specific enough alone, here it is not, and the code says so rather
than reusing the same threshold blindly.
Measured across fw/decomp: typed field accesses 9058 -> 10789, raw pointer-arithmetic
dereferences 10107 -> 9323, field share 47.3% -> 53.6%, struct-typed signatures 5.7% -> 6.0%.
More than half of all structured memory access in the artifacts is now through named fields.
Diffstat (limited to 'fw/ta_re.py')
| -rw-r--r-- | fw/ta_re.py | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/fw/ta_re.py b/fw/ta_re.py index e115502..d49f3c5 100644 --- a/fw/ta_re.py +++ b/fw/ta_re.py @@ -1058,6 +1058,40 @@ def run_type(ta: str, outdir: Path, limit: int | None, validate_only: bool) -> i % (nret, len(want)), flush=True) # Signature-based a1 typing for functions no name-keyed rule reaches. + # Signature+size typing for the shared formatting state, every module. + try: + fmt_off = set(_ti0.FMT_SIG_OFFSETS); fmt_sz = set(_ti0.FMT_SIG_SIZES) + fmt_ty = _ti0.FMT_SIG_TYPE; fmt_min = _ti0.FMT_SIG_MIN_DEREFS + except Exception: + fmt_off, fmt_sz, fmt_ty = set(), set(), None + nfmt = 0 + if fmt_off and fmt_ty: + for fn3 in funcs: + if fn3["size"] not in fmt_sz: + continue + ad3 = fn3["addr"] + nm3 = assigned.get(ad3, (None, None))[0] or fn3["name"] + if any(fr in nm3 for fr, _st in shared): + continue # already typed by name + try: + rr3 = client.call(remote_ops.decompile, addr=ad3, + include_addresses=False) or {} + cf3 = rr3.get("code") or "" + except Exception: + continue + hits3 = re.findall(r"\*\(\s*_?\w+\s*\*\s*\)\s*\(\s*a1\s*\+\s*" + r"(\d+|0x[0-9A-Fa-f]+)\s*\)", cf3) + if len(hits3) < fmt_min: + continue + offs3 = {int(x, 0) for x in hits3} + if not offs3 or not offs3 <= fmt_off: + continue + if retype_arg1(client, remote_ops, ad3, nm3, fmt_ty): + nfmt += 1 + if nfmt: + print(" fmt-state signature-typed a1 on %d functions" % nfmt, + flush=True) + if ta == "asd": core = set(getattr(_ti, "ASD_SIG_CORE", ()) if "_ti" in dir() else ()) try: |
