summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/bpz20.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/guest-diag/bpz20.py')
-rw-r--r--tools/guest-diag/bpz20.py78
1 files changed, 78 insertions, 0 deletions
diff --git a/tools/guest-diag/bpz20.py b/tools/guest-diag/bpz20.py
new file mode 100644
index 0000000..cf8ee8c
--- /dev/null
+++ b/tools/guest-diag/bpz20.py
@@ -0,0 +1,78 @@
+# gdb script: catch the write that ZEROES ds+0xe94 after the CASE1 body set
+# it to 0x18. Run via run_cycle.sh gdb-launch (device init happens during
+# cuInit, before the CDT_PAUSE).
+#
+# bpz18 showed: CASE1 (0x32e8be) hit at t=0.24; at FUN_003e3e80 (t=72.9)
+# ds+0xe94 == 0. Set a hardware watchpoint at the CASE1 hit and log every
+# write with a backtrace.
+import gdb
+import time
+
+gdb.execute("set pagination off")
+gdb.execute("set confirm off")
+gdb.execute("set environment CDT_PAUSE=60")
+gdb.execute("set environment CDT_HOLD=900")
+gdb.execute("catch load libcuda.so")
+gdb.execute("run")
+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
+
+CASE1 = base + 0x32e8be
+TERM = base + 0x2e3e80
+CALLER_RET = base + 0xd0eae1
+gdb.execute("break *0x%x" % CASE1)
+gdb.execute("break *0x%x" % TERM)
+
+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()
+watched = False
+for hit in range(200):
+ try:
+ gdb.execute("continue")
+ except gdb.error as e:
+ print("CONTINUE_END %s" % e)
+ break
+ rip = int(gdb.parse_and_eval("$rip")) & 0xffffffffffffffff
+ if rip == CASE1 and not watched:
+ rc = int(gdb.parse_and_eval("$rcx")) & 0xffffffffffffffff
+ gdb.execute("delete 1")
+ gdb.execute("set $wpaddr = 0x%x" % (rc + 0xe94))
+ gdb.execute("watch *(int*)$wpaddr")
+ watched = True
+ print("WATCH set on ds=0x%x +0xe94 (t=%.3f)" % (rc, time.time() - t0))
+ continue
+ if rip == TERM:
+ 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("TERMINATOR t=%.3f ds=0x%x e94=0x%x c4c=0x%x" %
+ (time.time() - t0, ds or 0, rd(ds + 0xe94) or 0, rd(ds + 0xc4c) or 0))
+ break
+ # watchpoint hit
+ addr = int(gdb.parse_and_eval("$wpaddr")) & 0xffffffffffffffff
+ val = rd(addr) or 0
+ print("WP hit t=%.3f pc=+0x%x val=0x%x" % (time.time() - t0, rip - base, val))
+ try:
+ print(gdb.execute("bt 6", to_string=True))
+ except Exception:
+ pass
+
+try:
+ gdb.execute("detach")
+except Exception:
+ pass