aboutsummaryrefslogtreecommitdiffstats
path: root/fw/ta_struct_re.py (follow)
Commit message (Collapse)AuthorAge
* harvest struct-field evidence, with a control that caught my own bad ↵user2026-10-01
controls twice Defining PSP structs by hand needs evidence, and the evidence is which offsets the code touches through each pointer and at what WIDTH. This reads that out of Hex-Rays output rather than re-implementing register dataflow: the decompiler has already resolved which register held an argument, and it writes accesses in forms that state offset and width directly. The value is in the control, and the control failed three times before it meant anything. First failure was circular. Validating on GCP after the pipeline had already applied GCP_DECLS meant the array accesses rendered as 'ctx->auth[i]', which the harvester skips by design, so it was being asked to rediscover a layout from a database that already had it. The control has to run on a freshly analysed, untyped build. Second failure was real and the harvester's fault. Array bases are not written against the argument: GCP computes 'v6 = a1 + 80 * HIBYTE(v4)' and then reads '*(_DWORD *)(v6 + 768)', so 0x300 only ever appears as an offset on the derived pointer. Scanning accesses through the argument alone can never see an array base. One level of alias tracking fixes it, and a scaled derivation is what distinguishes an array base from a field offset carried through. Third failure was the control itself being wrong. Demanding the literal bases 0x300 and 0x800 is not satisfiable even in principle, because the index is folded into the derived pointer and what is observable is base + FIELD -- the bare base shows up only when the field offset is zero. The requirement is now that each known region is reached and that offsets seen inside it lie within one element, which is what folding the index implies. With that, GCP's proven layout is rediscovered from code alone: auth[16] at 0x300 stride 80 (offsets 0x304/0x318/0x348 -> fields 4/24/72), crypto[64] at 0x800 stride 88 (0x820 -> field 32), and asd_refcount exactly at 0x1E00. drm[32] at base 0 is excluded from the control because offset 0 is indistinguishable from ordinary field access. Caveat to carry into the authoring work: the 'a1[i]' index form is scaled by the pointer's declared element width, so when Hex-Rays types an argument as _BYTE * the reported offsets are byte-scaled and will not line up with dword fields. XGMI arg1 shows offsets 0x1/0x2/0x3 at 4-byte width from exactly this, and they should not be read as real fields.