summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/wall2/t122.py
blob: 8c9c6fd1c48dff46023fc0f493088e9c49449649 (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
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import gdb
gr = gdb.execute
state = {"n": 0, "any": 0, "pend": None, "base": None, "chits": 0, "cleared": 0,
         "whits": 0, "wrote": 0}

def u32(a):
    return int(gdb.parse_and_eval("*(unsigned int*)0x%x" % a))
def u64(a):
    return int(gdb.parse_and_eval("*(unsigned long*)0x%x" % a))

def ioc(d, t, nr, size):
    return (d << 30) | (size << 16) | (t << 8) | nr

VIDHEAP = ioc(3, 0x46, 0x4a, 0xb8)

def glbase():
    try:
        pid = gdb.selected_inferior().pid
        for line in open("/proc/%d/maps" % pid):
            parts = line.split()
            if "libnvidia-eglcore" in line and int(parts[2], 16) == 0:
                return int(parts[0].split("-")[0], 16)
    except Exception:
        pass
    return None

class BC(gdb.Breakpoint):
    def __init__(self, addr):
        super().__init__("*0x%x" % addr, internal=False)
        self.silent = True
    def stop(self):
        state["chits"] += 1
        try:
            obj = int(gdb.parse_and_eval("$rdi"))
            n = int(gdb.parse_and_eval("$rsi"))
            cnt = u32(obj + 0x22efc)
            for i in range(0, min(cnt, 32)):
                p = u64(obj + 0x1428 + i * 8)
                if not p:
                    continue
                tgt = p + n * 0x10
                try:
                    v16 = int(gdb.parse_and_eval("*(unsigned short*)0x%x" % (tgt + 0xe)))
                    if v16 == 0xffff:
                        gr("set {unsigned short}0x%x = 0" % (tgt + 0xe))
                        gr("set {unsigned int}0x%x = 0" % tgt)
                        gr("set {unsigned short}0x%x = 0" % (tgt + 0xc))
                        state["cleared"] += 1
                        print("CLEAR#%d obj=0x%x n=0x%x tgt=0x%x" % (state["cleared"], obj, n, tgt), flush=True)
                except Exception:
                    pass
        except Exception:
            pass
        return False

class BW(gdb.Breakpoint):
    def __init__(self, addr):
        super().__init__("*0x%x" % addr, internal=False)
        self.silent = True
    def stop(self):
        state["whits"] += 1
        try:
            rbx = int(gdb.parse_and_eval("$rbx"))
            sub = u64(rbx + 0x70)
            obj2 = u64(sub + 0x58)
            off = u32(obj2 + 0x60)
            holder = u64(obj2 + 0x58)
            base2 = u64(holder + 0x58)
            word = base2 + off
            val = u32(word)
            if state["whits"] <= 6 or val == 0:
                print("WORD#%d addr=0x%x val=0x%x" % (state["whits"], word, val), flush=True)
            if val == 0:
                gr("set {unsigned int}0x%x = 1" % word)
                state["wrote"] += 1
        except Exception:
            pass
        return False

class IOC(gdb.Breakpoint):
    def __init__(self):
        super().__init__("ioctl", internal=False)
        self.silent = True
    def stop(self):
        if state["base"] is None:
            b = glbase()
            if b:
                state["base"] = b
                print("GLBASE 0x%x" % b, flush=True)
                try:
                    BC(b + 0xB33D30)
                    BW(b + 0xDCEBD9)
                    print("BC-BW-SET", flush=True)
                except Exception as e:
                    print("bpset-fail %s" % e, flush=True)
        try:
            req = int(gdb.parse_and_eval("$rsi")) & 0xFFFFFFFF
            arg = int(gdb.parse_and_eval("$rdx"))
        except Exception:
            return False
        if state["pend"] is not None:
            try:
                st = u32(state["pend"] + 0x14)
                at = u32(state["pend"] + 0x38)
                off = u64(state["pend"] + 0x68)
                print("PREV149-OUT st=0x%x attr=0x%x off=0x%x" % (st, at, off), flush=True)
            except Exception as e:
                print("PREV149-STATUS unreadable %s" % e, flush=True)
            state["pend"] = None
        if req != VIDHEAP:
            return False
        state["any"] += 1
        try:
            fn = u32(arg + 0x08)
            size = u64(arg + 0x58)
            attr = u32(arg + 0x38)
            owner = u32(arg + 0x28)
            flags = u32(arg + 0x34)
        except Exception:
            return False
        if fn == 2:
            state["n"] += 1
            if state["n"] >= 120:
                print("VH#%d size=0x%x align=0x%x attr=0x%x attr2=0x%x flags=0x%x owner=0x%x range=0x%x-0x%x" % (
                    state["n"], size, u64(arg + 0x60), attr, u32(arg + 0x90), flags, owner,
                    u64(arg + 0x80), u64(arg + 0x88)), flush=True)
            if size >= 0x10000 and (attr & 0xf000) == 0x2000 and owner == 0x474C0000:
                print("HIT149 size=0x%x attr=0x%x flags=0x%x" % (size, attr, flags), flush=True)
                gr("bt 12")
                newattr = attr & 0xFFFFCFFF
                gr("set {unsigned int}0x%x = 0x%x" % (arg + 0x38, newattr))
                print("FLIP149 attr 0x%x -> 0x%x" % (attr, newattr), flush=True)
            state["pend"] = arg
        return False

try:
    IOC()
    print("BPS-SET", flush=True)
except Exception as e:
    print("bpset-fail %s" % e, flush=True)

gr("set pagination off")
gr("set confirm off")
try:
    gr("run")
except Exception as e:
    print("runend %s" % e, flush=True)
print("T120-DONE n=%d any=%d chits=%d cleared=%d whits=%d wrote=%d" % (
    state["n"], state["any"], state["chits"], state["cleared"],
    state["whits"], state["wrote"]), flush=True)
gr("quit")