summaryrefslogtreecommitdiffstats
path: root/debuginfo-tests/dexter/dex/debugger/dbgeng/control.py
diff options
context:
space:
mode:
Diffstat (limited to 'debuginfo-tests/dexter/dex/debugger/dbgeng/control.py')
-rw-r--r--debuginfo-tests/dexter/dex/debugger/dbgeng/control.py405
1 files changed, 405 insertions, 0 deletions
diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/control.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/control.py
new file mode 100644
index 00000000000..38585c83f70
--- /dev/null
+++ b/debuginfo-tests/dexter/dex/debugger/dbgeng/control.py
@@ -0,0 +1,405 @@
+# DExTer : Debugging Experience Tester
+# ~~~~~~ ~ ~~ ~ ~~
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+from ctypes import *
+from functools import partial
+
+from .utils import *
+from .breakpoint import *
+
+class DEBUG_STACK_FRAME_EX(Structure):
+ _fields_ = [
+ ("InstructionOffset", c_ulonglong),
+ ("ReturnOffset", c_ulonglong),
+ ("FrameOffset", c_ulonglong),
+ ("StackOffset", c_ulonglong),
+ ("FuncTableEntry", c_ulonglong),
+ ("Params", c_ulonglong * 4),
+ ("Reserved", c_ulonglong * 6),
+ ("Virtual", c_bool),
+ ("FrameNumber", c_ulong),
+ ("InlineFrameContext", c_ulong),
+ ("Reserved1", c_ulong)
+ ]
+PDEBUG_STACK_FRAME_EX = POINTER(DEBUG_STACK_FRAME_EX)
+
+class DEBUG_VALUE_U(Union):
+ _fields_ = [
+ ("I8", c_byte),
+ ("I16", c_short),
+ ("I32", c_int),
+ ("I64", c_long),
+ ("F32", c_float),
+ ("F64", c_double),
+ ("RawBytes", c_ubyte * 24) # Force length to 24b.
+ ]
+
+class DEBUG_VALUE(Structure):
+ _fields_ = [
+ ("U", DEBUG_VALUE_U),
+ ("TailOfRawBytes", c_ulong),
+ ("Type", c_ulong)
+ ]
+PDEBUG_VALUE = POINTER(DEBUG_VALUE)
+
+class DebugValueType(IntEnum):
+ DEBUG_VALUE_INVALID = 0
+ DEBUG_VALUE_INT8 = 1
+ DEBUG_VALUE_INT16 = 2
+ DEBUG_VALUE_INT32 = 3
+ DEBUG_VALUE_INT64 = 4
+ DEBUG_VALUE_FLOAT32 = 5
+ DEBUG_VALUE_FLOAT64 = 6
+ DEBUG_VALUE_FLOAT80 = 7
+ DEBUG_VALUE_FLOAT82 = 8
+ DEBUG_VALUE_FLOAT128 = 9
+ DEBUG_VALUE_VECTOR64 = 10
+ DEBUG_VALUE_VECTOR128 = 11
+ DEBUG_VALUE_TYPES = 12
+
+# UUID for DebugControl7 interface.
+DebugControl7IID = IID(0xb86fb3b1, 0x80d4, 0x475b, IID_Data4_Type(0xae, 0xa3, 0xcf, 0x06, 0x53, 0x9c, 0xf6, 0x3a))
+
+class IDebugControl7(Structure):
+ pass
+
+class IDebugControl7Vtbl(Structure):
+ wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugControl7))
+ idc_getnumbereventfilters = wrp(c_ulong_p, c_ulong_p, c_ulong_p)
+ idc_setexceptionfiltersecondcommand = wrp(c_ulong, c_char_p)
+ idc_waitforevent = wrp(c_long, c_long)
+ idc_execute = wrp(c_long, c_char_p, c_long)
+ idc_setexpressionsyntax = wrp(c_ulong)
+ idc_addbreakpoint2 = wrp(c_ulong, c_ulong, POINTER(POINTER(DebugBreakpoint2)))
+ idc_setexecutionstatus = wrp(c_ulong)
+ idc_getexecutionstatus = wrp(c_ulong_p)
+ idc_getstacktraceex = wrp(c_ulonglong, c_ulonglong, c_ulonglong, PDEBUG_STACK_FRAME_EX, c_ulong, c_ulong_p)
+ idc_evaluate = wrp(c_char_p, c_ulong, PDEBUG_VALUE, c_ulong_p)
+ _fields_ = [
+ ("QueryInterface", c_void_p),
+ ("AddRef", c_void_p),
+ ("Release", c_void_p),
+ ("GetInterrupt", c_void_p),
+ ("SetInterrupt", c_void_p),
+ ("GetInterruptTimeout", c_void_p),
+ ("SetInterruptTimeout", c_void_p),
+ ("GetLogFile", c_void_p),
+ ("OpenLogFile", c_void_p),
+ ("CloseLogFile", c_void_p),
+ ("GetLogMask", c_void_p),
+ ("SetLogMask", c_void_p),
+ ("Input", c_void_p),
+ ("ReturnInput", c_void_p),
+ ("Output", c_void_p),
+ ("OutputVaList", c_void_p),
+ ("ControlledOutput", c_void_p),
+ ("ControlledOutputVaList", c_void_p),
+ ("OutputPrompt", c_void_p),
+ ("OutputPromptVaList", c_void_p),
+ ("GetPromptText", c_void_p),
+ ("OutputCurrentState", c_void_p),
+ ("OutputVersionInformation", c_void_p),
+ ("GetNotifyEventHandle", c_void_p),
+ ("SetNotifyEventHandle", c_void_p),
+ ("Assemble", c_void_p),
+ ("Disassemble", c_void_p),
+ ("GetDisassembleEffectiveOffset", c_void_p),
+ ("OutputDisassembly", c_void_p),
+ ("OutputDisassemblyLines", c_void_p),
+ ("GetNearInstruction", c_void_p),
+ ("GetStackTrace", c_void_p),
+ ("GetReturnOffset", c_void_p),
+ ("OutputStackTrace", c_void_p),
+ ("GetDebuggeeType", c_void_p),
+ ("GetActualProcessorType", c_void_p),
+ ("GetExecutingProcessorType", c_void_p),
+ ("GetNumberPossibleExecutingProcessorTypes", c_void_p),
+ ("GetPossibleExecutingProcessorTypes", c_void_p),
+ ("GetNumberProcessors", c_void_p),
+ ("GetSystemVersion", c_void_p),
+ ("GetPageSize", c_void_p),
+ ("IsPointer64Bit", c_void_p),
+ ("ReadBugCheckData", c_void_p),
+ ("GetNumberSupportedProcessorTypes", c_void_p),
+ ("GetSupportedProcessorTypes", c_void_p),
+ ("GetProcessorTypeNames", c_void_p),
+ ("GetEffectiveProcessorType", c_void_p),
+ ("SetEffectiveProcessorType", c_void_p),
+ ("GetExecutionStatus", idc_getexecutionstatus),
+ ("SetExecutionStatus", idc_setexecutionstatus),
+ ("GetCodeLevel", c_void_p),
+ ("SetCodeLevel", c_void_p),
+ ("GetEngineOptions", c_void_p),
+ ("AddEngineOptions", c_void_p),
+ ("RemoveEngineOptions", c_void_p),
+ ("SetEngineOptions", c_void_p),
+ ("GetSystemErrorControl", c_void_p),
+ ("SetSystemErrorControl", c_void_p),
+ ("GetTextMacro", c_void_p),
+ ("SetTextMacro", c_void_p),
+ ("GetRadix", c_void_p),
+ ("SetRadix", c_void_p),
+ ("Evaluate", idc_evaluate),
+ ("CoerceValue", c_void_p),
+ ("CoerceValues", c_void_p),
+ ("Execute", idc_execute),
+ ("ExecuteCommandFile", c_void_p),
+ ("GetNumberBreakpoints", c_void_p),
+ ("GetBreakpointByIndex", c_void_p),
+ ("GetBreakpointById", c_void_p),
+ ("GetBreakpointParameters", c_void_p),
+ ("AddBreakpoint", c_void_p),
+ ("RemoveBreakpoint", c_void_p),
+ ("AddExtension", c_void_p),
+ ("RemoveExtension", c_void_p),
+ ("GetExtensionByPath", c_void_p),
+ ("CallExtension", c_void_p),
+ ("GetExtensionFunction", c_void_p),
+ ("GetWindbgExtensionApis32", c_void_p),
+ ("GetWindbgExtensionApis64", c_void_p),
+ ("GetNumberEventFilters", idc_getnumbereventfilters),
+ ("GetEventFilterText", c_void_p),
+ ("GetEventFilterCommand", c_void_p),
+ ("SetEventFilterCommand", c_void_p),
+ ("GetSpecificFilterParameters", c_void_p),
+ ("SetSpecificFilterParameters", c_void_p),
+ ("GetSpecificFilterArgument", c_void_p),
+ ("SetSpecificFilterArgument", c_void_p),
+ ("GetExceptionFilterParameters", c_void_p),
+ ("SetExceptionFilterParameters", c_void_p),
+ ("GetExceptionFilterSecondCommand", c_void_p),
+ ("SetExceptionFilterSecondCommand", idc_setexceptionfiltersecondcommand),
+ ("WaitForEvent", idc_waitforevent),
+ ("GetLastEventInformation", c_void_p),
+ ("GetCurrentTimeDate", c_void_p),
+ ("GetCurrentSystemUpTime", c_void_p),
+ ("GetDumpFormatFlags", c_void_p),
+ ("GetNumberTextReplacements", c_void_p),
+ ("GetTextReplacement", c_void_p),
+ ("SetTextReplacement", c_void_p),
+ ("RemoveTextReplacements", c_void_p),
+ ("OutputTextReplacements", c_void_p),
+ ("GetAssemblyOptions", c_void_p),
+ ("AddAssemblyOptions", c_void_p),
+ ("RemoveAssemblyOptions", c_void_p),
+ ("SetAssemblyOptions", c_void_p),
+ ("GetExpressionSyntax", c_void_p),
+ ("SetExpressionSyntax", idc_setexpressionsyntax),
+ ("SetExpressionSyntaxByName", c_void_p),
+ ("GetNumberExpressionSyntaxes", c_void_p),
+ ("GetExpressionSyntaxNames", c_void_p),
+ ("GetNumberEvents", c_void_p),
+ ("GetEventIndexDescription", c_void_p),
+ ("GetCurrentEventIndex", c_void_p),
+ ("SetNextEventIndex", c_void_p),
+ ("GetLogFileWide", c_void_p),
+ ("OpenLogFileWide", c_void_p),
+ ("InputWide", c_void_p),
+ ("ReturnInputWide", c_void_p),
+ ("OutputWide", c_void_p),
+ ("OutputVaListWide", c_void_p),
+ ("ControlledOutputWide", c_void_p),
+ ("ControlledOutputVaListWide", c_void_p),
+ ("OutputPromptWide", c_void_p),
+ ("OutputPromptVaListWide", c_void_p),
+ ("GetPromptTextWide", c_void_p),
+ ("AssembleWide", c_void_p),
+ ("DisassembleWide", c_void_p),
+ ("GetProcessrTypeNamesWide", c_void_p),
+ ("GetTextMacroWide", c_void_p),
+ ("SetTextMacroWide", c_void_p),
+ ("EvaluateWide", c_void_p),
+ ("ExecuteWide", c_void_p),
+ ("ExecuteCommandFileWide", c_void_p),
+ ("GetBreakpointByIndex2", c_void_p),
+ ("GetBreakpointById2", c_void_p),
+ ("AddBreakpoint2", idc_addbreakpoint2),
+ ("RemoveBreakpoint2", c_void_p),
+ ("AddExtensionWide", c_void_p),
+ ("GetExtensionByPathWide", c_void_p),
+ ("CallExtensionWide", c_void_p),
+ ("GetExtensionFunctionWide", c_void_p),
+ ("GetEventFilterTextWide", c_void_p),
+ ("GetEventfilterCommandWide", c_void_p),
+ ("SetEventFilterCommandWide", c_void_p),
+ ("GetSpecificFilterArgumentWide", c_void_p),
+ ("SetSpecificFilterArgumentWide", c_void_p),
+ ("GetExceptionFilterSecondCommandWide", c_void_p),
+ ("SetExceptionFilterSecondCommandWider", c_void_p),
+ ("GetLastEventInformationWide", c_void_p),
+ ("GetTextReplacementWide", c_void_p),
+ ("SetTextReplacementWide", c_void_p),
+ ("SetExpressionSyntaxByNameWide", c_void_p),
+ ("GetExpressionSyntaxNamesWide", c_void_p),
+ ("GetEventIndexDescriptionWide", c_void_p),
+ ("GetLogFile2", c_void_p),
+ ("OpenLogFile2", c_void_p),
+ ("GetLogFile2Wide", c_void_p),
+ ("OpenLogFile2Wide", c_void_p),
+ ("GetSystemVersionValues", c_void_p),
+ ("GetSystemVersionString", c_void_p),
+ ("GetSystemVersionStringWide", c_void_p),
+ ("GetContextStackTrace", c_void_p),
+ ("OutputContextStackTrace", c_void_p),
+ ("GetStoredEventInformation", c_void_p),
+ ("GetManagedStatus", c_void_p),
+ ("GetManagedStatusWide", c_void_p),
+ ("ResetManagedStatus", c_void_p),
+ ("GetStackTraceEx", idc_getstacktraceex),
+ ("OutputStackTraceEx", c_void_p),
+ ("GetContextStackTraceEx", c_void_p),
+ ("OutputContextStackTraceEx", c_void_p),
+ ("GetBreakpointByGuid", c_void_p),
+ ("GetExecutionStatusEx", c_void_p),
+ ("GetSynchronizationStatus", c_void_p),
+ ("GetDebuggeeType2", c_void_p)
+ ]
+
+IDebugControl7._fields_ = [("lpVtbl", POINTER(IDebugControl7Vtbl))]
+
+class DebugStatus(IntEnum):
+ DEBUG_STATUS_NO_CHANGE = 0
+ DEBUG_STATUS_GO = 1
+ DEBUG_STATUS_GO_HANDLED = 2
+ DEBUG_STATUS_GO_NOT_HANDLED = 3
+ DEBUG_STATUS_STEP_OVER = 4
+ DEBUG_STATUS_STEP_INTO = 5
+ DEBUG_STATUS_BREAK = 6
+ DEBUG_STATUS_NO_DEBUGGEE = 7
+ DEBUG_STATUS_STEP_BRANCH = 8
+ DEBUG_STATUS_IGNORE_EVENT = 9
+ DEBUG_STATUS_RESTART_REQUESTED = 10
+ DEBUG_STATUS_REVERSE_GO = 11
+ DEBUG_STATUS_REVERSE_STEP_BRANCH = 12
+ DEBUG_STATUS_REVERSE_STEP_OVER = 13
+ DEBUG_STATUS_REVERSE_STEP_INTO = 14
+ DEBUG_STATUS_OUT_OF_SYNC = 15
+ DEBUG_STATUS_WAIT_INPUT = 16
+ DEBUG_STATUS_TIMEOUT = 17
+
+class DebugSyntax(IntEnum):
+ DEBUG_EXPR_MASM = 0
+ DEBUG_EXPR_CPLUSPLUS = 1
+
+class Control(object):
+ def __init__(self, control):
+ self.ptr = control
+ self.control = control.contents
+ self.vt = self.control.lpVtbl.contents
+ # Keep a handy ulong for passing into C methods.
+ self.ulong = c_ulong()
+
+ def GetExecutionStatus(self, doprint=False):
+ ret = self.vt.GetExecutionStatus(self.control, byref(self.ulong))
+ aborter(ret, "GetExecutionStatus")
+ status = DebugStatus(self.ulong.value)
+ if doprint:
+ print("Execution status: {}".format(status))
+ return status
+
+ def SetExecutionStatus(self, status):
+ assert isinstance(status, DebugStatus)
+ res = self.vt.SetExecutionStatus(self.control, status.value)
+ aborter(res, "SetExecutionStatus")
+
+ def WaitForEvent(self, timeout=100):
+ # No flags are taken by WaitForEvent, hence 0
+ ret = self.vt.WaitForEvent(self.control, 0, timeout)
+ aborter(ret, "WaitforEvent", ignore=[S_FALSE])
+ return ret
+
+ def GetNumberEventFilters(self):
+ specific_events = c_ulong()
+ specific_exceptions = c_ulong()
+ arbitrary_exceptions = c_ulong()
+ res = self.vt.GetNumberEventFilters(self.control, byref(specific_events),
+ byref(specific_exceptions),
+ byref(arbitrary_exceptions))
+ aborter(res, "GetNumberEventFilters")
+ return (specific_events.value, specific_exceptions.value,
+ arbitrary_exceptions.value)
+
+ def SetExceptionFilterSecondCommand(self, index, command):
+ buf = create_string_buffer(command.encode('ascii'))
+ res = self.vt.SetExceptionFilterSecondCommand(self.control, index, buf)
+ aborter(res, "SetExceptionFilterSecondCommand")
+ return
+
+ def AddBreakpoint2(self, offset=None, enabled=None):
+ breakpoint = POINTER(DebugBreakpoint2)()
+ res = self.vt.AddBreakpoint2(self.control, BreakpointTypes.DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, byref(breakpoint))
+ aborter(res, "Add breakpoint 2")
+ bp = Breakpoint(breakpoint)
+
+ if offset is not None:
+ bp.SetOffset(offset)
+ if enabled is not None and enabled:
+ bp.SetFlags(BreakpointFlags.DEBUG_BREAKPOINT_ENABLED)
+
+ return bp
+
+ def RemoveBreakpoint(self, bp):
+ res = self.vt.RemoveBreakpoint2(self.control, bp.breakpoint)
+ aborter(res, "RemoveBreakpoint2")
+ bp.die()
+
+ def GetStackTraceEx(self):
+ # XXX -- I can't find a way to query for how many stack frames there _are_
+ # in advance. Guess 128 for now.
+ num_frames_buffer = 128
+
+ frames = (DEBUG_STACK_FRAME_EX * num_frames_buffer)()
+ numframes = c_ulong()
+
+ # First three args are frame/stack/IP offsets -- leave them as zero to
+ # default to the current instruction.
+ res = self.vt.GetStackTraceEx(self.control, 0, 0, 0, frames, num_frames_buffer, byref(numframes))
+ aborter(res, "GetStackTraceEx")
+ return frames, numframes.value
+
+ def Execute(self, command):
+ # First zero is DEBUG_OUTCTL_*, which we leave as a default, second
+ # zero is DEBUG_EXECUTE_* flags, of which we set none.
+ res = self.vt.Execute(self.control, 0, command.encode('ascii'), 0)
+ aborter(res, "Client execute")
+
+ def SetExpressionSyntax(self, cpp=True):
+ if cpp:
+ syntax = DebugSyntax.DEBUG_EXPR_CPLUSPLUS
+ else:
+ syntax = DebugSyntax.DEBUG_EXPR_MASM
+
+ res = self.vt.SetExpressionSyntax(self.control, syntax)
+ aborter(res, "SetExpressionSyntax")
+
+ def Evaluate(self, expr):
+ ptr = DEBUG_VALUE()
+ res = self.vt.Evaluate(self.control, expr.encode("ascii"), DebugValueType.DEBUG_VALUE_INVALID, byref(ptr), None)
+ aborter(res, "Evaluate", ignore=[E_INTERNALEXCEPTION, E_FAIL])
+ if res != 0:
+ return None
+
+ val_type = DebugValueType(ptr.Type)
+
+ # Here's a map from debug value types to fields. Unclear what happens
+ # with unsigned values, as DbgEng doesn't present any unsigned fields.
+
+ extract_map = {
+ DebugValueType.DEBUG_VALUE_INT8 : ("I8", "char"),
+ DebugValueType.DEBUG_VALUE_INT16 : ("I16", "short"),
+ DebugValueType.DEBUG_VALUE_INT32 : ("I32", "int"),
+ DebugValueType.DEBUG_VALUE_INT64 : ("I64", "long"),
+ DebugValueType.DEBUG_VALUE_FLOAT32 : ("F32", "float"),
+ DebugValueType.DEBUG_VALUE_FLOAT64 : ("F64", "double")
+ } # And everything else is invalid.
+
+ if val_type not in extract_map:
+ raise Exception("Unexpected debug value type {} when evalutaing".format(val_type))
+
+ # Also produce a type name...
+
+ return getattr(ptr.U, extract_map[val_type][0]), extract_map[val_type][1]
OpenPOWER on IntegriCloud