summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/bpz4.py
blob: eca9618f49d3c84506772bf963161b49c715106b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# gdb script: identify the vtable slot that returns 999 in ctx bring-up.
#
# Run #3 found the failing store at file 0x275cec: the indirect call at
# 0x275ce6, slot +0x4580 of the table at [ctx+0x40], called with
# (ctx, r15+0xb8), returned 0x3e7. The table slot is installed by one of the
# architecture vtable installers; this script prints the runtime target so it
# can be mapped to its decompiled body, plus the call arguments.
#
# Run: sudo gdb -p <cdt-pid> -batch -x /tmp/bpz4.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:
    print("NO_LIBCUDA")
    raise SystemExit

gdb.execute("set pagination off")
gdb.execute("set confirm off")
for off in (0x275ce6, 0x275cec):
    gdb.execute("break *0x%x" % (base + off))

t0 = time.time()
for hit in range(20):
    try:
        gdb.execute("continue")
    except gdb.error as e:
        print("CONTINUE_END %s" % e)
        break
    rip = int(gdb.parse_and_eval("$rip")) & 0xffffffffffffffff
    off = rip - base
    print("HIT %d t=%.3f off=0x%x" % (hit, time.time() - t0, off))
    try:
        r12 = int(gdb.parse_and_eval("$r12")) & 0xffffffffffffffff
        r15 = int(gdb.parse_and_eval("$r15")) & 0xffffffffffffffff
        vec = int(gdb.parse_and_eval("*(unsigned long *)0x%x" % (r12 + 0x40)))
        tgt = int(gdb.parse_and_eval("*(unsigned long *)0x%x" % (vec + 0x4580)))
        print("  r12=0x%x r15=0x%x vec=0x%x TARGET=0x%x target_off=0x%x" %
              (r12, r15, vec, tgt, tgt - base))
        print("  r15+0xb8 words: " + gdb.execute(
            "x/8gx 0x%x" % (r15 + 0xb8), to_string=True).strip())
    except Exception as e:
        print("  deref_fail %s" % e)
    if off == 0x275cec:
        try:
            print("  call returned eax=0x%x" % (int(gdb.parse_and_eval("$rax")) & 0xffffffff))
        except Exception:
            pass
        try:
            print(gdb.execute("bt 8", to_string=True))
        except Exception as e:
            print("bt_fail %s" % e)

try:
    gdb.execute("detach")
except Exception:
    pass