Files

80 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""dump_dispatch.py — dump dispatch tables of bigkernel stubs at runtime.
Stubs of interest (from FIR loop / steps 14,17):
1409e0 -> table@182617508 ; 140ad0 -> ? ; 140b30 -> table@1826176c8
Nested stub inside 140a00: idx cell/table computed below.
Dumps tables pre-render (static) and during render (runtime-patched).
"""
import struct, subprocess, sys, time
import glob, os
BASE = 0x180000000
data = open('/home/m/re-tools/soothe_mem.bin','rb').read()
def find_host():
for p in glob.glob('/proc/[0-9]*'):
pid=int(os.path.basename(p))
try:
cmd=open(f'/proc/{pid}/cmdline','rb').read().replace(b'\0',b' ').decode('utf8','replace')
maps=open(f'/proc/{pid}/maps').read()
except Exception: continue
if 'soothe2' in maps and 'reaper' not in cmd: return pid
return None
def rd(a,n):
try: return os.pread(fd,n,a)
except OSError: return None
subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; "
"rm -rf /run/user/1000/yabridge-soothe2_x64-*; sleep 1", shell=True)
rpp=sys.argv[1] if len(sys.argv)>1 else '/tmp/opencode/multi.rpp'
proc=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject',rpp],
stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
t0=time.time(); host=None
while time.time()-t0<30 and not host:
host=find_host(); time.sleep(0.002)
print('host',host,flush=True)
if not host: sys.exit(1)
fd=os.open(f'/proc/{host}/mem',os.O_RDONLY)
TABLES={'bk140b30':0x1826176c8,'bk140b60':0x182617708,'bk1409e0':0x182617508,
'bk140ad0':None,'bk140a40':0x182617588}
# find bk140ad0 table: stub 140ad0 pattern movsxd rax,[rip+X]; lea r10,[rip+Y]
off=0x180140ad0-BASE
b=data[off:off+16]
rel1=struct.unpack('<i',b[3:7])[0]
rel2=struct.unpack('<i',b[10:14])[0]
idx_a=0x180140ad0+7+rel1
tbl_a=0x180140ad0+14+rel2
TABLES['bk140ad0']=tbl_a
print('bk140ad0 idx@%x tbl@%x' % (idx_a,tbl_a),flush=True)
def dump_tables(tag):
print(tag,'fd=',fd,flush=True)
for nm,t in TABLES.items():
b=rd(t,64)
if b is None:
import errno
print('%s %s unreadable err=%s'%(tag,nm,os.strerror(errno.EIO))); continue
vals=struct.unpack('<%dQ'%(len(b)//8),b[:len(b)//8*8])
nz=[(i,hex(v)) for i,v in enumerate(vals) if v]
print('%s %-9s: %s' % (tag,nm,nz), flush=True)
# also nested stub inside 140a00 (static parse):
off=0x140a10-BASE
b1=data[off:off+7]
if b1[:3]==b'\x48\x63\x05':
rel=struct.unpack('<i',b1[3:7])[0]
icell=0x180140a10+7+rel
b2=data[icell-BASE:4]
print('nested idx cell @%x static=%d' % (icell, struct.unpack('<i',b2)[0]),flush=True)
for k in range(30):
dump_tables('R%d'%k)
time.sleep(0.15)
try:
os.kill(proc.pid,0)
except ProcessLookupError:
break
os.close(fd)