tools: add sled (zero-drift) detector + capstone disassembly history in trap handler
This commit is contained in:
+37
-1
@@ -101,6 +101,12 @@ def main():
|
|||||||
last = [0]
|
last = [0]
|
||||||
from collections import deque
|
from collections import deque
|
||||||
hist = deque(maxlen=20000)
|
hist = deque(maxlen=20000)
|
||||||
|
# sled detector: sequential runs (pc == prev+2/4) longer than THRESH
|
||||||
|
# are zero-drifts; log run start (the jump/fall that entered it).
|
||||||
|
_sled_start = [0]
|
||||||
|
_sled_n = [0]
|
||||||
|
_sled_log = []
|
||||||
|
_SLED_TH = 100
|
||||||
calls = [] if "--calltrace" in sys.argv else None
|
calls = [] if "--calltrace" in sys.argv else None
|
||||||
rets = [] if "--retrace" in sys.argv else None
|
rets = [] if "--retrace" in sys.argv else None
|
||||||
qlog = [] if "--querylog" in sys.argv else None
|
qlog = [] if "--querylog" in sys.argv else None
|
||||||
@@ -134,6 +140,16 @@ def main():
|
|||||||
def hook_code(mu, addr, size, data):
|
def hook_code(mu, addr, size, data):
|
||||||
count[0] += 1
|
count[0] += 1
|
||||||
last[0] = addr
|
last[0] = addr
|
||||||
|
_pp = _prev[0]
|
||||||
|
_prev[0] = addr
|
||||||
|
if addr == _pp + 2 or addr == _pp + 4:
|
||||||
|
if _sled_n[0] == 0:
|
||||||
|
_sled_start[0] = _pp
|
||||||
|
_sled_n[0] += 1
|
||||||
|
else:
|
||||||
|
if _sled_n[0] >= _SLED_TH and len(_sled_log) < 20:
|
||||||
|
_sled_log.append((count[0], _sled_start[0], _pp, _sled_n[0]))
|
||||||
|
_sled_n[0] = 0
|
||||||
if 0x08006B8C <= addr < 0x08006B9E:
|
if 0x08006B8C <= addr < 0x08006B9E:
|
||||||
try:
|
try:
|
||||||
_lr = mu.reg_read(_LR)
|
_lr = mu.reg_read(_LR)
|
||||||
@@ -187,6 +203,21 @@ def main():
|
|||||||
print(f" [73A100]={bytes(mu.mem_read(0x073A100, 4)).hex()}")
|
print(f" [73A100]={bytes(mu.mem_read(0x073A100, 4)).hex()}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" [73A100] unreadable: {e}")
|
print(f" [73A100] unreadable: {e}")
|
||||||
|
try:
|
||||||
|
from capstone import Cs, CS_ARCH_ARM, CS_MODE_THUMB, CS_MODE_ARM
|
||||||
|
md_t = Cs(CS_ARCH_ARM, CS_MODE_THUMB)
|
||||||
|
md_a = Cs(CS_ARCH_ARM, CS_MODE_ARM)
|
||||||
|
for _pc, _th in list(hist)[-60:]:
|
||||||
|
try:
|
||||||
|
_b = _pc & ~1
|
||||||
|
_c = mu.mem_read(_b, 8 if _th else 12)
|
||||||
|
for _ins in (md_t if _th else md_a).disasm(_c, _b):
|
||||||
|
print(f" hist {_b:#x}{'t' if _th else 'a'}: {_ins.mnemonic} {_ins.op_str}")
|
||||||
|
break
|
||||||
|
except Exception:
|
||||||
|
print(f" hist {_pc:#x}: <unreadable>")
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
_trap_n[0] -= 1
|
_trap_n[0] -= 1
|
||||||
if _trap_n[0] <= 0 and "--trapn" in sys.argv:
|
if _trap_n[0] <= 0 and "--trapn" in sys.argv:
|
||||||
mu.emu_stop()
|
mu.emu_stop()
|
||||||
@@ -216,7 +247,6 @@ def main():
|
|||||||
if len(elog) < 20000:
|
if len(elog) < 20000:
|
||||||
elog.append((count[0], _prev[0], -addr, 2))
|
elog.append((count[0], _prev[0], -addr, 2))
|
||||||
_inrng[_i] = inside
|
_inrng[_i] = inside
|
||||||
_prev[0] = addr
|
|
||||||
if calls is not None and size in (2, 4):
|
if calls is not None and size in (2, 4):
|
||||||
try:
|
try:
|
||||||
if size == 2:
|
if size == 2:
|
||||||
@@ -585,6 +615,12 @@ def main():
|
|||||||
print(f" {pc:#x}: <unreadable>")
|
print(f" {pc:#x}: <unreadable>")
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("hist:", [hex(pc) for pc, _ in list(hist)[-12:]])
|
print("hist:", [hex(pc) for pc, _ in list(hist)[-12:]])
|
||||||
|
if _sled_log or _sled_n[0] >= _SLED_TH:
|
||||||
|
if _sled_n[0] >= _SLED_TH:
|
||||||
|
_sled_log.append((count[0], _sled_start[0], last[0], _sled_n[0]))
|
||||||
|
print(f"sleds: {len(_sled_log)}")
|
||||||
|
for n, s, e, c in _sled_log:
|
||||||
|
print(f" insn#{n} [{s:#x}..{e:#x}] len={c}")
|
||||||
if elog is not None:
|
if elog is not None:
|
||||||
print(f"entries: {len(elog)}")
|
print(f"entries: {len(elog)}")
|
||||||
for n, prev, cur, th in elog[:10]:
|
for n, prev, cur, th in elog[:10]:
|
||||||
|
|||||||
Reference in New Issue
Block a user