#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-3-Clause # Copyright (c) 2026 Open-IOV contributors # gdb script (run with: sudo gdb -p -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")