brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.0 KiB · e370738 Raw
451 lines · python
1# DExTer : Debugging Experience Tester2# ~~~~~~   ~         ~~         ~   ~~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-exception7 8from ctypes import *9from functools import partial10 11from .utils import *12from .breakpoint import *13 14 15class DEBUG_STACK_FRAME_EX(Structure):16    _fields_ = [17        ("InstructionOffset", c_ulonglong),18        ("ReturnOffset", c_ulonglong),19        ("FrameOffset", c_ulonglong),20        ("StackOffset", c_ulonglong),21        ("FuncTableEntry", c_ulonglong),22        ("Params", c_ulonglong * 4),23        ("Reserved", c_ulonglong * 6),24        ("Virtual", c_bool),25        ("FrameNumber", c_ulong),26        ("InlineFrameContext", c_ulong),27        ("Reserved1", c_ulong),28    ]29 30 31PDEBUG_STACK_FRAME_EX = POINTER(DEBUG_STACK_FRAME_EX)32 33 34class DEBUG_VALUE_U(Union):35    _fields_ = [36        ("I8", c_byte),37        ("I16", c_short),38        ("I32", c_int),39        ("I64", c_long),40        ("F32", c_float),41        ("F64", c_double),42        ("RawBytes", c_ubyte * 24),  # Force length to 24b.43    ]44 45 46class DEBUG_VALUE(Structure):47    _fields_ = [("U", DEBUG_VALUE_U), ("TailOfRawBytes", c_ulong), ("Type", c_ulong)]48 49 50PDEBUG_VALUE = POINTER(DEBUG_VALUE)51 52 53class DebugValueType(IntEnum):54    DEBUG_VALUE_INVALID = 055    DEBUG_VALUE_INT8 = 156    DEBUG_VALUE_INT16 = 257    DEBUG_VALUE_INT32 = 358    DEBUG_VALUE_INT64 = 459    DEBUG_VALUE_FLOAT32 = 560    DEBUG_VALUE_FLOAT64 = 661    DEBUG_VALUE_FLOAT80 = 762    DEBUG_VALUE_FLOAT82 = 863    DEBUG_VALUE_FLOAT128 = 964    DEBUG_VALUE_VECTOR64 = 1065    DEBUG_VALUE_VECTOR128 = 1166    DEBUG_VALUE_TYPES = 1267 68 69# UUID for DebugControl7 interface.70DebugControl7IID = IID(71    0xB86FB3B1,72    0x80D4,73    0x475B,74    IID_Data4_Type(0xAE, 0xA3, 0xCF, 0x06, 0x53, 0x9C, 0xF6, 0x3A),75)76 77 78class IDebugControl7(Structure):79    pass80 81 82class IDebugControl7Vtbl(Structure):83    wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugControl7))84    idc_getnumbereventfilters = wrp(c_ulong_p, c_ulong_p, c_ulong_p)85    idc_setexceptionfiltersecondcommand = wrp(c_ulong, c_char_p)86    idc_waitforevent = wrp(c_long, c_long)87    idc_execute = wrp(c_long, c_char_p, c_long)88    idc_setexpressionsyntax = wrp(c_ulong)89    idc_addbreakpoint2 = wrp(c_ulong, c_ulong, POINTER(POINTER(DebugBreakpoint2)))90    idc_setexecutionstatus = wrp(c_ulong)91    idc_getexecutionstatus = wrp(c_ulong_p)92    idc_getstacktraceex = wrp(93        c_ulonglong, c_ulonglong, c_ulonglong, PDEBUG_STACK_FRAME_EX, c_ulong, c_ulong_p94    )95    idc_evaluate = wrp(c_char_p, c_ulong, PDEBUG_VALUE, c_ulong_p)96    idc_setengineoptions = wrp(c_ulong)97    _fields_ = [98        ("QueryInterface", c_void_p),99        ("AddRef", c_void_p),100        ("Release", c_void_p),101        ("GetInterrupt", c_void_p),102        ("SetInterrupt", c_void_p),103        ("GetInterruptTimeout", c_void_p),104        ("SetInterruptTimeout", c_void_p),105        ("GetLogFile", c_void_p),106        ("OpenLogFile", c_void_p),107        ("CloseLogFile", c_void_p),108        ("GetLogMask", c_void_p),109        ("SetLogMask", c_void_p),110        ("Input", c_void_p),111        ("ReturnInput", c_void_p),112        ("Output", c_void_p),113        ("OutputVaList", c_void_p),114        ("ControlledOutput", c_void_p),115        ("ControlledOutputVaList", c_void_p),116        ("OutputPrompt", c_void_p),117        ("OutputPromptVaList", c_void_p),118        ("GetPromptText", c_void_p),119        ("OutputCurrentState", c_void_p),120        ("OutputVersionInformation", c_void_p),121        ("GetNotifyEventHandle", c_void_p),122        ("SetNotifyEventHandle", c_void_p),123        ("Assemble", c_void_p),124        ("Disassemble", c_void_p),125        ("GetDisassembleEffectiveOffset", c_void_p),126        ("OutputDisassembly", c_void_p),127        ("OutputDisassemblyLines", c_void_p),128        ("GetNearInstruction", c_void_p),129        ("GetStackTrace", c_void_p),130        ("GetReturnOffset", c_void_p),131        ("OutputStackTrace", c_void_p),132        ("GetDebuggeeType", c_void_p),133        ("GetActualProcessorType", c_void_p),134        ("GetExecutingProcessorType", c_void_p),135        ("GetNumberPossibleExecutingProcessorTypes", c_void_p),136        ("GetPossibleExecutingProcessorTypes", c_void_p),137        ("GetNumberProcessors", c_void_p),138        ("GetSystemVersion", c_void_p),139        ("GetPageSize", c_void_p),140        ("IsPointer64Bit", c_void_p),141        ("ReadBugCheckData", c_void_p),142        ("GetNumberSupportedProcessorTypes", c_void_p),143        ("GetSupportedProcessorTypes", c_void_p),144        ("GetProcessorTypeNames", c_void_p),145        ("GetEffectiveProcessorType", c_void_p),146        ("SetEffectiveProcessorType", c_void_p),147        ("GetExecutionStatus", idc_getexecutionstatus),148        ("SetExecutionStatus", idc_setexecutionstatus),149        ("GetCodeLevel", c_void_p),150        ("SetCodeLevel", c_void_p),151        ("GetEngineOptions", c_void_p),152        ("AddEngineOptions", c_void_p),153        ("RemoveEngineOptions", c_void_p),154        ("SetEngineOptions", idc_setengineoptions),155        ("GetSystemErrorControl", c_void_p),156        ("SetSystemErrorControl", c_void_p),157        ("GetTextMacro", c_void_p),158        ("SetTextMacro", c_void_p),159        ("GetRadix", c_void_p),160        ("SetRadix", c_void_p),161        ("Evaluate", idc_evaluate),162        ("CoerceValue", c_void_p),163        ("CoerceValues", c_void_p),164        ("Execute", idc_execute),165        ("ExecuteCommandFile", c_void_p),166        ("GetNumberBreakpoints", c_void_p),167        ("GetBreakpointByIndex", c_void_p),168        ("GetBreakpointById", c_void_p),169        ("GetBreakpointParameters", c_void_p),170        ("AddBreakpoint", c_void_p),171        ("RemoveBreakpoint", c_void_p),172        ("AddExtension", c_void_p),173        ("RemoveExtension", c_void_p),174        ("GetExtensionByPath", c_void_p),175        ("CallExtension", c_void_p),176        ("GetExtensionFunction", c_void_p),177        ("GetWindbgExtensionApis32", c_void_p),178        ("GetWindbgExtensionApis64", c_void_p),179        ("GetNumberEventFilters", idc_getnumbereventfilters),180        ("GetEventFilterText", c_void_p),181        ("GetEventFilterCommand", c_void_p),182        ("SetEventFilterCommand", c_void_p),183        ("GetSpecificFilterParameters", c_void_p),184        ("SetSpecificFilterParameters", c_void_p),185        ("GetSpecificFilterArgument", c_void_p),186        ("SetSpecificFilterArgument", c_void_p),187        ("GetExceptionFilterParameters", c_void_p),188        ("SetExceptionFilterParameters", c_void_p),189        ("GetExceptionFilterSecondCommand", c_void_p),190        ("SetExceptionFilterSecondCommand", idc_setexceptionfiltersecondcommand),191        ("WaitForEvent", idc_waitforevent),192        ("GetLastEventInformation", c_void_p),193        ("GetCurrentTimeDate", c_void_p),194        ("GetCurrentSystemUpTime", c_void_p),195        ("GetDumpFormatFlags", c_void_p),196        ("GetNumberTextReplacements", c_void_p),197        ("GetTextReplacement", c_void_p),198        ("SetTextReplacement", c_void_p),199        ("RemoveTextReplacements", c_void_p),200        ("OutputTextReplacements", c_void_p),201        ("GetAssemblyOptions", c_void_p),202        ("AddAssemblyOptions", c_void_p),203        ("RemoveAssemblyOptions", c_void_p),204        ("SetAssemblyOptions", c_void_p),205        ("GetExpressionSyntax", c_void_p),206        ("SetExpressionSyntax", idc_setexpressionsyntax),207        ("SetExpressionSyntaxByName", c_void_p),208        ("GetNumberExpressionSyntaxes", c_void_p),209        ("GetExpressionSyntaxNames", c_void_p),210        ("GetNumberEvents", c_void_p),211        ("GetEventIndexDescription", c_void_p),212        ("GetCurrentEventIndex", c_void_p),213        ("SetNextEventIndex", c_void_p),214        ("GetLogFileWide", c_void_p),215        ("OpenLogFileWide", c_void_p),216        ("InputWide", c_void_p),217        ("ReturnInputWide", c_void_p),218        ("OutputWide", c_void_p),219        ("OutputVaListWide", c_void_p),220        ("ControlledOutputWide", c_void_p),221        ("ControlledOutputVaListWide", c_void_p),222        ("OutputPromptWide", c_void_p),223        ("OutputPromptVaListWide", c_void_p),224        ("GetPromptTextWide", c_void_p),225        ("AssembleWide", c_void_p),226        ("DisassembleWide", c_void_p),227        ("GetProcessrTypeNamesWide", c_void_p),228        ("GetTextMacroWide", c_void_p),229        ("SetTextMacroWide", c_void_p),230        ("EvaluateWide", c_void_p),231        ("ExecuteWide", c_void_p),232        ("ExecuteCommandFileWide", c_void_p),233        ("GetBreakpointByIndex2", c_void_p),234        ("GetBreakpointById2", c_void_p),235        ("AddBreakpoint2", idc_addbreakpoint2),236        ("RemoveBreakpoint2", c_void_p),237        ("AddExtensionWide", c_void_p),238        ("GetExtensionByPathWide", c_void_p),239        ("CallExtensionWide", c_void_p),240        ("GetExtensionFunctionWide", c_void_p),241        ("GetEventFilterTextWide", c_void_p),242        ("GetEventfilterCommandWide", c_void_p),243        ("SetEventFilterCommandWide", c_void_p),244        ("GetSpecificFilterArgumentWide", c_void_p),245        ("SetSpecificFilterArgumentWide", c_void_p),246        ("GetExceptionFilterSecondCommandWide", c_void_p),247        ("SetExceptionFilterSecondCommandWider", c_void_p),248        ("GetLastEventInformationWide", c_void_p),249        ("GetTextReplacementWide", c_void_p),250        ("SetTextReplacementWide", c_void_p),251        ("SetExpressionSyntaxByNameWide", c_void_p),252        ("GetExpressionSyntaxNamesWide", c_void_p),253        ("GetEventIndexDescriptionWide", c_void_p),254        ("GetLogFile2", c_void_p),255        ("OpenLogFile2", c_void_p),256        ("GetLogFile2Wide", c_void_p),257        ("OpenLogFile2Wide", c_void_p),258        ("GetSystemVersionValues", c_void_p),259        ("GetSystemVersionString", c_void_p),260        ("GetSystemVersionStringWide", c_void_p),261        ("GetContextStackTrace", c_void_p),262        ("OutputContextStackTrace", c_void_p),263        ("GetStoredEventInformation", c_void_p),264        ("GetManagedStatus", c_void_p),265        ("GetManagedStatusWide", c_void_p),266        ("ResetManagedStatus", c_void_p),267        ("GetStackTraceEx", idc_getstacktraceex),268        ("OutputStackTraceEx", c_void_p),269        ("GetContextStackTraceEx", c_void_p),270        ("OutputContextStackTraceEx", c_void_p),271        ("GetBreakpointByGuid", c_void_p),272        ("GetExecutionStatusEx", c_void_p),273        ("GetSynchronizationStatus", c_void_p),274        ("GetDebuggeeType2", c_void_p),275    ]276 277 278IDebugControl7._fields_ = [("lpVtbl", POINTER(IDebugControl7Vtbl))]279 280 281class DebugStatus(IntEnum):282    DEBUG_STATUS_NO_CHANGE = 0283    DEBUG_STATUS_GO = 1284    DEBUG_STATUS_GO_HANDLED = 2285    DEBUG_STATUS_GO_NOT_HANDLED = 3286    DEBUG_STATUS_STEP_OVER = 4287    DEBUG_STATUS_STEP_INTO = 5288    DEBUG_STATUS_BREAK = 6289    DEBUG_STATUS_NO_DEBUGGEE = 7290    DEBUG_STATUS_STEP_BRANCH = 8291    DEBUG_STATUS_IGNORE_EVENT = 9292    DEBUG_STATUS_RESTART_REQUESTED = 10293    DEBUG_STATUS_REVERSE_GO = 11294    DEBUG_STATUS_REVERSE_STEP_BRANCH = 12295    DEBUG_STATUS_REVERSE_STEP_OVER = 13296    DEBUG_STATUS_REVERSE_STEP_INTO = 14297    DEBUG_STATUS_OUT_OF_SYNC = 15298    DEBUG_STATUS_WAIT_INPUT = 16299    DEBUG_STATUS_TIMEOUT = 17300 301 302class DebugSyntax(IntEnum):303    DEBUG_EXPR_MASM = 0304    DEBUG_EXPR_CPLUSPLUS = 1305 306 307class Control(object):308    def __init__(self, control):309        self.ptr = control310        self.control = control.contents311        self.vt = self.control.lpVtbl.contents312        # Keep a handy ulong for passing into C methods.313        self.ulong = c_ulong()314 315    def GetExecutionStatus(self, doprint=False):316        ret = self.vt.GetExecutionStatus(self.control, byref(self.ulong))317        aborter(ret, "GetExecutionStatus")318        status = DebugStatus(self.ulong.value)319        if doprint:320            print("Execution status: {}".format(status))321        return status322 323    def SetExecutionStatus(self, status):324        assert isinstance(status, DebugStatus)325        res = self.vt.SetExecutionStatus(self.control, status.value)326        aborter(res, "SetExecutionStatus")327 328    def WaitForEvent(self, timeout=100):329        # No flags are taken by WaitForEvent, hence 0330        ret = self.vt.WaitForEvent(self.control, 0, timeout)331        aborter(ret, "WaitforEvent", ignore=[S_FALSE])332        return ret333 334    def GetNumberEventFilters(self):335        specific_events = c_ulong()336        specific_exceptions = c_ulong()337        arbitrary_exceptions = c_ulong()338        res = self.vt.GetNumberEventFilters(339            self.control,340            byref(specific_events),341            byref(specific_exceptions),342            byref(arbitrary_exceptions),343        )344        aborter(res, "GetNumberEventFilters")345        return (346            specific_events.value,347            specific_exceptions.value,348            arbitrary_exceptions.value,349        )350 351    def SetExceptionFilterSecondCommand(self, index, command):352        buf = create_string_buffer(command.encode("ascii"))353        res = self.vt.SetExceptionFilterSecondCommand(self.control, index, buf)354        aborter(res, "SetExceptionFilterSecondCommand")355        return356 357    def AddBreakpoint2(self, offset=None, enabled=None):358        breakpoint = POINTER(DebugBreakpoint2)()359        res = self.vt.AddBreakpoint2(360            self.control,361            BreakpointTypes.DEBUG_BREAKPOINT_CODE,362            DEBUG_ANY_ID,363            byref(breakpoint),364        )365        aborter(res, "Add breakpoint 2")366        bp = Breakpoint(breakpoint)367 368        if offset is not None:369            bp.SetOffset(offset)370        if enabled is not None and enabled:371            bp.SetFlags(BreakpointFlags.DEBUG_BREAKPOINT_ENABLED)372 373        return bp374 375    def RemoveBreakpoint(self, bp):376        res = self.vt.RemoveBreakpoint2(self.control, bp.breakpoint)377        aborter(res, "RemoveBreakpoint2")378        bp.die()379 380    def GetStackTraceEx(self):381        # XXX -- I can't find a way to query for how many stack frames there _are_382        # in  advance. Guess 128 for now.383        num_frames_buffer = 128384 385        frames = (DEBUG_STACK_FRAME_EX * num_frames_buffer)()386        numframes = c_ulong()387 388        # First three args are frame/stack/IP offsets -- leave them as zero to389        # default to the current instruction.390        res = self.vt.GetStackTraceEx(391            self.control, 0, 0, 0, frames, num_frames_buffer, byref(numframes)392        )393        aborter(res, "GetStackTraceEx")394        return frames, numframes.value395 396    def Execute(self, command):397        # First zero is DEBUG_OUTCTL_*, which we leave as a default, second398        # zero is DEBUG_EXECUTE_* flags, of which we set none.399        res = self.vt.Execute(self.control, 0, command.encode("ascii"), 0)400        aborter(res, "Client execute")401 402    def SetExpressionSyntax(self, cpp=True):403        if cpp:404            syntax = DebugSyntax.DEBUG_EXPR_CPLUSPLUS405        else:406            syntax = DebugSyntax.DEBUG_EXPR_MASM407 408        res = self.vt.SetExpressionSyntax(self.control, syntax)409        aborter(res, "SetExpressionSyntax")410 411    def Evaluate(self, expr):412        ptr = DEBUG_VALUE()413        res = self.vt.Evaluate(414            self.control,415            expr.encode("ascii"),416            DebugValueType.DEBUG_VALUE_INVALID,417            byref(ptr),418            None,419        )420        aborter(res, "Evaluate", ignore=[E_INTERNALEXCEPTION, E_FAIL])421        if res != 0:422            return None423 424        val_type = DebugValueType(ptr.Type)425 426        # Here's a map from debug value types to fields. Unclear what happens427        # with unsigned values, as DbgEng doesn't present any unsigned fields.428 429        extract_map = {430            DebugValueType.DEBUG_VALUE_INT8: ("I8", "char"),431            DebugValueType.DEBUG_VALUE_INT16: ("I16", "short"),432            DebugValueType.DEBUG_VALUE_INT32: ("I32", "int"),433            DebugValueType.DEBUG_VALUE_INT64: ("I64", "long"),434            DebugValueType.DEBUG_VALUE_FLOAT32: ("F32", "float"),435            DebugValueType.DEBUG_VALUE_FLOAT64: ("F64", "double"),436        }  # And everything else is invalid.437 438        if val_type not in extract_map:439            raise Exception(440                "Unexpected debug value type {} when evalutaing".format(val_type)441            )442 443        # Also produce a type name...444 445        return getattr(ptr.U, extract_map[val_type][0]), extract_map[val_type][1]446 447    def SetEngineOptions(self, opt):448        res = self.vt.SetEngineOptions(self.control, opt)449        aborter(res, "SetEngineOptions")450        return451