diff options
author | Jeremy Morse <jeremy.morse@sony.com> | 2019-10-31 16:22:10 +0000 |
---|---|---|
committer | Jeremy Morse <jeremy.morse@sony.com> | 2019-10-31 16:22:10 +0000 |
commit | cb935f345683194e42e6e883d79c5a16479acd74 (patch) | |
tree | cfb11e7bf901b8edf3b78dc97bbb5275190e9b4c /debuginfo-tests/dexter/dex/debugger/dbgeng | |
parent | f2cb9c0eabc132152b5b3ad4c87a5a02345a883d (diff) | |
download | bcm5719-llvm-cb935f345683194e42e6e883d79c5a16479acd74.tar.gz bcm5719-llvm-cb935f345683194e42e6e883d79c5a16479acd74.zip |
Revert "Import Dexter to debuginfo-tests"
This reverts commit f78c236efda85af1e526ac35ed535ef4786450e3.
Green dragon breakage was observed; I'll take a look at why.
Diffstat (limited to 'debuginfo-tests/dexter/dex/debugger/dbgeng')
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/README.md | 60 | ||||
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/__init__.py | 19 | ||||
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/breakpoint.py | 88 | ||||
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/client.py | 185 | ||||
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/control.py | 405 | ||||
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py | 163 | ||||
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/probe_process.py | 80 | ||||
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/setup.py | 185 | ||||
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/symbols.py | 499 | ||||
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/symgroup.py | 98 | ||||
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/sysobjs.py | 200 | ||||
-rw-r--r-- | debuginfo-tests/dexter/dex/debugger/dbgeng/utils.py | 47 |
12 files changed, 0 insertions, 2029 deletions
diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/README.md b/debuginfo-tests/dexter/dex/debugger/dbgeng/README.md deleted file mode 100644 index f9b864206d3..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# Debugger Engine backend - -This directory contains the Dexter backend for the Windows Debugger Engine -(DbgEng), which powers tools such as WinDbg and CDB. - -## Overview - -DbgEng is available as a collection of unregistered COM-"like" objects that -one accesses by calling DebugCreate in DbgEng.dll. The unregistered nature -means normal COM tooling can't access them; as a result, this backend uses -ctypes to describe the COM objects and call their methods. - -This is obviously not a huge amount of fun; on the other hand, COM has -maintained ABI compatible interfaces for decades, and nothing is for free. - -The dexter backend follows the same formula as others; it creates a process -and breaks on "main", then steps through the program, observing states and -stack frames along the way. - -## Implementation details - -This backend uses a mixture of both APIs for accessing information, and the -direct command-string interface to DbgEng for performing some actions. We -have to use the DbgEng stepping interface, or we would effectively be -building a new debugger, but certain things (like enabling source-line -stepping) only seem to be possible from the command interface. - -Each segment of debugger responsibility has its own COM object: Client, -Control, Symbols, SymbolGroups, Breakpoint, SystemObjects. In this python -wrapper, each COM object gets a python object wrapping it. COM methods -that are relevant to our interests have a python method that wraps the COM -one and performs data marshalling. Some additional helper methods are added -to the python objects to extract data. - -The majority of the work occurs in setup.py and probe_process.py. The -former contains routines to launch a process and attach the debugger to -it, while the latter extracts as much information as possible from a -stopped process, returning a list of stack frames with associated variable -information. - -## Sharp edges - -For reasons still unclear, using CreateProcessAndAttach never appears to -allow the debuggee to resume, hence this implementation creates the -debuggee process manually, attaches, and resumes. - -On process startup, we set a breakpoint on main and then continue running -to it. This has the potential to never complete -- although of course, -there's no guarantee that the debuggee will ever do anything anyway. - -There doesn't appear to be a way to instruct DbgEng to "step into" a -function call, thus after reaching main, we scan the module for all -functions with line numbers in the source directory, and put breakpoints -on them. An alternative implementation would be putting breakpoints on -every known line number. - -Finally, it's unclear whether arbitrary expressions can be evaluated in -arbitrary stack frames, although this isn't something that Dexter currently -supports. - diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/__init__.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/__init__.py deleted file mode 100644 index 3c458f955b7..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# 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 . import dbgeng - -import platform -if platform.system() == 'Windows': - from . import breakpoint - from . import control - from . import probe_process - from . import setup - from . import symbols - from . import symgroup - from . import sysobjs - from . import utils diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/breakpoint.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/breakpoint.py deleted file mode 100644 index c966d8c9c88..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/breakpoint.py +++ /dev/null @@ -1,88 +0,0 @@ -# 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 enum import * -from functools import partial - -from .utils import * - -class BreakpointTypes(IntEnum): - DEBUG_BREAKPOINT_CODE = 0 - DEBUG_BREAKPOINT_DATA = 1 - DEBUG_BREAKPOINT_TIME = 2 - DEBUG_BREAKPOINT_INLINE = 3 - -class BreakpointFlags(IntFlag): - DEBUG_BREAKPOINT_GO_ONLY = 0x00000001 - DEBUG_BREAKPOINT_DEFERRED = 0x00000002 - DEBUG_BREAKPOINT_ENABLED = 0x00000004 - DEBUG_BREAKPOINT_ADDER_ONLY = 0x00000008 - DEBUG_BREAKPOINT_ONE_SHOT = 0x00000010 - -DebugBreakpoint2IID = IID(0x1b278d20, 0x79f2, 0x426e, IID_Data4_Type(0xa3, 0xf9, 0xc1, 0xdd, 0xf3, 0x75, 0xd4, 0x8e)) - -class DebugBreakpoint2(Structure): - pass - -class DebugBreakpoint2Vtbl(Structure): - wrp = partial(WINFUNCTYPE, c_long, POINTER(DebugBreakpoint2)) - idb_setoffset = wrp(c_ulonglong) - idb_setflags = wrp(c_ulong) - _fields_ = [ - ("QueryInterface", c_void_p), - ("AddRef", c_void_p), - ("Release", c_void_p), - ("GetId", c_void_p), - ("GetType", c_void_p), - ("GetAdder", c_void_p), - ("GetFlags", c_void_p), - ("AddFlags", c_void_p), - ("RemoveFlags", c_void_p), - ("SetFlags", idb_setflags), - ("GetOffset", c_void_p), - ("SetOffset", idb_setoffset), - ("GetDataParameters", c_void_p), - ("SetDataParameters", c_void_p), - ("GetPassCount", c_void_p), - ("SetPassCount", c_void_p), - ("GetCurrentPassCount", c_void_p), - ("GetMatchThreadId", c_void_p), - ("SetMatchThreadId", c_void_p), - ("GetCommand", c_void_p), - ("SetCommand", c_void_p), - ("GetOffsetExpression", c_void_p), - ("SetOffsetExpression", c_void_p), - ("GetParameters", c_void_p), - ("GetCommandWide", c_void_p), - ("SetCommandWide", c_void_p), - ("GetOffsetExpressionWide", c_void_p), - ("SetOffsetExpressionWide", c_void_p) - ] - -DebugBreakpoint2._fields_ = [("lpVtbl", POINTER(DebugBreakpoint2Vtbl))] - -class Breakpoint(object): - def __init__(self, breakpoint): - self.breakpoint = breakpoint.contents - self.vt = self.breakpoint.lpVtbl.contents - - def SetFlags(self, flags): - res = self.vt.SetFlags(self.breakpoint, flags) - aborter(res, "Breakpoint SetFlags") - - def SetOffset(self, offs): - res = self.vt.SetOffset(self.breakpoint, offs) - aborter(res, "Breakpoint SetOffset") - - def RemoveFlags(self, flags): - res = self.vt.RemoveFlags(self.breakpoint, flags) - aborter(res, "Breakpoint RemoveFlags") - - def die(self): - self.breakpoint = None - self.vt = None diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/client.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/client.py deleted file mode 100644 index a65e4ded2f3..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/client.py +++ /dev/null @@ -1,185 +0,0 @@ -# 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 enum import * -from functools import partial - -from .utils import * -from . import control -from . import symbols -from . import sysobjs - -class DebugAttach(IntFlag): - DEBUG_ATTACH_DEFAULT = 0 - DEBUG_ATTACH_NONINVASIVE = 1 - DEBUG_ATTACH_EXISTING = 2 - DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND = 4 - DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK = 8 - DEBUG_ATTACH_INVASIVE_RESUME_PROCESS = 0x10 - DEBUG_ATTACH_NONINVASIVE_ALLOW_PARTIAL = 0x20 - -# UUID for DebugClient7 interface. -DebugClient7IID = IID(0x13586be3, 0x542e, 0x481e, IID_Data4_Type(0xb1, 0xf2, 0x84, 0x97, 0xba, 0x74, 0xf9, 0xa9 )) - -class IDebugClient7(Structure): - pass - -class IDebugClient7Vtbl(Structure): - wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugClient7)) - idc_queryinterface = wrp(POINTER(IID), POINTER(c_void_p)) - idc_attachprocess = wrp(c_longlong, c_long, c_long) - idc_detachprocesses = wrp() - _fields_ = [ - ("QueryInterface", idc_queryinterface), - ("AddRef", c_void_p), - ("Release", c_void_p), - ("AttachKernel", c_void_p), - ("GetKernelConnectionOptions", c_void_p), - ("SetKernelConnectionOptions", c_void_p), - ("StartProcessServer", c_void_p), - ("ConnectProcessServer", c_void_p), - ("DisconnectProcessServer", c_void_p), - ("GetRunningProcessSystemIds", c_void_p), - ("GetRunningProcessSystemIdsByExecutableName", c_void_p), - ("GetRunningProcessDescription", c_void_p), - ("AttachProcess", idc_attachprocess), - ("CreateProcess", c_void_p), - ("CreateProcessAndAttach", c_void_p), - ("GetProcessOptions", c_void_p), - ("AddProcessOptions", c_void_p), - ("RemoveProcessOptions", c_void_p), - ("SetProcessOptions", c_void_p), - ("OpenDumpFile", c_void_p), - ("WriteDumpFile", c_void_p), - ("ConnectSession", c_void_p), - ("StartServer", c_void_p), - ("OutputServers", c_void_p), - ("TerminateProcesses", c_void_p), - ("DetachProcesses", idc_detachprocesses), - ("EndSession", c_void_p), - ("GetExitCode", c_void_p), - ("DispatchCallbacks", c_void_p), - ("ExitDispatch", c_void_p), - ("CreateClient", c_void_p), - ("GetInputCallbacks", c_void_p), - ("SetInputCallbacks", c_void_p), - ("GetOutputCallbacks", c_void_p), - ("SetOutputCallbacks", c_void_p), - ("GetOutputMask", c_void_p), - ("SetOutputMask", c_void_p), - ("GetOtherOutputMask", c_void_p), - ("SetOtherOutputMask", c_void_p), - ("GetOutputWidth", c_void_p), - ("SetOutputWidth", c_void_p), - ("GetOutputLinePrefix", c_void_p), - ("SetOutputLinePrefix", c_void_p), - ("GetIdentity", c_void_p), - ("OutputIdentity", c_void_p), - ("GetEventCallbacks", c_void_p), - ("SetEventCallbacks", c_void_p), - ("FlushCallbacks", c_void_p), - ("WriteDumpFile2", c_void_p), - ("AddDumpInformationFile", c_void_p), - ("EndProcessServer", c_void_p), - ("WaitForProcessServerEnd", c_void_p), - ("IsKernelDebuggerEnabled", c_void_p), - ("TerminateCurrentProcess", c_void_p), - ("DetachCurrentProcess", c_void_p), - ("AbandonCurrentProcess", c_void_p), - ("GetRunningProcessSystemIdByExecutableNameWide", c_void_p), - ("GetRunningProcessDescriptionWide", c_void_p), - ("CreateProcessWide", c_void_p), - ("CreateProcessAndAttachWide", c_void_p), - ("OpenDumpFileWide", c_void_p), - ("WriteDumpFileWide", c_void_p), - ("AddDumpInformationFileWide", c_void_p), - ("GetNumberDumpFiles", c_void_p), - ("GetDumpFile", c_void_p), - ("GetDumpFileWide", c_void_p), - ("AttachKernelWide", c_void_p), - ("GetKernelConnectionOptionsWide", c_void_p), - ("SetKernelConnectionOptionsWide", c_void_p), - ("StartProcessServerWide", c_void_p), - ("ConnectProcessServerWide", c_void_p), - ("StartServerWide", c_void_p), - ("OutputServerWide", c_void_p), - ("GetOutputCallbacksWide", c_void_p), - ("SetOutputCallbacksWide", c_void_p), - ("GetOutputLinePrefixWide", c_void_p), - ("SetOutputLinePrefixWide", c_void_p), - ("GetIdentityWide", c_void_p), - ("OutputIdentityWide", c_void_p), - ("GetEventCallbacksWide", c_void_p), - ("SetEventCallbacksWide", c_void_p), - ("CreateProcess2", c_void_p), - ("CreateProcess2Wide", c_void_p), - ("CreateProcessAndAttach2", c_void_p), - ("CreateProcessAndAttach2Wide", c_void_p), - ("PushOutputLinePrefix", c_void_p), - ("PushOutputLinePrefixWide", c_void_p), - ("PopOutputLinePrefix", c_void_p), - ("GetNumberInputCallbacks", c_void_p), - ("GetNumberOutputCallbacks", c_void_p), - ("GetNumberEventCallbacks", c_void_p), - ("GetQuitLockString", c_void_p), - ("SetQuitLockString", c_void_p), - ("GetQuitLockStringWide", c_void_p), - ("SetQuitLockStringWide", c_void_p), - ("SetEventContextCallbacks", c_void_p), - ("SetClientContext", c_void_p), - ] - -IDebugClient7._fields_ = [("lpVtbl", POINTER(IDebugClient7Vtbl))] - -class Client(object): - def __init__(self): - DbgEng = WinDLL("DbgEng") - DbgEng.DebugCreate.argtypes = [POINTER(IID), POINTER(POINTER(IDebugClient7))] - DbgEng.DebugCreate.restype = c_ulong - - # Call DebugCreate to create a new debug client - ptr = POINTER(IDebugClient7)() - res = DbgEng.DebugCreate(byref(DebugClient7IID), ptr) - aborter(res, "DebugCreate") - self.client = ptr.contents - self.vt = vt = self.client.lpVtbl.contents - - def QI(iface, ptr): - return vt.QueryInterface(self.client, byref(iface), byref(ptr)) - - # Query for a control object - ptr = c_void_p() - res = QI(control.DebugControl7IID, ptr) - aborter(res, "QueryInterface control") - self.control_ptr = cast(ptr, POINTER(control.IDebugControl7)) - self.Control = control.Control(self.control_ptr) - - # Query for a SystemObjects object - ptr = c_void_p() - res = QI(sysobjs.DebugSystemObjects4IID, ptr) - aborter(res, "QueryInterface sysobjects") - self.sysobjects_ptr = cast(ptr, POINTER(sysobjs.IDebugSystemObjects4)) - self.SysObjects = sysobjs.SysObjects(self.sysobjects_ptr) - - # Query for a Symbols object - ptr = c_void_p() - res = QI(symbols.DebugSymbols5IID, ptr) - aborter(res, "QueryInterface debugsymbosl5") - self.symbols_ptr = cast(ptr, POINTER(symbols.IDebugSymbols5)) - self.Symbols = symbols.Symbols(self.symbols_ptr) - - def AttachProcess(self, pid): - # Zero process-server id means no process-server. - res = self.vt.AttachProcess(self.client, 0, pid, DebugAttach.DEBUG_ATTACH_DEFAULT) - aborter(res, "AttachProcess") - return - - def DetachProcesses(self): - res = self.vt.DetachProcesses(self.client) - aborter(res, "DetachProcesses") - return diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/control.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/control.py deleted file mode 100644 index 38585c83f70..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/control.py +++ /dev/null @@ -1,405 +0,0 @@ -# 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] diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py deleted file mode 100644 index 66d01f03e8f..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py +++ /dev/null @@ -1,163 +0,0 @@ -# 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 - -import sys -import os -import platform - -from dex.debugger.DebuggerBase import DebuggerBase -from dex.dextIR import FrameIR, LocIR, StepIR, StopReason, ValueIR -from dex.dextIR import ProgramState, StackFrame, SourceLocation -from dex.utils.Exceptions import DebuggerException, LoadDebuggerException -from dex.utils.ReturnCode import ReturnCode - -if platform.system() == "Windows": - # Don't load on linux; _load_interface will croak before any names are used. - from . import setup - from . import probe_process - from . import breakpoint - -class DbgEng(DebuggerBase): - def __init__(self, context, *args): - self.breakpoints = [] - self.running = False - self.finished = False - self.step_info = None - super(DbgEng, self).__init__(context, *args) - - def _custom_init(self): - try: - res = setup.setup_everything(self.context.options.executable) - self.client, self.hProcess = res - self.running = True - except Exception as e: - raise Exception('Failed to start debuggee: {}'.format(e)) - - def _custom_exit(self): - setup.cleanup(self.client, self.hProcess) - - def _load_interface(self): - arch = platform.architecture()[0] - machine = platform.machine() - if arch == '32bit' and machine == 'AMD64': - # This python process is 32 bits, but is sitting on a 64 bit machine. - # Bad things may happen, don't support it. - raise LoadDebuggerException('Can\'t run Dexter dbgeng on 32 bit python in a 64 bit environment') - - if platform.system() != 'Windows': - raise LoadDebuggerException('DbgEng supports Windows only') - - # Otherwise, everything was imported earlier - - @classmethod - def get_name(cls): - return 'dbgeng' - - @classmethod - def get_option_name(cls): - return 'dbgeng' - - @property - def frames_below_main(self): - return [] - - @property - def version(self): - # I don't believe there's a well defined DbgEng version, outside of the - # version of Windows being used. - return "1" - - def clear_breakpoints(self): - for x in self.breakpoints: - x.RemoveFlags(breakpoint.BreakpointFlags.DEBUG_BREAKPOINT_ENABLED) - self.client.Control.RemoveBreakpoint(x) - - def add_breakpoint(self, file_, line): - # This is something to implement in the future -- as it stands, Dexter - # doesn't test for such things as "I can set a breakpoint on this line". - # This is only called AFAICT right now to ensure we break on every step. - pass - - def launch(self): - # We are, by this point, already launched. - self.step_info = probe_process.probe_state(self.client) - - def step(self): - res = setup.step_once(self.client) - if not res: - self.finished = True - self.step_info = res - - def go(self): - # We never go -- we always single step. - pass - - def get_step_info(self): - frames = self.step_info - state_frames = [] - - # For now assume the base function is the... function, ignoring - # inlining. - dex_frames = [] - for i, x in enumerate(frames): - # XXX Might be able to get columns out through - # GetSourceEntriesByOffset, not a priority now - loc = LocIR(path=x.source_file, lineno=x.line_no, column=0) - new_frame = FrameIR(function=x.function_name, is_inlined=False, loc=loc) - dex_frames.append(new_frame) - - state_frame = StackFrame(function=new_frame.function, - is_inlined=new_frame.is_inlined, - location=SourceLocation(path=x.source_file, - lineno=x.line_no, - column=0), - watches={}) - for expr in map( - lambda watch, idx=i: self.evaluate_expression(watch, idx), - self.watches): - state_frame.watches[expr.expression] = expr - state_frames.append(state_frame) - - return StepIR( - step_index=self.step_index, frames=dex_frames, - stop_reason=StopReason.STEP, - program_state=ProgramState(state_frames)) - - @property - def is_running(self): - return False # We're never free-running - - @property - def is_finished(self): - return self.finished - - def evaluate_expression(self, expression, frame_idx=0): - # XXX: cdb insists on using '->' to examine fields of structures, - # as it appears to reserve '.' for other purposes. - fixed_expr = expression.replace('.', '->') - - orig_scope_idx = self.client.Symbols.GetCurrentScopeFrameIndex() - self.client.Symbols.SetScopeFrameByIndex(frame_idx) - - res = self.client.Control.Evaluate(fixed_expr) - if res is not None: - result, typename = self.client.Control.Evaluate(fixed_expr) - could_eval = True - else: - result, typename = (None, None) - could_eval = False - - self.client.Symbols.SetScopeFrameByIndex(orig_scope_idx) - - return ValueIR( - expression=expression, - value=str(result), - type_name=typename, - error_string="", - could_evaluate=could_eval, - is_optimized_away=False, - is_irretrievable=not could_eval) diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/probe_process.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/probe_process.py deleted file mode 100644 index 8bd7f607081..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/probe_process.py +++ /dev/null @@ -1,80 +0,0 @@ -# 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 - -import os - -from .utils import * - -class Frame(object): - def __init__(self, frame, idx, Symbols): - # Store some base information about the frame - self.ip = frame.InstructionOffset - self.scope_idx = idx - self.virtual = frame.Virtual - self.inline_frame_context = frame.InlineFrameContext - self.func_tbl_entry = frame.FuncTableEntry - - # Fetch the module/symbol we're in, with displacement. Useful for debugging. - self.descr = Symbols.GetNearNameByOffset(self.ip) - split = self.descr.split('!')[0] - self.module = split[0] - self.symbol = split[1] - - # Fetch symbol group for this scope. - prevscope = Symbols.GetCurrentScopeFrameIndex() - if Symbols.SetScopeFrameByIndex(idx): - symgroup = Symbols.GetScopeSymbolGroup2() - Symbols.SetScopeFrameByIndex(prevscope) - self.symgroup = symgroup - else: - self.symgroup = None - - # Fetch the name according to the line-table, using inlining context. - name = Symbols.GetNameByInlineContext(self.ip, self.inline_frame_context) - self.function_name = name.split('!')[-1] - - try: - tup = Symbols.GetLineByInlineContext(self.ip, self.inline_frame_context) - self.source_file, self.line_no = tup - except WinError as e: - # Fall back to trying to use a non-inlining-aware line number - # XXX - this is not inlining aware - sym = Symbols.GetLineByOffset(self.ip) - if sym is not None: - self.source_file, self.line_no = sym - else: - self.source_file = None - self.line_no = None - self.basename = None - - if self.source_file is not None: - self.basename = os.path.basename(self.source_file) - else: - self.basename = None - - - - def __str__(self): - return '{}:{}({}) {}'.format(self.basename, self.line, self.descr, self.function_name) - -def main_on_stack(Symbols, frames): - module_name = Symbols.get_exefile_module_name() - main_name = "{}!main".format(module_name) - for x in frames: - if main_name in x.descr: # Could be less hard coded... - return True - return False - -def probe_state(Client): - # Fetch the state of the program -- represented by the stack frames. - frames, numframes = Client.Control.GetStackTraceEx() - - the_frames = [Frame(frames[x], x, Client.Symbols) for x in range(numframes)] - if not main_on_stack(Client.Symbols, the_frames): - return None - - return the_frames diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/setup.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/setup.py deleted file mode 100644 index 30a62f6dd42..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/setup.py +++ /dev/null @@ -1,185 +0,0 @@ -# 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 . import client -from . import control -from . import symbols -from .probe_process import probe_state -from .utils import * - -class STARTUPINFOA(Structure): - _fields_ = [ - ('cb', c_ulong), - ('lpReserved', c_char_p), - ('lpDesktop', c_char_p), - ('lpTitle', c_char_p), - ('dwX', c_ulong), - ('dwY', c_ulong), - ('dwXSize', c_ulong), - ('dwYSize', c_ulong), - ('dwXCountChars', c_ulong), - ('dwYCountChars', c_ulong), - ('dwFillAttribute', c_ulong), - ('wShowWindow', c_ushort), - ('cbReserved2', c_ushort), - ('lpReserved2', c_char_p), - ('hStdInput', c_void_p), - ('hStdOutput', c_void_p), - ('hStdError', c_void_p) - ] - -class PROCESS_INFORMATION(Structure): - _fields_ = [ - ('hProcess', c_void_p), - ('hThread', c_void_p), - ('dwProcessId', c_ulong), - ('dwThreadId', c_ulong) - ] - -def fetch_local_function_syms(Symbols, prefix): - syms = Symbols.get_all_functions() - - def is_sym_in_src_dir(sym): - name, data = sym - symdata = Symbols.GetLineByOffset(data.Offset) - if symdata is not None: - srcfile, line = symdata - if prefix in srcfile: - return True - return False - - syms = [x for x in syms if is_sym_in_src_dir(x)] - return syms - -def break_on_all_but_main(Control, Symbols, main_offset): - mainfile, _ = Symbols.GetLineByOffset(main_offset) - prefix = '\\'.join(mainfile.split('\\')[:-1]) - - for name, rec in fetch_local_function_syms(Symbols, prefix): - if name == "main": - continue - bp = Control.AddBreakpoint2(offset=rec.Offset, enabled=True) - - # All breakpoints are currently discarded: we just sys.exit for cleanup - return - -def process_creator(binfile): - Kernel32 = WinDLL("Kernel32") - - # Another flavour of process creation - startupinfoa = STARTUPINFOA() - startupinfoa.cb = sizeof(STARTUPINFOA) - startupinfoa.lpReserved = None - startupinfoa.lpDesktop = None - startupinfoa.lpTitle = None - startupinfoa.dwX = 0 - startupinfoa.dwY = 0 - startupinfoa.dwXSize = 0 - startupinfoa.dwYSize = 0 - startupinfoa.dwXCountChars = 0 - startupinfoa.dwYCountChars = 0 - startupinfoa.dwFillAttribute = 0 - startupinfoa.dwFlags = 0 - startupinfoa.wShowWindow = 0 - startupinfoa.cbReserved2 = 0 - startupinfoa.lpReserved2 = None - startupinfoa.hStdInput = None - startupinfoa.hStdOutput = None - startupinfoa.hStdError = None - processinformation = PROCESS_INFORMATION() - - # 0x4 below specifies CREATE_SUSPENDED. - ret = Kernel32.CreateProcessA(binfile.encode("ascii"), None, None, None, False, 0x4, None, None, byref(startupinfoa), byref(processinformation)) - if ret == 0: - raise Exception('CreateProcess running {}'.format(binfile)) - - return processinformation.dwProcessId, processinformation.dwThreadId, processinformation.hProcess, processinformation.hThread - -def thread_resumer(hProcess, hThread): - Kernel32 = WinDLL("Kernel32") - - # For reasons unclear to me, other suspend-references seem to be opened on - # the opened thread. Clear them all. - while True: - ret = Kernel32.ResumeThread(hThread) - if ret <= 0: - break - if ret < 0: - Kernel32.TerminateProcess(hProcess, 1) - raise Exception("Couldn't resume process after startup") - - return - -def setup_everything(binfile): - from . import client - from . import symbols - Client = client.Client() - - created_pid, created_tid, hProcess, hThread = process_creator(binfile) - - # Load lines as well as general symbols - sym_opts = Client.Symbols.GetSymbolOptions() - sym_opts |= symbols.SymbolOptionFlags.SYMOPT_LOAD_LINES - Client.Symbols.SetSymbolOptions(sym_opts) - - Client.AttachProcess(created_pid) - - # Need to enter the debugger engine to let it attach properly - Client.Control.WaitForEvent(timeout=1) - Client.SysObjects.set_current_thread(created_pid, created_tid) - Client.Control.Execute("l+t") - Client.Control.SetExpressionSyntax(cpp=True) - - module_name = Client.Symbols.get_exefile_module_name() - offset = Client.Symbols.GetOffsetByName("{}!main".format(module_name)) - breakpoint = Client.Control.AddBreakpoint2(offset=offset, enabled=True) - thread_resumer(hProcess, hThread) - Client.Control.SetExecutionStatus(control.DebugStatus.DEBUG_STATUS_GO) - - # Problem: there is no guarantee that the client will ever reach main, - # something else exciting could happen in that time, the host system may - # be very loaded, and similar. Wait for some period, say, five seconds, and - # abort afterwards: this is a trade-off between spurious timeouts and - # completely hanging in the case of a environmental/programming error. - res = Client.Control.WaitForEvent(timeout=5000) - if res == S_FALSE: - Kernel32.TerminateProcess(hProcess, 1) - raise Exception("Debuggee did not reach main function in a timely manner") - - break_on_all_but_main(Client.Control, Client.Symbols, offset) - - # Set the default action on all exceptions to be "quit and detach". If we - # don't, dbgeng will merrily spin at the exception site forever. - filts = Client.Control.GetNumberEventFilters() - for x in range(filts[0], filts[0] + filts[1]): - Client.Control.SetExceptionFilterSecondCommand(x, "qd") - - return Client, hProcess - -def step_once(client): - client.Control.Execute("p") - try: - client.Control.WaitForEvent() - except Exception as e: - if client.Control.GetExecutionStatus() == control.DebugStatus.DEBUG_STATUS_NO_DEBUGGEE: - return None # Debuggee has gone away, likely due to an exception. - raise e - # Could assert here that we're in the "break" state - client.Control.GetExecutionStatus() - return probe_state(client) - -def main_loop(client): - res = True - while res is not None: - res = step_once(client) - -def cleanup(client, hProcess): - res = client.DetachProcesses() - Kernel32 = WinDLL("Kernel32") - Kernel32.TerminateProcess(hProcess, 1) diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/symbols.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/symbols.py deleted file mode 100644 index bc998facb4e..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/symbols.py +++ /dev/null @@ -1,499 +0,0 @@ -# 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 collections import namedtuple -from ctypes import * -from enum import * -from functools import reduce, partial - -from .symgroup import SymbolGroup, IDebugSymbolGroup2 -from .utils import * - -class SymbolOptionFlags(IntFlag): - SYMOPT_CASE_INSENSITIVE = 0x00000001 - SYMOPT_UNDNAME = 0x00000002 - SYMOPT_DEFERRED_LOADS = 0x00000004 - SYMOPT_NO_CPP = 0x00000008 - SYMOPT_LOAD_LINES = 0x00000010 - SYMOPT_OMAP_FIND_NEAREST = 0x00000020 - SYMOPT_LOAD_ANYTHING = 0x00000040 - SYMOPT_IGNORE_CVREC = 0x00000080 - SYMOPT_NO_UNQUALIFIED_LOADS = 0x00000100 - SYMOPT_FAIL_CRITICAL_ERRORS = 0x00000200 - SYMOPT_EXACT_SYMBOLS = 0x00000400 - SYMOPT_ALLOW_ABSOLUTE_SYMBOLS = 0x00000800 - SYMOPT_IGNORE_NT_SYMPATH = 0x00001000 - SYMOPT_INCLUDE_32BIT_MODULES = 0x00002000 - SYMOPT_PUBLICS_ONLY = 0x00004000 - SYMOPT_NO_PUBLICS = 0x00008000 - SYMOPT_AUTO_PUBLICS = 0x00010000 - SYMOPT_NO_IMAGE_SEARCH = 0x00020000 - SYMOPT_SECURE = 0x00040000 - SYMOPT_NO_PROMPTS = 0x00080000 - SYMOPT_DEBUG = 0x80000000 - -class ScopeGroupFlags(IntFlag): - DEBUG_SCOPE_GROUP_ARGUMENTS = 0x00000001 - DEBUG_SCOPE_GROUP_LOCALS = 0x00000002 - DEBUG_SCOPE_GROUP_ALL = 0x00000003 - DEBUG_SCOPE_GROUP_BY_DATAMODEL = 0x00000004 - -class DebugModuleNames(IntEnum): - DEBUG_MODNAME_IMAGE = 0x00000000 - DEBUG_MODNAME_MODULE = 0x00000001 - DEBUG_MODNAME_LOADED_IMAGE = 0x00000002 - DEBUG_MODNAME_SYMBOL_FILE = 0x00000003 - DEBUG_MODNAME_MAPPED_IMAGE = 0x00000004 - -class DebugModuleFlags(IntFlag): - DEBUG_MODULE_LOADED = 0x00000000 - DEBUG_MODULE_UNLOADED = 0x00000001 - DEBUG_MODULE_USER_MODE = 0x00000002 - DEBUG_MODULE_EXE_MODULE = 0x00000004 - DEBUG_MODULE_EXPLICIT = 0x00000008 - DEBUG_MODULE_SECONDARY = 0x00000010 - DEBUG_MODULE_SYNTHETIC = 0x00000020 - DEBUG_MODULE_SYM_BAD_CHECKSUM = 0x00010000 - -class DEBUG_MODULE_PARAMETERS(Structure): - _fields_ = [ - ("Base", c_ulonglong), - ("Size", c_ulong), - ("TimeDateStamp", c_ulong), - ("Checksum", c_ulong), - ("Flags", c_ulong), - ("SymbolType", c_ulong), - ("ImageNameSize", c_ulong), - ("ModuleNameSize", c_ulong), - ("LoadedImageNameSize", c_ulong), - ("SymbolFileNameSize", c_ulong), - ("MappedImageNameSize", c_ulong), - ("Reserved", c_ulonglong * 2) - ] -PDEBUG_MODULE_PARAMETERS = POINTER(DEBUG_MODULE_PARAMETERS) - -class DEBUG_MODULE_AND_ID(Structure): - _fields_ = [ - ("ModuleBase", c_ulonglong), - ("Id", c_ulonglong) - ] -PDEBUG_MODULE_AND_ID = POINTER(DEBUG_MODULE_AND_ID) - -class DEBUG_SYMBOL_ENTRY(Structure): - _fields_ = [ - ("ModuleBase", c_ulonglong), - ("Offset", c_ulonglong), - ("Id", c_ulonglong), - ("Arg64", c_ulonglong), - ("Size", c_ulong), - ("Flags", c_ulong), - ("TypeId", c_ulong), - ("NameSize", c_ulong), - ("Token", c_ulong), - ("Tag", c_ulong), - ("Arg32", c_ulong), - ("Reserved", c_ulong) - ] -PDEBUG_SYMBOL_ENTRY = POINTER(DEBUG_SYMBOL_ENTRY) - -# UUID for DebugSymbols5 interface. -DebugSymbols5IID = IID(0xc65fa83e, 0x1e69, 0x475e, IID_Data4_Type(0x8e, 0x0e, 0xb5, 0xd7, 0x9e, 0x9c, 0xc1, 0x7e)) - -class IDebugSymbols5(Structure): - pass - -class IDebugSymbols5Vtbl(Structure): - wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugSymbols5)) - ids_getsymboloptions = wrp(c_ulong_p) - ids_setsymboloptions = wrp(c_ulong) - ids_getmoduleparameters = wrp(c_ulong, c_ulong64_p, c_ulong, PDEBUG_MODULE_PARAMETERS) - ids_getmodulenamestring = wrp(c_ulong, c_ulong, c_ulonglong, c_char_p, c_ulong, c_ulong_p) - ids_getoffsetbyname = wrp(c_char_p, c_ulong64_p) - ids_getlinebyoffset = wrp(c_ulonglong, c_ulong_p, c_char_p, c_ulong, c_ulong_p, c_ulong64_p) - ids_getsymbolentriesbyname = wrp(c_char_p, c_ulong, PDEBUG_MODULE_AND_ID, c_ulong, c_ulong_p) - ids_getsymbolentrystring = wrp(PDEBUG_MODULE_AND_ID, c_ulong, c_char_p, c_ulong, c_ulong_p) - ids_getsymbolentryinformation = wrp(PDEBUG_MODULE_AND_ID, PDEBUG_SYMBOL_ENTRY) - ids_getcurrentscopeframeindex = wrp(c_ulong_p) - ids_getnearnamebyoffset = wrp(c_ulonglong, c_long, c_char_p, c_ulong, c_ulong_p, c_ulong64_p) - ids_setscopeframebyindex = wrp(c_ulong) - ids_getscopesymbolgroup2 = wrp(c_ulong, POINTER(IDebugSymbolGroup2), POINTER(POINTER(IDebugSymbolGroup2))) - ids_getnamebyinlinecontext = wrp(c_ulonglong, c_ulong, c_char_p, c_ulong, c_ulong_p, c_ulong64_p) - ids_getlinebyinlinecontext = wrp(c_ulonglong, c_ulong, c_ulong_p, c_char_p, c_ulong, c_ulong_p, c_ulong64_p) - _fields_ = [ - ("QueryInterface", c_void_p), - ("AddRef", c_void_p), - ("Release", c_void_p), - ("GetSymbolOptions", ids_getsymboloptions), - ("AddSymbolOptions", c_void_p), - ("RemoveSymbolOptions", c_void_p), - ("SetSymbolOptions", ids_setsymboloptions), - ("GetNameByOffset", c_void_p), - ("GetOffsetByName", ids_getoffsetbyname), - ("GetNearNameByOffset", ids_getnearnamebyoffset), - ("GetLineByOffset", ids_getlinebyoffset), - ("GetOffsetByLine", c_void_p), - ("GetNumberModules", c_void_p), - ("GetModuleByIndex", c_void_p), - ("GetModuleByModuleName", c_void_p), - ("GetModuleByOffset", c_void_p), - ("GetModuleNames", c_void_p), - ("GetModuleParameters", ids_getmoduleparameters), - ("GetSymbolModule", c_void_p), - ("GetTypeName", c_void_p), - ("GetTypeId", c_void_p), - ("GetTypeSize", c_void_p), - ("GetFieldOffset", c_void_p), - ("GetSymbolTypeId", c_void_p), - ("GetOffsetTypeId", c_void_p), - ("ReadTypedDataVirtual", c_void_p), - ("WriteTypedDataVirtual", c_void_p), - ("OutputTypedDataVirtual", c_void_p), - ("ReadTypedDataPhysical", c_void_p), - ("WriteTypedDataPhysical", c_void_p), - ("OutputTypedDataPhysical", c_void_p), - ("GetScope", c_void_p), - ("SetScope", c_void_p), - ("ResetScope", c_void_p), - ("GetScopeSymbolGroup", c_void_p), - ("CreateSymbolGroup", c_void_p), - ("StartSymbolMatch", c_void_p), - ("GetNextSymbolMatch", c_void_p), - ("EndSymbolMatch", c_void_p), - ("Reload", c_void_p), - ("GetSymbolPath", c_void_p), - ("SetSymbolPath", c_void_p), - ("AppendSymbolPath", c_void_p), - ("GetImagePath", c_void_p), - ("SetImagePath", c_void_p), - ("AppendImagePath", c_void_p), - ("GetSourcePath", c_void_p), - ("GetSourcePathElement", c_void_p), - ("SetSourcePath", c_void_p), - ("AppendSourcePath", c_void_p), - ("FindSourceFile", c_void_p), - ("GetSourceFileLineOffsets", c_void_p), - ("GetModuleVersionInformation", c_void_p), - ("GetModuleNameString", ids_getmodulenamestring), - ("GetConstantName", c_void_p), - ("GetFieldName", c_void_p), - ("GetTypeOptions", c_void_p), - ("AddTypeOptions", c_void_p), - ("RemoveTypeOptions", c_void_p), - ("SetTypeOptions", c_void_p), - ("GetNameByOffsetWide", c_void_p), - ("GetOffsetByNameWide", c_void_p), - ("GetNearNameByOffsetWide", c_void_p), - ("GetLineByOffsetWide", c_void_p), - ("GetOffsetByLineWide", c_void_p), - ("GetModuleByModuleNameWide", c_void_p), - ("GetSymbolModuleWide", c_void_p), - ("GetTypeNameWide", c_void_p), - ("GetTypeIdWide", c_void_p), - ("GetFieldOffsetWide", c_void_p), - ("GetSymbolTypeIdWide", c_void_p), - ("GetScopeSymbolGroup2", ids_getscopesymbolgroup2), - ("CreateSymbolGroup2", c_void_p), - ("StartSymbolMatchWide", c_void_p), - ("GetNextSymbolMatchWide", c_void_p), - ("ReloadWide", c_void_p), - ("GetSymbolPathWide", c_void_p), - ("SetSymbolPathWide", c_void_p), - ("AppendSymbolPathWide", c_void_p), - ("GetImagePathWide", c_void_p), - ("SetImagePathWide", c_void_p), - ("AppendImagePathWide", c_void_p), - ("GetSourcePathWide", c_void_p), - ("GetSourcePathElementWide", c_void_p), - ("SetSourcePathWide", c_void_p), - ("AppendSourcePathWide", c_void_p), - ("FindSourceFileWide", c_void_p), - ("GetSourceFileLineOffsetsWide", c_void_p), - ("GetModuleVersionInformationWide", c_void_p), - ("GetModuleNameStringWide", c_void_p), - ("GetConstantNameWide", c_void_p), - ("GetFieldNameWide", c_void_p), - ("IsManagedModule", c_void_p), - ("GetModuleByModuleName2", c_void_p), - ("GetModuleByModuleName2Wide", c_void_p), - ("GetModuleByOffset2", c_void_p), - ("AddSyntheticModule", c_void_p), - ("AddSyntheticModuleWide", c_void_p), - ("RemoveSyntheticModule", c_void_p), - ("GetCurrentScopeFrameIndex", ids_getcurrentscopeframeindex), - ("SetScopeFrameByIndex", ids_setscopeframebyindex), - ("SetScopeFromJitDebugInfo", c_void_p), - ("SetScopeFromStoredEvent", c_void_p), - ("OutputSymbolByOffset", c_void_p), - ("GetFunctionEntryByOffset", c_void_p), - ("GetFieldTypeAndOffset", c_void_p), - ("GetFieldTypeAndOffsetWide", c_void_p), - ("AddSyntheticSymbol", c_void_p), - ("AddSyntheticSymbolWide", c_void_p), - ("RemoveSyntheticSymbol", c_void_p), - ("GetSymbolEntriesByOffset", c_void_p), - ("GetSymbolEntriesByName", ids_getsymbolentriesbyname), - ("GetSymbolEntriesByNameWide", c_void_p), - ("GetSymbolEntryByToken", c_void_p), - ("GetSymbolEntryInformation", ids_getsymbolentryinformation), - ("GetSymbolEntryString", ids_getsymbolentrystring), - ("GetSymbolEntryStringWide", c_void_p), - ("GetSymbolEntryOffsetRegions", c_void_p), - ("GetSymbolEntryBySymbolEntry", c_void_p), - ("GetSourceEntriesByOffset", c_void_p), - ("GetSourceEntriesByLine", c_void_p), - ("GetSourceEntriesByLineWide", c_void_p), - ("GetSourceEntryString", c_void_p), - ("GetSourceEntryStringWide", c_void_p), - ("GetSourceEntryOffsetRegions", c_void_p), - ("GetsourceEntryBySourceEntry", c_void_p), - ("GetScopeEx", c_void_p), - ("SetScopeEx", c_void_p), - ("GetNameByInlineContext", ids_getnamebyinlinecontext), - ("GetNameByInlineContextWide", c_void_p), - ("GetLineByInlineContext", ids_getlinebyinlinecontext), - ("GetLineByInlineContextWide", c_void_p), - ("OutputSymbolByInlineContext", c_void_p), - ("GetCurrentScopeFrameIndexEx", c_void_p), - ("SetScopeFrameByIndexEx", c_void_p) - ] - -IDebugSymbols5._fields_ = [("lpVtbl", POINTER(IDebugSymbols5Vtbl))] - -SymbolId = namedtuple("SymbolId", ["ModuleBase", "Id"]) -SymbolEntry = namedtuple("SymbolEntry", ["ModuleBase", "Offset", "Id", "Arg64", "Size", "Flags", "TypeId", "NameSize", "Token", "Tag", "Arg32"]) -DebugModuleParams = namedtuple("DebugModuleParams", ["Base", "Size", "TimeDateStamp", "Checksum", "Flags", "SymbolType", "ImageNameSize", "ModuleNameSize", "LoadedImageNameSize", "SymbolFileNameSize", "MappedImageNameSize"]) - -class SymTags(IntEnum): - Null = 0 - Exe = 1 - SymTagFunction = 5 - -def make_debug_module_params(cdata): - fieldvalues = map(lambda y: getattr(cdata, y), DebugModuleParams._fields) - return DebugModuleParams(*fieldvalues) - -class Symbols(object): - def __init__(self, symbols): - self.ptr = symbols - self.symbols = symbols.contents - self.vt = self.symbols.lpVtbl.contents - # Keep some handy ulongs for passing into C methods. - self.ulong = c_ulong() - self.ulong64 = c_ulonglong() - - def GetCurrentScopeFrameIndex(self): - res = self.vt.GetCurrentScopeFrameIndex(self.symbols, byref(self.ulong)) - aborter(res, "GetCurrentScopeFrameIndex") - return self.ulong.value - - def SetScopeFrameByIndex(self, idx): - res = self.vt.SetScopeFrameByIndex(self.symbols, idx) - aborter(res, "SetScopeFrameByIndex", ignore=[E_EINVAL]) - return res != E_EINVAL - - def GetOffsetByName(self, name): - res = self.vt.GetOffsetByName(self.symbols, name.encode("ascii"), byref(self.ulong64)) - aborter(res, "GetOffsetByName {}".format(name)) - return self.ulong64.value - - def GetNearNameByOffset(self, addr): - ptr = create_string_buffer(256) - pulong = c_ulong() - disp = c_ulonglong() - # Zero arg -> "delta" indicating how many symbols to skip - res = self.vt.GetNearNameByOffset(self.symbols, addr, 0, ptr, 255, byref(pulong), byref(disp)) - if res == E_NOINTERFACE: - return "{noname}" - aborter(res, "GetNearNameByOffset") - ptr[255] = '\0'.encode("ascii") - return '{}+{}'.format(string_at(ptr).decode("ascii"), disp.value) - - def GetModuleByModuleName2(self, name): - # First zero arg -> module index to search from, second zero arg -> - # DEBUG_GETMOD_* flags, none of which we use. - res = self.vt.GetModuleByModuleName2(self.symbols, name, 0, 0, None, byref(self.ulong64)) - aborter(res, "GetModuleByModuleName2") - return self.ulong64.value - - def GetScopeSymbolGroup2(self): - retptr = POINTER(IDebugSymbolGroup2)() - res = self.vt.GetScopeSymbolGroup2(self.symbols, ScopeGroupFlags.DEBUG_SCOPE_GROUP_ALL, None, retptr) - aborter(res, "GetScopeSymbolGroup2") - return SymbolGroup(retptr) - - def GetSymbolEntryString(self, idx, module): - symid = DEBUG_MODULE_AND_ID() - symid.ModuleBase = module - symid.Id = idx - ptr = create_string_buffer(1024) - # Zero arg is the string index -- symbols can have multiple names, for now - # only support the first one. - res = self.vt.GetSymbolEntryString(self.symbols, symid, 0, ptr, 1023, byref(self.ulong)) - aborter(res, "GetSymbolEntryString") - return string_at(ptr).decode("ascii") - - def GetSymbolEntryInformation(self, module, theid): - symid = DEBUG_MODULE_AND_ID() - symentry = DEBUG_SYMBOL_ENTRY() - symid.ModuleBase = module - symid.Id = theid - res = self.vt.GetSymbolEntryInformation(self.symbols, symid, symentry) - aborter(res, "GetSymbolEntryInformation") - # Fetch fields into SymbolEntry object - fields = map(lambda x: getattr(symentry, x), SymbolEntry._fields) - return SymbolEntry(*fields) - - def GetSymbolEntriesByName(self, symstr): - # Initial query to find number of symbol entries - res = self.vt.GetSymbolEntriesByName(self.symbols, symstr.encode("ascii"), 0, None, 0, byref(self.ulong)) - aborter(res, "GetSymbolEntriesByName") - - # Build a buffer and query for 'length' entries - length = self.ulong.value - symrecs = (DEBUG_MODULE_AND_ID * length)() - # Zero arg -> flags, of which there are none defined. - res = self.vt.GetSymbolEntriesByName(self.symbols, symstr.encode("ascii"), 0, symrecs, length, byref(self.ulong)) - aborter(res, "GetSymbolEntriesByName") - - # Extract 'length' number of SymbolIds - length = self.ulong.value - def extract(x): - sym = symrecs[x] - return SymbolId(sym.ModuleBase, sym.Id) - return [extract(x) for x in range(length)] - - def GetSymbolPath(self): - # Query for length of buffer to allocate - res = self.vt.GetSymbolPath(self.symbols, None, 0, byref(self.ulong)) - aborter(res, "GetSymbolPath", ignore=[S_FALSE]) - - # Fetch 'length' length symbol path string - length = self.ulong.value - arr = create_string_buffer(length) - res = self.vt.GetSymbolPath(self.symbols, arr, length, byref(self.ulong)) - aborter(res, "GetSymbolPath") - - return string_at(arr).decode("ascii") - - def GetSourcePath(self): - # Query for length of buffer to allocate - res = self.vt.GetSourcePath(self.symbols, None, 0, byref(self.ulong)) - aborter(res, "GetSourcePath", ignore=[S_FALSE]) - - # Fetch a string of len 'length' - length = self.ulong.value - arr = create_string_buffer(length) - res = self.vt.GetSourcePath(self.symbols, arr, length, byref(self.ulong)) - aborter(res, "GetSourcePath") - - return string_at(arr).decode("ascii") - - def SetSourcePath(self, string): - res = self.vt.SetSourcePath(self.symbols, string.encode("ascii")) - aborter(res, "SetSourcePath") - return - - def GetModuleParameters(self, base): - self.ulong64.value = base - params = DEBUG_MODULE_PARAMETERS() - # Fetch one module params struct, starting at idx zero - res = self.vt.GetModuleParameters(self.symbols, 1, byref(self.ulong64), 0, byref(params)) - aborter(res, "GetModuleParameters") - return make_debug_module_params(params) - - def GetSymbolOptions(self): - res = self.vt.GetSymbolOptions(self.symbols, byref(self.ulong)) - aborter(res, "GetSymbolOptions") - return SymbolOptionFlags(self.ulong.value) - - def SetSymbolOptions(self, opts): - assert isinstance(opts, SymbolOptionFlags) - res = self.vt.SetSymbolOptions(self.symbols, opts.value) - aborter(res, "SetSymbolOptions") - return - - def GetLineByOffset(self, offs): - # Initial query for filename buffer size - res = self.vt.GetLineByOffset(self.symbols, offs, None, None, 0, byref(self.ulong), None) - if res == E_FAIL: - return None # Sometimes we just can't get line numbers, of course - aborter(res, "GetLineByOffset", ignore=[S_FALSE]) - - # Allocate filename buffer and query for line number too - filenamelen = self.ulong.value - text = create_string_buffer(filenamelen) - line = c_ulong() - res = self.vt.GetLineByOffset(self.symbols, offs, byref(line), text, filenamelen, byref(self.ulong), None) - aborter(res, "GetLineByOffset") - - return string_at(text).decode("ascii"), line.value - - def GetModuleNameString(self, whichname, base): - # Initial query for name string length - res = self.vt.GetModuleNameString(self.symbols, whichname, DEBUG_ANY_ID, base, None, 0, byref(self.ulong)) - aborter(res, "GetModuleNameString", ignore=[S_FALSE]) - - module_name_len = self.ulong.value - module_name = (c_char * module_name_len)() - res = self.vt.GetModuleNameString(self.symbols, whichname, DEBUG_ANY_ID, base, module_name, module_name_len, None) - aborter(res, "GetModuleNameString") - - return string_at(module_name).decode("ascii") - - def GetNameByInlineContext(self, pc, ctx): - # None args -> ignore output name size and displacement - buf = create_string_buffer(256) - res = self.vt.GetNameByInlineContext(self.symbols, pc, ctx, buf, 255, None, None) - aborter(res, "GetNameByInlineContext") - return string_at(buf).decode("ascii") - - def GetLineByInlineContext(self, pc, ctx): - # None args -> ignore output filename size and displacement - buf = create_string_buffer(256) - res = self.vt.GetLineByInlineContext(self.symbols, pc, ctx, byref(self.ulong), buf, 255, None, None) - aborter(res, "GetLineByInlineContext") - return string_at(buf).decode("ascii"), self.ulong.value - - def get_all_symbols(self): - main_module_name = self.get_exefile_module_name() - idnumbers = self.GetSymbolEntriesByName("{}!*".format(main_module_name)) - lst = [] - for symid in idnumbers: - s = self.GetSymbolEntryString(symid.Id, symid.ModuleBase) - symentry = self.GetSymbolEntryInformation(symid.ModuleBase, symid.Id) - lst.append((s, symentry)) - return lst - - def get_all_functions(self): - syms = self.get_all_symbols() - return [x for x in syms if x[1].Tag == SymTags.SymTagFunction] - - def get_all_modules(self): - params = DEBUG_MODULE_PARAMETERS() - idx = 0 - res = 0 - all_modules = [] - while res != E_EINVAL: - res = self.vt.GetModuleParameters(self.symbols, 1, None, idx, byref(params)) - aborter(res, "GetModuleParameters", ignore=[E_EINVAL]) - all_modules.append(make_debug_module_params(params)) - idx += 1 - return all_modules - - def get_exefile_module(self): - all_modules = self.get_all_modules() - reduce_func = lambda x, y: y if y.Flags & DebugModuleFlags.DEBUG_MODULE_EXE_MODULE else x - main_module = reduce(reduce_func, all_modules, None) - if main_module is None: - raise Exception("Couldn't find the exefile module") - return main_module - - def get_module_name(self, base): - return self.GetModuleNameString(DebugModuleNames.DEBUG_MODNAME_MODULE, base) - - def get_exefile_module_name(self): - return self.get_module_name(self.get_exefile_module().Base) diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/symgroup.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/symgroup.py deleted file mode 100644 index 2775af3279b..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/symgroup.py +++ /dev/null @@ -1,98 +0,0 @@ -# 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 collections import namedtuple -from ctypes import * -from functools import partial - -from .utils import * - -Symbol = namedtuple("Symbol", ["num", "name", "type", "value"]) - -class IDebugSymbolGroup2(Structure): - pass - -class IDebugSymbolGroup2Vtbl(Structure): - wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugSymbolGroup2)) - ids_getnumbersymbols = wrp(c_ulong_p) - ids_getsymbolname = wrp(c_ulong, c_char_p, c_ulong, c_ulong_p) - ids_getsymboltypename = wrp(c_ulong, c_char_p, c_ulong, c_ulong_p) - ids_getsymbolvaluetext = wrp(c_ulong, c_char_p, c_ulong, c_ulong_p) - _fields_ = [ - ("QueryInterface", c_void_p), - ("AddRef", c_void_p), - ("Release", c_void_p), - ("GetNumberSymbols", ids_getnumbersymbols), - ("AddSymbol", c_void_p), - ("RemoveSymbolByName", c_void_p), - ("RemoveSymbolByIndex", c_void_p), - ("GetSymbolName", ids_getsymbolname), - ("GetSymbolParameters", c_void_p), - ("ExpandSymbol", c_void_p), - ("OutputSymbols", c_void_p), - ("WriteSymbol", c_void_p), - ("OutputAsType", c_void_p), - ("AddSymbolWide", c_void_p), - ("RemoveSymbolByNameWide", c_void_p), - ("GetSymbolNameWide", c_void_p), - ("WritesymbolWide", c_void_p), - ("OutputAsTypeWide", c_void_p), - ("GetSymbolTypeName", ids_getsymboltypename), - ("GetSymbolTypeNameWide", c_void_p), - ("GetSymbolSize", c_void_p), - ("GetSymbolOffset", c_void_p), - ("GetSymbolRegister", c_void_p), - ("GetSymbolValueText", ids_getsymbolvaluetext), - ("GetSymbolValueTextWide", c_void_p), - ("GetSymbolEntryInformation", c_void_p) - ] - -IDebugSymbolGroup2._fields_ = [("lpVtbl", POINTER(IDebugSymbolGroup2Vtbl))] - -class SymbolGroup(object): - def __init__(self, symgroup): - self.symgroup = symgroup.contents - self.vt = self.symgroup.lpVtbl.contents - self.ulong = c_ulong() - - def GetNumberSymbols(self): - res = self.vt.GetNumberSymbols(self.symgroup, byref(self.ulong)) - aborter(res, "GetNumberSymbols") - return self.ulong.value - - def GetSymbolName(self, idx): - buf = create_string_buffer(256) - res = self.vt.GetSymbolName(self.symgroup, idx, buf, 255, byref(self.ulong)) - aborter(res, "GetSymbolName") - thelen = self.ulong.value - return string_at(buf).decode("ascii") - - def GetSymbolTypeName(self, idx): - buf = create_string_buffer(256) - res = self.vt.GetSymbolTypeName(self.symgroup, idx, buf, 255, byref(self.ulong)) - aborter(res, "GetSymbolTypeName") - thelen = self.ulong.value - return string_at(buf).decode("ascii") - - def GetSymbolValueText(self, idx, handleserror=False): - buf = create_string_buffer(256) - res = self.vt.GetSymbolValueText(self.symgroup, idx, buf, 255, byref(self.ulong)) - if res != 0 and handleserror: - return None - aborter(res, "GetSymbolTypeName") - thelen = self.ulong.value - return string_at(buf).decode("ascii") - - def get_symbol(self, idx): - name = self.GetSymbolName(idx) - thetype = self.GetSymbolTypeName(idx) - value = self.GetSymbolValueText(idx) - return Symbol(idx, name, thetype, value) - - def get_all_symbols(self): - num_syms = self.GetNumberSymbols() - return list(map(self.get_symbol, list(range(num_syms)))) diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/sysobjs.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/sysobjs.py deleted file mode 100644 index 0e9844a363b..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/sysobjs.py +++ /dev/null @@ -1,200 +0,0 @@ -# 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 * - -# UUID For SystemObjects4 interface. -DebugSystemObjects4IID = IID(0x489468e6, 0x7d0f, 0x4af5, IID_Data4_Type(0x87, 0xab, 0x25, 0x20, 0x74, 0x54, 0xd5, 0x53)) - -class IDebugSystemObjects4(Structure): - pass - -class IDebugSystemObjects4Vtbl(Structure): - wrp = partial(WINFUNCTYPE, c_long, POINTER(IDebugSystemObjects4)) - ids_getnumberprocesses = wrp(POINTER(c_ulong)) - ids_getprocessidsbyindex = wrp(c_ulong, c_ulong, c_ulong_p, c_ulong_p) - ids_setcurrentprocessid = wrp(c_ulong) - ids_getnumberthreads = wrp(c_ulong_p) - ids_getthreadidsbyindex = wrp(c_ulong, c_ulong, c_ulong_p, c_ulong_p) - ids_setcurrentthreadid = wrp(c_ulong) - _fields_ = [ - ("QueryInterface", c_void_p), - ("AddRef", c_void_p), - ("Release", c_void_p), - ("GetEventThread", c_void_p), - ("GetEventProcess", c_void_p), - ("GetCurrentThreadId", c_void_p), - ("SetCurrentThreadId", ids_setcurrentthreadid), - ("GetCurrentProcessId", c_void_p), - ("SetCurrentProcessId", ids_setcurrentprocessid), - ("GetNumberThreads", ids_getnumberthreads), - ("GetTotalNumberThreads", c_void_p), - ("GetThreadIdsByIndex", ids_getthreadidsbyindex), - ("GetThreadIdByProcessor", c_void_p), - ("GetCurrentThreadDataOffset", c_void_p), - ("GetThreadIdByDataOffset", c_void_p), - ("GetCurrentThreadTeb", c_void_p), - ("GetThreadIdByTeb", c_void_p), - ("GetCurrentThreadSystemId", c_void_p), - ("GetThreadIdBySystemId", c_void_p), - ("GetCurrentThreadHandle", c_void_p), - ("GetThreadIdByHandle", c_void_p), - ("GetNumberProcesses", ids_getnumberprocesses), - ("GetProcessIdsByIndex", ids_getprocessidsbyindex), - ("GetCurrentProcessDataOffset", c_void_p), - ("GetProcessIdByDataOffset", c_void_p), - ("GetCurrentProcessPeb", c_void_p), - ("GetProcessIdByPeb", c_void_p), - ("GetCurrentProcessSystemId", c_void_p), - ("GetProcessIdBySystemId", c_void_p), - ("GetCurrentProcessHandle", c_void_p), - ("GetProcessIdByHandle", c_void_p), - ("GetCurrentProcessExecutableName", c_void_p), - ("GetCurrentProcessUpTime", c_void_p), - ("GetImplicitThreadDataOffset", c_void_p), - ("SetImplicitThreadDataOffset", c_void_p), - ("GetImplicitProcessDataOffset", c_void_p), - ("SetImplicitProcessDataOffset", c_void_p), - ("GetEventSystem", c_void_p), - ("GetCurrentSystemId", c_void_p), - ("SetCurrentSystemId", c_void_p), - ("GetNumberSystems", c_void_p), - ("GetSystemIdsByIndex", c_void_p), - ("GetTotalNumberThreadsAndProcesses", c_void_p), - ("GetCurrentSystemServer", c_void_p), - ("GetSystemByServer", c_void_p), - ("GetCurrentSystemServerName", c_void_p), - ("GetCurrentProcessExecutableNameWide", c_void_p), - ("GetCurrentSystemServerNameWide", c_void_p) - ] - -IDebugSystemObjects4._fields_ = [("lpVtbl", POINTER(IDebugSystemObjects4Vtbl))] - -class SysObjects(object): - def __init__(self, sysobjects): - self.ptr = sysobjects - self.sysobjects = sysobjects.contents - self.vt = self.sysobjects.lpVtbl.contents - # Keep a handy ulong for passing into C methods. - self.ulong = c_ulong() - - def GetNumberSystems(self): - res = self.vt.GetNumberSystems(self.sysobjects, byref(self.ulong)) - aborter(res, "GetNumberSystems") - return self.ulong.value - - def GetNumberProcesses(self): - res = self.vt.GetNumberProcesses(self.sysobjects, byref(self.ulong)) - aborter(res, "GetNumberProcesses") - return self.ulong.value - - def GetNumberThreads(self): - res = self.vt.GetNumberThreads(self.sysobjects, byref(self.ulong)) - aborter(res, "GetNumberThreads") - return self.ulong.value - - def GetTotalNumberThreadsAndProcesses(self): - tthreads = c_ulong() - tprocs = c_ulong() - pulong3 = c_ulong() - res = self.vt.GetTotalNumberThreadsAndProcesses(self.sysobjects, byref(tthreads), byref(tprocs), byref(pulong3), byref(pulong3), byref(pulong3)) - aborter(res, "GettotalNumberThreadsAndProcesses") - return tthreads.value, tprocs.value - - def GetCurrentProcessId(self): - res = self.vt.GetCurrentProcessId(self.sysobjects, byref(self.ulong)) - aborter(res, "GetCurrentProcessId") - return self.ulong.value - - def SetCurrentProcessId(self, sysid): - res = self.vt.SetCurrentProcessId(self.sysobjects, sysid) - aborter(res, "SetCurrentProcessId") - return - - def GetCurrentThreadId(self): - res = self.vt.GetCurrentThreadId(self.sysobjects, byref(self.ulong)) - aborter(res, "GetCurrentThreadId") - return self.ulong.value - - def SetCurrentThreadId(self, sysid): - res = self.vt.SetCurrentThreadId(self.sysobjects, sysid) - aborter(res, "SetCurrentThreadId") - return - - def GetProcessIdsByIndex(self): - num_processes = self.GetNumberProcesses() - if num_processes == 0: - return [] - engineids = (c_ulong * num_processes)() - pids = (c_ulong * num_processes)() - for x in range(num_processes): - engineids[x] = DEBUG_ANY_ID - pids[x] = DEBUG_ANY_ID - res = self.vt.GetProcessIdsByIndex(self.sysobjects, 0, num_processes, engineids, pids) - aborter(res, "GetProcessIdsByIndex") - return list(zip(engineids, pids)) - - def GetThreadIdsByIndex(self): - num_threads = self.GetNumberThreads() - if num_threads == 0: - return [] - engineids = (c_ulong * num_threads)() - tids = (c_ulong * num_threads)() - for x in range(num_threads): - engineids[x] = DEBUG_ANY_ID - tids[x] = DEBUG_ANY_ID - # Zero -> start index - res = self.vt.GetThreadIdsByIndex(self.sysobjects, 0, num_threads, engineids, tids) - aborter(res, "GetThreadIdsByIndex") - return list(zip(engineids, tids)) - - def GetCurThreadHandle(self): - pulong64 = c_ulonglong() - res = self.vt.GetCurrentThreadHandle(self.sysobjects, byref(pulong64)) - aborter(res, "GetCurrentThreadHandle") - return pulong64.value - - def set_current_thread(self, pid, tid): - proc_sys_id = -1 - for x in self.GetProcessIdsByIndex(): - sysid, procid = x - if procid == pid: - proc_sys_id = sysid - - if proc_sys_id == -1: - raise Exception("Couldn't find designated PID {}".format(pid)) - - self.SetCurrentProcessId(proc_sys_id) - - thread_sys_id = -1 - for x in self.GetThreadIdsByIndex(): - sysid, threadid = x - if threadid == tid: - thread_sys_id = sysid - - if thread_sys_id == -1: - raise Exception("Couldn't find designated TID {}".format(tid)) - - self.SetCurrentThreadId(thread_sys_id) - return - - def print_current_procs_threads(self): - procs = [] - for x in self.GetProcessIdsByIndex(): - sysid, procid = x - procs.append(procid) - - threads = [] - for x in self.GetThreadIdsByIndex(): - sysid, threadid = x - threads.append(threadid) - - print("Current processes: {}".format(procs)) - print("Current threads: {}".format(threads)) diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/utils.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/utils.py deleted file mode 100644 index 0c9197aa1c9..00000000000 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/utils.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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 * - -# Error codes are negative when received by python, but are typically -# represented by unsigned hex elsewhere. Subtract 2^32 from the unsigned -# hex to produce negative error codes. -E_NOINTERFACE = 0x80004002 - 0x100000000 -E_FAIL = 0x80004005 - 0x100000000 -E_EINVAL = 0x80070057 - 0x100000000 -E_INTERNALEXCEPTION = 0x80040205 - 0x100000000 -S_FALSE = 1 - -# This doesn't fit into any convenient category -DEBUG_ANY_ID = 0xFFFFFFFF - -class WinError(Exception): - def __init__(self, msg, hstatus): - self.hstatus = hstatus - super(WinError, self).__init__(msg) - -def aborter(res, msg, ignore=[]): - if res != 0 and res not in ignore: - # Convert a negative error code to a positive unsigned one, which is - # now NTSTATUSes appear in documentation. - if res < 0: - res += 0x100000000 - msg = '{:08X} : {}'.format(res, msg) - raise WinError(msg, res) - -IID_Data4_Type = c_ubyte * 8 - -class IID(Structure): - _fields_ = [ - ("Data1", c_uint), - ("Data2", c_ushort), - ("Data3", c_ushort), - ("Data4", IID_Data4_Type) - ] - -c_ulong_p = POINTER(c_ulong) -c_ulong64_p = POINTER(c_ulonglong) |