summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-30 02:15:32 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-30 02:15:32 -0400
commitaff268424b1c9953c99cef45767b55d9f73ac05f (patch)
treefad1d3448c1515fa8a8c698aee47554483076ff6 /tools/guest-diag
parent40fc44fce89b1053b4445f6b092a2e7c68685284 (diff)
downloadopen-iov-aff268424b1c9953c99cef45767b55d9f73ac05f.tar.gz
open-iov-aff268424b1c9953c99cef45767b55d9f73ac05f.zip
guest-diag: bpz10 - trace every call return inside FUN_003e90c0
Diffstat (limited to 'tools/guest-diag')
-rw-r--r--tools/guest-diag/bpz10.py125
-rwxr-xr-xtools/guest-diag/push_guest_tools.sh1
2 files changed, 126 insertions, 0 deletions
diff --git a/tools/guest-diag/bpz10.py b/tools/guest-diag/bpz10.py
new file mode 100644
index 0000000..30aa1da
--- /dev/null
+++ b/tools/guest-diag/bpz10.py
@@ -0,0 +1,125 @@
+# gdb script: name the first failing call inside FUN_003e90c0 (ucode-image
+# create, second half) after FUN_003d1e70 (blob parse) succeeded.
+#
+# PART 76 chain: FUN_00e21850 -> FUN_003e99d0 -> FUN_003d1e70 OK ->
+# FUN_003e90c0 returns 1. This script breaks after EVERY call in
+# FUN_003e90c0 (file 0x2e90c0..0x2e99b5), prints the return value, and
+# finally prints the function's return + the caller's test site
+# (CREATE2_RET at 0x2e9a3f).
+#
+# Run: sudo gdb -p <cdt-pid> -batch -x /tmp/bpz10.py
+import gdb
+import time
+
+out = gdb.execute("info proc mappings", to_string=True)
+base = None
+for line in out.splitlines():
+ if "libcuda" in line and "r-xp" in line:
+ f = line.split()
+ base = int(f[0], 16) - int(f[3], 16)
+ break
+print("BASE=0x%x" % (base or 0))
+if base is None:
+ raise SystemExit
+
+gdb.execute("set pagination off")
+gdb.execute("set confirm off")
+
+# (file offset of the instruction AFTER the call, short name)
+SITES = [
+ (0x2e9110, "calloc"),
+ (0x2e912a, "FUN_004aa820_alloc"),
+ (0x2e918e, "FUN_00390290_status"),
+ (0x2e91b3, "FUN_003df0d0_status"),
+ (0x2e91f1, "destr_2e84d0"),
+ (0x2e921d, "FUN_00391ee0_status"),
+ (0x2e923c, "FUN_00371fa0_status"),
+ (0x2e9282, "mutex_lock84"),
+ (0x2e92b7, "mutex_unlock84"),
+ (0x2e92bf, "FUN_00e4f3e0_status"),
+ (0x2e9304, "mutex_lock68"),
+ (0x2e931a, "mutex_unlock68"),
+ (0x2e932a, "FUN_00363430_bool"),
+ (0x2e9336, "FUN_003df340_bool"),
+ (0x2e9363, "FUN_00406ff0_status"),
+ (0x2e93ba, "FUN_00394190_status"),
+ (0x2e93c9, "FUN_003bf520_status"),
+ (0x2e9449, "free_a"),
+ (0x2e9478, "FUN_00400550"),
+ (0x2e948e, "FUN_004ab390"),
+ (0x2e9497, "free_b"),
+ (0x2e94a8, "free_c"),
+ (0x2e94b6, "free_d_fail"),
+ (0x2e9505, "FUN_003011e0_status"),
+ (0x2e9525, "ind_0xa0_status"),
+ (0x2e9564, "unlock_fail"),
+ (0x2e9598, "unlock_b"),
+ (0x2e95fc, "FUN_00e4b8c0"),
+ (0x2e9615, "ind_0x4a48_ptr"),
+ (0x2e9628, "FUN_005a5530"),
+ (0x2e9643, "FUN_003df340_bool2"),
+ (0x2e967a, "FUN_00e4f200_status"),
+ (0x2e9687, "FUN_0034a4d0_bool"),
+ (0x2e96e4, "FUN_00251730_done"),
+ (0x2e9717, "unlock_ret0"),
+ (0x2e9788, "FUN_003bf520_status2"),
+ (0x2e97fa, "fprintf_fail"),
+ (0x2e9808, "FUN_003be020_bool"),
+ (0x2e9824, "FUN_0036b900_bool"),
+ (0x2e9857, "FUN_003df340_bool3"),
+ (0x2e9936, "FUN_00e4f2d0"),
+ (0x2e9203, "FUN_3e90c0_RET"),
+ (0x2e9a23, "PARSE_RET"),
+ (0x2e9a3f, "CREATE2_RET"),
+]
+NAMES = dict(SITES)
+for off, name in SITES:
+ gdb.execute("break *0x%x" % (base + off))
+
+t0 = time.time()
+hits = 0
+last_nonzero = None
+inv = 0
+while hits < 500:
+ try:
+ gdb.execute("continue")
+ except gdb.error as e:
+ print("CONTINUE_END %s" % e)
+ break
+ hits += 1
+ rip = int(gdb.parse_and_eval("$rip")) & 0xffffffffffffffff
+ off = rip - base
+ name = NAMES.get(off, "?")
+ eax = int(gdb.parse_and_eval("$eax")) & 0xffffffff
+ r15 = int(gdb.parse_and_eval("$r15d")) & 0xffffffff
+ print("HIT %d t=%.3f off=0x%x %-24s eax=0x%x r15=0x%x" %
+ (hits, time.time() - t0, off, name, eax, r15))
+ if name in ("FUN_00390290_status", "FUN_003df0d0_status",
+ "FUN_00391ee0_status", "FUN_00371fa0_status",
+ "FUN_00e4f3e0_status", "FUN_00406ff0_status",
+ "FUN_00394190_status", "FUN_003bf520_status",
+ "FUN_003bf520_status2", "FUN_003011e0_status",
+ "FUN_00e4f200_status") and eax != 0:
+ last_nonzero = (name, eax)
+ print(" >>> LAST NONZERO %s = 0x%x" % (name, eax))
+ if name == "FUN_3e90c0_RET":
+ inv += 1
+ print("INV %d FUN_3e90c0 return r15/eax=0x%x" % (inv, r15))
+ if last_nonzero:
+ print(" last nonzero status call: %s = 0x%x" % last_nonzero)
+ if r15 != 0:
+ try:
+ print(gdb.execute("bt 6", to_string=True))
+ except Exception as e:
+ print("bt_fail %s" % e)
+ break
+ last_nonzero = None
+ if name == "CREATE2_RET":
+ print("CREATE2_RET eax=0x%x" % eax)
+ if eax != 0:
+ 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 2bcf9a7..660072d 100755
--- a/tools/guest-diag/push_guest_tools.sh
+++ b/tools/guest-diag/push_guest_tools.sh
@@ -37,6 +37,7 @@ push_b64 "$HERE/bpz6.py" /tmp/bpz6.py
push_b64 "$HERE/bpz7.py" /tmp/bpz7.py
push_b64 "$HERE/bpz8.py" /tmp/bpz8.py
push_b64 "$HERE/bpz9.py" /tmp/bpz9.py
+push_b64 "$HERE/bpz10.py" /tmp/bpz10.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