chore: track audit-runs summary artifacts (md/csv/diff/txt/json/etc)
Snapshot of every non-log artifact under audit-runs/ from audits 003 through 058: findings.md per audit, comparison CSVs, probe diffs, schema docs, register-dump txts, lr-trace JSONL streams, the saved canary patch diffs, etc. ~284 files / ~52 MB total. Excluded (per .gitignore): probe stdout/stderr/log streams (the raw firehose), guest-memory dumps under audit-026/027/029 (4.5 GB of .bin files; *.bin pattern added to .gitignore this commit). Also adds the orphan audit-058-sub825070F0-activation directory that a subagent accidentally created at project-root instead of under xenia-rs/audit-runs/; relocated to its proper home. Purpose: cross-machine continuity. With these summaries committed, a fresh clone gives the next session the full per-audit context (findings + tables + cascade predictions) without dependence on local-only working tree. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
152
audit-runs/audit-026-mem-diff/diff_v80.py
Normal file
152
audit-runs/audit-026-mem-diff/diff_v80.py
Normal file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Comprehensive dword-level diff of canary's v80 vs ours.
|
||||
|
||||
For every 4-byte BE-aligned dword in [0x80000000, 0x90000000):
|
||||
- canary_dw = canary[i*4..i*4+4] interpreted as BE u32
|
||||
- ours_dw = ours [i*4..i*4+4] interpreted as BE u32
|
||||
|
||||
Records:
|
||||
CASE A (primary): canary_dw in 0x82000000..0x82A00000 (game-code addr) AND ours_dw != canary_dw
|
||||
CASE B (inverse): ours_dw in 0x82000000..0x82A00000 AND canary_dw != ours_dw
|
||||
|
||||
Produces:
|
||||
diff.txt full sorted A-list
|
||||
diff-b.txt inverse B-list (smaller, often empty)
|
||||
histogram.txt bucket count by canary PC's 0x1000-aligned function
|
||||
l1-hits.txt specific renderer cluster L1 PC hits
|
||||
tables.txt runs of >=4 consecutive dwords with same divergence shape
|
||||
"""
|
||||
import struct
|
||||
import sys
|
||||
import os
|
||||
from collections import defaultdict
|
||||
|
||||
V80_BASE = 0x80000000
|
||||
V80_LEN = 0x10000000
|
||||
PC_LO = 0x82000000
|
||||
PC_HI = 0x82A00000
|
||||
|
||||
L1_PCS = {
|
||||
0x822919C8: "sub_822919C8",
|
||||
0x82293448: "sub_82293448",
|
||||
0x82288028: "sub_82288028",
|
||||
0x82292D80: "sub_82292d80",
|
||||
0x822851E0: "sub_822851e0",
|
||||
0x82286BC8: "sub_82286bc8",
|
||||
# also worth flagging from the AUDIT-025 audio path:
|
||||
0x82006CF4: "audio_system_vtable_0x82006CF4", # unlikely in v80 but worth logging
|
||||
0x824D23B0: "sub_824D23B0_audio_KeSetEvent",
|
||||
}
|
||||
|
||||
NAMED_ANCHORS = {
|
||||
0x828F3D08: "0x100c dispatcher",
|
||||
0x828F3EC0: "0x1004 dispatcher",
|
||||
0x828F4070: "0x15e4 worker singleton",
|
||||
0x828F4838: "audit-023 listener struct",
|
||||
0x828A3230: "audio buffer-completion semaphore",
|
||||
0x828A3254: "audit-025 audio wait target",
|
||||
0x40BA9A80: "audit-016 listener struct (heap)",
|
||||
}
|
||||
|
||||
def main():
|
||||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
canary_path = os.path.join(here, "canary-v80.bin")
|
||||
ours_path = os.path.join(here, "ours-v80.bin")
|
||||
canary = open(canary_path, "rb").read()
|
||||
ours = open(ours_path, "rb").read()
|
||||
assert len(canary) == V80_LEN, len(canary)
|
||||
assert len(ours) == V80_LEN, len(ours)
|
||||
|
||||
a_list = [] # canary has PC, ours different
|
||||
b_list = [] # ours has PC, canary different
|
||||
for i in range(0, V80_LEN, 4):
|
||||
cdw = struct.unpack_from(">I", canary, i)[0]
|
||||
odw = struct.unpack_from(">I", ours, i)[0]
|
||||
if cdw == odw:
|
||||
continue
|
||||
addr = V80_BASE + i
|
||||
if PC_LO <= cdw < PC_HI:
|
||||
a_list.append((addr, cdw, odw))
|
||||
if PC_LO <= odw < PC_HI:
|
||||
b_list.append((addr, cdw, odw))
|
||||
|
||||
print(f"[i] case A divergences (canary has PC, ours differs): {len(a_list)}")
|
||||
print(f"[i] case B divergences (ours has PC, canary differs): {len(b_list)}")
|
||||
|
||||
with open(os.path.join(here, "diff.txt"), "w") as f:
|
||||
f.write(f"# A-list: {len(a_list)} entries — canary has 0x82xxxxxx PC, ours differs\n")
|
||||
for addr, c, o in a_list:
|
||||
f.write(f"addr={addr:#010x} canary={c:#010x} ours={o:#010x}\n")
|
||||
with open(os.path.join(here, "diff-b.txt"), "w") as f:
|
||||
f.write(f"# B-list: {len(b_list)} entries — ours has 0x82xxxxxx PC, canary differs\n")
|
||||
for addr, c, o in b_list:
|
||||
f.write(f"addr={addr:#010x} canary={c:#010x} ours={o:#010x}\n")
|
||||
|
||||
# Histogram by canary PC value (0x1000-aligned)
|
||||
bucket = defaultdict(int)
|
||||
for _addr, c, _o in a_list:
|
||||
bucket[c & ~0xFFF] += 1
|
||||
sorted_b = sorted(bucket.items(), key=lambda x: -x[1])
|
||||
with open(os.path.join(here, "histogram.txt"), "w") as f:
|
||||
f.write("# canary PC value bucket (0x1000-aligned) -> count of A-list entries\n")
|
||||
for k, v in sorted_b:
|
||||
f.write(f"{k:#010x} {v}\n")
|
||||
print(f"[i] top 10 PC buckets (canary value):")
|
||||
for k, v in sorted_b[:10]:
|
||||
print(f" {k:#010x} {v}")
|
||||
|
||||
# L1 PC explicit hits
|
||||
l1_hits = []
|
||||
for addr, c, o in a_list:
|
||||
if c in L1_PCS:
|
||||
l1_hits.append((addr, c, o, L1_PCS[c]))
|
||||
with open(os.path.join(here, "l1-hits.txt"), "w") as f:
|
||||
f.write(f"# Renderer cluster L1 PC hits in canary's v80 (count={len(l1_hits)})\n")
|
||||
for addr, c, o, name in l1_hits:
|
||||
f.write(f"addr={addr:#010x} canary={c:#010x} ours={o:#010x} // {name}\n")
|
||||
print(f"[i] L1 PC hits: {len(l1_hits)}")
|
||||
for addr, c, o, name in l1_hits[:20]:
|
||||
print(f" addr={addr:#010x} canary={c:#010x} // {name}")
|
||||
|
||||
# Table detection: runs of 4+ consecutive 4-byte dwords where canary
|
||||
# has any 0x82xxxxxx and ours has zero (or 0xFFFFFFFF sentinel).
|
||||
addr_set_a = {a for a, _c, _o in a_list}
|
||||
runs = []
|
||||
i = 0
|
||||
a_sorted = sorted(a_list, key=lambda x: x[0])
|
||||
j = 0
|
||||
while j < len(a_sorted):
|
||||
start = j
|
||||
while j + 1 < len(a_sorted) and a_sorted[j+1][0] == a_sorted[j][0] + 4:
|
||||
j += 1
|
||||
if j - start + 1 >= 4:
|
||||
entries = a_sorted[start:j+1]
|
||||
zero_count = sum(1 for _a, _c, o in entries if o == 0)
|
||||
runs.append((entries[0][0], len(entries), zero_count, entries))
|
||||
j += 1
|
||||
runs.sort(key=lambda r: -r[1])
|
||||
with open(os.path.join(here, "tables.txt"), "w") as f:
|
||||
f.write(f"# Consecutive A-list runs (>=4 dwords): {len(runs)} runs\n\n")
|
||||
for base, length, zeros, entries in runs[:80]:
|
||||
f.write(f"=== run base={base:#010x} length={length} zeros_in_ours={zeros} ===\n")
|
||||
for addr, c, o in entries[:32]:
|
||||
f.write(f" +{addr-base:#06x}: canary={c:#010x} ours={o:#010x}\n")
|
||||
if length > 32:
|
||||
f.write(f" ... and {length-32} more\n")
|
||||
f.write("\n")
|
||||
print(f"[i] table-shaped runs (>=4 consecutive A-list dwords): {len(runs)}")
|
||||
for base, length, zeros, _ in runs[:8]:
|
||||
print(f" base={base:#010x} length={length} zeros={zeros}")
|
||||
|
||||
# Anchor-address neighborhood reports
|
||||
with open(os.path.join(here, "anchors.txt"), "w") as f:
|
||||
f.write("# Diff entries within ±0x100 of named anchor addresses\n\n")
|
||||
for anchor, name in NAMED_ANCHORS.items():
|
||||
f.write(f"=== {anchor:#010x} ({name}) ===\n")
|
||||
for addr, c, o in a_list:
|
||||
if abs(addr - anchor) <= 0x100:
|
||||
f.write(f" addr={addr:#010x} canary={c:#010x} ours={o:#010x}\n")
|
||||
f.write("\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user