summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/wall2/t79.py
blob: c2fe381e6f56ba52b02bfee0788623b42a4a5ae3 (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
import gdb, sys

inf = gdb.selected_inferior()
pid = inf.pid
base = None
for line in open("/proc/%d/maps" % pid):
    if "libnvidia-eglcore.so.570.144" in line:
        parts = line.split()
        lo, hi = [int(x, 16) for x in parts[0].split('-')]
        off = int(parts[2], 16)
        if off == 0:
            base = lo
            break
if base is None:
    print("EGLBASE not found"); gdb.execute("detach"); sys.exit(1)
print("EGLBASE 0x%x PID %d" % (base, pid))

maps = []
for line in open("/proc/%d/maps" % pid):
    parts = line.split()
    try:
        lo, hi = [int(x, 16) for x in parts[0].split('-')]
        maps.append((lo, hi, parts[1], parts[-1] if len(parts) > 5 else "anon"))
    except Exception:
        pass

def resolve(addr):
    for lo, hi, perm, name in maps:
        if lo <= addr < hi:
            return "0x%x-0x%x %s %s" % (lo, hi, perm, name)
    return "?"

def rd(a, n):
    return inf.read_memory(a, n).tobytes()
def u32(a):
    return int.from_bytes(rd(a, 4), 'little')
def u64(a):
    return int.from_bytes(rd(a, 8), 'little')

state = {"done": False}

class B(gdb.Breakpoint):
    def __init__(self, spec, fn, limit=100000):
        super().__init__(spec, internal=False)
        self.fn = fn; self.limit = limit; self.hits = 0
        self.silent = True
    def stop(self):
        self.hits += 1
        try:
            stop = bool(self.fn(self))
        except Exception as e:
            print("ERR@0x%x %s" % (int(gdb.parse_and_eval("$pc")), e))
            stop = False
        return stop or self.hits >= self.limit

def loophead(bp):
    if state["done"]:
        return False
    state["done"] = True
    rbx = int(gdb.parse_and_eval("$rbx"))
    sub = u64(rbx+0x70)
    print("WAIT rbx=0x%x sub=0x%x" % (rbx, sub))
    try:
        obj2 = u64(sub+0x58)
        off = u32(obj2+0x60)
        holder = u64(obj2+0x58)
        base2 = u64(holder+0x58)
        word_addr = base2 + off
        val = u32(word_addr)
        print("WAIT obj2=0x%x off=0x%x holder=0x%x base=0x%x word=0x%x val=0x%x" %
              (obj2, off, holder, base2, word_addr, val))
        print("WAIT word map:", resolve(word_addr))
        print("WAIT holder obj2+0x50=0x%x obj2+0x64=0x%x" % (u64(obj2+0x50), u32(obj2+0x64)))
        try:
            hd = rd(holder, 0x30)
            print("WAIT holder dump:", " ".join("%02x" % b for b in hd))
        except Exception as e:
            print("WAIT holder dump err", e)
    except Exception as e:
        print("WAIT chain err", e)
    # dump the client's nvidiactl rw-s mappings
    print("WAIT nvidiactl maps:")
    for lo, hi, perm, name in maps:
        if "nvidiactl" in name and "rw-s" in perm:
            print("  0x%x-0x%x size=0x%x" % (lo, hi, hi-lo))
    return True

B("*0x%x" % (base+0xdcebd9), loophead, 1)

try:
    gdb.execute("continue")
except gdb.error as e:
    print("CONT-ERR %s" % e)
print("TRACE-END")
try:
    gdb.execute("detach")
except gdb.error as e:
    print("DETACH-ERR %s" % e)
gdb.execute("quit")