| Home | Trees | Indices | Help |
|
|---|
|
|
1 # Copyright (c) 2009, Mario Vilas
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are met:
6 #
7 # * Redistributions of source code must retain the above copyright notice,
8 # this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above copyright
10 # notice,this list of conditions and the following disclaimer in the
11 # documentation and/or other materials provided with the distribution.
12 # * Neither the name of the copyright holder nor the names of its
13 # contributors may be used to endorse or promote products derived from
14 # this software without specific prior written permission.
15 #
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 # POSSIBILITY OF SUCH DAMAGE.
27
28 """
29 Debugging module.
30
31 @see: U{http://apps.sourceforge.net/trac/winappdbg/wiki/wiki/Debugging}
32
33 @group Instrumentation: System, Process, Thread, Module
34 @group Debugging: Debug, EventHandler
35 """
36
37 __revision__ = "$Id: debug.py 452 2009-11-24 21:34:08Z qvasimodo $"
38
39 __all__ = [
40 # the main debugger class
41 'Debug',
42 ]
43
44 import win32
45 from system import System, Process, Thread, Module
46 from breakpoint import BreakpointContainer, CodeBreakpoint
47 from event import EventHandler, EventDispatcher, EventFactory, ExitProcessEvent
48
49 import sys
50 import ctypes
51 ##import traceback
52
53 #==============================================================================
54
55 # TODO
56 # * Add memory read and write operations, similar to those in the Process
57 # class, but hiding the presence of the code breakpoints.
58 # * Add a method to get the memory map of a process, but hiding the presence
59 # of the page breakpoints.
60 # * Maybe the previous two features should be implemented at the Process class
61 # instead, but how to communicate with the Debug object without creating
62 # circular references? Perhaps the "overrides" could be set using private
63 # members (so users won't see them), but then there's the problem of the
64 # users being able to access the snapshot (i.e. clear it), which is why it's
65 # not such a great idea to use the snapshot to store data that really belongs
66 # to the Debug class.
67
69 """
70 The main debugger class.
71
72 @see: U{http://apps.sourceforge.net/trac/winappdbg/wiki/wiki/Debugging}
73
74 @group Debugging:
75 attach, detach, detach_from_all, execv, execl, clear,
76 get_debugee_count, get_debugee_pids,
77 is_debugee, is_debugee_attached, is_debugee_started
78
79 @group Debugging loop:
80 loop, next, wait, dispatch, cont, stop
81
82 @group Event notifications (private):
83 notify_create_process,
84 notify_create_thread,
85 notify_load_dll,
86 notify_unload_dll,
87 notify_rip,
88 notify_debug_control_c,
89 notify_ms_vc_exception
90
91 @type system: L{System}
92 @ivar system: A System snapshot that is automatically updated for
93 processes being debugged. Processes not being debugged in this snapshot
94 may be outdated.
95 """
96
99 """
100 Debugger object.
101
102 @type eventHandler: L{EventHandler}
103 @param eventHandler:
104 (Optional, recommended) Custom event handler object.
105
106 @type bKillOnExit: bool
107 @param bKillOnExit: (Optional) Global kill on exit mode.
108 C{True} to kill the process on exit, C{False} to detach.
109 Ignored under Windows 2000 and below.
110
111 @type bHostileCode: bool
112 @param bHostileCode: (Optional) Hostile code mode.
113 Set to C{True} to take some basic precautions against anti-debug
114 tricks. Disabled by default.
115
116 @note: The L{eventHandler} parameter may be any callable Python object
117 (for example a function, or an instance method).
118 However you'll probably find it more convenient to use an instance
119 of a subclass of L{EventHandler} here.
120
121 @raise WindowsError: Raises an exception on error.
122 """
123 EventDispatcher.__init__(self, eventHandler)
124 BreakpointContainer.__init__(self)
125
126 self.system = System()
127 self.__bKillOnExit = bKillOnExit
128 self.__bHostileCode = bHostileCode
129 self.__attachedDebugees = set()
130 self.__startedDebugees = set()
131
132 ## self.system.request_debug_privileges(bIgnoreExceptions = True)
133 self.system.request_debug_privileges()
134
135 ## # It's not hard to create circular references,
136 ## # and since we have a destructor, we end up leaking everything.
137 ## # It's best to code the debugging loop properly to always
138 ## # stop the debugger before going out of scope.
139 ## def __del__(self):
140 ## try:
141 ## self.stop()
142 ## except Exception, e:
143 ## pass
144 #### traceback.print_exc()
145 #### print
146
148 """
149 @rtype: int
150 @return: Number of processes being debugged.
151 """
152 return self.get_debugee_count()
153
154 #------------------------------------------------------------------------------
155
157 """
158 Attaches to an existing process for debugging.
159
160 @see: L{detach}, L{execv}, L{execl}
161
162 @type dwProcessId: int
163 @param dwProcessId: Global ID of a process to attach to.
164
165 @rtype: L{Process}
166 @return: A new Process object.
167
168 @raise WindowsError: Raises an exception on error.
169 """
170 win32.DebugActiveProcess(dwProcessId)
171 self.__attachedDebugees.add(dwProcessId)
172
173 # We can only set the kill on exit mode after having
174 # established at least one debugging connection.
175 self.system.set_kill_on_exit_mode(self.__bKillOnExit)
176
177 # The process has to be registered with the debugger,
178 # otherwise the list of processes may be empty, and the
179 # debugger loop will quit too soon. When the create process
180 # event arrives, the process handle is replaced.
181 if not self.system.has_process(dwProcessId):
182 aProcess = Process(dwProcessId)
183 self.system._ProcessContainer__add_process(aProcess)
184 else:
185 aProcess = self.system.get_process(dwProcessId)
186
187 # XXX
188 # Scan the process threads and loaded modules.
189 # This is prefered because the thread and library events do not
190 # properly give some information, like the filename for each module.
191 aProcess.scan_threads()
192 aProcess.scan_modules()
193
194 return aProcess
195
197 """
198 Detaches from a process currently being debugged.
199
200 @see: L{attach}, L{detach_from_all}
201
202 @type dwProcessId: int
203 @param dwProcessId: Global ID of a process to detach from.
204
205 @type bIgnoreExceptions: bool
206 @param bIgnoreExceptions: C{True} to ignore any exceptions that may be
207 raised when detaching.
208
209 @raise WindowsError: Raises an exception on error, unless
210 C{bIgnoreExceptions} is C{True}.
211 """
212
213 # Disable all breakpoints in the process.
214 # XXX maybe they should be erased?
215 try:
216 self.disable_process_breakpoints(dwProcessId)
217 except Exception:
218 if not bIgnoreExceptions:
219 raise
220 ## traceback.print_exc()
221 ## print
222
223 # Stop tracing all threads in the process.
224 try:
225 self.stop_tracing_process(dwProcessId)
226 except Exception:
227 if not bIgnoreExceptions:
228 raise
229 ## traceback.print_exc()
230 ## print
231
232 # The process is no longer a debugee.
233 try:
234 if dwProcessId in self.__attachedDebugees:
235 self.__attachedDebugees.remove(dwProcessId)
236 if dwProcessId in self.__startedDebugees:
237 self.__startedDebugees.remove(dwProcessId)
238 except Exception:
239 if not bIgnoreExceptions:
240 raise
241 ## traceback.print_exc()
242 ## print
243
244 # Detach from the process.
245 try:
246 win32.DebugActiveProcessStop(dwProcessId)
247 except Exception:
248 if not bIgnoreExceptions:
249 raise
250 ## traceback.print_exc()
251 ## print
252
254 """
255 Detaches from all processes currently being debugged.
256
257 @note: To better handle last debugging event, call L{stop} instead.
258
259 @type bIgnoreExceptions: bool
260 @param bIgnoreExceptions: C{True} to ignore any exceptions that may be
261 raised when detaching.
262
263 @raise WindowsError: Raises an exception on error, unless
264 C{bIgnoreExceptions} is C{True}.
265 """
266 for pid in self.get_debugee_pids():
267 self.detach(pid, bIgnoreExceptions = bIgnoreExceptions)
268
269 - def execv(self, argv, bConsole = False,
270 bFollow = False,
271 bSuspended = False,
272 bInheritHandles = False,
273 dwParentProcessId = None):
274 """
275 Starts a new process for debugging.
276
277 This method uses a list of arguments. To use a command line string
278 instead, use L{execl}.
279
280 @see: L{attach}, L{detach}
281
282 @type argv: list( str... )
283 @param argv: List of command line arguments to pass to the debugee.
284 The first element must be the debugee executable filename.
285
286 @type bConsole: bool
287 @param bConsole: True to inherit the console of the debugger.
288 Defaults to C{False}.
289
290 @type bFollow: bool
291 @param bFollow: C{True} to automatically attach to child processes.
292 Defaults to C{False}.
293
294 @type bSuspended: bool
295 @param bSuspended: C{True} to suspend the main thread before any code
296 is executed in the debugee. Defaults to C{False}.
297
298 @type bInheritHandles: bool
299 @param bInheritHandles: C{True} if the new process should inherit it's
300 parent process' handles. Defaults to C{False}.
301
302 @type dwParentProcessId: int or None
303 @param dwParentProcessId: C{None} if the debugger process should be the
304 parent process (default), or a process ID to forcefully set as the
305 debuguee's parent (only available for Windows Vista and above).
306
307 @rtype: L{Process}
308 @return: A new Process object.
309
310 @raise WindowsError: Raises an exception on error.
311 """
312 lpCmdLine = self.system.argv_to_cmdline(argv)
313 return self.execl(lpCmdLine, bConsole = bConsole,
314 bFollow = bFollow,
315 bSuspended = bSuspended,
316 bInheritHandles = bInheritHandles,
317 dwParentProcessId = dwParentProcessId)
318
319 - def execl(self, lpCmdLine, bConsole = False,
320 bFollow = False,
321 bSuspended = False,
322 bInheritHandles = False,
323 dwParentProcessId = None):
324 """
325 Starts a new process for debugging.
326
327 This method uses a command line string. To use a list of arguments
328 instead, use L{execv}.
329
330 @see: L{attach}, L{detach}
331
332 @type lpCmdLine: str
333 @param lpCmdLine: Command line string to execute.
334 The first token must be the debugee executable filename.
335 Tokens with spaces must be enclosed in double quotes.
336 Tokens including double quote characters must be escaped with a
337 backslash.
338
339 @type bConsole: bool
340 @param bConsole: C{True} to inherit the console of the debugger.
341 Defaults to C{False}.
342
343 @type bFollow: bool
344 @param bFollow: C{True} to automatically attach to child processes.
345 Defaults to C{False}.
346
347 @type bSuspended: bool
348 @param bSuspended: C{True} to suspend the main thread before any code
349 is executed in the debugee. Defaults to C{False}.
350
351 @type bInheritHandles: bool
352 @param bInheritHandles: C{True} if the new process should inherit it's
353 parent process' handles. Defaults to C{False}.
354
355 @type dwParentProcessId: int or None
356 @param dwParentProcessId: C{None} if the debugger process should be the
357 parent process (default), or a process ID to forcefully set as the
358 debuguee's parent (only available for Windows Vista and above).
359
360 @rtype: L{Process}
361 @return: A new Process object.
362
363 @raise WindowsError: Raises an exception on error.
364 """
365 aProcess = self.system.start_process(lpCmdLine,
366 bConsole = bConsole,
367 bDebug = True,
368 bFollow = bFollow,
369 bSuspended = bSuspended,
370 bInheritHandles = bInheritHandles,
371 dwParentProcessId = dwParentProcessId,
372 )
373
374 self.__startedDebugees.add( aProcess.get_pid() )
375
376 # We can only set the kill on exit mode after having
377 # established at least one debugging connection.
378 self.system.set_kill_on_exit_mode(self.__bKillOnExit)
379
380 return aProcess
381
382 #------------------------------------------------------------------------------
383
385 """
386 Waits for the next debug event and returns an L{Event} object.
387
388 @see: L{cont}, L{dispatch}, L{loop}
389
390 @type dwMilliseconds: int
391 @param dwMilliseconds: (Optional) Timeout in milliseconds.
392 Use C{INFINITE} or C{None} for no timeout.
393
394 @rtype: L{Event}
395 @return: An event that occured in one of the debugees.
396
397 @raise WindowsError: Raises an exception on error.
398 """
399
400 # Return the next debug event.
401 raw = win32.WaitForDebugEvent(dwMilliseconds)
402 event = EventFactory.get(self, raw)
403 return event
404
406 """
407 Calls the debug event notify callbacks.
408
409 @see: L{cont}, L{loop}, L{wait}
410
411 @type event: L{Event}
412 @param event: Event object returned by L{wait}.
413
414 @raise WindowsError: Raises an exception on error.
415 """
416
417 # Ignore dummy events.
418 if not event:
419 return
420
421 # By default, exceptions are handled by the debugee.
422 if event.get_event_code() == win32.EXCEPTION_DEBUG_EVENT:
423 event.continueStatus = win32.DBG_EXCEPTION_NOT_HANDLED
424 else:
425 # Other events need this continue code.
426 # Sometimes other codes can be used and are ignored, sometimes not.
427 # For example, when using the DBG_EXCEPTION_NOT_HANDLED code,
428 # debug strings are sent twice (!)
429 event.continueStatus = win32.DBG_CONTINUE
430
431 # Dispatch the debug event.
432 return EventDispatcher.dispatch(self, event)
433
435 """
436 Resumes execution after processing a debug event.
437
438 @see: dispatch(), loop(), wait()
439
440 @type event: L{Event}
441 @param event: Event object returned by L{wait}.
442
443 @raise WindowsError: Raises an exception on error.
444 """
445
446 # Ignore dummy events.
447 if not event:
448 return
449
450 # Get the event continue status information.
451 dwProcessId = event.get_pid()
452 dwThreadId = event.get_tid()
453 dwContinueStatus = event.continueStatus
454
455 # Try to flush the instruction cache.
456 try:
457 if self.system.has_process(dwProcessId):
458 aProcess = self.system.get_process(dwProcessId)
459 else:
460 aProcess = Process(dwProcessId)
461 aProcess.flush_instruction_cache()
462 except WindowsError:
463 pass
464
465 # Continue execution of the debugee.
466 win32.ContinueDebugEvent(dwProcessId, dwThreadId, dwContinueStatus)
467
469 """
470 Stops debugging all processes.
471
472 If C{bKillOnExit} was set to C{True} when instancing the C{Debug}
473 object, all debugees are terminated. Otherwise, the debugger detaches
474 from all debugees.
475
476 @note: This method is better than L{detach_from_all} because it can
477 gracefully handle the last debugging event before detaching.
478
479 @type event: L{Event}
480 @param event: (Optional) Event object returned by L{wait}.
481 By passing this parameter, the last debugging event may be
482 continued gracefully.
483
484 @type bIgnoreExceptions: bool
485 @param bIgnoreExceptions: C{True} to ignore any exceptions that may be
486 raised when detaching.
487 """
488 # All these try / except / finally blocks may be masking some errors,
489 # but this way we get a better cleanup. Like that battery-powered
490 # rabbit, it just keeps going, and going, and going.
491 try:
492 if self.__bKillOnExit:
493 for pid in self.get_debugee_pids():
494 try:
495 self.system.get_process(pid).kill()
496 except Exception:
497 if not bIgnoreExceptions:
498 raise
499 try:
500 if event:
501 try:
502 try:
503 pid = event.get_pid()
504 self.disable_process_breakpoints(pid)
505 finally:
506 self.cont(event)
507 except Exception:
508 if not bIgnoreExceptions:
509 raise
510 finally:
511 self.detach_from_all(bIgnoreExceptions)
512 except Exception:
513 if not bIgnoreExceptions:
514 raise
515
517 """
518 Handles the next debug event.
519
520 @see: L{cont}, L{dispatch}, L{wait}, L{stop}
521
522 @rtype: L{Event}
523 @return: Handled debug event.
524
525 @raise WindowsError: Raises an exception on error.
526
527 If the wait operation causes an error, debugging is stopped
528 (meaning all debugees are either killed or detached from).
529
530 If the event dispatching causes an error, the event is still
531 continued before returning. This may happen, for example, if the
532 event handler raises an exception nobody catches.
533 """
534 try:
535 event = self.wait()
536 except Exception:
537 self.stop()
538 try:
539 self.dispatch(event)
540 finally:
541 self.cont(event)
542 return event
543
545 """
546 Simple debugging loop.
547
548 This debugging loop is meant to be useful for most simple scripts.
549 It iterates as long as there is at least one debuguee, or an exception
550 is raised. Multiple calls are allowed.
551
552 This is a trivial example script::
553
554 import sys
555 debug = Debug()
556 debug.execv( sys.argv [ 1 : ] )
557 try:
558 debug.loop()
559 finally:
560 debug.stop()
561
562 @see: L{next}, L{stop}
563
564 U{http://msdn.microsoft.com/en-us/library/ms681675(VS.85).aspx}
565
566 @raise WindowsError: Raises an exception on error.
567
568 If the wait operation causes an error, debugging is stopped
569 (meaning all debugees are either killed or detached from).
570
571 If the event dispatching causes an error, the event is still
572 continued before returning. This may happen, for example, if the
573 event handler raises an exception nobody catches.
574 """
575 while self.get_debugee_count() > 0:
576 self.next()
577
579 """
580 @rtype: int
581 @return: Number of processes being debugged.
582 """
583 return len(self.__attachedDebugees) + len(self.__startedDebugees)
584
586 """
587 @rtype: list( int... )
588 @return: Global IDs of processes being debugged.
589 """
590 return list(self.__attachedDebugees) + list(self.__startedDebugees)
591
593 """
594 @type dwProcessId: int
595 @param dwProcessId: Process global ID.
596
597 @rtype: bool
598 @return: C{True} if the given process is being debugged
599 by this L{Debug} instance.
600 """
601 return self.is_debugee_attached(dwProcessId) or \
602 self.is_debugee_started(dwProcessId)
603
605 """
606 @type dwProcessId: int
607 @param dwProcessId: Process global ID.
608
609 @rtype: bool
610 @return: C{True} if the given process was started for debugging by this
611 L{Debug} instance.
612 """
613 return dwProcessId in self.__startedDebugees
614
616 """
617 @type dwProcessId: int
618 @param dwProcessId: Process global ID.
619
620 @rtype: bool
621 @return: C{True} if the given process is attached to this
622 L{Debug} instance.
623 """
624 return dwProcessId in self.__attachedDebugees
625
626 #------------------------------------------------------------------------------
627
629 """
630 Detach from all processes and clean up internal structures.
631
632 @see: L{System}
633
634 @raise WindowsError: Raises an exception on error.
635 """
636 self.erase_all_breakpoints()
637 self.detach_from_all()
638 self.system.clear()
639
640 #------------------------------------------------------------------------------
641
643 """
644 Notify the creation of a new process.
645
646 @warning: This method is meant to be used internally by the debugger.
647
648 @type event: L{ExitProcessEvent}
649 @param event: Exit process event.
650
651 @rtype: bool
652 @return: C{True} to call the user-defined handle, C{False} otherwise.
653 """
654 dwProcessId = event.get_pid()
655 if dwProcessId not in self.__attachedDebugees:
656 if dwProcessId not in self.__startedDebugees:
657 self.__startedDebugees.add(dwProcessId)
658
659 retval = self.system.notify_create_process(event)
660
661 # Defeat isDebuggerPresent by patching PEB->BeingDebugged.
662 # When we do this, some debugging APIs cease to work as expected.
663 # For example, the system breakpoint isn't hit when we attach.
664 # For that reason we need to define a code breakpoint at the
665 # code location where a new thread is spawned by the debugging
666 # APIs, ntdll!DbgUiRemoteBreakin.
667 if self.__bHostileCode:
668 aProcess = self.system.get_process(dwProcessId)
669 try:
670 pbi = win32.NtQueryInformationProcess(aProcess.get_handle(),
671 win32.ProcessBasicInformation)
672 ptr = pbi.PebBaseAddress + 2
673 if aProcess.peek(ptr, 1) == '\x01':
674 aProcess.poke(ptr, '\x00')
675 except WindowsError:
676 pass
677
678 return retval
679
681 """
682 Notify the creation of a new thread.
683
684 @warning: This method is meant to be used internally by the debugger.
685
686 @type event: L{CreateThreadEvent}
687 @param event: Create thread event.
688
689 @rtype: bool
690 @return: C{True} to call the user-defined handle, C{False} otherwise.
691 """
692 return event.get_process().notify_create_thread(event)
693
695 """
696 Notify the load of a new module.
697
698 @warning: This method is meant to be used internally by the debugger.
699
700 @type event: L{LoadDLLEvent}
701 @param event: Load DLL event.
702
703 @rtype: bool
704 @return: C{True} to call the user-defined handle, C{False} otherwise.
705 """
706
707 # Get the process where the DLL was loaded.
708 aProcess = event.get_process()
709
710 # Pass the event to the process.
711 retval = aProcess.notify_load_dll(event)
712
713 # Anti-anti-debugging tricks on ntdll.dll.
714 if self.__bHostileCode:
715 aModule = event.get_module()
716 if aModule.match_name('ntdll.dll'):
717
718 ## # Check the int3 instruction where
719 ## # the system breakpoint should be.
720 ## # If missing, restore it. This defeats
721 ## # a simple anti-debugging trick.
722 #### address = aModule.resolve('DbgBreakPoint')
723 #### address = aModule.resolve('DbgUserBreakPoint')
724 ## address = aProcess.get_system_breakpoint()
725 ## if address is not None:
726 ## aProcess.poke(address, CodeBreakpoint.int3)
727 ## address = aProcess.get_user_breakpoint()
728 ## if address is not None:
729 ## aProcess.poke(address, CodeBreakpoint.int3)
730
731 # Since we've overwritten the PEB to hide
732 # ourselves, we no longer have the system
733 # breakpoint when attaching to the process.
734 # Set a breakpoint at ntdll!DbgUiRemoteBreakin
735 # instead (that's where the debug API spawns
736 # it's auxiliary threads). This also defeats
737 # a simple anti-debugging trick: the hostile
738 # process could have overwritten the int3
739 # instruction at the system breakpoint.
740 DbgUiRemoteBreakin = 'ntdll!DbgUiRemoteBreakin'
741 DbgUiRemoteBreakin = aProcess.resolve_label(DbgUiRemoteBreakin)
742 self.break_at(aProcess.get_pid(), DbgUiRemoteBreakin)
743
744 return retval
745
747 """
748 Notify the termination of a process.
749
750 @warning: This method is meant to be used internally by the debugger.
751
752 @type event: L{ExitProcessEvent}
753 @param event: Exit process event.
754
755 @rtype: bool
756 @return: C{True} to call the user-defined handle, C{False} otherwise.
757 """
758 dwProcessId = event.get_pid()
759 if dwProcessId in self.__attachedDebugees:
760 self.__attachedDebugees.remove(dwProcessId)
761 if dwProcessId in self.__startedDebugees:
762 self.__startedDebugees.remove(dwProcessId)
763
764 bCallHandler = BreakpointContainer.notify_exit_process(self, event)
765 bCallHandler = bCallHandler and self.system.notify_exit_process(event)
766 return bCallHandler
767
769 """
770 Notify the termination of a thread.
771
772 @warning: This method is meant to be used internally by the debugger.
773
774 @type event: L{ExitThreadEvent}
775 @param event: Exit thread event.
776
777 @rtype: bool
778 @return: C{True} to call the user-defined handle, C{False} otherwise.
779 """
780 bCallHandler = BreakpointContainer.notify_exit_thread(self, event)
781 bCallHandler = bCallHandler and \
782 event.get_process().notify_exit_thread(event)
783 return bCallHandler
784
786 """
787 Notify the unload of a module.
788
789 @warning: This method is meant to be used internally by the debugger.
790
791 @type event: L{UnloadDLLEvent}
792 @param event: Unload DLL event.
793
794 @rtype: bool
795 @return: C{True} to call the user-defined handle, C{False} otherwise.
796 """
797 bCallHandler = BreakpointContainer.notify_unload_dll(self, event)
798 bCallHandler = bCallHandler and \
799 event.get_process().notify_unload_dll(event)
800
802 """
803 Notify of a RIP event.
804
805 @warning: This method is meant to be used internally by the debugger.
806
807 @type event: L{RIPEvent}
808 @param event: RIP event.
809
810 @rtype: bool
811 @return: C{True} to call the user-defined handle, C{False} otherwise.
812 """
813 event.debug.detach( event.get_pid() )
814 return True
815
816 ## def notify_breakpoint(self, event):
817 ## """
818 ## Notify the debugger of a breakpoint exception event.
819 ##
820 ## @type event: L{ExceptionEvent}
821 ## @param event: Breakpoint exception event.
822 ## """
823 ## # Defeat isDebuggerPresent by patching PEB->BeingDebugged.
824 ## if self.__bHostileCode:
825 ## address = event.get_exception_address()
826 ## if event.get_process().get_system_breakpoint() == address:
827 ## aProcess = self.system.get_process(dwProcessId)
828 ## try:
829 ## pbi = win32.NtQueryInformationProcess(aProcess.get_handle(),
830 ## win32.ProcessBasicInformation)
831 ## ptr = pbi.PebBaseAddress + 2
832 ## if aProcess.peek(ptr, 1) == '\x01':
833 ## aProcess.poke(ptr, '\x00')
834 ## except WindowsError:
835 ## pass
836 ## return BreakpointContainer.notify_breakpoint(self, event)
837
839 """
840 Notify of a Debug Ctrl-C exception.
841
842 @warning: This method is meant to be used internally by the debugger.
843
844 @note: This exception is only raised when a debugger is attached, and
845 applications are not supposed to handle it, so we need to handle it
846 ourselves or the application may crash.
847
848 @see: U{http://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx}
849
850 @type event: L{ExceptionEvent}
851 @param event: Debug Ctrl-C exception event.
852
853 @rtype: bool
854 @return: C{True} to call the user-defined handle, C{False} otherwise.
855 """
856 if event.is_first_chance():
857 event.continueStatus = win32.DBG_EXCEPTION_HANDLED
858 return True
859
861 """
862 Notify of a Microsoft Visual C exception.
863
864 @warning: This method is meant to be used internally by the debugger.
865
866 @note: This allows the debugger to understand the
867 Microsoft Visual C thread naming convention.
868
869 @see: U{http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx}
870
871 @type event: L{ExceptionEvent}
872 @param event: Microsoft Visual C exception event.
873
874 @rtype: bool
875 @return: C{True} to call the user-defined handle, C{False} otherwise.
876 """
877 dwType = event.get_exception_information(0)
878 if dwType == 0x1000:
879 pszName = event.get_exception_information(1)
880 dwThreadId = event.get_exception_information(2)
881 dwFlags = event.get_exception_information(3)
882
883 aProcess = event.get_process()
884 szName = aProcess.peek_string(pszName, fUnicode = False)
885 if szName:
886
887 if dwThreadId == -1:
888 dwThreadId = event.get_tid()
889
890 if aProcess.has_thread(dwThreadId):
891 aThread = aProcess.get_thread(dwThreadId)
892 else:
893 aThread = Thread(dwThreadId)
894 aProcess._ThreadContainer__add_thread(aThread)
895
896 ## if aThread.get_name() is None:
897 ## aThread.set_name(szName)
898 aThread.set_name(szName)
899
900 return True
901
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Fri Feb 12 19:47:54 2010 | http://epydoc.sourceforge.net |