@@ -39,19 +39,19 @@ class Debugger(object):
3939
4040 * Standard BP (int3)
4141 * Hardware-Exec BP (DrX)
42- * Memory BP (virtual_protect)"""
42+ * Memory BP (virtual_protect)
43+ """
4344
4445 def __init__ (self , target ):
4546 """``target`` must be a debuggable :class:`WinProcess`."""
4647 self ._init_dispatch_handlers ()
4748 self .target = target
4849 self .is_target_launched = False
49- #if not already_debuggable:
50- # winproxy.DebugActiveProcess(target.pid)
5150 self .processes = {}
5251 self .threads = {}
5352 self .current_process = None
5453 self .current_thread = None
54+ self .first_bp_encoutered = False
5555 # List of breakpoints
5656 self .breakpoints = {}
5757 self ._pending_breakpoints = {} #Breakpoints to put in new process / threads
@@ -497,6 +497,15 @@ def _handle_unknown_debug_event(self, debug_event):
497497
498498 def _handle_exception_breakpoint (self , exception , excp_addr ):
499499 excp_bitness = self .get_exception_bitness (exception )
500+ # Sub-method _do_setup() ?
501+ if not self .first_bp_encoutered :
502+ dbg_has_setup = not getattr (self .on_setup , "_abstract_on_setup_" , False )
503+ self .first_bp_encoutered = True
504+ if dbg_has_setup :
505+ with self .DisabledMemoryBreakpoint ():
506+ continue_flag = self .on_setup () # Handle single-step here ?
507+ # Check killed in action ?
508+ # What if setup + BP object()
500509 if excp_addr in self .breakpoints [self .current_process .pid ]:
501510 thread = self .current_thread
502511 if self .current_process .bitness == 32 and excp_bitness == 64 :
@@ -517,6 +526,8 @@ def _handle_exception_breakpoint(self, exception, excp_addr):
517526 # Setup BP if not suppressed
518527 self ._pass_breakpoint (excp_addr )
519528 return continue_flag
529+ if dbg_has_setup : # setup() was called on this BP-event: no on_exception()
530+ return continue_flag
520531 with self .DisabledMemoryBreakpoint ():
521532 return self .on_exception (exception )
522533
@@ -624,7 +635,7 @@ def _handle_exception(self, debug_event):
624635
625636 excp_code = exception .ExceptionRecord .ExceptionCode
626637 excp_addr = exception .ExceptionRecord .ExceptionAddress
627- if excp_code in [EXCEPTION_BREAKPOINT , STATUS_WX86_BREAKPOINT ] and excp_addr in self . breakpoints [ self . current_process . pid ] :
638+ if excp_code in [EXCEPTION_BREAKPOINT , STATUS_WX86_BREAKPOINT ]:
628639 return self ._handle_exception_breakpoint (exception , excp_addr )
629640 elif excp_code in [EXCEPTION_SINGLE_STEP , STATUS_WX86_SINGLE_STEP ]:
630641 return self ._handle_exception_singlestep (exception , excp_addr )
@@ -956,6 +967,24 @@ def get_exception_bitness(self, exc):
956967 return 64
957968
958969 # Public callback
970+ def on_setup (self ):
971+ """Called on the first breakpoint event occuring in the debugger.
972+ This callback allow to setup hook / interact with the debugee when ready:
973+
974+ - If :func:`on_setup` is overriden by a subclass it will be called and :func:`on_exception` will NOT be called for this event (first BP).
975+ - If :func:`on_setup` is not defined the first BP will trigger an :func:`on_exception`.
976+
977+ .. note::
978+
979+ see sample :ref:`sample_debugger_on_setup`
980+
981+ """
982+ return None
983+
984+ # Help detect if on_setup was override
985+ on_setup ._abstract_on_setup_ = True
986+
987+
959988 def on_exception (self , exception ):
960989 """Called on exception event other that known breakpoint or requested single step. ``exception`` is one of the following type:
961990
0 commit comments