From fe9297d33fa495996f6ac1609a52c8091dc4d110 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 30 Sep 2026 03:15:57 -0400 Subject: guest-diag: bpz16 - live-probe chip-info vtable + 0xc48/0xc4c at the failing call --- tools/guest-diag/bpz16.py | 71 ++++++++++++++++++++++++++++++++++++ tools/guest-diag/push_guest_tools.sh | 1 + 2 files changed, 72 insertions(+) create mode 100644 tools/guest-diag/bpz16.py diff --git a/tools/guest-diag/bpz16.py b/tools/guest-diag/bpz16.py new file mode 100644 index 0000000..c67175d --- /dev/null +++ b/tools/guest-diag/bpz16.py @@ -0,0 +1,71 @@ +# gdb script: probe the guest's chip-info vtable call (ds->[0x4d38]) and the +# 0xc48/0xc4c fields at the FUN_003e3e80 call from FUN_00e0e970. +# +# Host oracle: FUN_00338f70(ChipId=0x160, Rev=4) -> out (0xc48=6, 0xc4c=0x27, +# 0xc50=7, 0xc54=5). Guest FAILS the 0xc4c switch -> 0xe94 stays 0. +# This calls ds->[0x4d38] in-process to see what the guest returns. +# +# Run: sudo gdb -p -batch -x /tmp/bpz16.py +import gdb +import time + +out = gdb.execute("info proc mappings", to_string=True) +base = None +lo = hi = 0 +for line in out.splitlines(): + if "libcuda" in line: + f = line.split() + b = int(f[0], 16) + lo, hi = b, b + int(f[1], 16) + if "r-xp" in line: + base = b - int(f[3], 16) +print("BASE=0x%x libcuda=[0x%x,0x%x)" % (base or 0, lo, hi)) +if base is None: + raise SystemExit + +gdb.execute("set pagination off") +gdb.execute("set confirm off") +CALLER_RET = base + 0xd0eae1 +gdb.execute("break *0x%x" % (base + 0x2e3e80)) + +def rd(addr, n=4, fmt="unsigned int"): + try: + return int(gdb.parse_and_eval("*(%s*)0x%x" % (fmt, addr))) & ((1 << (8 * n)) - 1) + except Exception: + return None + +t0 = time.time() +for hit in range(300): + try: + gdb.execute("continue") + except gdb.error as e: + print("CONTINUE_END %s" % e) + break + ret = rd(int(gdb.parse_and_eval("$rsp")), 8, "unsigned long") + if ret != CALLER_RET: + continue + rdi = int(gdb.parse_and_eval("$rdi")) & 0xffffffffffffffff + ds = rd(rdi + 0x40, 8, "unsigned long") + print("FUN_003e3e80 dev=0x%x ds=0x%x t=%.3f" % (rdi, ds or 0, time.time() - t0)) + for off in [0xc48, 0xc4c, 0xc50, 0xc54, 0xe94, 0xf5c, 0x5330]: + print(" ds+0x%x = 0x%x" % (off, rd(ds + off) or 0)) + fn = rd(ds + 0x4d38, 8, "unsigned long") + print(" ds->[0x4d38] = 0x%x in_libcuda=%s" % (fn or 0, lo <= (fn or 0) < hi)) + if fn and lo <= fn < hi: + sp = (int(gdb.parse_and_eval("$rsp")) - 0x200) & ~0xf + try: + gdb.execute("set $chip = 0x%x" % (sp + 0x10)) + gdb.execute("set $rev = 0x%x" % (sp + 0x20)) + res = int(gdb.parse_and_eval( + "((unsigned int (*)(unsigned long, unsigned long, unsigned long))0x%x)(0x%x, $chip, $rev)" + % (fn, ds))) + print(" CALL ret=0x%x chip=0x%x rev=0x%x" % + (res, rd(sp + 0x10) or 0xdead, rd(sp + 0x20) or 0xdead)) + except Exception as e: + print(" CALL failed: %s" % e) + break + +try: + gdb.execute("detach") +except Exception: + pass diff --git a/tools/guest-diag/push_guest_tools.sh b/tools/guest-diag/push_guest_tools.sh index 68d4e64..ffb9b29 100755 --- a/tools/guest-diag/push_guest_tools.sh +++ b/tools/guest-diag/push_guest_tools.sh @@ -42,6 +42,7 @@ push_b64 "$HERE/bpz11.py" /tmp/bpz11.py push_b64 "$HERE/bpz12.py" /tmp/bpz12.py push_b64 "$HERE/bpz13.py" /tmp/bpz13.py push_b64 "$HERE/bpz14.py" /tmp/bpz14.py +push_b64 "$HERE/bpz16.py" /tmp/bpz16.py push_b64 "$HERE/invd.py" /tmp/invd.py push_b64 "$HERE/bpwait.py" /tmp/bpwait.py push_b64 "$HERE/ctx999.py" /tmp/ctx999.py -- cgit v1.2.3