wine_ptrace_trace: add chain breakpoints + live-dump chain I/O (DIV confirmed: input is VLAW output 0-17.6, tmp6f8 ~0.8)

This commit is contained in:
2026-08-31 01:05:28 +03:00
parent 9d10169157
commit 59fcb7eb56
2 changed files with 50 additions and 4 deletions
+7
View File
@@ -125,6 +125,13 @@ err = db(ta(out,1000)/ta(ref,1000)) # err в dB, цель <0.1
**Статус:** chain отключен, используется VLAW path (`RT_VLAW=1`). Target `0.314→<0.05` требует **live-dump chain I/O** или полной транскрипции data flow из decompilation.
**Live-dump chain (ptrace):** chain вызывается в рантайме (DIV#0-7 на `0x1803a06a0`):
- Input: `a` = bands_curve (VLAW output, min=0, max=17.6, mean=0.048)
- `b` = tmp6f8 (step 9b accumulation, min=0, max=0.8, mean=0.8)
- 8 DIV hits на одном кадре (dual-band: 2 bands × 4 iterations?)
**Для полного live-dump нужно:** breakpoints на всех шагах 9-19 (LOG#1, DIVIDE, dc40, FMA, EXP#1, array-mul, kWarp, LOG#2, IIR4×2, EXP#2).
---
## Чистая работа
+43 -4
View File
@@ -37,6 +37,11 @@ BP_CIN = 0x180529c60
BP_COUT = 0x180529ee1
BP_AIN = 0x180016140
BP_AOUT = 0x18000332c
# Chain 9-19 breakpoints (BLOCKMAP:620-644)
BP_CHAIN_START = 0x18052a580 # band loop start (52a580)
BP_CHAIN_LOG1 = 0x18052a63a # LOG#1 in chain (52a63a)
BP_CHAIN_LOG2 = 0x18052aefd # LOG#2 in chain (52aefd)
BP_CHAIN_END = 0x18052b3cd # chain end / FIR start (52b3cd)
CTX_SLOTS = {'scr': 0x540628, 'trk': 0x540688, 'cur': 0x540678,
'fir_ptr': 0x540668}
@@ -281,7 +286,12 @@ def main():
('DIV', BP_DIV), ('DC40', BP_DC40),
('EXPVAR', BP_EXPVAR), ('FN', BP_FN),
('CIN', BP_CIN), ('COUT', BP_COUT),
('AIN', BP_AIN), ('AOUT', BP_AOUT)):
('AIN', BP_AIN), ('AOUT', BP_AOUT),
# Chain 9-19 breakpoints
('CHAIN_START', BP_CHAIN_START),
('CHAIN_LOG1', BP_CHAIN_LOG1),
('CHAIN_LOG2', BP_CHAIN_LOG2),
('CHAIN_END', BP_CHAIN_END)):
if not mapped(addr):
print('!! %s@%#x не смапплен — пропуск' % (nm_ := name, addr), flush=True)
continue
@@ -299,9 +309,11 @@ def main():
samples = []
hits = {'COPY': 0, 'EXP': 0, 'DF0': 0, 'DF0RET': 0, 'TRACKSAVE': 0,
'DIV': 0, 'DC40': 0, 'EXPVAR': 0, 'FN': 0,
'CIN': 0, 'COUT': 0, 'AIN': 0, 'AOUT': 0}
'CIN': 0, 'COUT': 0, 'AIN': 0, 'AOUT': 0,
'CHAIN_START': 0, 'CHAIN_LOG1': 0, 'CHAIN_LOG2': 0, 'CHAIN_END': 0}
track_by_tid = {}
track_dumps = []
chain_dumps = []
regs_by_tid = {}
t_start = time.time()
@@ -410,8 +422,35 @@ def main():
continue
if kind == 'DF0':
track_by_tid[pid] = regs.rdx
# Chain 9-19: dump buffers at key points
if kind in ('CHAIN_START', 'CHAIN_LOG1', 'CHAIN_LOG2', 'CHAIN_END'):
rec_c = {'kind': kind, 'tid': pid,
't': round(time.time()-t_start, 4),
'rcx': regs.rcx, 'rdx': regs.rdx,
'r8': regs.r8, 'r9': regs.r9,
'rsp': regs.rsp}
try:
# chain input: [678i] = rcx (bands_curve), [6f8] = rdx (tmp6f8)
if regs.rcx > 0x10000 and regs.rdx > 0x10000:
rec_c['bands_in'] = rd_f32(regs.rcx, min(2050, 512)) # first 512 vals
rec_c['tmp6f8_in'] = rd_f32(regs.rdx, min(2050, 512))
rec_c['acc_ptr'] = regs.r8 if regs.r8 > 0x10000 else 0
if rec_c['acc_ptr']:
rec_c['acc_in'] = rd_f32(rec_c['acc_ptr'], min(2050, 512))
except OSError as e:
rec_c['err'] = str(e)
chain_dumps.append(rec_c)
hits[kind] += 1
# standard int3 handling
poke(pid, site, (peek(pid, site) & ~0xFF) | obyte)
regs.rip = site
setregs(pid, regs)
pt(PTRACE_SINGLESTEP, pid, 0, 0)
os.waitpid(pid, __WALL)
poke(pid, site, (peek(pid, site) & ~0xFF) | 0xCC)
pt(PTRACE_CONT, pid, 0, 0)
continue
if kind in ('CIN','COUT'):
key='cin_%d'%pid if kind=='CIN' else 'cout_%d'%pid
if kind=='CIN':
regs_by_tid[pid]=dict(rdx=regs.rdx,r12=regs.r12,
rcx=regs.rcx)
@@ -632,7 +671,7 @@ def main():
snap_ptrs[nm] = p
snap_arr[nm] = rd_f32(p, 4100)
with open(os.path.join(outdir, 'chain_samples.pkl'), 'wb') as f:
pickle.dump({'samples': samples, 'snap_ptrs': snap_ptrs, 'ctx': ctx}, f)
pickle.dump({'samples': samples, 'chain_dumps': chain_dumps, 'snap_ptrs': snap_ptrs, 'ctx': ctx}, f)
np.savez_compressed(os.path.join(outdir, 'ctx_snap.npz'), **snap_arr)
print('saved %d -> %s' % (len(samples), outdir), flush=True)
for _ in range(600):