#!/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])