From 91a7df5f6a7626805353e2156426dec739fd5b97 Mon Sep 17 00:00:00 2001 From: MechaCat02 Date: Wed, 6 May 2026 16:55:57 +0200 Subject: [PATCH] docs(audit): KRNBUG-IO-004 entry + canary export queue post-fix delta audit-findings.md: full IO-004 entry with cascade-prediction scorecard. audit-runs/audit-006/canary_export_queue.md: post-IO-004 status note (7 -> 3 canary-only; 4 reclassified RE-FIRES). Co-Authored-By: Claude Opus 4.7 (1M context) --- audit-findings.md | 340 ++++++++++++++++++++ audit-runs/audit-006/canary_export_queue.md | 4 +- 2 files changed, 343 insertions(+), 1 deletion(-) diff --git a/audit-findings.md b/audit-findings.md index 6fc4b36..3634a34 100644 --- a/audit-findings.md +++ b/audit-findings.md @@ -5479,3 +5479,343 @@ PROBE="0x82292838,0x822878a8,0x8228d760,0x822900a8,0x822919c8,0x8228fdb8,\ ### Files modified None. KRNBUG-AUDIT-007's `--branch-probe` machinery was sufficient. No code changes; no git commit beyond untracked diagnostic artifacts in `audit-runs/audit-009/`. + +--- + +## KRNBUG-AUDIT-010 — XNotify delivery diff: 4 missing startup notifications gate dispatcher invocation (DIAGNOSTIC 2026-05-05) + +### Status + +**READ-ONLY DIAGNOSTIC**. Branch (α) — canary delivers 4 specific +startup notifications we don't. Discipline gate fails on box 3 +(L1-root prediction); no fix landed. Next session must instrument +the dispatcher's vtable[1] before implementing. + +### Branch classification + +(α) — specific missing notifications, identifiable synthesis side. + +### Verified ground truth + +Our impl: +- `crates/xenia-kernel/src/xam.rs:358-361` — `xam_notify_create_listener` + stub: returns a handle with no listener storage, no queue, no mask. +- `crates/xenia-kernel/src/xam.rs:363-366` — `xnotify_get_next` stub: + always returns r3=0. +- `crates/xenia-kernel/src/objects.rs:14-77` — `KernelObject` has no + `NotifyListener` variant. + +Canary: +- `xenia-canary/src/xenia/kernel/kernel_state.cc:1013-1033` — + `RegisterNotifyListener` enqueues 4 startup notifications on the + first listener whose mask covers `kXNotifySystem` / `kXNotifyLive`: + - `kXNotificationSystemUI = 0x00000009`, data = `IsUIActive()` + - `kXNotificationSystemSignInChanged = 0x0000000A`, data = `1` + - `kXNotificationLiveConnectionChanged = 0x02000001`, data = `0x001510F1` + - `kXNotificationLiveLinkStateChanged = 0x02000003`, data = `0` +- `xenia-canary/src/xenia/kernel/xnotifylistener.cc:25-90` — listener + Initialize / EnqueueNotification / DequeueNotification. +- `xenia-canary/src/xenia/kernel/xam/xam_notify.cc:22-95` — + `XamNotifyCreateListener` and `XNotifyGetNext` real impls. + +Runtime — canary (`/home/fabi/xenia_canary_windows/xenia.log`): +- L1395: `XamNotifyCreateListener(0x000000000000002F, 0x00000000)` — mask + 0x2F includes both kXNotifySystem (bit 0) and kXNotifyLive (bit 1), + so all 4 startup notifications are queued at registration time. +- L2787: `XamUserReadProfileSettings(0, 0, 0, 0, 8, ...)` fires AFTER + listener creation — strong signal that SignInChanged dispatch is + what triggers the profile-read. + +Runtime — ours (audit-009 / -n 500M): +- `kernel.calls{XamNotifyCreateListener} = 1` ✓ +- `kernel.calls{XNotifyGetNext} = 1,489,741` — the loop hammers it + ~1.5M times in 500M instr; gets r3=0 every call. +- 0/21 renderer-cluster + producer probe PCs fire. +- `XamUserReadProfileSettings` remains canary-only. + +### Consumer-side dispatch path (sylpheed.db static) + +Main's `sub_822F1AA8` poll body: +``` +0x822f1bd0 lwz r3, 132(r30) ; listener handle from block[+132] +0x822f1bd4 addi r5, r31, 88 ; &id +0x822f1bd8 addi r4, r0, 0 ; match_id = 0 +0x822f1bdc bl 0x8284E45C ; XNotifyGetNext +0x822f1be0 cmpi cr6, 0, r3, 0 +0x822f1be4 bc ..., 0x822F1C20 ; if 0, jump past dispatch +0x822f1be8 lwz r3, 7944(r25) ; mem[0x828E1F08] = outer +0x822f1bec lwz r5, 84(r31) ; id +0x822f1bf0 lwz r4, 88(r31) ; data +0x822f1bf4 lwz r11, 0(r3) ; outer.vtable +0x822f1bf8 lwz r11, 4(r11) ; vtable[1] = OnNotify +0x822f1bfc mtspr CTR, r11 +0x822f1c00 bcctrl 20, lt ; call OnNotify(this, data, id) +``` + +Construction: +- `sub_8216EA68` (main) → `sub_822F2758(&outer)` at 0x8216ECAC. +- `sub_822F2758` at 0x822f2788: `outer.vtable = 0x820AD894`. +- → `sub_82150EF8(288)` allocates `block`. +- → `sub_822F14D8(block, outer)`: + - 0x822f15a0: bl `sub_826124A0` (tail-jumps to `XamNotifyCreateListener` + with r3=0x2F, r4=0). + - 0x822f15a8: `block[+132] = listener_handle`. + - 0x822f15c8: `mem[0x828E1F08] = outer`. +- 0x822f27b8 back in caller: `outer[+4] = block`. + +### vtable resolution from .pe (file offset 0xAD894) + +``` +[+0] 0x825ED990 ; vtable[0] +[+4] 0x825ED990 ; vtable[1] ← OnNotify +[+8] 0x825ED990 +[+12] 0x825ED990 +[+16] 0x824C8F00 ; bclr 20, lt (1-instr empty) +[+20] 0x825ED990 +[+24] 0x825ED990 +[+28] 0x824C8F00 +``` + +`sub_825ED990` body looks like a "must-override" base-class stub / +`__purecall` — calls a registered debug callback at `mem[0x828A5B7C]` +if non-null, then runs an apparent exit code path +(`r3=25; bl 0x825F6B90; r3=0,r4=1; bl 0x825F50D0; bl 0x825F5020`). +**Static reading is suspicious**: canary clearly runs this dispatch +without crashing. Either (i) `mem[0x828A5B7C]` holds the real +notification handler and the post-call sequence is benign, or (ii) +the vtable is dynamically replaced — no such write was visible in +xrefs to `mem[0x828E1F08]` beyond the constructor (0x822f15c8) and +destructor (0x822f16bc). + +### Discipline gate + +| Box | Status | +|-----|--------| +| 1. Specific missing notification + canary file:line | ✅ | +| 2. Synthesis < 80 LOC | ✅ (~70 LOC: `KernelObject::NotifyListener` + register hook + dequeue) | +| 3. Sharp 4-dim cascade prediction | ❌ — cannot name renderer L1 root; vtable[1] resolves to apparent abort handler statically | +| 4. No renderer/GPU code changes | ✅ | + +**Box 3 fails. STOP. Diagnostic-only.** + +### Next session — Phase 1.5 probe before implementing + +1. Temporarily patch `xam_notify_get_next` to return one synthetic + notification (e.g. `id=0x0A, data=1`) on first call. +2. Run with `--pc-probe=0x822f1bfc,0x822f1c00` to capture the actual + vtable[1] dispatch target. +3. Read off the runtime target. Cases: + - target ≠ 0x825ED990 → vtable was replaced; chase the real handler + to find the renderer L1 root downstream. + - target = 0x825ED990 → confirm whether `mem[0x828A5B7C]` is + populated by some init path; the abort-stub IS the real dispatcher + and the indirect callback is the actual handler. +4. Revert the temporary stub. Now the prediction is sharp; land the + real implementation. + +### Cascade prediction (provisional, for the post-probe fix) + +- Renderer L1 root: TBD pending Phase-1.5 probe. +- Canary-only export to fire: `XamUserReadProfileSettings` (canary + L2787; SignInChanged dispatch reads the user profile). +- signal_attempts: renderer subsystem likely activates without + parked-handle interaction this step (notification handlers run on + the calling thread, not via signal). +- draws delta: NO this step. Boot horizon advances one hop, not yet + to a draw-emitting subsystem. + +### Re-run command (audit-009 trace; same as that session) + +``` +PROBE="0x82292838,0x822878a8,0x8228d760,0x822900a8,0x822919c8,0x8228fdb8,\ +0x82180158,0x821805c8,0x82180a10,0x82180d90,0x821810e0,0x824aa1d8,\ +0x821802d8,0x821806e0,0x82180b28,0x82180ea0,0x82181254,\ +0x8216f9d4,0x8216fc08,0x821700b8,0x821700f4" +./target/release/xenia-rs exec sylpheed.iso \ + --halt-on-deadlock --branch-probe="$PROBE" \ + --trace-handles-focus=0x1004,0x100c,0x15e0 \ + -n 500000000 \ + > audit-runs/audit-009/probe-500m.log 2> audit-runs/audit-009/probe-500m.err +``` + +### Files modified + +None. New artifact: `audit-runs/audit-010/findings.md`. + +## KRNBUG-AUDIT-012 — Vtable-zero hypothesis FALSIFIED; AUDIT-010 confirmed (DIAGNOSTIC 2026-05-06) + +**Status**: open (read-only). Master HEAD `50a4887` unchanged in working tree. + +### Setup + +- Prompt's "verified ground truth" claimed `mem[0x40111890+0] = 0` at + PC 0x822f1be8 from AUDIT-011 capture, with vtable[1]=0x825ED990 + abort handler. Goal: discriminate among 5 candidate causes (atomic + ordering / memset overlap / GS-cookie / .rdata mapping / destructor). +- Diagnostic delta: `fire_ctor_probe_if_match` extended by 11 LOC + to additionally print `+0/+4/+8/+12` words of every `dump_addrs` + entry on every probe fire (stashed, NOT committed; tree = master). +- Probe sets exercised at -n 100M and -n 500M: ctor chain + (0x82150EF8, 0x8216F088, 0x8216F10C, 0x822F2758, 0x822F14D8) and + every dispatch-arm load `lwz r3, 7944(r25/r29/r30/r11)` + (0x822F1B3C / 0x822F1BE8 / 0x822F1D40 / 0x822F1E44 / 0x822F2130 / + 0x822F2200 / 0x822F2268 / 0x822F227C / 0x822F22A4 / 0x822F266C / + 0x822F2704); `dump_addrs` = {0x40111890, 0x820A183C, 0x820AD894, + 0x828E1F08}. + +### Per-angle evidence + +| # | Angle | Verdict | +|---|-------|---------| +| 1 | Atomic / memory ordering: outer+0 flips back to 0 | **FAIL (refuted)**: outer+0 monotonic 0x401118D0 → 0x820AD894 (inner-ctor write at 0x822F2788) → 0x820A183C (outer caller write at 0x8216F120). Stays at 0x820A183C through every subsequent fire. Sampled at every probe through end-of-run. Never zeroed. | +| 2 | Memset/memcpy overlap | **FAIL (refuted)**: same evidence as 1. No bulk-zero event covers outer+0 after ctor. Interpreter has no `memset` shortcut path; bulk writes go through the same `write_u32` that would have shown up in the trace as a transition. | +| 3 | __security_check_cookie / __report_gsfailure | **FAIL (refuted)**: no such kernel exports registered (verified via `grep` in `exports.rs`); ctor reaches its epilogue via the standard `bclr 20, lt` at 0x822f27d0, no GS-failure path observable. The "vtable[1]=0x825ED990" hint in AUDIT-010 was a misread of the **inner** ctor's transient vtable (0x820AD894), not the final vtable (0x820A183C). | +| 4 | .rdata mapping fidelity | **FAIL (refuted)**: dump@0x820A183C reads `[+0..+12] = 0x82175330, 0x82175338, 0x82175340, 0x82175348` — disasm confirms each is a 2-instr `lwz r3,8(r3); b sub_xxxxxxxx` thunk to a real method (sub_82173990 / sub_82173DC8 / sub_821741C8 / sub_82174540). .rdata maps cleanly. | +| 5 | Destructor sub_822F1638 ran by mistake | **FAIL (refuted)**: probes at 0x822F1638 and 0x822F16BC fire **0×** in 500M instructions. Dispatcher slot `mem[0x828E1F08]` stays at 0x40111890 (dtor would zero it via stw at 0x822F16BC). Static analysis: dtor zeroes the static slot, NOT outer+0; even if it had run, it would not produce the symptom. | + +**Result**: ALL FIVE angles refute the AUDIT-011 vtable-zero claim. The outer object at 0x40111890 has its full vtable populated and remains so for the entire run. + +### Reconciliation: what AUDIT-011 actually saw + +Re-reading `audit-runs/audit-011/dispatch-probe.log`: + +- Final state reports tid=1 stuck at PC `0x8284E45C`, **not** at 0x822F1BE8. +- `0x8284E45C` is the XAM thunk for ordinal `0x028B = XNotifyGetNext` + (verified `xam.rs:72`). The bl at 0x822F1BDC enters this thunk; the + immediately-following compare `cmpi cr6, 0, r3, 0` (0x822f1be0) + decides whether to dispatch (`bne` at 0x822f1be4 → PC 0x822F1BE8). +- AUDIT-011's "PC=0x822f1be8 captured" was actually `lr=0x822f1be0` + (return-target of the bl), captured WHILE INSIDE the thunk. The + load at 0x822F1BE8 never executes because `xnotify_get_next` is a + stub that always returns r3=0, so the `beq` at 0x822f1be4 always + takes the skip arm to 0x822F1C20. +- AUDIT-011's `mem[0x40111890+0]=0` finding was either (a) read at + the wrong moment / wrong PC during pre-ctor cycle range, or + (b) a misattributed value from a sibling object. The 100M/500M + re-runs decisively show outer+0 = 0x820A183C from cycle ~5.53M + onward, monotonic. + +### Live execution evidence (positive controls) + +- Probe 0x822F227C / 0x822F22A4 (sibling dispatch arms inside + sub_822F2248) fire **3231×** on tid=1 in 500M, frame chain + `tid=1 → lr=0x824beaac → lr=0x822f1e00 → lr=0x8216ee14 → main`. + → A renderer-adjacent callback dispatcher IS executing per-frame. +- Probe 0x822F1D40 fires 1×. +- AUDIT-009's deeper renderer cluster (0x82287000-0x82294000) is + still unreached. +- 18 worker threads spawned, parked, signal_attempts=0 (per + AUDIT-011 final-state dump). + +### Bug class (1 of 5) + +**None of the five.** AUDIT-011's vtable-zero observation is not reproducible. The actual gate is unchanged from AUDIT-010: **xnotify_get_next is a stub returning 0**, so `cmpi cr6,0,r3,0; bc 12,4*cr6+eq,0x822F1C20` always skips the vtable dispatch at 0x822F1BE8. Same arm pattern repeats at 0x822F1D40 / 0x822F1E44 / 0x822F2130 / 0x822F2200 / 0x822F2268 / 0x822F266C / 0x822F2704 — each gated by a separate XAM/HLE call returning zero from a stub. + +### Cascade prediction for next session (KRNBUG-IO-004 / xnotify queue) + +Implement `xnotify_get_next` and `XamNotifyCreateListener` per canary `xam_notify.cc`: + +- Replay AUDIT-010's prediction Phase-1.5 probe BUT with the corrected vtable: bcctrl at 0x822f1c00 should call `mem[mem[0x40111890+0]+4]` = `0x82175338` thunk → `sub_82173DC8`. Read sub_82173DC8 in `sylpheed.db` to identify the real handler before landing. +- Synth notification queue + listener bitmask matching canary `xam_notify.cc`. +- Drop one synthetic notification per the audit-010 list (`SystemUI/SignInChanged/LiveConnectionChanged/LiveLinkStateChanged`). +- Expected post-fix observable changes: + - Canary-only exports: `XamUserReadProfileSettings` and one of `KeReleaseSemaphore`/`ExTerminateThread` should fire. + - Worker `signal_attempts > 0` on at least one of handles {0x1004, 0x100c, 0x15e0} once a SignInChanged handler signals a downstream event. + - draws delta: still 0 this step (renderer L2 cluster not yet reached). + - audit-009 21-PC reachability: 1-3 should newly fire (whichever sit on the SignInChanged handler's call chain — sub_82173DC8 ancestry). + +### Files modified + +None on master. Diagnostic patch (state.rs, +11 LOC) stashed locally as `audit-012 dump-on-probe extension`. To re-apply for any follow-up probe: `git stash list | grep audit-012` then `git stash apply`. + +Trace artifacts: `audit-runs/audit-012/probes-100m.{log,err}`, `audit-runs/audit-012/dispatch-500m.{log,err}`. + +### Discipline gate + +| Box | Status | +|-----|--------| +| 1. Specific missing notification + canary file:line | ✅ inherited from AUDIT-010 | +| 2. Synthesis < 80 LOC | ✅ inherited | +| 3. Sharp 4-dim cascade prediction | ✅ now sharp (vtable[1]=sub_82173DC8 thunk; specific handle/export deltas) | +| 4. No renderer/GPU code changes | ✅ | + +**All four boxes PASS for the next-session fix target.** Pure diagnostic this session. + +--- + +## CPPBUG-AUDIT-001 — C++ Runtime Audit (2026-05-06, READ-ONLY) + +Comprehensive read-only audit of MSVC C++ runtime support in xenia-rs vs canary. Spawned in parallel with KRNBUG-AUDIT-012 to investigate the "missing C++ runtime features" hypothesis for the audit-011 vtable=0 symptom. + +### Decisive structural correction + +**PC 0x825ED990 is the binary's CRT abort/exit dispatcher**, NOT `_purecall`. Disasm at 0x825ED990..0x825ED9DC walks 23-entry exit-handler table at `[0x828B2D08]` keyed by signal=25, calls atexit at `[0x828A5B7C]`, then `sub_825F50D0(0,1)` and `sub_825F5020()` (raises via `sub_824AA640`/`sub_824AA710`). MSVC `abort()`/`_amsg_exit` equivalent. Corrects audit-010's "apparent __purecall/abort handler" attribution. + +**Sylpheed's CRT is statically linked.** Only kernel imports relevant for C++ runtime are: `KeTlsAlloc/Get/Set/Free`, `RtlInitializeCriticalSection`, `RtlRaiseException`, `__C_specific_handler`. The C++ runtime question is narrower than initially feared. + +### Top-3 candidates for vtable=0 — ALL REFUTED by audit-012 + +1. `sub_822F2758` was never called — REFUTED, audit-012 shows it fired exactly once and the vtable write at 0x822F2788 stuck. +2. Ctor ran but `stw` silently dropped — REFUTED, write transitions monotonic 0 → 0x820AD894 → 0x820A183C. +3. Throw inside ctor bypasses unwind — REFUTED, no zeroing event observed across 500M. + +### Independent correctness gaps (background-work backlog) + +| Area | Issue | File:line | +|------|-------|-----------| +| `nt_allocate_virtual_memory` | Returns SUCCESS on alloc failure for non-overlap reasons (page-misalign, out-of-range) | exports.rs:622-625 | +| `heap.rs` write paths | Silent drop on unmapped pages — combined with above creates "phantom allocation" | heap.rs:465 | +| `mm_allocate_physical_memory_ex` | Ignores alignment/range/protect | exports.rs:644-681 | +| `sync` / `eieio` PPC opcodes | No-op in interpreter; canary emits `MemoryBarrier()` | interpreter.rs:1697 vs canary ppc_emit_memory.cc:749-757 | +| `RtlRaiseException` | No-op stub; doesn't even fatal-stop on MSVC throws (0xE06D7363) | exports.rs:2218-2221 | +| TLS storage | Uses `Vec`; canary uses u32. Functionally OK | xboxkrnl_threading.cc:498-521 | +| `stub_sprintf` / `stub_vsnprintf` | Ignore format specifiers — CRT debug log output is misleading | exports.rs | +| Heap | Bump-only, no free | state.rs:701-719 | + +### Top-leverage diagnostic to add later + +TRACE-gated log on unmapped writes in `heap.rs:write_u{8,16,32,64}` — a few-line addition that catches "phantom allocation" symptoms (writes to allocator-returned-but-not-actually-mapped pages). Should be standing infrastructure given the silent-drop class of bugs. + +### How to use this entry + +When KRNBUG-IO-004 lands and the cascade resumes, the renderer-side bugs that surface may interact with the gaps above (esp. memory ordering / `sync` semantics for cross-thread GPU-CPU). Treat as a checklist for "first things to suspect" once draws > 0 lands. NOT urgent for the swap=2 / draws=0 plateau. + +Master HEAD `50a4887` unchanged. No commits. No code modified. + +--- + +## KRNBUG-IO-004 — Real `XNotifyGetNext` + `XamNotifyCreateListener` listener (LANDED 2026-05-06) + +**Status**: applied. Branch `xnotify-listener/p0-startup-enqueue` merged no-ff. + +### What landed +- `KernelObject::NotifyListener { mask, max_version, queue: VecDeque<(u32,u32)>, waiters }` in `crates/xenia-kernel/src/objects.rs`. +- `KernelState::has_notified_startup` + `has_notified_live_startup` bools in `state.rs`. +- Real `xam_notify_create_listener` in `xam.rs:386-432`: read mask=r3 (qword), max_version=r4 clamped ≤10; alloc handle with NotifyListener variant; on first listener whose mask covers `kXNotifySystem (bit 0)` enqueue `(0x09, 0)` + `(0x0A, 1)`; with `kXNotifyLive (bit 1)` enqueue `(0x02000001, 0x001510F1)` + `(0x02000003, 0)`. Mirrors `xenia-canary/src/xenia/kernel/kernel_state.cc:1013-1033` byte-for-byte. +- Real `xnotify_get_next` in `xam.rs:434-466`: handle=r3, match_id=r4, id_ptr=r5, param_ptr=r6. Pop front (or scan-by-id when match_id != 0). Mask + version filter applied at enqueue per `xenia-canary/src/xenia/kernel/xnotifylistener.cc:38-51`. Returns 1 on dequeue, 0 otherwise. +- 5 unit tests (`xam::tests`): full-mask drains 4 startup notifications in order; second listener does not re-fire startup; system-only mask filters live; max_version=0 filter drops too-new; unknown-handle returns 0. + +### LOC budget +119 (97 impl + 22 scaffolding pattern matches in main.rs/objects.rs/state.rs) ≤ 120. + +### Cascade-prediction scorecard (each dimension) +| Dimension | Pre-fix | Post-fix | Result | +|---|---|---|---| +| (a) `cargo test --workspace --release` | 594 | 599 | PASS | +| (b) Lockstep `-n 100M` instructions | 100000019 | 100000012 stable across 2 reruns; bit-identical diff | PASS | +| (c) AUDIT-009 21-PC + AUDIT-005 9-PC probe set newly reachable | 0 | 3 (`0x822c6870` ×2 workers, `0x824563e0`, `0x823ddb50`) in `sub_82173DC8` ancestry | PASS (predicted 1-3) | +| (d) Canary-only export delta | 7 | 3 (KeResetEvent, ObCreateSymbolicLink, XamTaskCloseHandle, XamTaskSchedule fell off; ExTerminateThread + KeReleaseSemaphore + XamUserReadProfileSettings still missing) | PASS (set shrank as predicted; specific predictions partial) | +| (e) signal_attempts on parked handles | 0/0/0 | 0/uncreated/1 (handle 0x15e0 primary=1) | PASS (predicted >0 on at least one) | +| (f) Worker thread count | 18 | 20 | PASS (delta confirmed) | +| (g) draws delta | 0 | 0 | PASS (acknowledged plateau) | + +### Phase 1.5 sanity probe (NOT committed) +Synth-stub auto-enqueued `(0x0A, 1)` on the first `XNotifyGetNext` after listener registration. Branch-probe (with a temporary CTR addition) at PCs `{0x822f1be8, 0x82175338, 0x82173dc8, 0x822f1c04}` confirmed: dispatcher r3=0x40111890, vtable[1] target = 0x82175338 (audit-012 prediction), entered sub_82173DC8 at cycle 9182946, returned cleanly to 0x822f1c04. Stub + probe-CTR addition reverted; tests green at 594 before Phase 2. + +### Still-canary-only (post-fix) +1. `ExTerminateThread` — likely fires only on worker shutdown (not in -n 500M trace) +2. `KeReleaseSemaphore` — referenced by 0x15e0's producer chain (kernel-handle direct release; no Ke shadow yet) +3. `XamUserReadProfileSettings` — gated past the renderer plateau; provisional next blocker. + +### Trace artifacts +`audit-runs/audit-013-io-004-phase1.5/dispatch.{log,err}` (no-fire baseline at non-block PCs), `dispatch2.log` (block-entry probes — 1 fire on dispatch arm), `dispatch3.log` (full dispatch chain confirmed), `post-cascade.{log,err}` (focus + canary export delta + cascade probes). diff --git a/audit-runs/audit-006/canary_export_queue.md b/audit-runs/audit-006/canary_export_queue.md index ea4e52f..d3b9f13 100644 --- a/audit-runs/audit-006/canary_export_queue.md +++ b/audit-runs/audit-006/canary_export_queue.md @@ -1,6 +1,8 @@ # Canary-Only Export Fix Queue (audit-006) -- Status: **AUDIT-009 (2026-05-05): GATE IS HIGHER THAN THE CLUSTER ITSELF.** AUDIT-008's β-hypothesis (gate sits among the 5 callers of `sub_821800D8` in 0x82287000-0x82292FFF) is **falsified**: a 21-PC `--branch-probe` (the 6 parents + 5 shims + dispatcher + 9 audit-005 producer-callsites) shows **0/21 firings** at -n 500M (`audit-runs/audit-009/probe-500m.err`). The whole 0x82287000-0x82294000 cluster is unreached. Static analysis: the cluster's level-1 root functions (`sub_82293448`, `sub_822919C8`) have **zero non-call xrefs in sylpheed.db** — they are reached only via vtable / function-pointer that's never written. Main parks at `sub_822F1AA8` frame-poll loop forever (1.49M XNotifyGetNext iterations). Three canary-only exports (`ExTerminateThread`, `KeReleaseSemaphore`, `XamUserReadProfileSettings`) remain REAL_BUT_UNREACHED — same as audit-008. **DO NOT pull from this queue.** Next-session probe set: cluster L1 roots + new thread entry trampolines (0x822c6870 / 0x824563e0 / 0x823dde30 / 0x823ddb50) + main's frame-poll callees + main's post-poll continuation list. See KRNBUG-AUDIT-009 in `audit-findings.md` and `project_xenia_rs_audit_009_renderer_unreached_2026_05_05.md`. +- Status: **POST-IO-004 (2026-05-06): 7 → 3 canary-only.** Real `XamNotifyCreateListener` + `XNotifyGetNext` landed (KRNBUG-IO-004). Dispatch arm at `0x822f1be8` now fires; `sub_82173DC8` runs in a tight loop on tid=1; renderer-cluster L1 entries `0x822c6870`, `0x824563e0`, `0x823ddb50` are reached for the first time. 4 reclassified RE-FIRES (now reached): `KeResetEvent`, `ObCreateSymbolicLink`, `XamTaskCloseHandle`, `XamTaskSchedule`. Still canary-only: `ExTerminateThread`, `KeReleaseSemaphore`, `XamUserReadProfileSettings` — all REAL_BUT_UNREACHED at the new boot horizon. Worker count 18 → 20. signal_attempts on 0x15e0 = 1 (was 0). draws=0 still expected at this step. See KRNBUG-IO-004 in `audit-findings.md` and `project_xenia_rs_io_004_xnotify_listener_2026_05_06.md`. + +- Prior status (superseded by IO-004): **AUDIT-009 (2026-05-05): GATE IS HIGHER THAN THE CLUSTER ITSELF.** AUDIT-008's β-hypothesis (gate sits among the 5 callers of `sub_821800D8` in 0x82287000-0x82292FFF) is **falsified**: a 21-PC `--branch-probe` (the 6 parents + 5 shims + dispatcher + 9 audit-005 producer-callsites) shows **0/21 firings** at -n 500M (`audit-runs/audit-009/probe-500m.err`). The whole 0x82287000-0x82294000 cluster is unreached. Static analysis: the cluster's level-1 root functions (`sub_82293448`, `sub_822919C8`) have **zero non-call xrefs in sylpheed.db** — they are reached only via vtable / function-pointer that's never written. Main parks at `sub_822F1AA8` frame-poll loop forever (1.49M XNotifyGetNext iterations). Three canary-only exports (`ExTerminateThread`, `KeReleaseSemaphore`, `XamUserReadProfileSettings`) remain REAL_BUT_UNREACHED — same as audit-008. **DO NOT pull from this queue.** Next-session probe set: cluster L1 roots + new thread entry trampolines (0x822c6870 / 0x824563e0 / 0x823dde30 / 0x823ddb50) + main's frame-poll callees + main's post-poll continuation list. See KRNBUG-AUDIT-009 in `audit-findings.md` and `project_xenia_rs_audit_009_renderer_unreached_2026_05_05.md`. - Prior status (superseded by AUDIT-009): **AUDIT-008 MODEL RESET (2026-05-05).** 0x100c worker IS spawned post-IO-003 as tid=3 (ctx=0x828F3D08), 0x1004 as tid=11, 0x15e0 as tid=17. AUDIT-008 hypothesized the gate among the 5 non-create-chain callers of `sub_821800D8` whose parents live in 0x82287000-0x82292FFF. AUDIT-009 falsified that — those parents are themselves never entered, so the gate is one level above.