1# DExTer : Debugging Experience Tester
2# ~~~~~~   ~         ~~         ~   ~~
3#
4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5# See https://llvm.org/LICENSE.txt for license information.
6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7
8from ctypes import *
9from enum import *
10from functools import partial
11
12from .utils import *
13
14class BreakpointTypes(IntEnum):
15  DEBUG_BREAKPOINT_CODE =   0
16  DEBUG_BREAKPOINT_DATA =   1
17  DEBUG_BREAKPOINT_TIME =   2
18  DEBUG_BREAKPOINT_INLINE = 3
19
20class BreakpointFlags(IntFlag):
21  DEBUG_BREAKPOINT_GO_ONLY =    0x00000001
22  DEBUG_BREAKPOINT_DEFERRED =   0x00000002
23  DEBUG_BREAKPOINT_ENABLED =    0x00000004
24  DEBUG_BREAKPOINT_ADDER_ONLY = 0x00000008
25  DEBUG_BREAKPOINT_ONE_SHOT =   0x00000010
26
27DebugBreakpoint2IID = IID(0x1b278d20, 0x79f2, 0x426e, IID_Data4_Type(0xa3, 0xf9, 0xc1, 0xdd, 0xf3, 0x75, 0xd4, 0x8e))
28
29class DebugBreakpoint2(Structure):
30  pass
31
32class DebugBreakpoint2Vtbl(Structure):
33  wrp = partial(WINFUNCTYPE, c_long, POINTER(DebugBreakpoint2))
34  idb_setoffset = wrp(c_ulonglong)
35  idb_setflags = wrp(c_ulong)
36  _fields_ = [
37      ("QueryInterface", c_void_p),
38      ("AddRef", c_void_p),
39      ("Release", c_void_p),
40      ("GetId", c_void_p),
41      ("GetType", c_void_p),
42      ("GetAdder", c_void_p),
43      ("GetFlags", c_void_p),
44      ("AddFlags", c_void_p),
45      ("RemoveFlags", c_void_p),
46      ("SetFlags", idb_setflags),
47      ("GetOffset", c_void_p),
48      ("SetOffset", idb_setoffset),
49      ("GetDataParameters", c_void_p),
50      ("SetDataParameters", c_void_p),
51      ("GetPassCount", c_void_p),
52      ("SetPassCount", c_void_p),
53      ("GetCurrentPassCount", c_void_p),
54      ("GetMatchThreadId", c_void_p),
55      ("SetMatchThreadId", c_void_p),
56      ("GetCommand", c_void_p),
57      ("SetCommand", c_void_p),
58      ("GetOffsetExpression", c_void_p),
59      ("SetOffsetExpression", c_void_p),
60      ("GetParameters", c_void_p),
61      ("GetCommandWide", c_void_p),
62      ("SetCommandWide", c_void_p),
63      ("GetOffsetExpressionWide", c_void_p),
64      ("SetOffsetExpressionWide", c_void_p)
65    ]
66
67DebugBreakpoint2._fields_ = [("lpVtbl", POINTER(DebugBreakpoint2Vtbl))]
68
69class Breakpoint(object):
70  def __init__(self, breakpoint):
71    self.breakpoint = breakpoint.contents
72    self.vt = self.breakpoint.lpVtbl.contents
73
74  def SetFlags(self, flags):
75    res = self.vt.SetFlags(self.breakpoint, flags)
76    aborter(res, "Breakpoint SetFlags")
77
78  def SetOffset(self, offs):
79    res = self.vt.SetOffset(self.breakpoint, offs)
80    aborter(res, "Breakpoint SetOffset")
81
82  def RemoveFlags(self, flags):
83    res = self.vt.RemoveFlags(self.breakpoint, flags)
84    aborter(res, "Breakpoint RemoveFlags")
85
86  def die(self):
87    self.breakpoint = None
88    self.vt = None
89