# AUDIT-060 PROBE C-WIN — canary side, fnptr-array bootstrap Date: 2026-05-12 Engine: xenia-canary Windows Debug under Wine 9.0 (`6de80dffe` clean + AUDIT-030 patch re-applied/reverted) ISO: Project Sylpheed - Arc of Deception (USA/EU) Output dir: `xenia-rs/audit-runs/audit-060-fnptr-array-bootstrap/` Discipline: READ-ONLY wrt logic; audit-030 patch reverted clean at exit. ## Phase 1: sanity check — PASS PC `0x825070F0`, 90s wallclock → **1 fire, lr=0x824F7B24** — bit-identical to AUDIT-058 Linux Debug canary. Windows Debug canary under Wine reaches the same activation phase. **New oracle validated** for future audits. ## Phase 2: `sub_821B6DF4` entry — 0× fires - 120s → 0 fires (`canary-sub821B6DF4-120s.log`) - 240s → 0 fires (`canary-sub821B6DF4-240s.log`) **Does not fire in canary either** at the runtimes probed. Cross-reference with PROBE-O (ours-summary.md) — which dis-asmed `sub_821B6DF4` and found `subi r31, r12, 112; mflr r12; ...` prolog + MSVC FuncInfo magic 0x19930522 at `.rdata:0x820C1994` referencing it — confirms `sub_821B6DF4` is a **C++ EH catch-handler thunk**, not a normal call target. AUDIT-058's "static caller ladder" was reading EH handler-array linkage as if it were a call ladder. ## Phase 3: `sub_8245FEB8` entry — 2× fires, single caller PC - 120s → **2 fires, both lr=0x8246020C** (`canary-sub8245FEB8.log`) - Fire 1: r3=BC365C40 r4=00000004 r5=701CF340 r6=0 r31=701CF2E0 - Fire 2: r3=BC365C40 r4=00000001 r5=705AFB00 r6=0 r31=705AFAA0 - Same r3, different r4 (4 then 1) — installing two different slot indices into same dispatch object. ## Phase 4: LR resolution + caller chain LR `0x8246020C` → containing fn `sub_824601A0` (824601A0..82460254). Linear caller chain in DB: ``` sub_8245FEB8 (vptr installer) ← sub_824601A0 (1 static caller) ← sub_82460118 (1 static caller) ← sub_82452AB8 (6 static callers — branches; AUDIT-050 direct target of sub_82452DC0) ← sub_82452DC0 (work-submitter; AUDIT-050-054 root) ``` Verified: `sub_82452DC0 → sub_82452AB8` is one of the 9 edges AUDIT-050 enumerated as direct targets of the work-submitter. ## Phase 5: cross-reference `sub_8245FEB8` has 2 static callers: - `sub_824601A0` (1 site, PC=0x82460208) — the one canary fires via in this run - `sub_8245FB68` (2 sites, PCs 0x8245FD00 + 0x8245FD28) — internal lib path The PROBE-O parallel track (xenia-rs side) found `sub_8245FEB8` actually **fires 5× in ours**, called from multiple paths including `sub_824601A0+0x68` (PC=0x82460208) — i.e. **the exact same call site canary uses**. AUDIT-059's "vptr installer dead in ours" was **FALSIFIED at runtime by PROBE-O**. ## Combined verdict (this run + PROBE-O) 1. **AUDIT-058's caller ladder is an EH unwind path, not a normal activation chain.** `sub_821B6DF4` is a C++ catch-handler. The 6-level ladder up from `sub_825070F0` is throw-side EH metadata, fires iff a specific exception type-id is thrown. Doesn't fire in canary at 240s and doesn't fire in ours at 500M instr — neither engine throws this exception in our window. 2. **AUDIT-059's "vptr installer dead in ours" is false** (PROBE-O measured 5× fires). The dispatch-table-installer infrastructure (`sub_8245FEB8`) is ALIVE in both engines. The γ-wedge bug is NOT a missing vptr-install — it's downstream. 3. **Convergence on AUDIT-050-054 territory:** the bootstrap path for the two AUDIT-059 signalers AND the AUDIT-058 `sub_825070F0` chain all funnel through `sub_82452DC0` (work-submitter). This is the SAME gate AUDIT-051's `+0x78 beq cr6` predicate identifies. AUDIT-060 collapses the gamma investigation into AUDIT-051's struct-population bug — there is ONE root cause, not multiple parallel "dead clusters". 4. **New Windows Debug canary oracle is operational.** Wine + audit-030 patch reproduces Linux Debug canary results bit-identically (verified at PC `0x825070F0`). Can be used for future probes including potentially deeper traces. ## Files - `canary-sanity-825070F0.log` — Phase 1 (1 fire) - `canary-sub821B6DF4-120s.log` — Phase 2 first run (0 fires) - `canary-sub821B6DF4-240s.log` — Phase 2 extended (0 fires) - `canary-sub8245FEB8.log` — Phase 3 (2 fires lr=0x8246020C) - `p2-stdout.log`, `p2b-stdout.log`, `p3-stdout.log` — wine stdout - `ours-summary.md` — PROBE-O parallel track (xenia-rs side) - `canary-summary.md` — this file ## Recommendation for AUDIT-061 Echoing PROBE-O's recommendation: - Drop the "find fnptr-array activator" framing — `sub_821B6DF4` is an EH catch handler. - Drop "vptr installer dead" framing — measured 5× live in ours. - Re-focus on AUDIT-051's struct-population bug at `sub_82452DC0+0x78` (the `[r3+0]/[r3+4]` predicate gate from 80-byte stack-local at `r31+96`). With Windows Debug canary oracle online, mid-fn PC probes inside `sub_82452DC0` become feasible at scale. - Optional: investigate `_CxxThrowException`-equivalent fire-counts canary vs ours — if canary throws an exception ours doesn't (or vice versa) at boot, that would explain the AUDIT-058 ladder differential.