From 483f52f296553cf359b6deaae595288b78d4980b Mon Sep 17 00:00:00 2001 From: Matiq Date: Tue, 25 Aug 2026 10:16:48 +0300 Subject: [PATCH] 24hh-2: runtime dispatch tables STABLE (=static); bigkernels resolve to IMPORTS (outside dump); iat_name.py PE-export parser drafted (needs SIGSTOP race fix); once named, full cascade simulator becomes implementable --- handoff/NOTES_LEVEL.md | 14 +++++ scripts/dump_dispatch.py | 79 ++++++++++++++++++++++++++ scripts/iat_name.py | 117 +++++++++++++++++++++++++++++++++++++++ scripts/probe_mem.py | 25 +++++++++ 4 files changed, 235 insertions(+) create mode 100644 scripts/dump_dispatch.py create mode 100644 scripts/iat_name.py create mode 100644 scripts/probe_mem.py diff --git a/handoff/NOTES_LEVEL.md b/handoff/NOTES_LEVEL.md index 44d2fa2..7d7b278 100644 --- a/handoff/NOTES_LEVEL.md +++ b/handoff/NOTES_LEVEL.md @@ -3624,3 +3624,17 @@ fc500 ОДИН тон (f-серия) 1.1530 0.4038 +0.33 0.0013!! ### Инструменты/данные раунда scripts/finish_f.py; k-серия (sc_k*, k*_ref); f-серия (sc_f*, f*_ref); k_series.pkl, f_series.pkl. Все рефы отрендеры чисто (без kill). + +## ============ ДОПОЛНЕНИЕ 24gg-2: рантайм-таблицы стабильны; bigkernels = ИМПОРТЫ; имя ждёт PE-парсера ============ + +Дамп таблиц диспатча во время рендера (dump_dispatch.py): содержимое +СТАБИЛЬНО и совпадает со статикой; idx=4 валиден. Entry[4] bigkernel'ов +→ second-level thunks (141880 и со.) → IAT-слоты ВНЕ дампа ⇒ тела +bigkernel'ов = ИМПОРТИРОВАННЫЕ функции (UCRT/хост-DLL). +Инструмент iat_name.py читает рантайм-IAT и парсит PE-экспорты +владельца-модуля — первый прогон дал мусор из-за гонки с завершением +рендера (host умирает ~7 c); требует чтения ДО завершения или фиксации +процесса SIGSTOP на время разбора. +Как только имена получены (ожидаемо expf/powf/log10f класс), семантика +bigkernel'ов замыкается, и полный каскадный симулятор шагов 9–19+FIR +становится реализуемым без дальнейшей археологии. diff --git a/scripts/dump_dispatch.py b/scripts/dump_dispatch.py new file mode 100644 index 0000000..0906d4b --- /dev/null +++ b/scripts/dump_dispatch.py @@ -0,0 +1,79 @@ +#!/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(' {name: rva}""" + try: + f=open(path,'rb').read() + except Exception: + return {} + if f[:2]!=b'MZ': return {} + pe=struct.unpack('%x runtime=%x owner=%s' % (stub,tbl,tgt,ow[2] if ow else '?'),flush=True) + if ow: + lo,rva,path=ow + exps=pe_exports(path) + best=[nm for nm,r in exps.items() if r==rva] + print(' export:',best,flush=True) +os.close(fd) diff --git a/scripts/probe_mem.py b/scripts/probe_mem.py new file mode 100644 index 0000000..d4b2176 --- /dev/null +++ b/scripts/probe_mem.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import struct, subprocess, time, os, glob +def find_host(): + for p in glob.glob('/proc/[0-9]*'): + pid=int(os.path.basename(p)) + try: + cmd=open('/proc/%d/cmdline'%pid,'rb').read().replace(b'\0',b' ').decode('utf8','replace') + maps=open('/proc/%d/maps'%pid).read() + except Exception: continue + if 'soothe2' in maps and 'reaper' not in cmd: return pid + return None +subprocess.run("pkill -9 -x reaper; pkill -9 -f '[y]abridge'; sleep 1; " + "rm -rf /run/user/1000/yabridge-soothe2_x64-*", shell=True) +proc=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject','/tmp/opencode/multi.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) +fd=os.open('/proc/%d/mem'%host,os.O_RDONLY) +for addr,nm in ((0x1824ac210,'vtbl'),(0x182617508,'bk-table'),(0x180140ad0,'stub-code'),(0x180533340,'iir-gen')): + try: + b=os.pread(fd,16,addr) + print('%-10s %x OK: %s' % (nm,addr,b[:8].hex())) + except OSError as e: + print('%-10s %x FAIL: %s' % (nm,addr,e))