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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
#!/usr/bin/env python3
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2026 Open-IOV contributors
# gdb script (run with: sudo gdb -p <pid> -batch -x /tmp/trkinfo.py)
# Drills into the libcuda tracker wait: dumps every wait entry, the tracker
# objects they reference (channel/context layout at p+0x9410 with the sem
# object at +0x9430), and the progress object at p+0x48 (size/idx/cursor and
# the 0x38-byte slots it indexes).
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 libbase=0x%x" % (tid, pc, ctx, base))
count = r32(ctx + 0x10)
ent = r64(ctx + 0x18)
print("count=%d entries=0x%x" % (count, ent))
n = min(count, 48)
for i in range(n):
e = ent + i * 0x28
typ = r32(e)
p = r64(e + 8)
v = r64(e + 0x10)
x18 = r64(e + 0x18)
x20 = r64(e + 0x20)
if typ != 1:
print("e%d type=0x%x p=0x%x v=0x%x x18=0x%x x20=0x%x" % (i, typ, p, v, x18, x20))
if p:
try:
print(" obj[0:0x28]=%s" % rmem(p, 0x28).hex())
except Exception:
pass
continue
t = p + 0x9410
try:
trk = rmem(t, 0x40)
except Exception as ex:
print("e%d tracker unreadable: %s" % (i, ex))
continue
sub = int.from_bytes(trk[0x08:0x10], "little")
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 sub=0x%x last=0x%x cur=0x%x sem_obj=0x%x"
% (i, p, v, t, sub, 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)
try:
q = r64(p + 0x48)
print(" prog_obj=0x%x next=0x%x cblist=0x%x idx_u32=0x%x flags95bc=0x%x"
% (q, r64(p + 0x9470), r64(p + 0x9458), r32(p + 0x34), r32(p + 0x95bc)))
if q:
size = r32(q + 8)
idx = r32(q + 0x48)
cur2 = r32(q + 0x4c)
arr = r64(q + 0x40)
print(" q+8=size=%d idx=0x%x cursor=0x%x arr=0x%x" % (size, idx, cur2, arr))
for s in (idx, cur2):
if size:
slot = arr + (s % size) * 0x38
else:
slot = arr + s * 0x38
try:
print(" slot[%d]@0x%x=%s" % (s, slot, rmem(slot, 0x38).hex()))
except Exception as ex:
print(" slot[%d] unreadable: %s" % (s, ex))
except Exception as ex:
print(" prog unreadable: %s" % ex)
print("DONE_TRK")
|