From 493b9e057366073e32bb9b7e91a8c0c3068f0759 Mon Sep 17 00:00:00 2001 From: funman300 Date: Thu, 2 Jul 2026 18:03:50 -0700 Subject: [PATCH] probe: run-4 connect-state lifecycle spread (8 targets) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expands to 8 entry probes across the connect-state lifecycle (ctor, controller accessor, four vtable steps) to distinguish entered-but-stalled from never-entered. Result: ctor fires x4, everything else 0 — subsystem created but dormant. Co-Authored-By: Claude Fable 5 --- openfut-hook/src/probe.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/openfut-hook/src/probe.rs b/openfut-hook/src/probe.rs index 4ce7c7c..fc208fa 100644 --- a/openfut-hook/src/probe.rs +++ b/openfut-hook/src/probe.rs @@ -186,13 +186,20 @@ struct Target { /// - `OnlineStatus.deser` (+0x278a4d0): confirms our pushed OnlineStatusEvent still /// arrives during the test (control signal). const TARGETS: &[Target] = &[ - Target { module: b"\0", rva: 0x2861910, label: "nucleusConnectREST", main_exe: true }, - Target { module: b"\0", rva: 0x5078370, label: "nucleusConnectTrusted", main_exe: true }, - Target { module: b"\0", rva: 0x507d660, label: "connectState.tick", main_exe: true }, - Target { module: b"\0", rva: 0x278a4d0, label: "OnlineStatus.deser", main_exe: true }, + // Run 4: settle "connect state entered-but-stalled" vs "never entered". If the ctor + // fires but nothing else, the connect states are created at init but never used; if + // GetByIdx / any vtable step fires, the online subsystem is iterating them. + Target { module: b"\0", rva: 0x5078d20, label: "connectState.ctor", main_exe: true }, + Target { module: b"\0", rva: 0x4f46570, label: "ctrl.GetConnState", main_exe: true }, + Target { module: b"\0", rva: 0x507cd60, label: "connState.m_a8", main_exe: true }, + Target { module: b"\0", rva: 0x507cf90, label: "connState.m_b0", main_exe: true }, + Target { module: b"\0", rva: 0x507d660, label: "connState.tick_b8", main_exe: true }, + Target { module: b"\0", rva: 0x507d760, label: "connState.m_c0", main_exe: true }, + Target { module: b"\0", rva: 0x2861910, label: "nucleusConnectREST", main_exe: true }, + Target { module: b"\0", rva: 0x278a4d0, label: "OnlineStatus.deser", main_exe: true }, ]; -const N: usize = 4; // must equal TARGETS.len() +const N: usize = 8; // must equal TARGETS.len() static ADDRS: [AtomicUsize; N] = [const { AtomicUsize::new(0) }; N]; static mut ORIG: [[u8; 14]; N] = [[0u8; 14]; N]; @@ -202,7 +209,7 @@ static CALLS: [AtomicUsize; N] = [const { AtomicUsize::new(0) }; N]; const LOG_CAP: usize = 24; type ProbeFn = unsafe extern "system" fn(usize, usize, usize, usize) -> usize; -const PROBE_FNS: [ProbeFn; N] = [p0, p1, p2, p3]; +const PROBE_FNS: [ProbeFn; N] = [p0, p1, p2, p3, p4, p5, p6, p7]; unsafe fn write_jmp(addr: *mut u8, dest: u64) { let mut old: u32 = 0; @@ -253,6 +260,10 @@ unsafe extern "system" fn p0(a: usize, b: usize, c: usize, d: usize) -> usize { unsafe extern "system" fn p1(a: usize, b: usize, c: usize, d: usize) -> usize { generic(1, a, b, c, d) } unsafe extern "system" fn p2(a: usize, b: usize, c: usize, d: usize) -> usize { generic(2, a, b, c, d) } unsafe extern "system" fn p3(a: usize, b: usize, c: usize, d: usize) -> usize { generic(3, a, b, c, d) } +unsafe extern "system" fn p4(a: usize, b: usize, c: usize, d: usize) -> usize { generic(4, a, b, c, d) } +unsafe extern "system" fn p5(a: usize, b: usize, c: usize, d: usize) -> usize { generic(5, a, b, c, d) } +unsafe extern "system" fn p6(a: usize, b: usize, c: usize, d: usize) -> usize { generic(6, a, b, c, d) } +unsafe extern "system" fn p7(a: usize, b: usize, c: usize, d: usize) -> usize { generic(7, a, b, c, d) } /// Spawn a background thread that waits for anadius64.dll to load, then installs /// all probes. anadius may not be present when our DllMain runs, so we defer