#!/usr/bin/env python3 """AUDIT-044: M5.5 typed-vptr indirect-reachability survey of the audit-009 cluster 0x82285000-0x82294000 in sylpheed.db. READ-ONLY. Do not write to the DB. Run from xenia-rs root: python3 audit-runs/audit-044-m55-cluster-survey/survey.py """ import csv import os import duckdb CLUSTER_LO = 0x82285000 CLUSTER_HI = 0x82294000 DB = "sylpheed.db" OUT = "audit-runs/audit-044-m55-cluster-survey/query_outputs" # audit-009 L1 PCs L1_PCS = [ ("sub_822919C8", 0x822919C8), ("sub_82293448", 0x82293448), ("sub_82288028", 0x82288028), ("sub_82292D80", 0x82292D80), ("sub_822851E0", 0x822851E0), ("sub_82286BC8", 0x82286BC8), ] # audit-033 CTOR-PROBE chain (leaf -> root) AUDIT033_CHAIN = [ ("sub_82451E20", 0x82451E20), ("sub_82450720", 0x82450720), ("sub_82450638", 0x82450638), ("sub_821CB968", 0x821CB968), ("sub_821CD458", 0x821CD458), ("sub_821CBEA8", 0x821CBEA8), ("sub_821CECF0", 0x821CECF0), ("sub_821C4988", 0x821C4988), ] EXTRA_REFERENCED = [ ("sub_8228E138", 0x8228E138), ("sub_8228E498", 0x8228E498), ("sub_82172BA0", 0x82172BA0), ("sub_8228A628", 0x8228A628), ] def main(): os.makedirs(OUT, exist_ok=True) con = duckdb.connect(DB, read_only=True) # preload reach sets so we use Python set ops, not nested SQL static_reach = {r[0] for r in con.execute("SELECT addr FROM v_reachability_from_entry").fetchall()} ind_reach = {r[0] for r in con.execute("SELECT addr FROM v_indirect_reachability_from_entry").fetchall()} print(f"static reach |X|={len(static_reach)}; indirect reach |X|={len(ind_reach)};" f" newly via M5.5={len(ind_reach - static_reach)}") # ---------- Q1/Q2 cluster reach ---------- q1 = con.execute( "SELECT COUNT(DISTINCT f.address) FROM functions f " "JOIN v_reachability_from_entry r ON r.addr=f.address " "WHERE f.address>=? AND f.address=? AND f.address=? AND address=? AND f.address=? AND idc.method_address=? AND m.function_addressroot):") for name, pc in AUDIT033_CHAIN + EXTRA_REFERENCED + L1_PCS: s = pc in static_reach; i = pc in ind_reach print(f" {name:<14} 0x{pc:08x} static={'Y' if s else 'N'} indirect={'Y' if i else 'N'}") # ---------- vptr writer (constructor) reachability ---------- print("Cluster-vtable vptr-writers (constructors):") ctors = con.execute(""" SELECT vw.vtable_address, vw.writer_pc, vw.writer_function, f.name FROM vptr_writes vw LEFT JOIN functions f ON f.address=vw.writer_function WHERE vw.vtable_address IN (?, ?) ORDER BY vw.vtable_address, vw.writer_pc """, [0x820a9c28, 0x820aa024]).fetchall() for vt, wpc, wfn, name in ctors: sr = wfn in static_reach; ir = wfn in ind_reach print(f" vt=0x{vt:08x} writer_fn=0x{wfn:08x} ({name}) writer_pc=0x{wpc:08x} " f"static={'Y' if sr else 'N'} indirect={'Y' if ir else 'N'}") con.close() if __name__ == "__main__": main()