Package winappdbg :: Module debug
[hide private]
[frames] | no frames]

Source Code for Module winappdbg.debug

   1  #!~/.wine/drive_c/Python25/python.exe 
   2  # -*- coding: utf-8 -*- 
   3   
   4  # Copyright (c) 2009-2014, Mario Vilas 
   5  # All rights reserved. 
   6  # 
   7  # Redistribution and use in source and binary forms, with or without 
   8  # modification, are permitted provided that the following conditions are met: 
   9  # 
  10  #     * Redistributions of source code must retain the above copyright notice, 
  11  #       this list of conditions and the following disclaimer. 
  12  #     * Redistributions in binary form must reproduce the above copyright 
  13  #       notice,this list of conditions and the following disclaimer in the 
  14  #       documentation and/or other materials provided with the distribution. 
  15  #     * Neither the name of the copyright holder nor the names of its 
  16  #       contributors may be used to endorse or promote products derived from 
  17  #       this software without specific prior written permission. 
  18  # 
  19  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
  20  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  21  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  22  # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
  23  # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  24  # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  25  # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  26  # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  27  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  28  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  29  # POSSIBILITY OF SUCH DAMAGE. 
  30   
  31  """ 
  32  Debugging. 
  33   
  34  @group Debugging: 
  35      Debug 
  36   
  37  @group Warnings: 
  38      MixedBitsWarning 
  39  """ 
  40   
  41  __revision__ = "$Id: debug.py 1299 2013-12-20 09:30:55Z qvasimodo $" 
  42   
  43  __all__ = [ 'Debug', 'MixedBitsWarning' ] 
  44   
  45  import win32 
  46  from system import System 
  47  from process import Process 
  48  from thread import Thread 
  49  from module import Module 
  50  from window import Window 
  51  from breakpoint import _BreakpointContainer, CodeBreakpoint 
  52  from event import Event, EventHandler, EventDispatcher, EventFactory 
  53  from interactive import ConsoleDebugger 
  54   
  55  import warnings 
