Files
llamamod/notes/dev/mountain3-diag/rd.py
T

55 lines
3.0 KiB
Python
Executable File

#!/usr/bin/env python3
"""rd.py SESSION : attach briefly with winedbg, dump diag data, print summary"""
import os, re, subprocess, sys, struct
S = sys.argv[1]; DATA = 0x70f010; N = 4992
env = dict(os.environ, WINEPREFIX='/home/elias/.claude/jobs/90c6eed7/tmp/%s/data/wine' % S, WINEDEBUG='-all')
def dbg(cmds):
out = subprocess.run(['winedbg'], input='\n'.join(cmds) + '\ndetach\nquit\n', env=env, capture_output=True, text=True, timeout=60).stdout
return out
pl = dbg(['info proc'])
m = re.search(r'([0-9a-f]{8})\s+\d+\s+\\_ \'groove.exe\'', pl)
if not m: print('no groove.exe'); sys.exit(1)
pid = m.group(1)
out = dbg(['attach 0x' + pid, 'x/%dx 0x%x' % (N // 4, DATA), 'x/16x 0x58499c'])
words = {}
for l in out.splitlines():
mm = re.match(r'.*?0x([0-9a-f]{8}):\s+((?:[0-9a-f]{8}\s*)+)$', l)
if mm:
a = int(mm.group(1), 16)
for i, w in enumerate(mm.group(2).split()): words[a + 4 * i] = int(w, 16)
def W(o): return words.get(DATA + o, 0)
names = set()
for base, cnt in ((64, 32), (1408, 64)):
for i in range(cnt):
e = DATA + base + 32 * i
for k in (16, 20):
if words.get(e + k): names.add(words[e + k])
nm = {}
if names:
o2 = dbg(['attach 0x' + pid] + ['x/s 0x%x' % a for a in sorted(names)])
ss = [l for l in o2.splitlines() if l.startswith('Wine-dbg>') and '"' not in l or True]
segs = o2.split('Wine-dbg>')
for i, a in enumerate(sorted(names)):
nm[a] = segs[2 + i].strip() if 2 + i < len(segs) else hex(a)
print('parent_ok=%d stale_addr=%d stale_pop=%d free=%d alloc=%d anomalies=%d staleidx=%d allidx=%d' % (W(16), W(20), W(24), W(28), W(36), W(32), W(40), W(44)))
def ring(base, cnt, idx, label, last=12):
print('--', label)
n = min(idx, cnt)
for j in range(max(0, idx - last), idx):
e = base + 32 * (j % cnt)
s, p, k, vi, sn, pn, pv, pec = (W(e + 4 * q) for q in range(8))
print(' #%d kind=%x strat=%x(%s) parent=%x(%s) v%d parentvars=%x parent_ec=%x target=%x' % (j, k, s, nm.get(sn, '-'), p, nm.get(pn, '-'), vi, pv, pec, pv + 4 * vi))
ring(64, 32, W(40), 'stale', 32)
for j in range(max(0, W(40) - 32), W(40)):
e = 4480 + 16 * (j % 32); t, h, su, v = (W(e + 4 * q) for q in range(4))
print(' stale#%d target=%x block=%x off=+0x%x %s size=%d value_before=%x%s' % (j, t, h, t - h if h else 0, 'USED' if su >> 16 else 'FREE', su & 0xffff, v, ' <<< HEADER HIT' if h and t - h < 12 else ''))
ring(1408, 64, W(44), 'all parent accesses (last 16)', 16)
if W(32):
print('ANOMALY code=%d hdr=%x prevhdr=%x hdr.next=%x hdr.prev=%x sizeused=%x frees=%d allocs=%d staleidx=%d caller=%x lastfree=%x lastalloc=%d' % tuple(W(1088 + 4 * q) for q in range(12)))
d = [W(1152 + 4 * q) for q in range(64)]
for q in range(0, 64, 8): print(' ' + ' '.join('%08x' % x for x in d[q:q + 8]))
fh = [(W(3456 + 16 * q), W(3456 + 16 * q + 4), W(3456 + 16 * q + 8), W(3456 + 16 * q + 12)) for q in range(64)]
print('heapbase', hex(words.get(0x58499c, 0)))
if '-f' in sys.argv:
for q in range(64): print(' free ptr=%x caller=%x sizeused=%x next=%x' % fh[q])