xref: /llvm-project/cross-project-tests/debuginfo-tests/dexter/dex/debugger/dbgeng/sysobjs.py (revision f98ee40f4b5d7474fc67e82824bf6abbaedb7b1c)
1# DExTer : Debugging Experience Tester
2# ~~~~~~   ~         ~~         ~   ~~
3#
4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5# See https://llvm.org/LICENSE.txt for license information.
6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7
8from ctypes import *
9from functools import partial
10
11from .utils import *
12
13# UUID For SystemObjects4 interface.
14DebugSystemObjects4IID = IID(
15    0x489468E6,
16    0x7D0F,
17    0x4AF5,
18    IID_Data4_Type(0x87, 0xAB, 0x25, 0x20, 0x74, 0x54, 0xD5, 0x53),
19)
20
21
22class IDebugSystemObjects4(Structure):
23    pass
24
25
26class IDebugSystemObjects4Vtbl(Structure):
27    wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugSystemObjects4))
28    ids_getnumberprocesses = wrp(POINTER(c_ulong))
29    ids_getprocessidsbyindex = wrp(c_ulong, c_ulong, c_ulong_p, c_ulong_p)
30    ids_setcurrentprocessid = wrp(c_ulong)
31    ids_getnumberthreads = wrp(c_ulong_p)
32    ids_getthreadidsbyindex = wrp(c_ulong, c_ulong, c_ulong_p, c_ulong_p)
33    ids_setcurrentthreadid = wrp(c_ulong)
34    _fields_ = [
35        ("QueryInterface", c_void_p),
36        ("AddRef", c_void_p),
37        ("Release", c_void_p),
38        ("GetEventThread", c_void_p),
39        ("GetEventProcess", c_void_p),
40        ("GetCurrentThreadId", c_void_p),
41        ("SetCurrentThreadId", ids_setcurrentthreadid),
42        ("GetCurrentProcessId", c_void_p),
43        ("SetCurrentProcessId", ids_setcurrentprocessid),
44        ("GetNumberThreads", ids_getnumberthreads),
45        ("GetTotalNumberThreads", c_void_p),
46        ("GetThreadIdsByIndex", ids_getthreadidsbyindex),
47        ("GetThreadIdByProcessor", c_void_p),
48        ("GetCurrentThreadDataOffset", c_void_p),
49        ("GetThreadIdByDataOffset", c_void_p),
50        ("GetCurrentThreadTeb", c_void_p),
51        ("GetThreadIdByTeb", c_void_p),
52        ("GetCurrentThreadSystemId", c_void_p),
53        ("GetThreadIdBySystemId", c_void_p),
54        ("GetCurrentThreadHandle", c_void_p),
55        ("GetThreadIdByHandle", c_void_p),
56        ("GetNumberProcesses", ids_getnumberprocesses),
57        ("GetProcessIdsByIndex", ids_getprocessidsbyindex),
58        ("GetCurrentProcessDataOffset", c_void_p),
59        ("GetProcessIdByDataOffset", c_void_p),
60        ("GetCurrentProcessPeb", c_void_p),
61        ("GetProcessIdByPeb", c_void_p),
62        ("GetCurrentProcessSystemId", c_void_p),
63        ("GetProcessIdBySystemId", c_void_p),
64        ("GetCurrentProcessHandle", c_void_p),
65        ("GetProcessIdByHandle", c_void_p),
66        ("GetCurrentProcessExecutableName", c_void_p),
67        ("GetCurrentProcessUpTime", c_void_p),
68        ("GetImplicitThreadDataOffset", c_void_p),
69        ("SetImplicitThreadDataOffset", c_void_p),
70        ("GetImplicitProcessDataOffset", c_void_p),
71        ("SetImplicitProcessDataOffset", c_void_p),
72        ("GetEventSystem", c_void_p),
73        ("GetCurrentSystemId", c_void_p),
74        ("SetCurrentSystemId", c_void_p),
75        ("GetNumberSystems", c_void_p),
76        ("GetSystemIdsByIndex", c_void_p),
77        ("GetTotalNumberThreadsAndProcesses", c_void_p),
78        ("GetCurrentSystemServer", c_void_p),
79        ("GetSystemByServer", c_void_p),
80        ("GetCurrentSystemServerName", c_void_p),
81        ("GetCurrentProcessExecutableNameWide", c_void_p),
82        ("GetCurrentSystemServerNameWide", c_void_p),
83    ]
84
85
86IDebugSystemObjects4._fields_ = [("lpVtbl", POINTER(IDebugSystemObjects4Vtbl))]
87
88
89class SysObjects(object):
90    def __init__(self, sysobjects):
91        self.ptr = sysobjects
92        self.sysobjects = sysobjects.contents
93        self.vt = self.sysobjects.lpVtbl.contents
94        # Keep a handy ulong for passing into C methods.
95        self.ulong = c_ulong()
96
97    def GetNumberSystems(self):
98        res = self.vt.GetNumberSystems(self.sysobjects, byref(self.ulong))
99        aborter(res, "GetNumberSystems")
100        return self.ulong.value
101
102    def GetNumberProcesses(self):
103        res = self.vt.GetNumberProcesses(self.sysobjects, byref(self.ulong))
104        aborter(res, "GetNumberProcesses")
105        return self.ulong.value
106
107    def GetNumberThreads(self):
108        res = self.vt.GetNumberThreads(self.sysobjects, byref(self.ulong))
109        aborter(res, "GetNumberThreads")
110        return self.ulong.value
111
112    def GetTotalNumberThreadsAndProcesses(self):
113        tthreads = c_ulong()
114        tprocs = c_ulong()
115        pulong3 = c_ulong()
116        res = self.vt.GetTotalNumberThreadsAndProcesses(
117            self.sysobjects,
118            byref(tthreads),
119            byref(tprocs),
120            byref(pulong3),
121            byref(pulong3),
122            byref(pulong3),
123        )
124        aborter(res, "GettotalNumberThreadsAndProcesses")
125        return tthreads.value, tprocs.value
126
127    def GetCurrentProcessId(self):
128        res = self.vt.GetCurrentProcessId(self.sysobjects, byref(self.ulong))
129        aborter(res, "GetCurrentProcessId")
130        return self.ulong.value
131
132    def SetCurrentProcessId(self, sysid):
133        res = self.vt.SetCurrentProcessId(self.sysobjects, sysid)
134        aborter(res, "SetCurrentProcessId")
135        return
136
137    def GetCurrentThreadId(self):
138        res = self.vt.GetCurrentThreadId(self.sysobjects, byref(self.ulong))
139        aborter(res, "GetCurrentThreadId")
140        return self.ulong.value
141
142    def SetCurrentThreadId(self, sysid):
143        res = self.vt.SetCurrentThreadId(self.sysobjects, sysid)
144        aborter(res, "SetCurrentThreadId")
145        return
146
147    def GetProcessIdsByIndex(self):
148        num_processes = self.GetNumberProcesses()
149        if num_processes == 0:
150            return []
151        engineids = (c_ulong * num_processes)()
152        pids = (c_ulong * num_processes)()
153        for x in range(num_processes):
154            engineids[x] = DEBUG_ANY_ID
155            pids[x] = DEBUG_ANY_ID
156        res = self.vt.GetProcessIdsByIndex(
157            self.sysobjects, 0, num_processes, engineids, pids
158        )
159        aborter(res, "GetProcessIdsByIndex")
160        return list(zip(engineids, pids))
161
162    def GetThreadIdsByIndex(self):
163        num_threads = self.GetNumberThreads()
164        if num_threads == 0:
165            return []
166        engineids = (c_ulong * num_threads)()
167        tids = (c_ulong * num_threads)()
168        for x in range(num_threads):
169            engineids[x] = DEBUG_ANY_ID
170            tids[x] = DEBUG_ANY_ID
171        # Zero -> start index
172        res = self.vt.GetThreadIdsByIndex(
173            self.sysobjects, 0, num_threads, engineids, tids
174        )
175        aborter(res, "GetThreadIdsByIndex")
176        return list(zip(engineids, tids))
177
178    def GetCurThreadHandle(self):
179        pulong64 = c_ulonglong()
180        res = self.vt.GetCurrentThreadHandle(self.sysobjects, byref(pulong64))
181        aborter(res, "GetCurrentThreadHandle")
182        return pulong64.value
183
184    def set_current_thread(self, pid, tid):
185        proc_sys_id = -1
186        for x in self.GetProcessIdsByIndex():
187            sysid, procid = x
188            if procid == pid:
189                proc_sys_id = sysid
190
191        if proc_sys_id == -1:
192            raise Exception("Couldn't find designated PID {}".format(pid))
193
194        self.SetCurrentProcessId(proc_sys_id)
195
196        thread_sys_id = -1
197        for x in self.GetThreadIdsByIndex():
198            sysid, threadid = x
199            if threadid == tid:
200                thread_sys_id = sysid
201
202        if thread_sys_id == -1:
203            raise Exception("Couldn't find designated TID {}".format(tid))
204
205        self.SetCurrentThreadId(thread_sys_id)
206        return
207
208    def print_current_procs_threads(self):
209        procs = []
210        for x in self.GetProcessIdsByIndex():
211            sysid, procid = x
212            procs.append(procid)
213
214        threads = []
215        for x in self.GetThreadIdsByIndex():
216            sysid, threadid = x
217            threads.append(threadid)
218
219        print("Current processes: {}".format(procs))
220        print("Current threads: {}".format(threads))
221