DF-3017 / walkzones.py
#!/usr/bin/env python3 """gdbstub walker: deref CPU_prvspace[cpu] -> gd -> ZoneAry[zi] zones -> head chunks; dump a stale devfs_node (Ndev) template and the 320-class picture. Writes /tmp/opencode/node_tpl.bin on the host. usage: walkzones.py [zi]""" import socket, time, sys _sock = socket.create_connection(("127.0.0.1", 1235), timeout=10) _sock.settimeout(2.5) def rsp(cmd, timeout=2.5): pkt = b"$" + cmd + b"#%02x" % (sum(cmd) & 0xFF) _sock.sendall(pkt) buf = b"" t0 = time.time() while time.time() - t0 < timeout: try: d = _sock.recv(65536) except socket.timeout: break if not d: raise RuntimeError("eof") buf += d if b"$" in buf and b"#" in buf[buf.index(b"$")+1:]: try: _sock.sendall(b"+") except Exception: pass i = buf.index(b"$"); j = buf.index(b"#", i+1) return buf[i+1:j] raise RuntimeError("timeout") _sock.sendall(b"$qSupported#37"); time.sleep(0.3) try: _sock.recv(65536) except Exception: pass _sock.sendall(b"+") def rd(a, n): b = rsp(b"m%x,%x" % (a, n)) if b.startswith(b"E"): raise RuntimeError(b.decode()) return bytes.fromhex(b.decode()) def rq(a): return int.from_bytes(rd(a, 8), "little") def u32(a): return int.from_bytes(rd(a, 4), "little") CPU_PRVSPACE = 0xffffffff8113d620 # struct privatespace *[MAXCPU] GD_SLAB = 0x2f00 ZI = int(sys.argv[1]) if len(sys.argv) > 1 else 22 tpl = None for cpu in range(6): try: ps = rq(CPU_PRVSPACE + cpu * 8) gd = ps cpuid = u32(gd + 0x48) z = rq(gd + GD_SLAB + ZI * 16) print("cpu%d prvspace=%#x cpuid=%d ZoneAry[%d] head=%#x" % (cpu, ps, cpuid, ZI, z)) n = 0 while z and n < 4: print(" zone %#x zi=%d cpu=%d nfree=%d/%d chunk=%d lch=%#x rch=%#x" % (z, u32(z+0x44), u32(z+4), u32(z+0x28), u32(z+0x2c), u32(z+0x40), rq(z+0x50), rq(z+0x60))) c = rq(z + 0x50) k = 0 while c and k < 6: try: blk = rd(c, 0x100) except Exception: break d_dev = int.from_bytes(blk[0:8], "little") mp = int.from_bytes(blk[8:16], "little") ntype = int.from_bytes(blk[0x38:0x3c], "little") uid = int.from_bytes(blk[0x84:0x88], "little") print(" chunk %#x d_dev=%#x mp=%#x type=%d uid=%d" % (c, d_dev, mp, ntype, uid)) if tpl is None and ntype == 4 and (mp >> 48) == 0xffff and uid == 1001: tpl = blk[:232] c = int.from_bytes(blk[0:8], "little") # freelist link at +0 k += 1 z = rq(z + 0x10) n += 1 except Exception as e: print("cpu%d err %s" % (cpu, e)) if tpl is not None: break if tpl: open("/tmp/opencode/node_tpl.bin", "wb").write(tpl) mp = int.from_bytes(tpl[8:16], "little") print("[TPL] saved 232B node template, mp=%#x" % mp) else: print("[TPL] none found") # resume the VM (gdbstub attach halts it) try: _sock.sendall(b"$c#63") time.sleep(0.2) _sock.close() except Exception: pass |