summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/trkinfo.py
blob: 46b6a69e7b75e5e3bf72336feb9c3979d077f54a (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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env python3
# gdb script (run with: sudo gdb -p <pid> -batch -x /tmp/trkinfo.py)
# Drills into the libcuda tracker the client spins on (the wait loop around
# libcuda+0x23f700): dumps the tracker object at p+0x9410, the semaphore
# object it references at +0x20, and the u32 semaphore memory that object
# points at (+0x10), plus the VMA that memory lives in.
import gdb

def r32(a):
    return int.from_bytes(gdb.selected_inferior().read_memory(a, 4).tobytes(), "little")
def r64(a):
    return int.from_bytes(gdb.selected_inferior().read_memory(a, 8).tobytes(), "little")
def rmem(a, n):
    return gdb.selected_inferior().read_memory(a, n).tobytes()

out = gdb.execute("info proc mappings", to_string=True)
base = None
maps = []
for line in out.splitlines():
    f = line.split()
    if len(f) >= 5:
        try:
            lo = int(f[0], 16); hi = int(f[1], 16)
            maps.append((lo, hi, line.strip()))
        except Exception:
            pass
    if "libcuda" in line and "r-xp" in line and base is None:
        base = int(f[0], 16) - int(f[3], 16)

def vma_of(addr):
    for lo, hi, line in maps:
        if lo <= addr < hi:
            return line
    return "(none)"

if base is None:
    print("NO_LIBCUDA_BASE")
    raise SystemExit
LO = base + 0x23f700
HI = base + 0x23fd10

found = None
for t in gdb.selected_inferior().threads():
    t.switch()
    f = gdb.newest_frame()
    for i in range(14):
        if f is None:
            break
        try:
            pc = int(f.pc())
        except Exception:
            pc = 0
        if LO <= pc < HI:
            try:
                ctx = int(f.read_register("rbx")) & 0xffffffffffffffff
            except Exception:
                ctx = None
            found = (t.num, pc, ctx)
            break
        f = f.older()
    if found:
        break

if not found:
    print("NO_SPIN_FRAME")
    raise SystemExit

tid, pc, ctx = found
print("SPINNER tid=%s pc=0x%x ctx=0x%x" % (tid, pc, ctx))
count = r32(ctx + 0x10)
ent = r64(ctx + 0x18)
print("count=%d entries=0x%x" % (count, ent))
n = min(count, 32)
for i in range(n):
    e = ent + i * 0x28
    typ = r32(e)
    p = r64(e + 8)
    v = r32(e + 0x10)
    if typ != 1:
        print("e%d type=%d p=0x%x v=0x%x (skip)" % (i, typ, p, v))
        continue
    t = p + 0x9410
    try:
        trk = rmem(t, 0x40)
    except Exception as ex:
        print("e%d tracker unreadable: %s" % (i, ex))
        continue
    last = int.from_bytes(trk[0x10:0x18], "little")
    cur = int.from_bytes(trk[0x18:0x20], "little")
    sem = int.from_bytes(trk[0x20:0x28], "little")
    print("e%d p=0x%x v=0x%x TRK=0x%x last=0x%x cur=0x%x sem_obj=0x%x"
          % (i, p, v, t, last, cur, sem))
    try:
        so = rmem(sem, 0x40)
        print("  sem_obj[0:0x40]=%s" % so.hex())
        mem = int.from_bytes(so[0x10:0x18], "little")
        print("  sem_mem=0x%x vma=%s" % (mem, vma_of(mem)))
        try:
            mv = rmem(mem & ~0xfff, 0x40)
            print("  sem_page[0:0x40]=%s val@+0x%x=0x%x" % (mv.hex(), mem & 0xfff, r32(mem)))
        except Exception as ex:
            print("  sem_page unreadable: %s" % ex)
    except Exception as ex:
        print("  sem_obj unreadable: %s" % ex)
print("DONE_TRK")