#!/usr/bin/env python3 """Translate the trigger-count guest VA into a HOST address gdb can watch. gdb debugs the host emulator process, so a guest VA is meaningless to it. Canary backs guest memory with one shared-memory file, so the chain is: guest VA -> file offset gmem.va_to_off file offset -> host address the shm mapping in /proc//maps, host = map_start - map_file_offset + off Prints the host address on stdout, and the working on stderr. """ import os import sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import gmem import isl import squadron_state as S ssb = isl.load('/tmp/Stage02.ssb') path = gmem.mem_path() size = os.path.getsize(path) with open(path, 'rb', buffering=0) as f: m, _fb = S.find_mission(f, size, ssb) if m is None: print('NOTFOUND'); sys.exit(1) ph = S.u32(f, m + 4) va = ph + 272 + 20 off = gmem.va_to_off(va) shm = os.path.basename(path) pids = [p for p in os.listdir('/proc') if p.isdigit() and os.path.exists('/proc/%s/comm' % p) and open('/proc/%s/comm' % p).read().strip() == 'xenia_canary'] if not pids: print('NOPID'); sys.exit(1) host = None for line in open('/proc/%s/maps' % pids[0]): if shm not in line: continue rng, _perm, mo = line.split()[0], line.split()[1], line.split()[2] a, b = (int(x, 16) for x in rng.split('-')) mo = int(mo, 16) if mo <= off < mo + (b - a): host = a - mo + off break if host is None: print('NOMAP'); sys.exit(1) print('mission 0x%08X phase 0x%08X va 0x%08X off 0x%X -> host 0x%X' % (m, ph, va, off, host), file=sys.stderr) print('0x%X' % host)