Files

132 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""rtdeep2.py — find DSP ctx object via phase-table pointer beacon, then dump window 0x540658 & neighbors."""
import subprocess, time, glob, os, sys
import numpy as np
import struct
RPP = sys.argv[1] if len(sys.argv) > 1 else '/home/m/soothe-bt/dual300.rpp'
BEACON = np.uint64(0x182615608)
def get_maps(pid):
try:
return open(f'/proc/{pid}/maps').read()
except Exception:
return ''
def readable_regions(pid):
out = []
for line in get_maps(pid).splitlines():
p = line.split()[0]
lo, hi = int(p.split('-')[0], 16), int(p.split('-')[1], 16)
out.append((lo, hi))
return out
def find_beacon(pid):
try:
mem = os.open(f'/proc/{pid}/mem', os.O_RDONLY)
except Exception:
return []
res = []
for lo, hi in readable_regions(pid):
sz = hi - lo
if sz <= 0 or sz > 0x200000000:
continue
if sz < 65536:
continue
off = 0
while off < sz:
chunk = min(sz - off, 4 << 20)
try:
buf = os.pread(mem, int(chunk), lo + off)
except Exception:
break
arr = np.frombuffer(buf[:len(buf) & ~7], dtype='<u8')
if len(arr):
idx = np.where(arr == BEACON)[0]
for i in idx:
res.append(lo + off + int(i) * 8)
off += int(chunk)
if len(res) > 64:
break
if len(res) > 64:
break
os.close(mem)
return res
def main():
proc = subprocess.Popen(['reaper', '-nosplash', '-renderproject', RPP],
stdout=open('/tmp/rtdeep2.log', 'w'), stderr=subprocess.STDOUT)
t0 = time.time()
host = None
while time.time() - t0 < 60:
for p in glob.glob('/proc/[0-9]*'):
pid = int(os.path.basename(p))
if 'soothe2' in (get_maps(pid) or ''):
host = pid
break
if host:
break
time.sleep(0.01)
print(f'host={host}', flush=True)
if not host:
proc.wait(timeout=10)
return
mem = os.open(f'/proc/{host}/mem', os.O_RDONLY)
t1 = time.time()
regs = []
for line in get_maps(host).splitlines():
p = line.split()[0]
lo, hi = int(p.split('-')[0], 16), int(p.split('-')[1], 16)
if 'vst3' in line or 'reaper' in line or 'soothe2' in line and 'rw' not in line.split()[1][:2]:
continue
if 'rw' not in line.split()[1][:2]:
continue
if hi - lo > 0x10000000:
continue
regs.append((lo, hi))
print(f'{len(regs)} rw regions to capture', flush=True)
with open('/tmp/host_rw.bin', 'wb') as f:
for lo, hi in regs:
try:
buf = os.pread(mem, hi - lo, lo)
f.write(lo.to_bytes(8, 'little'))
f.write((hi - lo).to_bytes(8, 'little'))
f.write(buf)
except Exception:
pass
print(f'captured {os.path.getsize("/tmp/host_rw.bin")} bytes', flush=True)
while time.time() - t1 < 30:
hits = find_beacon(host)
ctxs = set()
for p in hits:
for d in (0x540548, 0x540550, 0x540598):
ctxc = p - d
if 0x10000000 < ctxc < 0x7fff00000000:
ctxs.add(ctxc)
if ctxs:
print(f't={time.time()-t1:.1f}s hits={len(hits)} ctx_cands={sorted(hex(c) for c in ctxs)}', flush=True)
for ctx in sorted(ctxs):
d = os.pread(mem, 4096, ctx + 0x540658)
if len(d) < 4096:
continue
fl = np.frombuffer(d, dtype='<f4')
if np.all(np.isfinite(fl)) and fl.min() >= -1 and fl.max() <= 2:
print(f' ctx={hex(ctx)} WIN@+0x540658 head={[round(float(x),4) for x in fl[:8]]} mid={[round(float(x),4) for x in fl[1024:1032]]}', flush=True)
blk = os.pread(mem, 0x8000, ctx + 0x540000)
open(f'/tmp/ctx_{ctx:x}_win.bin', 'wb').write(blk)
break
time.sleep(0.05)
os.close(mem)
try:
proc.wait(timeout=5)
except Exception:
proc.kill()
print('done', flush=True)
if __name__ == '__main__':
main()