56 ##import traceback 57 58 #============================================================================== 59 60 # If you set this warning to be considered as an error, you can stop the 61 # debugger from attaching to 64-bit processes from a 32-bit Python VM and 62 # visceversa. 63 -class MixedBitsWarning (RuntimeWarning):
64 """ 65 This warning is issued when mixing 32 and 64 bit processes. 66 """
67
68 #============================================================================== 69 70 # TODO 71 # * Add memory read and write operations, similar to those in the Process 72 # class, but hiding the presence of the code breakpoints. 73 # * Add a method to get the memory map of a process, but hiding the presence 74 # of the page breakpoints. 75 # * Maybe the previous two features should be implemented at the Process class 76 # instead, but how to communicate with the Debug object without creating 77 # circular references? Perhaps the "overrides" could be set using private 78 # members (so users won't see them), but then there's the problem of the 79 # users being able to access the snapshot (i.e. clear it), which is why it's 80 # not such a great idea to use the snapshot to store data that really belongs 81 # to the Debug class. 82 83 -class Debug (EventDispatcher, _BreakpointContainer):
84 """ 85 The main debugger class. 86 87 @group Debugging: 88 interactive, attach, detach, detach_from_all, execv, execl, 89 kill, kill_all, 90 get_debugee_count, get_debugee_pids, 91 is_debugee, is_debugee_attached, is_debugee_started, 92 in_hostile_mode, 93 add_existing_session 94 95 @group Debugging loop: 96 loop, stop, next, wait, dispatch, cont 97 98 @undocumented: force_garbage_collection 99 100 @type system: L{System} 101 @ivar system: A System snapshot that is automatically updated for 102 processes being debugged. Processes not being debugged in this snapshot 103 may be outdated. 104 """ 105 106 # Automatically set to True the first time a Debug object is instanced. 107 _debug_static_init = False 108
109 - def __init__(self, eventHandler = None, bKillOnExit = False, 110 bHostileCode = False):
111 """ 112 Debugger object. 113 114 @type eventHandler: L{EventHandler} 115 @param eventHandler: 116 (Optional, recommended) Custom event handler object. 117 118 @type bKillOnExit: bool 119 @param bKillOnExit: (Optional) Kill on exit mode. 120 If C{True} debugged processes are killed when the debugger is 121 stopped. If C{False} when the debugger stops it detaches from all 122 debugged processes and leaves them running (default). 123 124 @type bHostileCode: bool 125 @param bHostileCode: (Optional) Hostile code mode. 126 Set to C{True} to take some basic precautions against anti-debug 127 tricks. Disabled by default. 128 129 @warn: When hostile mode is enabled, some things may not work as 130 expected! This is because the anti-anti debug tricks may disrupt 131 the behavior of the Win32 debugging APIs or WinAppDbg itself. 132 133 @note: The L{eventHandler} parameter may be any callable Python object 134 (for example a function, or an instance method). 135 However you'll probably find it more convenient to use an instance 136 of a subclass of L{EventHandler} here. 137 138 @raise WindowsError: Raises an exception on error. 139 """ 140 EventDispatcher.__init__(self, eventHandler) 141 _BreakpointContainer.__init__(self) 142 143 self.system = System() 144 self.lastEvent = None 145 self.__firstDebugee = True 146 self.__bKillOnExit = bKillOnExit 147 self.__bHostileCode = bHostileCode 148 self.__breakOnEP = set() # set of pids 149 self.__attachedDebugees = set() # set of pids 150 self.__startedDebugees = set() # set of pids 151 152 if not self._debug_static_init: 153 self._debug_static_init = True 154 155 # Request debug privileges for the current process. 156 # Only do this once, and only after instancing a Debug object, 157 # so passive debuggers don't get detected because of this. 158 self.system.request_debug_privileges(bIgnoreExceptions = False) 159 160 # Try to fix the symbol store path if it wasn't set. 161 # But don't enable symbol downloading by default, since it may 162 # degrade performance severely. 163 self.system.fix_symbol_store_path(remote = False, force = False)
164 165 ## # It's hard not to create circular references, 166 ## # and if we have a destructor, we can end up leaking everything. 167 ## # It's best to code the debugging loop properly to always 168 ## # stop the debugger before going out of scope. 169 ## def __del__(self): 170 ## self.stop() 171
172 - def __enter__(self):
173 """ 174 Compatibility with the "C{with}" Python statement. 175 """ 176 return self
177
178 - def __exit__(self, type, value, traceback):
179 """ 180 Compatibility with the "C{with}" Python statement. 181 """ 182 self.stop()
183
184 - def __len__(self):
185 """ 186 @rtype: int 187 @return: Number of processes being debugged. 188 """ 189 return self.get_debugee_count()
190 191 # TODO: maybe custom __bool__ to break out of loop() ? 192 # it already does work (because of __len__) but it'd be 193 # useful to do it from the event handler anyway 194 195 #------------------------------------------------------------------------------ 196
197 - def __setSystemKillOnExitMode(self):
198 # Make sure the default system behavior on detaching from processes 199 # versus killing them matches our preferences. This only affects the 200 # scenario where the Python VM dies unexpectedly without running all 201 # the finally clauses, or the user failed to either instance the Debug 202 # object inside a with block or call the stop() method before quitting. 203 if self.__firstDebugee: 204 try: 205 System.set_kill_on_exit_mode(self.__bKillOnExit) 206 self.__firstDebugee = False 207 except Exception: 208 pass
209
210 - def attach(self, dwProcessId):
211 """ 212 Attaches to an existing process for debugging. 213 214 @see: L{detach}, L{execv}, L{execl} 215 216 @type dwProcessId: int 217 @param dwProcessId: Global ID of a process to attach to. 218 219 @rtype: L{Process} 220 @return: A new Process object. Normally you don't need to use it now, 221 it's best to interact with the process from the event handler. 222 223 @raise WindowsError: Raises an exception on error. 224 Depending on the circumstances, the debugger may or may not have 225 attached to the target process. 226 """ 227 228 # Get the Process object from the snapshot, 229 # if missing create a new one. 230 try: 231 aProcess = self.system.get_process(dwProcessId) 232 except KeyError: 233 aProcess = Process(dwProcessId) 234 235 # Warn when mixing 32 and 64 bits. 236 # This also allows the user to stop attaching altogether, 237 # depending on how the warnings are configured. 238 if System.bits != aProcess.get_bits(): 239 msg = "Mixture of 32 and 64 bits is considered experimental." \ 240 " Use at your own risk!" 241 warnings.warn(msg, MixedBitsWarning) 242 243 # Attach to the process. 244 win32.DebugActiveProcess(dwProcessId) 245 246 # Add the new PID to the set of debugees. 247 self.__attachedDebugees.add(dwProcessId) 248 249 # Match the system kill-on-exit flag to our own. 250 self.__setSystemKillOnExitMode() 251 252 # If the Process object was not in the snapshot, add it now. 253 if not self.system.has_process(dwProcessId): 254 self.system._add_process(aProcess) 255 256 # Scan the process threads and loaded modules. 257 # This is prefered because the thread and library events do not 258 # properly give some information, like the filename for each module. 259 aProcess.scan_threads() 260 aProcess.scan_modules() 261 262 # Return the Process object, like the execv() and execl() methods. 263 return aProcess
264
265 - def execv(self, argv, **kwargs):
266 """ 267 Starts a new process for debugging. 268 269 This method uses a list of arguments. To use a command line string 270 instead, use L{execl}. 271 272 @see: L{attach}, L{detach} 273 274 @type argv: list( str... ) 275 @param argv: List of command line arguments to pass to the debugee. 276 The first element must be the debugee executable filename. 277 278 @type bBreakOnEntryPoint: bool 279 @keyword bBreakOnEntryPoint: C{True} to automatically set a breakpoint 280 at the program entry point. 281 282 @type bConsole: bool 283 @keyword bConsole: True to inherit the console of the debugger. 284 Defaults to C{False}. 285 286 @type bFollow: bool 287 @keyword bFollow: C{True} to automatically attach to child processes. 288 Defaults to C{False}. 289 290 @type bInheritHandles: bool 291 @keyword bInheritHandles: C{True} if the new process should inherit 292 it's parent process' handles. Defaults to C{False}. 293 294 @type bSuspended: bool 295 @keyword bSuspended: C{True} to suspend the main thread before any code 296 is executed in the debugee. Defaults to C{False}. 297 298 @keyword dwParentProcessId: C{None} or C{0} if the debugger process 299 should be the parent process (default), or a process ID to 300 forcefully set as the debugee's parent (only available for Windows 301 Vista and above). 302 303 In hostile mode, the default is not the debugger process but the 304 process ID for "explorer.exe". 305 306 @type iTrustLevel: int or None 307 @keyword iTrustLevel: Trust level. 308 Must be one of the following values: 309 - 0: B{No trust}. May not access certain resources, such as 310 cryptographic keys and credentials. Only available since 311 Windows XP and 2003, desktop editions. This is the default 312 in hostile mode. 313 - 1: B{Normal trust}. Run with the same privileges as a normal 314 user, that is, one that doesn't have the I{Administrator} or 315 I{Power User} user rights. Only available since Windows XP 316 and 2003, desktop editions. 317 - 2: B{Full trust}. Run with the exact same privileges as the 318 current user. This is the default in normal mode. 319 320 @type bAllowElevation: bool 321 @keyword bAllowElevation: C{True} to allow the child process to keep 322 UAC elevation, if the debugger itself is running elevated. C{False} 323 to ensure the child process doesn't run with elevation. Defaults to 324 C{True}. 325 326 This flag is only meaningful on Windows Vista and above, and if the 327 debugger itself is running with elevation. It can be used to make 328 sure the child processes don't run elevated as well. 329 330 This flag DOES NOT force an elevation prompt when the debugger is 331 not running with elevation. 332 333 Note that running the debugger with elevation (or the Python 334 interpreter at all for that matter) is not normally required. 335 You should only need to if the target program requires elevation 336 to work properly (for example if you try to debug an installer). 337 338 @rtype: L{Process} 339 @return: A new Process object. Normally you don't need to use it now, 340 it's best to interact with the process from the event handler. 341 342 @raise WindowsError: Raises an exception on error. 343 """ 344 if type(argv) in (str, unicode): 345 raise TypeError("Debug.execv expects a list, not a string") 346 lpCmdLine = self.system.argv_to_cmdline(argv) 347 return self.execl(lpCmdLine, **kwargs)
348
349 - def execl(self, lpCmdLine, **kwargs):
350 """ 351 Starts a new process for debugging. 352 353 This method uses a command line string. To use a list of arguments 354 instead, use L{execv}. 355 356 @see: L{attach}, L{detach} 357 358 @type lpCmdLine: str 359 @param lpCmdLine: Command line string to execute. 360 The first token must be the debugee executable filename. 361 Tokens with spaces must be enclosed in double quotes. 362 Tokens including double quote characters must be escaped with a 363 backslash. 364 365 @type bBreakOnEntryPoint: bool 366 @keyword bBreakOnEntryPoint: C{True} to automatically set a breakpoint 367 at the program entry point. Defaults to C{False}. 368 369 @type bConsole: bool 370 @keyword bConsole: True to inherit the console of the debugger. 371 Defaults to C{False}. 372 373 @type bFollow: bool 374 @keyword bFollow: C{True} to automatically attach to child processes. 375 Defaults to C{False}. 376 377 @type bInheritHandles: bool 378 @keyword bInheritHandles: C{True} if the new process should inherit 379 it's parent process' handles. Defaults to C{False}. 380 381 @type bSuspended: bool 382 @keyword bSuspended: C{True} to suspend the main thread before any code 383 is executed in the debugee. Defaults to C{False}. 384 385 @type dwParentProcessId: int or None 386 @keyword dwParentProcessId: C{None} or C{0} if the debugger process 387 should be the parent process (default), or a process ID to 388 forcefully set as the debugee's parent (only available for Windows 389 Vista and above). 390 391 In hostile mode, the default is not the debugger process but the 392 process ID for "explorer.exe". 393 394 @type iTrustLevel: int 395 @keyword iTrustLevel: Trust level. 396 Must be one of the following values: 397 - 0: B{No trust}. May not access certain resources, such as 398 cryptographic keys and credentials. Only available since 399 Windows XP and 2003, desktop editions. This is the default 400 in hostile mode. 401 - 1: B{Normal trust}. Run with the same privileges as a normal 402 user, that is, one that doesn't have the I{Administrator} or 403 I{Power User} user rights. Only available since Windows XP 404 and 2003, desktop editions. 405 - 2: B{Full trust}. Run with the exact same privileges as the 406 current user. This is the default in normal mode. 407 408 @type bAllowElevation: bool 409 @keyword bAllowElevation: C{True} to allow the child process to keep 410 UAC elevation, if the debugger itself is running elevated. C{False} 411 to ensure the child process doesn't run with elevation. Defaults to 412 C{True} in normal mode and C{False} in hostile mode. 413 414 This flag is only meaningful on Windows Vista and above, and if the 415 debugger itself is running with elevation. It can be used to make 416 sure the child processes don't run elevated as well. 417 418 This flag DOES NOT force an elevation prompt when the debugger is 419 not running with elevation. 420 421 Note that running the debugger with elevation (or the Python 422 interpreter at all for that matter) is not normally required. 423 You should only need to if the target program requires elevation 424 to work properly (for example if you try to debug an installer). 425 426 @rtype: L{Process} 427 @return: A new Process object. Normally you don't need to use it now, 428 it's best to interact with the process from the event handler. 429 430 @raise WindowsError: Raises an exception on error. 431 """ 432 if type(lpCmdLine) not in (str, unicode): 433 warnings.warn("Debug.execl expects a string") 434 435 # Set the "debug" flag to True. 436 kwargs['bDebug'] = True 437 438 # Pop the "break on entry point" flag. 439 bBreakOnEntryPoint = kwargs.pop('bBreakOnEntryPoint', False) 440 441 # Set the default trust level if requested. 442 if 'iTrustLevel' not in kwargs: 443 if self.__bHostileCode: 444 kwargs['iTrustLevel'] = 0 445 else: 446 kwargs['iTrustLevel'] = 2 447 448 # Set the default UAC elevation flag if requested. 449 if 'bAllowElevation' not in kwargs: 450 kwargs['bAllowElevation'] = not self.__bHostileCode 451 452 # In hostile mode the default parent process is explorer.exe. 453 # Only supported for Windows Vista and above. 454 if self.__bHostileCode and not kwargs.get('dwParentProcessId', None): 455 try: 456 vista_and_above = self.__vista_and_above 457 except AttributeError: 458 osi = win32.OSVERSIONINFOEXW() 459 osi.dwMajorVersion = 6 460 osi.dwMinorVersion = 0 461 osi.dwPlatformId = win32.VER_PLATFORM_WIN32_NT 462 mask = 0 463 mask = win32.VerSetConditionMask(mask, 464 win32.VER_MAJORVERSION, 465 win32.VER_GREATER_EQUAL) 466 mask = win32.VerSetConditionMask(mask, 467 win32.VER_MAJORVERSION, 468 win32.VER_GREATER_EQUAL) 469 mask = win32.VerSetConditionMask(mask, 470 win32.VER_PLATFORMID, 471 win32.VER_EQUAL) 472 vista_and_above = win32.VerifyVersionInfoW(osi, 473 win32.VER_MAJORVERSION | \ 474 win32.VER_MINORVERSION | \ 475 win32.VER_PLATFORMID, 476 mask) 477 self.__vista_and_above = vista_and_above 478 if vista_and_above: 479 dwParentProcessId = self.system.get_explorer_pid() 480 if dwParentProcessId: 481 kwargs['dwParentProcessId'] = dwParentProcessId 482 else: 483 msg = ("Failed to find \"explorer.exe\"!" 484 " Using the debugger as parent process.") 485 warnings.warn(msg, RuntimeWarning) 486 487 # Start the new process. 488 aProcess = None 489 try: 490 aProcess = self.system.start_process(lpCmdLine, **kwargs) 491 dwProcessId = aProcess.get_pid() 492 493 # Match the system kill-on-exit flag to our own. 494 self.__setSystemKillOnExitMode() 495 496 # Warn when mixing 32 and 64 bits. 497 # This also allows the user to stop attaching altogether, 498 # depending on how the warnings are configured. 499 if System.bits != aProcess.get_bits(): 500 msg = "Mixture of 32 and 64 bits is considered experimental." \ 501 " Use at your own risk!" 502 warnings.warn(msg, MixedBitsWarning) 503 504 # Add the new PID to the set of debugees. 505 self.__startedDebugees.add(dwProcessId) 506 507 # Add the new PID to the set of "break on EP" debugees if needed. 508 if bBreakOnEntryPoint: 509 self.__breakOnEP.add(dwProcessId) 510 511 # Return the Process object. 512 return aProcess 513 514 # On error kill the new process and raise an exception. 515 except: 516 if aProcess is not None: 517 try: 518 try: 519 self.__startedDebugees.remove(aProcess.get_pid()) 520 except KeyError: 521 pass 522 finally: 523 try: 524 try: 525 self.__breakOnEP.remove(aProcess.get_pid()) 526 except KeyError: 527 pass 528 finally: 529 try: 530 aProcess.kill() 531 except Exception: 532 pass 533 raise
534
535 - def add_existing_session(self, dwProcessId, bStarted = False):
536 """ 537 Use this method only when for some reason the debugger's been attached 538 to the target outside of WinAppDbg (for example when integrating with 539 other tools). 540 541 You don't normally need to call this method. Most users should call 542 L{attach}, L{execv} or L{execl} instead. 543 544 @type dwProcessId: int 545 @param dwProcessId: Global process ID. 546 547 @type bStarted: bool 548 @param bStarted: C{True} if the process was started by the debugger, 549 or C{False} if the process was attached to instead. 550 551 @raise WindowsError: The target process does not exist, is not attached 552 to the debugger anymore. 553 """ 554 555 # Register the process object with the snapshot. 556 if not self.system.has_process(dwProcessId): 557 aProcess = Process(dwProcessId) 558 self.system._add_process(aProcess) 559 else: 560 aProcess = self.system.get_process(dwProcessId) 561 562 # Test for debug privileges on the target process. 563 # Raises WindowsException on error. 564 aProcess.get_handle() 565 566 # Register the process ID with the debugger. 567 if bStarted: 568 self.__attachedDebugees.add(dwProcessId) 569 else: 570 self.__startedDebugees.add(dwProcessId) 571 572 # Match the system kill-on-exit flag to our own. 573 self.__setSystemKillOnExitMode() 574 575 # Scan the process threads and loaded modules. 576 # This is prefered because the thread and library events do not 577 # properly give some information, like the filename for each module. 578 aProcess.scan_threads() 579 aProcess.scan_modules()
580
581 - def __cleanup_process(self, dwProcessId, bIgnoreExceptions = False):
582 """ 583 Perform the necessary cleanup of a process about to be killed or 584 detached from. 585 586 This private method is called by L{kill} and L{detach}. 587 588 @type dwProcessId: int 589 @param dwProcessId: Global ID of a process to kill. 590 591 @type bIgnoreExceptions: bool 592 @param bIgnoreExceptions: C{True} to ignore any exceptions that may be 593 raised when killing the process. 594 595 @raise WindowsError: Raises an exception on error, unless 596 C{bIgnoreExceptions} is C{True}. 597 """ 598 # If the process is being debugged... 599 if self.is_debugee(dwProcessId): 600 601 # Make sure a Process object exists or the following calls fail. 602 if not self.system.has_process(dwProcessId): 603 aProcess = Process(dwProcessId) 604 try: 605 aProcess.get_handle() 606 except WindowsError: 607 pass # fails later on with more specific reason 608 self.system._add_process(aProcess) 609 610 # Erase all breakpoints in the process. 611 try: 612 self.erase_process_breakpoints(dwProcessId) 613 except Exception, e: 614 if not bIgnoreExceptions: 615 raise 616 warnings.warn(str(e), RuntimeWarning) 617 618 # Stop tracing all threads in the process. 619 try: 620 self.stop_tracing_process(dwProcessId) 621 except Exception, e: 622 if not bIgnoreExceptions: 623 raise 624 warnings.warn(str(e), RuntimeWarning) 625 626 # The process is no longer a debugee. 627 try: 628 if dwProcessId in self.__attachedDebugees: 629 self.__attachedDebugees.remove(dwProcessId) 630 if dwProcessId in self.__startedDebugees: 631 self.__startedDebugees.remove(dwProcessId) 632 except Exception, e: 633 if not bIgnoreExceptions: 634 raise 635 warnings.warn(str(e), RuntimeWarning) 636 637 # Clear and remove the process from the snapshot. 638 # If the user wants to do something with it after detaching 639 # a new Process instance should be created. 640 try: 641 if self.system.has_process(dwProcessId): 642 try: 643 self.system.get_process(dwProcessId).clear() 644 finally: 645 self.system._del_process(dwProcessId) 646 except Exception, e: 647 if not bIgnoreExceptions: 648 raise 649 warnings.warn(str(e), RuntimeWarning) 650 651 # If the last debugging event is related to this process, forget it. 652 try: 653 if self.lastEvent and self.lastEvent.get_pid() == dwProcessId: 654 self.lastEvent = None 655 except Exception, e: 656 if not bIgnoreExceptions: 657 raise 658 warnings.warn(str(e), RuntimeWarning)
659
660 - def kill(self, dwProcessId, bIgnoreExceptions = False):
661 """ 662 Kills a process currently being debugged. 663 664 @see: L{detach} 665 666 @type dwProcessId: int 667 @param dwProcessId: Global ID of a process to kill. 668 669 @type bIgnoreExceptions: bool 670 @param bIgnoreExceptions: C{True} to ignore any exceptions that may be 671 raised when killing the process. 672 673 @raise WindowsError: Raises an exception on error, unless 674 C{bIgnoreExceptions} is C{True}. 675 """ 676 677 # Keep a reference to the process. We'll need it later. 678 try: 679 aProcess = self.system.get_process(dwProcessId) 680 except KeyError: 681 aProcess = Process(dwProcessId) 682 683 # Cleanup all data referring to the process. 684 self.__cleanup_process(dwProcessId, 685 bIgnoreExceptions = bIgnoreExceptions) 686 687 # Kill the process. 688 try: 689 try: 690 if self.is_debugee(dwProcessId): 691 try: 692 if aProcess.is_alive(): 693 aProcess.suspend() 694 finally: 695 self.detach(dwProcessId, 696 bIgnoreExceptions = bIgnoreExceptions) 697 finally: 698 aProcess.kill() 699 except Exception, e: 700 if not bIgnoreExceptions: 701 raise 702 warnings.warn(str(e), RuntimeWarning) 703 704 # Cleanup what remains of the process data. 705 try: 706 aProcess.clear() 707 except Exception, e: 708 if not bIgnoreExceptions: 709 raise 710 warnings.warn(str(e), RuntimeWarning)
711
712 - def kill_all(self, bIgnoreExceptions = False):
713 """ 714 Kills from all processes currently being debugged. 715 716 @type bIgnoreExceptions: bool 717 @param bIgnoreExceptions: C{True} to ignore any exceptions that may be 718 raised when killing each process. C{False} to stop and raise an 719 exception when encountering an error. 720 721 @raise WindowsError: Raises an exception on error, unless 722 C{bIgnoreExceptions} is C{True}. 723 """ 724 for pid in self.get_debugee_pids(): 725 self.kill(pid, bIgnoreExceptions = bIgnoreExceptions)
726
727 - def detach(self, dwProcessId, bIgnoreExceptions = False):
728 """ 729 Detaches from a process currently being debugged. 730 731 @note: On Windows 2000 and below the process is killed. 732 733 @see: L{attach}, L{detach_from_all} 734 735 @type dwProcessId: int 736 @param dwProcessId: Global ID of a process to detach from. 737 738 @type bIgnoreExceptions: bool 739 @param bIgnoreExceptions: C{True} to ignore any exceptions that may be 740 raised when detaching. C{False} to stop and raise an exception when 741 encountering an error. 742 743 @raise WindowsError: Raises an exception on error, unless 744 C{bIgnoreExceptions} is C{True}. 745 """ 746 747 # Keep a reference to the process. We'll need it later. 748 try: 749 aProcess = self.system.get_process(dwProcessId) 750 except KeyError: 751 aProcess = Process(dwProcessId) 752 753 # Determine if there is support for detaching. 754 # This check should only fail on Windows 2000 and older. 755 try: 756 win32.DebugActiveProcessStop 757 can_detach = True 758 except AttributeError: 759 can_detach = False 760 761 # Continue the last event before detaching. 762 # XXX not sure about this... 763 try: 764 if can_detach and self.lastEvent and \ 765 self.lastEvent.get_pid() == dwProcessId: 766 self.cont(self.lastEvent) 767 except Exception, e: 768 if not bIgnoreExceptions: 769 raise 770 warnings.warn(str(e), RuntimeWarning) 771 772 # Cleanup all data referring to the process. 773 self.__cleanup_process(dwProcessId, 774 bIgnoreExceptions = bIgnoreExceptions) 775 776 try: 777 # Detach from the process. 778 # On Windows 2000 and before, kill the process. 779 if can_detach: 780 try: 781 win32.DebugActiveProcessStop(dwProcessId) 782 except Exception, e: 783 if not bIgnoreExceptions: 784 raise 785 warnings.warn(str(e), RuntimeWarning) 786 else: 787 try: 788 aProcess.kill() 789 except Exception, e: 790 if not bIgnoreExceptions: 791 raise 792 warnings.warn(str(e), RuntimeWarning) 793 794 finally: 795 796 # Cleanup what remains of the process data. 797 aProcess.clear()
798
799 - def detach_from_all(self, bIgnoreExceptions = False):
800 """ 801 Detaches from all processes currently being debugged. 802 803 @note: To better handle last debugging event, call L{stop} instead. 804 805 @type bIgnoreExceptions: bool 806 @param bIgnoreExceptions: C{True} to ignore any exceptions that may be 807 raised when detaching. 808 809 @raise WindowsError: Raises an exception on error, unless 810 C{bIgnoreExceptions} is C{True}. 811 """ 812 for pid in self.get_debugee_pids(): 813 self.detach(pid, bIgnoreExceptions = bIgnoreExceptions)
814 815 #------------------------------------------------------------------------------ 816
817 - def wait(self, dwMilliseconds = None):
818 """ 819 Waits for the next debug event. 820 821 @see: L{cont}, L{dispatch}, L{loop} 822 823 @type dwMilliseconds: int 824 @param dwMilliseconds: (Optional) Timeout in milliseconds. 825 Use C{INFINITE} or C{None} for no timeout. 826 827 @rtype: L{Event} 828 @return: An event that occured in one of the debugees. 829 830 @raise WindowsError: Raises an exception on error. 831 If no target processes are left to debug, 832 the error code is L{win32.ERROR_INVALID_HANDLE}. 833 """ 834 835 # Wait for the next debug event. 836 raw = win32.WaitForDebugEvent(dwMilliseconds) 837 event = EventFactory.get(self, raw) 838 839 # Remember it. 840 self.lastEvent = event 841 842 # Return it. 843 return event
844
845 - def dispatch(self, event = None):
846 """ 847 Calls the debug event notify callbacks. 848 849 @see: L{cont}, L{loop}, L{wait} 850 851 @type event: L{Event} 852 @param event: (Optional) Event object returned by L{wait}. 853 854 @raise WindowsError: Raises an exception on error. 855 """ 856 857 # If no event object was given, use the last event. 858 if event is None: 859 event = self.lastEvent 860 861 # Ignore dummy events. 862 if not event: 863 return 864 865 # Determine the default behaviour for this event. 866 # XXX HACK 867 # Some undocumented flags are used, but as far as I know in those 868 # versions of Windows that don't support them they should behave 869 # like DGB_CONTINUE. 870 871 code = event.get_event_code() 872 if code == win32.EXCEPTION_DEBUG_EVENT: 873 874 # At this point, by default some exception types are swallowed by 875 # the debugger, because we don't know yet if it was caused by the 876 # debugger itself or the debugged process. 877 # 878 # Later on (see breakpoint.py) if we determined the exception was 879 # not caused directly by the debugger itself, we set the default 880 # back to passing the exception to the debugee. 881 # 882 # The "invalid handle" exception is also swallowed by the debugger 883 # because it's not normally generated by the debugee. But in 884 # hostile mode we want to pass it to the debugee, as it may be the 885 # result of an anti-debug trick. In that case it's best to disable 886 # bad handles detection with Microsoft's gflags.exe utility. See: 887 # http://msdn.microsoft.com/en-us/library/windows/hardware/ff549557(v=vs.85).aspx 888 889 exc_code = event.get_exception_code() 890 if exc_code in ( 891 win32.EXCEPTION_BREAKPOINT, 892 win32.EXCEPTION_WX86_BREAKPOINT, 893 win32.EXCEPTION_SINGLE_STEP, 894 win32.EXCEPTION_GUARD_PAGE, 895 ): 896 event.continueStatus = win32.DBG_CONTINUE 897 elif exc_code == win32.EXCEPTION_INVALID_HANDLE: 898 if self.__bHostileCode: 899 event.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED 900 else: 901 event.continueStatus = win32.DBG_CONTINUE 902 else: 903 event.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED 904 905 elif code == win32.RIP_EVENT and \ 906 event.get_rip_type() == win32.SLE_ERROR: 907 908 # RIP events that signal fatal events should kill the process. 909 event.continueStatus = win32.DBG_TERMINATE_PROCESS 910 911 else: 912 913 # Other events need this continue code. 914 # Sometimes other codes can be used and are ignored, sometimes not. 915 # For example, when using the DBG_EXCEPTION_NOT_HANDLED code, 916 # debug strings are sent twice (!) 917 event.continueStatus = win32.DBG_CONTINUE 918 919 # Dispatch the debug event. 920 return EventDispatcher.dispatch(self, event)
921
922 - def cont(self, event = None):
923 """ 924 Resumes execution after processing a debug event. 925 926 @see: dispatch(), loop(), wait() 927 928 @type event: L{Event} 929 @param event: (Optional) Event object returned by L{wait}. 930 931 @raise WindowsError: Raises an exception on error. 932 """ 933 934 # If no event object was given, use the last event. 935 if event is None: 936 event = self.lastEvent 937 938 # Ignore dummy events. 939 if not event: 940 return 941 942 # Get the event continue status information. 943 dwProcessId = event.get_pid() 944 dwThreadId = event.get_tid() 945 dwContinueStatus = event.continueStatus 946 947 # Check if the process is still being debugged. 948 if self.is_debugee(dwProcessId): 949 950 # Try to flush the instruction cache. 951 try: 952 if self.system.has_process(dwProcessId): 953 aProcess = self.system.get_process(dwProcessId) 954 else: 955 aProcess = Process(dwProcessId) 956 aProcess.flush_instruction_cache() 957 except WindowsError: 958 pass 959 960 # XXX TODO 961 # 962 # Try to execute the UnhandledExceptionFilter for second chance 963 # exceptions, at least when in hostile mode (in normal mode it 964 # would be breaking compatibility, as users may actually expect 965 # second chance exceptions to be raised again). 966 # 967 # Reportedly in Windows 7 (maybe in Vista too) this seems to be 968 # happening already. In XP and below the UnhandledExceptionFilter 969 # was never called for processes being debugged. 970 971 # Continue execution of the debugee. 972 win32.ContinueDebugEvent(dwProcessId, dwThreadId, dwContinueStatus) 973 974 # If the event is the last event, forget it. 975 if event == self.lastEvent: 976 self.lastEvent = None
977
978 - def stop(self, bIgnoreExceptions = True):
979 """ 980 Stops debugging all processes. 981 982 If the kill on exit mode is on, debugged processes are killed when the 983 debugger is stopped. Otherwise when the debugger stops it detaches from 984 all debugged processes and leaves them running (default). For more 985 details see: L{__init__} 986 987 @note: This method is better than L{detach_from_all} because it can 988 gracefully handle the last debugging event before detaching. 989 990 @type bIgnoreExceptions: bool 991 @param bIgnoreExceptions: C{True} to ignore any exceptions that may be 992 raised when detaching. 993 """ 994 995 # Determine if we have a last debug event that we need to continue. 996 try: 997 event = self.lastEvent 998 has_event = bool(event) 999 except Exception, e: 1000 if not bIgnoreExceptions: 1001 raise 1002 warnings.warn(str(e), RuntimeWarning) 1003 has_event = False 1004 1005 # If we do... 1006 if has_event: 1007 1008 # Disable all breakpoints in the process before resuming execution. 1009 try: 1010 pid = event.get_pid() 1011 self.disable_process_breakpoints(pid) 1012 except Exception, e: 1013 if not bIgnoreExceptions: 1014 raise 1015 warnings.warn(str(e), RuntimeWarning) 1016 1017 # Disable all breakpoints in the thread before resuming execution. 1018 try: 1019 tid = event.get_tid() 1020 self.disable_thread_breakpoints(tid) 1021 except Exception, e: 1022 if not bIgnoreExceptions: 1023 raise 1024 warnings.warn(str(e), RuntimeWarning) 1025 1026 # Resume execution. 1027 try: 1028 event.continueDebugEvent = win32.DBG_CONTINUE 1029 self.cont(event) 1030 except Exception, e: 1031 if not bIgnoreExceptions: 1032 raise 1033 warnings.warn(str(e), RuntimeWarning) 1034 1035 # Detach from or kill all debuggees. 1036 try: 1037 if self.__bKillOnExit: 1038 self.kill_all(bIgnoreExceptions) 1039 else: 1040 self.detach_from_all(bIgnoreExceptions) 1041 except Exception, e: 1042 if not bIgnoreExceptions: 1043 raise 1044 warnings.warn(str(e), RuntimeWarning) 1045 1046 # Cleanup the process snapshots. 1047 try: 1048 self.system.clear() 1049 except Exception, e: 1050 if not bIgnoreExceptions: 1051 raise 1052 warnings.warn(str(e), RuntimeWarning) 1053 1054 # Close all Win32 handles the Python garbage collector failed to close. 1055 self.force_garbage_collection(bIgnoreExceptions)
1056
1057 - def next(self):
1058 """ 1059 Handles the next debug event. 1060 1061 @see: L{cont}, L{dispatch}, L{wait}, L{stop} 1062 1063 @raise WindowsError: Raises an exception on error. 1064 1065 If the wait operation causes an error, debugging is stopped 1066 (meaning all debugees are either killed or detached from). 1067 1068 If the event dispatching causes an error, the event is still 1069 continued before returning. This may happen, for example, if the 1070 event handler raises an exception nobody catches. 1071 """ 1072 try: 1073 event = self.wait() 1074 except Exception: 1075 self.stop() 1076 raise 1077 try: 1078 self.dispatch() 1079 finally: 1080 self.cont()
1081
1082 - def loop(self):
1083 """ 1084 Simple debugging loop. 1085 1086 This debugging loop is meant to be useful for most simple scripts. 1087 It iterates as long as there is at least one debugee, or an exception 1088 is raised. Multiple calls are allowed. 1089 1090 This is a trivial example script:: 1091 import sys 1092 debug = Debug() 1093 try: 1094 debug.execv( sys.argv [ 1 : ] ) 1095 debug.loop() 1096 finally: 1097 debug.stop() 1098 1099 @see: L{next}, L{stop} 1100 1101 U{http://msdn.microsoft.com/en-us/library/ms681675(VS.85).aspx} 1102 1103 @raise WindowsError: Raises an exception on error. 1104 1105 If the wait operation causes an error, debugging is stopped 1106 (meaning all debugees are either killed or detached from). 1107 1108 If the event dispatching causes an error, the event is still 1109 continued before returning. This may happen, for example, if the 1110 event handler raises an exception nobody catches. 1111 """ 1112 while self: 1113 self.next()
1114
1115 - def get_debugee_count(self):
1116 """ 1117 @rtype: int 1118 @return: Number of processes being debugged. 1119 """ 1120 return len(self.__attachedDebugees) + len(self.__startedDebugees)
1121
1122 - def get_debugee_pids(self):
1123 """ 1124 @rtype: list( int... ) 1125 @return: Global IDs of processes being debugged. 1126 """ 1127 return list(self.__attachedDebugees) + list(self.__startedDebugees)
1128
1129 - def is_debugee(self, dwProcessId):
1130 """ 1131 Determine if the debugger is debugging the given process. 1132 1133 @see: L{is_debugee_attached}, L{is_debugee_started} 1134 1135 @type dwProcessId: int 1136 @param dwProcessId: Process global ID. 1137 1138 @rtype: bool 1139 @return: C{True} if the given process is being debugged 1140 by this L{Debug} instance. 1141 """ 1142 return self.is_debugee_attached(dwProcessId) or \ 1143 self.is_debugee_started(dwProcessId)
1144
1145 - def is_debugee_started(self, dwProcessId):
1146 """ 1147 Determine if the given process was started by the debugger. 1148 1149 @see: L{is_debugee}, L{is_debugee_attached} 1150 1151 @type dwProcessId: int 1152 @param dwProcessId: Process global ID. 1153 1154 @rtype: bool 1155 @return: C{True} if the given process was started for debugging by this 1156 L{Debug} instance. 1157 """ 1158 return dwProcessId in self.__startedDebugees
1159
1160 - def is_debugee_attached(self, dwProcessId):
1161 """ 1162 Determine if the debugger is attached to the given process. 1163 1164 @see: L{is_debugee}, L{is_debugee_started} 1165 1166 @type dwProcessId: int 1167 @param dwProcessId: Process global ID. 1168 1169 @rtype: bool 1170 @return: C{True} if the given process is attached to this 1171 L{Debug} instance. 1172 """ 1173 return dwProcessId in self.__attachedDebugees
1174
1175 - def in_hostile_mode(self):
1176 """ 1177 Determine if we're in hostile mode (anti-anti-debug). 1178 1179 @rtype: bool 1180 @return: C{True} if this C{Debug} instance was started in hostile mode, 1181 C{False} otherwise. 1182 """ 1183 return self.__bHostileCode
1184 1185 #------------------------------------------------------------------------------ 1186
1187 - def interactive(self, bConfirmQuit = True, bShowBanner = True):
1188 """ 1189 Start an interactive debugging session. 1190 1191 @type bConfirmQuit: bool 1192 @param bConfirmQuit: Set to C{True} to ask the user for confirmation 1193 before closing the session, C{False} otherwise. 1194 1195 @type bShowBanner: bool 1196 @param bShowBanner: Set to C{True} to show a banner before entering 1197 the session and after leaving it, C{False} otherwise. 1198 1199 @warn: This will temporarily disable the user-defined event handler! 1200 1201 This method returns when the user closes the session. 1202 """ 1203 print 1204 print "-" * 79 1205 print "Interactive debugging session started." 1206 print "Use the \"help\" command to list all available commands." 1207 print "Use the \"quit\" command to close this session." 1208 print "-" * 79 1209 if self.lastEvent is None: 1210 print 1211 console = ConsoleDebugger() 1212 console.confirm_quit = bConfirmQuit 1213 console.load_history() 1214 try: 1215 console.start_using_debugger(self) 1216 console.loop() 1217 finally: 1218 console.stop_using_debugger() 1219 console.save_history() 1220 print 1221 print "-" * 79 1222 print "Interactive debugging session closed." 1223 print "-" * 79 1224 print
1225 1226 #------------------------------------------------------------------------------ 1227 1228 @staticmethod
1229 - def force_garbage_collection(bIgnoreExceptions = True):
1230 """ 1231 Close all Win32 handles the Python garbage collector failed to close. 1232 1233 @type bIgnoreExceptions: bool 1234 @param bIgnoreExceptions: C{True} to ignore any exceptions that may be 1235 raised when detaching. 1236 """ 1237 try: 1238 import gc 1239 gc.collect() 1240 bRecollect = False 1241 for obj in list(gc.garbage): 1242 try: 1243 if isinstance(obj, win32.Handle): 1244 obj.close() 1245 elif isinstance(obj, Event): 1246 obj.debug = None 1247 elif isinstance(obj, Process): 1248 obj.clear() 1249 elif isinstance(obj, Thread): 1250 obj.set_process(None) 1251 obj.clear() 1252 elif isinstance(obj, Module): 1253 obj.set_process(None) 1254 elif isinstance(obj, Window): 1255 obj.set_process(None) 1256 else: 1257 continue 1258 gc.garbage.remove(obj) 1259 del obj 1260 bRecollect = True 1261 except Exception, e: 1262 if not bIgnoreExceptions: 1263 raise 1264 warnings.warn(str(e), RuntimeWarning) 1265 if bRecollect: 1266 gc.collect() 1267 except Exception, e: 1268 if not bIgnoreExceptions: 1269 raise 1270 warnings.warn(str(e), RuntimeWarning)
1271 1272 #------------------------------------------------------------------------------ 1273
1274 - def _notify_create_process(self, event):
1275 """ 1276 Notify the creation of a new process. 1277 1278 @warning: This method is meant to be used internally by the debugger. 1279 1280 @type event: L{CreateProcessEvent} 1281 @param event: Create process event. 1282 1283 @rtype: bool 1284 @return: C{True} to call the user-defined handle, C{False} otherwise. 1285 """ 1286 dwProcessId = event.get_pid() 1287 if dwProcessId not in self.__attachedDebugees: 1288 if dwProcessId not in self.__startedDebugees: 1289 self.__startedDebugees.add(dwProcessId) 1290 1291 retval = self.system._notify_create_process(event) 1292 1293 # Set a breakpoint on the program's entry point if requested. 1294 # Try not to use the Event object's entry point value, as in some cases 1295 # it may be wrong. See: http://pferrie.host22.com/misc/lowlevel3.htm 1296 if dwProcessId in self.__breakOnEP: 1297 try: 1298 lpEntryPoint = event.get_process().get_entry_point() 1299 except Exception: 1300 lpEntryPoint = event.get_start_address() 1301 1302 # It'd be best to use a hardware breakpoint instead, at least in 1303 # hostile mode. But since the main thread's context gets smashed 1304 # by the loader, I haven't found a way to make it work yet. 1305 self.break_at(dwProcessId, lpEntryPoint) 1306 1307 # Defeat isDebuggerPresent by patching PEB->BeingDebugged. 1308 # When we do this, some debugging APIs cease to work as expected. 1309 # For example, the system breakpoint isn't hit when we attach. 1310 # For that reason we need to define a code breakpoint at the 1311 # code location where a new thread is spawned by the debugging 1312 # APIs, ntdll!DbgUiRemoteBreakin. 1313 if self.__bHostileCode: 1314 aProcess = event.get_process() 1315 try: 1316 hProcess = aProcess.get_handle(win32.PROCESS_QUERY_INFORMATION) 1317 pbi = win32.NtQueryInformationProcess( 1318 hProcess, win32.ProcessBasicInformation) 1319 ptr = pbi.PebBaseAddress + 2 1320 if aProcess.peek(ptr, 1) == '\x01': 1321 aProcess.poke(ptr, '\x00') 1322 except WindowsError, e: 1323 warnings.warn( 1324 "Cannot patch PEB->BeingDebugged, reason: %s" % e.strerror) 1325 1326 return retval
1327
1328 - def _notify_create_thread(self, event):
1329 """ 1330 Notify the creation of a new thread. 1331 1332 @warning: This method is meant to be used internally by the debugger. 1333 1334 @type event: L{CreateThreadEvent} 1335 @param event: Create thread event. 1336 1337 @rtype: bool 1338 @return: C{True} to call the user-defined handle, C{False} otherwise. 1339 """ 1340 return event.get_process()._notify_create_thread(event)
1341
1342 - def _notify_load_dll(self, event):
1343 """ 1344 Notify the load of a new module. 1345 1346 @warning: This method is meant to be used internally by the debugger. 1347 1348 @type event: L{LoadDLLEvent} 1349 @param event: Load DLL event. 1350 1351 @rtype: bool 1352 @return: C{True} to call the user-defined handle, C{False} otherwise. 1353 """ 1354 1355 # Pass the event to the breakpoint container. 1356 bCallHandler = _BreakpointContainer._notify_load_dll(self, event) 1357 1358 # Get the process where the DLL was loaded. 1359 aProcess = event.get_process() 1360 1361 # Pass the event to the process. 1362 bCallHandler = aProcess._notify_load_dll(event) and bCallHandler 1363 1364 # Anti-anti-debugging tricks on ntdll.dll. 1365 if self.__bHostileCode: 1366 aModule = event.get_module() 1367 if aModule.match_name('ntdll.dll'): 1368 1369 # Since we've overwritten the PEB to hide 1370 # ourselves, we no longer have the system 1371 # breakpoint when attaching to the process. 1372 # Set a breakpoint at ntdll!DbgUiRemoteBreakin 1373 # instead (that's where the debug API spawns 1374 # it's auxiliary threads). This also defeats 1375 # a simple anti-debugging trick: the hostile 1376 # process could have overwritten the int3 1377 # instruction at the system breakpoint. 1378 self.break_at(aProcess.get_pid(), 1379 aProcess.resolve_label('ntdll!DbgUiRemoteBreakin')) 1380 1381 return bCallHandler
1382
1383 - def _notify_exit_process(self, event):
1384 """ 1385 Notify the termination of a process. 1386 1387 @warning: This method is meant to be used internally by the debugger. 1388 1389 @type event: L{ExitProcessEvent} 1390 @param event: Exit process event. 1391 1392 @rtype: bool 1393 @return: C{True} to call the user-defined handle, C{False} otherwise. 1394 """ 1395 bCallHandler1 = _BreakpointContainer._notify_exit_process(self, event) 1396 bCallHandler2 = self.system._notify_exit_process(event) 1397 1398 try: 1399 self.detach( event.get_pid() ) 1400 except WindowsError, e: 1401 if e.winerror != win32.ERROR_INVALID_PARAMETER: 1402 warnings.warn( 1403 "Failed to detach from dead process, reason: %s" % str(e), 1404 RuntimeWarning) 1405 except Exception, e: 1406 warnings.warn( 1407 "Failed to detach from dead process, reason: %s" % str(e), 1408 RuntimeWarning) 1409 1410 return bCallHandler1 and bCallHandler2
1411
1412 - def _notify_exit_thread(self, event):
1413 """ 1414 Notify the termination of a thread. 1415 1416 @warning: This method is meant to be used internally by the debugger. 1417 1418 @type event: L{ExitThreadEvent} 1419 @param event: Exit thread event. 1420 1421 @rtype: bool 1422 @return: C{True} to call the user-defined handle, C{False} otherwise. 1423 """ 1424 bCallHandler1 = _BreakpointContainer._notify_exit_thread(self, event) 1425 bCallHandler2 = event.get_process()._notify_exit_thread(event) 1426 return bCallHandler1 and bCallHandler2
1427
1428 - def _notify_unload_dll(self, event):
1429 """ 1430 Notify the unload of a module. 1431 1432 @warning: This method is meant to be used internally by the debugger. 1433 1434 @type event: L{UnloadDLLEvent} 1435 @param event: Unload DLL event. 1436 1437 @rtype: bool 1438 @return: C{True} to call the user-defined handle, C{False} otherwise. 1439 """ 1440 bCallHandler1 = _BreakpointContainer._notify_unload_dll(self, event) 1441 bCallHandler2 = event.get_process()._notify_unload_dll(event) 1442 return bCallHandler1 and bCallHandler2
1443
1444 - def _notify_rip(self, event):
1445 """ 1446 Notify of a RIP event. 1447 1448 @warning: This method is meant to be used internally by the debugger. 1449 1450 @type event: L{RIPEvent} 1451 @param event: RIP event. 1452 1453 @rtype: bool 1454 @return: C{True} to call the user-defined handle, C{False} otherwise. 1455 """ 1456 event.debug.detach( event.get_pid() ) 1457 return True
1458
1459 - def _notify_debug_control_c(self, event):
1460 """ 1461 Notify of a Debug Ctrl-C exception. 1462 1463 @warning: This method is meant to be used internally by the debugger. 1464 1465 @note: This exception is only raised when a debugger is attached, and 1466 applications are not supposed to handle it, so we need to handle it 1467 ourselves or the application may crash. 1468 1469 @see: U{http://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx} 1470 1471 @type event: L{ExceptionEvent} 1472 @param event: Debug Ctrl-C exception event. 1473 1474 @rtype: bool 1475 @return: C{True} to call the user-defined handle, C{False} otherwise. 1476 """ 1477 if event.is_first_chance(): 1478 event.continueStatus = win32.DBG_EXCEPTION_HANDLED 1479 return True
1480
1481 - def _notify_ms_vc_exception(self, event):
1482 """ 1483 Notify of a Microsoft Visual C exception. 1484 1485 @warning: This method is meant to be used internally by the debugger. 1486 1487 @note: This allows the debugger to understand the 1488 Microsoft Visual C thread naming convention. 1489 1490 @see: U{http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx} 1491 1492 @type event: L{ExceptionEvent} 1493 @param event: Microsoft Visual C exception event. 1494 1495 @rtype: bool 1496 @return: C{True} to call the user-defined handle, C{False} otherwise. 1497 """ 1498 dwType = event.get_exception_information(0) 1499 if dwType == 0x1000: 1500 pszName = event.get_exception_information(1) 1501 dwThreadId = event.get_exception_information(2) 1502 dwFlags = event.get_exception_information(3) 1503 1504 aProcess = event.get_process() 1505 szName = aProcess.peek_string(pszName, fUnicode = False) 1506 if szName: 1507 1508 if dwThreadId == -1: 1509 dwThreadId = event.get_tid() 1510 1511 if aProcess.has_thread(dwThreadId): 1512 aThread = aProcess.get_thread(dwThreadId) 1513 else: 1514 aThread = Thread(dwThreadId) 1515 aProcess._add_thread(aThread) 1516 1517 ## if aThread.get_name() is None: 1518 ## aThread.set_name(szName) 1519 aThread.set_name(szName) 1520 1521 return True
1522