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")
|