summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/bpwait.py
blob: 9b708c8b42698dffd362fddd07809af464682bda (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
65
66
67
68
69
70
71
72
73
74
# gdb script: catch the tracker-gate exit with a NONZERO dispatcher status and
# dump the wait-entry array the gate polls. This names the wait that ends the
# client's context-init spin (the value that becomes the CUDA error).
#
# Site (libcuda+0x23f9e7): the gate loops
#     call 0xd50e50            ; wait dispatcher
#   0x23f9ec: mov %eax,%edx
#   0x23f9ee: test %eax,%eax
#   0x23f9f0: je 0x23f9c0      ; still pending -> poll again
#   0x23f9f2: mov %edx,%eax    ; <- nonzero status: gate exits with it
# Entry object: { *(void**)rsi; u32 count @+0x10; void *array @+0x18 }
# Array entries are 0x28 bytes: type @+0x0, then type-specific fields.
# Run: sudo gdb -p <cdt-pid> -batch -x /tmp/bpwait.py
import gdb

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")
gdb.execute("break *0x%x" % (base + 0x23f9f2))
try:
    gdb.execute("continue")
except gdb.error as e:
    print("CONTINUE_ERR %s" % e)
print("STOPPED")


def rd64(a):
    try:
        return int(gdb.parse_and_eval("*(unsigned long *)0x%x" % a)) & 0xffffffffffffffff
    except Exception:
        return None


def rd32(a):
    try:
        return int(gdb.parse_and_eval("*(unsigned int *)0x%x" % a)) & 0xffffffff
    except Exception:
        return None


try:
    rip = int(gdb.parse_and_eval("$rip")) & 0xffffffffffffffff
    edx = int(gdb.parse_and_eval("$edx")) & 0xffffffff
    rsi = int(gdb.parse_and_eval("$rsi")) & 0xffffffffffffffff
    print("RIP=0x%x off=0x%x status(edx)=0x%x" % (rip, rip - base, edx))
    print(gdb.execute("bt 16", to_string=True))
    ent = rd64(rsi)
    cnt = rd32(rsi + 0x10)
    arr = rd64(rsi + 0x18)
    print("entry_obj=0x%x count=0x%x array=0x%x" % (ent or 0, cnt or 0, arr or 0))
    if ent and arr:
        print("entity hdr: " + " ".join("+0x%x=0x%x" % (o, rd32(ent + o) or 0)
                                        for o in (0, 4, 8, 0xc, 0x10, 0x14, 0x18, 0x1c)))
    if arr and cnt and cnt < 64:
        for i in range(cnt):
            e = arr + i * 0x28
            words = [rd32(e + o) or 0 for o in (0, 4, 8, 0xc, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24)]
            print("entry[%d] " % i + " ".join("0x%08x" % w for w in words))
except Exception as e:
    print("dump_fail %s" % e)
try:
    gdb.execute("detach")
except Exception:
    pass