re: counter-example weakens the probe-causes-freeze correlation
A pilot-only run froze at t~150.7s (frozen.py: max_pixel_delta=0), found by accident when the sweep-free experiment aborted at startup and the run flew with no script probe attached. The tally is now 3-of-3 frozen with the probe versus 1-of-3 without, not 3-versus-0. Still a lean, but not the clean separation the previous entry claimed, and marked down accordingly -- the fourth time a freeze conclusion here has had to be softened by one more run. The sweep-free test itself could not run: ScriptMission is re-allocated per run, so the address from an earlier run (0xBC7A2A20) read back all zeros. The cheap self-consistency check ([m+44] must equal the phase's [+244]) rejected it instead of reporting garbage, which is the part that worked. Names the cheaper replacement: a BOUNDED pointer scan. Every ScriptMission seen so far sits in 0xBC79xxxx-0xBC7Axxxx, so ~32MB instead of ~371MB would cut the sweep cost roughly tenfold. Not yet implemented.
This commit is contained in:
@@ -14,7 +14,14 @@ It also does two things the earlier probes had to learn the hard way:
|
||||
* re-locates the ScriptMission if the pointer stops validating, rather than
|
||||
silently reporting stale numbers.
|
||||
|
||||
Usage: phase_watch.py <Stage02.ssb> [secs] [every_s]
|
||||
`--mission 0x...` skips the two full guest-memory sweeps `find_mission()` does
|
||||
and validates the given address with a handful of reads instead. That exists
|
||||
because the sweeps are the leading suspect for the in-mission freeze: runs with
|
||||
this probe attached froze at ~70/126/253 s, while the same runs without it went
|
||||
936 s and 1064 s clean (mission-freeze-resume-spin.md). Sweep-free mode is the
|
||||
experiment that separates "the sweeps do it" from "the per-sample reads do it".
|
||||
|
||||
Usage: phase_watch.py <Stage02.ssb> [secs] [every_s] [--mission 0xADDR]
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
@@ -33,15 +40,35 @@ def main():
|
||||
sym2 = isl.symbols(ssb, 2)
|
||||
secs = float(sys.argv[2]) if len(sys.argv) > 2 else 900
|
||||
every = float(sys.argv[3]) if len(sys.argv) > 3 else 5
|
||||
given = None
|
||||
if '--mission' in sys.argv:
|
||||
given = int(sys.argv[sys.argv.index('--mission') + 1], 0)
|
||||
path = gmem.mem_path()
|
||||
size = os.path.getsize(path)
|
||||
import frozen
|
||||
t0 = time.time()
|
||||
with open(path, 'rb', buffering=0) as f:
|
||||
m, fb = S.find_mission(f, size, ssb)
|
||||
if m is None:
|
||||
print('ScriptMission not located'); return 1
|
||||
print('file base 0x%08X ScriptMission 0x%08X' % (fb, m), flush=True)
|
||||
if given is not None:
|
||||
# Validate WITHOUT sweeping: the mission's symtab1 pointer must equal
|
||||
# the phase's, and the code base must be a plausible pointer. Both
|
||||
# are self-consistency checks internal to the two objects, so they
|
||||
# cost four reads instead of two full scans.
|
||||
code = S.u32(f, given + 24)
|
||||
s44 = S.u32(f, given + 44)
|
||||
ph = S.u32(f, given + 4)
|
||||
p244 = S.u32(f, ph + 244) if ph else None
|
||||
ok = (code and 0x10000 <= code < 0xFFFFFFF0 and s44 and s44 == p244)
|
||||
if not ok:
|
||||
print('given ScriptMission 0x%08X does not validate '
|
||||
'(code=%s s44=%s phase244=%s)' % (given, code, s44, p244))
|
||||
return 1
|
||||
m, fb = given, None
|
||||
print('ScriptMission 0x%08X (given, validated, NO sweeps)' % m, flush=True)
|
||||
else:
|
||||
m, fb = S.find_mission(f, size, ssb)
|
||||
if m is None:
|
||||
print('ScriptMission not located'); return 1
|
||||
print('file base 0x%08X ScriptMission 0x%08X' % (fb, m), flush=True)
|
||||
last = None
|
||||
next_frozen = 0.0
|
||||
while time.time() - t0 < secs:
|
||||
|
||||
Reference in New Issue
Block a user