probe: run-4 connect-state lifecycle spread (8 targets)
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user