# -*- coding: utf-8 -*- """验证 struct_40_9 的消歧特征是否跨构建稳定。 判别: A 组: 闭包体最后写入 **空串** (PUSH_EMPTY_STR; SET_PROP) B 组: 闭包体最后写入 **随机 int32** (PUSH_IMM ; SET_PROP) """ import glob import sys from collections import Counter, defaultdict from pathlib import Path ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT / "tools")) import tdc_modules as tm # noqa: E402 import tdc_program as tp # noqa: E402 BATCH = sorted(glob.glob(str(ROOT / "har" / "online" / "*" / "tdc_*.js"))) def closure_body(p, entry): """取模块唯一闭包的 target 体。""" cls = [c for c in p.closures if p.owner(c.pc) == entry] if not cls: return None return p.function_code(cls[0].target) def disamb(p, entry): """返回 'empty' | 'rand' | None""" body = closure_body(p, entry) if body is None: return None imms = [x["operands"][0] for x in body if x["name"] == "PUSH_IMM" and x["operands"]] big = [v for v in imms if v > 1_000_000] if big: return "rand" return "empty" stats = defaultdict(lambda: defaultdict(list)) for f in BATCH: p = tp.load(f) reg = dict(p.module_registry(0)) rows = tm.analyze(f) for r in rows: if r["name"] != "struct_40_9": continue d = disamb(p, reg[r["module"]]) stats[f.split("/")[-1]][d or "?"].append((r["item"], r["module"])) print("%-24s %-8s %s" % ("构建", "判别", "项(模块)")) print("-" * 70) ok = True for f, groups in stats.items(): for d, members in sorted(groups.items()): print("%-24s %-8s %s" % (f, d, members)) # 每份构建必须 empty 1 个 + rand 1 个 if len(groups.get("empty", [])) != 1 or len(groups.get("rand", [])) != 1: ok = False print() print(">>> 每份构建都是 empty×1 + rand×1 :", ok) print(">>> 结论:", "可静态消歧(写入空串 vs 写入随机 int32)" if ok else "仍不可分")