sots-re/verify/results/research-completion-abi-independent/reproduce_run_735fcb8f4876c10285b03fad.py

106 lines
4.6 KiB
Python

#!/usr/bin/env python3
"""Fresh verifier-owned static ABI reproduction; refuses output overwrite."""
import hashlib
import json
import pathlib
import subprocess
ROOT = pathlib.Path("/home/alex/sots-re")
OUT = ROOT / "verify/results/research-completion-abi-independent/run-735fcb8f4876c10285b03fad"
EXE = ROOT / "dumps/sots.exe"
OBJDUMP = pathlib.Path("/usr/bin/objdump")
# Six repaired narrow/wide pairs, four controls whose original stops were complete,
# and the dedup/helper/callee windows needed to test description and NaN claims.
WINDOWS = [
("observed-alloc-narrow", "D", 0x0057E590, 0x0057E5E4),
("observed-alloc-wide", "D", 0x0057E590, 0x0057E5E6),
("player-append-narrow", "D", 0x0086C580, 0x0086C62E),
("player-append-wide", "D", 0x0086C580, 0x0086C630),
("player-copy-narrow", "D", 0x007693F0, 0x007694C0),
("player-copy-wide", "D", 0x007693F0, 0x007694C2),
("observed-push-narrow", "D", 0x007B7320, 0x007B739F),
("observed-push-wide", "D", 0x007B7320, 0x007B73A1),
("observed-realloc-narrow", "D", 0x007B34E0, 0x007B35EF),
("observed-realloc-wide", "D", 0x007B34E0, 0x007B35F1),
("string-alloc-narrow", "D", 0x004249A0, 0x00424ADA),
("string-alloc-wide", "D", 0x004249A0, 0x00424ADC),
("observed-ctor-control", "D", 0x008562A0, 0x0085630D),
("observed-copy-control", "D", 0x0079A150, 0x0079A1D9),
("player-dtor-control", "D", 0x0061AE90, 0x0061AEFC),
("import-thunks-control", "D", 0x00924FAA, 0x00924FBC),
("dedup-narrow", "D", 0x00825D40, 0x00825E65),
("dedup-wide", "D", 0x00825D40, 0x00825E67),
("string-not-equal", "D", 0x0046F8C0, 0x0046F8F0),
("string-compare", "D", 0x004236A0, 0x0042370D),
("byte-compare", "D", 0x00422720, 0x00422796),
("player-ctor", "D", 0x0084EE30, 0x0084EEF4),
]
EXPECTED = {
"observed-alloc": "c2 04 00",
"player-append": "c2 04 00",
"player-copy": "c2 04 00",
"observed-push": "c2 04 00",
"observed-realloc": "c2 04 00",
"string-alloc": "c2 08 00",
"dedup": "c2 08 00",
}
def digest(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()
def instruction_rows(data: bytes) -> list[bytes]:
return [line.rstrip() for line in data.splitlines() if b":" in line and line.lstrip()[:1].isdigit()]
OUT.mkdir(exist_ok=False)
streams = {}
records = []
for name, mode, start, stop in WINDOWS:
args = [str(OBJDUMP), f"-{mode}"]
if mode == "D":
args.append("-Mintel")
args += [f"--start-address=0x{start:08x}", f"--stop-address=0x{stop:08x}", "dumps/sots.exe"]
proc = subprocess.run(args, cwd=ROOT, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False)
streams[name] = proc.stdout
(OUT / f"{name}.stdout.txt").write_bytes(proc.stdout)
(OUT / f"{name}.stderr.txt").write_bytes(proc.stderr)
records.append({
"name": name, "argv": args, "cwd": str(ROOT), "returncode": proc.returncode,
"stdout": {"bytes": len(proc.stdout), "sha256": digest(proc.stdout)},
"stderr": {"bytes": len(proc.stderr), "sha256": digest(proc.stderr)},
"instruction_rows": len(instruction_rows(proc.stdout)),
})
comparisons = []
for base, expected_wide in EXPECTED.items():
narrow_rows = instruction_rows(streams[f"{base}-narrow"])
wide_rows = instruction_rows(streams[f"{base}-wide"])
narrow_terminal = narrow_rows[-1].decode("ascii")
wide_terminal = wide_rows[-1].decode("ascii")
preceding_equal = narrow_rows[:-1] == wide_rows[:-1]
passed = preceding_equal and "\tc2 " in narrow_terminal and expected_wide in wide_terminal
comparisons.append({
"name": base, "preceding_rows_equal": preceding_equal,
"narrow_terminal": narrow_terminal, "wide_terminal": wide_terminal,
"expected_wide_bytes": expected_wide, "pass": passed,
})
manifest = {
"schema": "sots-abi-independent-static/1",
"session": "run-735fcb8f4876c10285b03fad",
"actor": "research-abi-independent",
"scope": "independent static reproduction only; no game/allocator/RNG execution",
"input": {"path": "dumps/sots.exe", "bytes": EXE.stat().st_size, "sha256": digest(EXE.read_bytes())},
"tool": {"path": str(OBJDUMP), "sha256": digest(OBJDUMP.read_bytes())},
"windows": records,
"comparisons": comparisons,
"all_processes_positive": all(r["returncode"] == 0 and r["stdout"]["bytes"] > 0 and r["stderr"]["bytes"] == 0 for r in records),
"all_boundary_predictions_hold": all(c["pass"] for c in comparisons),
}
(OUT / "manifest.json").write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
if not manifest["all_processes_positive"] or not manifest["all_boundary_predictions_hold"]:
raise SystemExit(1)