11364750dSJames Henderson# DExTer : Debugging Experience Tester 21364750dSJames Henderson# ~~~~~~ ~ ~~ ~ ~~ 31364750dSJames Henderson# 41364750dSJames Henderson# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 51364750dSJames Henderson# See https://llvm.org/LICENSE.txt for license information. 61364750dSJames Henderson# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 71364750dSJames Henderson 81364750dSJames Hendersonfrom ctypes import * 91364750dSJames Hendersonfrom enum import * 101364750dSJames Hendersonfrom functools import partial 111364750dSJames Henderson 121364750dSJames Hendersonfrom .utils import * 131364750dSJames Hendersonfrom . import control 141364750dSJames Hendersonfrom . import symbols 151364750dSJames Hendersonfrom . import sysobjs 161364750dSJames Henderson 17*f98ee40fSTobias Hieta 181364750dSJames Hendersonclass DebugAttach(IntFlag): 191364750dSJames Henderson DEBUG_ATTACH_DEFAULT = 0 201364750dSJames Henderson DEBUG_ATTACH_NONINVASIVE = 1 211364750dSJames Henderson DEBUG_ATTACH_EXISTING = 2 221364750dSJames Henderson DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND = 4 231364750dSJames Henderson DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK = 8 241364750dSJames Henderson DEBUG_ATTACH_INVASIVE_RESUME_PROCESS = 0x10 251364750dSJames Henderson DEBUG_ATTACH_NONINVASIVE_ALLOW_PARTIAL = 0x20 261364750dSJames Henderson 27*f98ee40fSTobias Hieta 281364750dSJames Henderson# UUID for DebugClient7 interface. 29*f98ee40fSTobias HietaDebugClient7IID = IID( 30*f98ee40fSTobias Hieta 0x13586BE3, 31*f98ee40fSTobias Hieta 0x542E, 32*f98ee40fSTobias Hieta 0x481E, 33*f98ee40fSTobias Hieta IID_Data4_Type(0xB1, 0xF2, 0x84, 0x97, 0xBA, 0x74, 0xF9, 0xA9), 34*f98ee40fSTobias Hieta) 35*f98ee40fSTobias Hieta 361364750dSJames Henderson 371364750dSJames Hendersonclass DEBUG_CREATE_PROCESS_OPTIONS(Structure): 381364750dSJames Henderson _fields_ = [ 391364750dSJames Henderson ("CreateFlags", c_ulong), 401364750dSJames Henderson ("EngCreateFlags", c_ulong), 411364750dSJames Henderson ("VerifierFlags", c_ulong), 42*f98ee40fSTobias Hieta ("Reserved", c_ulong), 431364750dSJames Henderson ] 441364750dSJames Henderson 45*f98ee40fSTobias Hieta 461364750dSJames Hendersonclass IDebugClient7(Structure): 471364750dSJames Henderson pass 481364750dSJames Henderson 49*f98ee40fSTobias Hieta 501364750dSJames Hendersonclass IDebugClient7Vtbl(Structure): 511364750dSJames Henderson wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugClient7)) 521364750dSJames Henderson idc_queryinterface = wrp(POINTER(IID), POINTER(c_void_p)) 531364750dSJames Henderson idc_attachprocess = wrp(c_longlong, c_long, c_long) 541364750dSJames Henderson idc_detachprocesses = wrp() 551364750dSJames Henderson idc_terminateprocesses = wrp() 56*f98ee40fSTobias Hieta idc_createprocessandattach2 = wrp( 57*f98ee40fSTobias Hieta c_ulonglong, c_char_p, c_void_p, c_ulong, c_char_p, c_char_p, c_ulong, c_ulong 58*f98ee40fSTobias Hieta ) 591364750dSJames Henderson _fields_ = [ 601364750dSJames Henderson ("QueryInterface", idc_queryinterface), 611364750dSJames Henderson ("AddRef", c_void_p), 621364750dSJames Henderson ("Release", c_void_p), 631364750dSJames Henderson ("AttachKernel", c_void_p), 641364750dSJames Henderson ("GetKernelConnectionOptions", c_void_p), 651364750dSJames Henderson ("SetKernelConnectionOptions", c_void_p), 661364750dSJames Henderson ("StartProcessServer", c_void_p), 671364750dSJames Henderson ("ConnectProcessServer", c_void_p), 681364750dSJames Henderson ("DisconnectProcessServer", c_void_p), 691364750dSJames Henderson ("GetRunningProcessSystemIds", c_void_p), 701364750dSJames Henderson ("GetRunningProcessSystemIdsByExecutableName", c_void_p), 711364750dSJames Henderson ("GetRunningProcessDescription", c_void_p), 721364750dSJames Henderson ("AttachProcess", idc_attachprocess), 731364750dSJames Henderson ("CreateProcess", c_void_p), 741364750dSJames Henderson ("CreateProcessAndAttach", c_void_p), 751364750dSJames Henderson ("GetProcessOptions", c_void_p), 761364750dSJames Henderson ("AddProcessOptions", c_void_p), 771364750dSJames Henderson ("RemoveProcessOptions", c_void_p), 781364750dSJames Henderson ("SetProcessOptions", c_void_p), 791364750dSJames Henderson ("OpenDumpFile", c_void_p), 801364750dSJames Henderson ("WriteDumpFile", c_void_p), 811364750dSJames Henderson ("ConnectSession", c_void_p), 821364750dSJames Henderson ("StartServer", c_void_p), 831364750dSJames Henderson ("OutputServers", c_void_p), 841364750dSJames Henderson ("TerminateProcesses", idc_terminateprocesses), 851364750dSJames Henderson ("DetachProcesses", idc_detachprocesses), 861364750dSJames Henderson ("EndSession", c_void_p), 871364750dSJames Henderson ("GetExitCode", c_void_p), 881364750dSJames Henderson ("DispatchCallbacks", c_void_p), 891364750dSJames Henderson ("ExitDispatch", c_void_p), 901364750dSJames Henderson ("CreateClient", c_void_p), 911364750dSJames Henderson ("GetInputCallbacks", c_void_p), 921364750dSJames Henderson ("SetInputCallbacks", c_void_p), 931364750dSJames Henderson ("GetOutputCallbacks", c_void_p), 941364750dSJames Henderson ("SetOutputCallbacks", c_void_p), 951364750dSJames Henderson ("GetOutputMask", c_void_p), 961364750dSJames Henderson ("SetOutputMask", c_void_p), 971364750dSJames Henderson ("GetOtherOutputMask", c_void_p), 981364750dSJames Henderson ("SetOtherOutputMask", c_void_p), 991364750dSJames Henderson ("GetOutputWidth", c_void_p), 1001364750dSJames Henderson ("SetOutputWidth", c_void_p), 1011364750dSJames Henderson ("GetOutputLinePrefix", c_void_p), 1021364750dSJames Henderson ("SetOutputLinePrefix", c_void_p), 1031364750dSJames Henderson ("GetIdentity", c_void_p), 1041364750dSJames Henderson ("OutputIdentity", c_void_p), 1051364750dSJames Henderson ("GetEventCallbacks", c_void_p), 1061364750dSJames Henderson ("SetEventCallbacks", c_void_p), 1071364750dSJames Henderson ("FlushCallbacks", c_void_p), 1081364750dSJames Henderson ("WriteDumpFile2", c_void_p), 1091364750dSJames Henderson ("AddDumpInformationFile", c_void_p), 1101364750dSJames Henderson ("EndProcessServer", c_void_p), 1111364750dSJames Henderson ("WaitForProcessServerEnd", c_void_p), 1121364750dSJames Henderson ("IsKernelDebuggerEnabled", c_void_p), 1131364750dSJames Henderson ("TerminateCurrentProcess", c_void_p), 1141364750dSJames Henderson ("DetachCurrentProcess", c_void_p), 1151364750dSJames Henderson ("AbandonCurrentProcess", c_void_p), 1161364750dSJames Henderson ("GetRunningProcessSystemIdByExecutableNameWide", c_void_p), 1171364750dSJames Henderson ("GetRunningProcessDescriptionWide", c_void_p), 1181364750dSJames Henderson ("CreateProcessWide", c_void_p), 1191364750dSJames Henderson ("CreateProcessAndAttachWide", c_void_p), 1201364750dSJames Henderson ("OpenDumpFileWide", c_void_p), 1211364750dSJames Henderson ("WriteDumpFileWide", c_void_p), 1221364750dSJames Henderson ("AddDumpInformationFileWide", c_void_p), 1231364750dSJames Henderson ("GetNumberDumpFiles", c_void_p), 1241364750dSJames Henderson ("GetDumpFile", c_void_p), 1251364750dSJames Henderson ("GetDumpFileWide", c_void_p), 1261364750dSJames Henderson ("AttachKernelWide", c_void_p), 1271364750dSJames Henderson ("GetKernelConnectionOptionsWide", c_void_p), 1281364750dSJames Henderson ("SetKernelConnectionOptionsWide", c_void_p), 1291364750dSJames Henderson ("StartProcessServerWide", c_void_p), 1301364750dSJames Henderson ("ConnectProcessServerWide", c_void_p), 1311364750dSJames Henderson ("StartServerWide", c_void_p), 1321364750dSJames Henderson ("OutputServerWide", c_void_p), 1331364750dSJames Henderson ("GetOutputCallbacksWide", c_void_p), 1341364750dSJames Henderson ("SetOutputCallbacksWide", c_void_p), 1351364750dSJames Henderson ("GetOutputLinePrefixWide", c_void_p), 1361364750dSJames Henderson ("SetOutputLinePrefixWide", c_void_p), 1371364750dSJames Henderson ("GetIdentityWide", c_void_p), 1381364750dSJames Henderson ("OutputIdentityWide", c_void_p), 1391364750dSJames Henderson ("GetEventCallbacksWide", c_void_p), 1401364750dSJames Henderson ("SetEventCallbacksWide", c_void_p), 1411364750dSJames Henderson ("CreateProcess2", c_void_p), 1421364750dSJames Henderson ("CreateProcess2Wide", c_void_p), 1431364750dSJames Henderson ("CreateProcessAndAttach2", idc_createprocessandattach2), 1441364750dSJames Henderson ("CreateProcessAndAttach2Wide", c_void_p), 1451364750dSJames Henderson ("PushOutputLinePrefix", c_void_p), 1461364750dSJames Henderson ("PushOutputLinePrefixWide", c_void_p), 1471364750dSJames Henderson ("PopOutputLinePrefix", c_void_p), 1481364750dSJames Henderson ("GetNumberInputCallbacks", c_void_p), 1491364750dSJames Henderson ("GetNumberOutputCallbacks", c_void_p), 1501364750dSJames Henderson ("GetNumberEventCallbacks", c_void_p), 1511364750dSJames Henderson ("GetQuitLockString", c_void_p), 1521364750dSJames Henderson ("SetQuitLockString", c_void_p), 1531364750dSJames Henderson ("GetQuitLockStringWide", c_void_p), 1541364750dSJames Henderson ("SetQuitLockStringWide", c_void_p), 1551364750dSJames Henderson ("SetEventContextCallbacks", c_void_p), 1561364750dSJames Henderson ("SetClientContext", c_void_p), 1571364750dSJames Henderson ] 1581364750dSJames Henderson 159*f98ee40fSTobias Hieta 1601364750dSJames HendersonIDebugClient7._fields_ = [("lpVtbl", POINTER(IDebugClient7Vtbl))] 1611364750dSJames Henderson 162*f98ee40fSTobias Hieta 1631364750dSJames Hendersonclass Client(object): 1641364750dSJames Henderson def __init__(self): 1651364750dSJames Henderson DbgEng = WinDLL("DbgEng") 1661364750dSJames Henderson DbgEng.DebugCreate.argtypes = [POINTER(IID), POINTER(POINTER(IDebugClient7))] 1671364750dSJames Henderson DbgEng.DebugCreate.restype = c_ulong 1681364750dSJames Henderson 1691364750dSJames Henderson # Call DebugCreate to create a new debug client 1701364750dSJames Henderson ptr = POINTER(IDebugClient7)() 1711364750dSJames Henderson res = DbgEng.DebugCreate(byref(DebugClient7IID), ptr) 1721364750dSJames Henderson aborter(res, "DebugCreate") 1731364750dSJames Henderson self.client = ptr.contents 1741364750dSJames Henderson self.vt = vt = self.client.lpVtbl.contents 1751364750dSJames Henderson 1761364750dSJames Henderson def QI(iface, ptr): 1771364750dSJames Henderson return vt.QueryInterface(self.client, byref(iface), byref(ptr)) 1781364750dSJames Henderson 1791364750dSJames Henderson # Query for a control object 1801364750dSJames Henderson ptr = c_void_p() 1811364750dSJames Henderson res = QI(control.DebugControl7IID, ptr) 1821364750dSJames Henderson aborter(res, "QueryInterface control") 1831364750dSJames Henderson self.control_ptr = cast(ptr, POINTER(control.IDebugControl7)) 1841364750dSJames Henderson self.Control = control.Control(self.control_ptr) 1851364750dSJames Henderson 1861364750dSJames Henderson # Query for a SystemObjects object 1871364750dSJames Henderson ptr = c_void_p() 1881364750dSJames Henderson res = QI(sysobjs.DebugSystemObjects4IID, ptr) 1891364750dSJames Henderson aborter(res, "QueryInterface sysobjects") 1901364750dSJames Henderson self.sysobjects_ptr = cast(ptr, POINTER(sysobjs.IDebugSystemObjects4)) 1911364750dSJames Henderson self.SysObjects = sysobjs.SysObjects(self.sysobjects_ptr) 1921364750dSJames Henderson 1931364750dSJames Henderson # Query for a Symbols object 1941364750dSJames Henderson ptr = c_void_p() 1951364750dSJames Henderson res = QI(symbols.DebugSymbols5IID, ptr) 1961364750dSJames Henderson aborter(res, "QueryInterface debugsymbosl5") 1971364750dSJames Henderson self.symbols_ptr = cast(ptr, POINTER(symbols.IDebugSymbols5)) 1981364750dSJames Henderson self.Symbols = symbols.Symbols(self.symbols_ptr) 1991364750dSJames Henderson 2001364750dSJames Henderson def AttachProcess(self, pid): 2011364750dSJames Henderson # Zero process-server id means no process-server. 202*f98ee40fSTobias Hieta res = self.vt.AttachProcess( 203*f98ee40fSTobias Hieta self.client, 0, pid, DebugAttach.DEBUG_ATTACH_DEFAULT 204*f98ee40fSTobias Hieta ) 2051364750dSJames Henderson aborter(res, "AttachProcess") 2061364750dSJames Henderson return 2071364750dSJames Henderson 2081364750dSJames Henderson def DetachProcesses(self): 2091364750dSJames Henderson res = self.vt.DetachProcesses(self.client) 2101364750dSJames Henderson aborter(res, "DetachProcesses") 2111364750dSJames Henderson return 2121364750dSJames Henderson 2131364750dSJames Henderson def TerminateProcesses(self): 2141364750dSJames Henderson res = self.vt.TerminateProcesses(self.client) 2151364750dSJames Henderson aborter(res, "TerminateProcesses") 2161364750dSJames Henderson return 2171364750dSJames Henderson 2181364750dSJames Henderson def CreateProcessAndAttach2(self, cmdline): 2191364750dSJames Henderson options = DEBUG_CREATE_PROCESS_OPTIONS() 2201364750dSJames Henderson options.CreateFlags = 0x2 # DEBUG_ONLY_THIS_PROCESS 2211364750dSJames Henderson options.EngCreateFlags = 0 2221364750dSJames Henderson options.VerifierFlags = 0 2231364750dSJames Henderson options.Reserved = 0 2241364750dSJames Henderson attach_flags = 0 225*f98ee40fSTobias Hieta res = self.vt.CreateProcessAndAttach2( 226*f98ee40fSTobias Hieta self.client, 227*f98ee40fSTobias Hieta 0, 228*f98ee40fSTobias Hieta cmdline.encode("ascii"), 229*f98ee40fSTobias Hieta byref(options), 230*f98ee40fSTobias Hieta sizeof(options), 231*f98ee40fSTobias Hieta None, 232*f98ee40fSTobias Hieta None, 233*f98ee40fSTobias Hieta 0, 234*f98ee40fSTobias Hieta attach_flags, 235*f98ee40fSTobias Hieta ) 2361364750dSJames Henderson aborter(res, "CreateProcessAndAttach2") 2371364750dSJames Henderson return 238