Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
6.4 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. debug.c
  5. Abstract:
  6. Main debug loop for pfmon
  7. Author:
  8. Mark Lucovsky (markl) 26-Jan-1995
  9. Revision History:
  10. --*/
  11. #include "pfmonp.h"
  12. DWORD
  13. DebugEventHandler(
  14. LPDEBUG_EVENT DebugEvent
  15. );
  16. VOID
  17. DebugEventLoop( VOID )
  18. {
  19. DEBUG_EVENT DebugEvent;
  20. DWORD ContinueStatus;
  21. DWORD OldPriority;
  22. //
  23. // We want to process debug events quickly
  24. //
  25. OldPriority = GetPriorityClass( GetCurrentProcess() );
  26. SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS );
  27. do {
  28. retry_debug_wait:
  29. ProcessPfMonData();
  30. if (!WaitForDebugEvent( &DebugEvent, 500 )) {
  31. if ( GetLastError() == ERROR_SEM_TIMEOUT ) {
  32. goto retry_debug_wait;
  33. }
  34. DeclareError( PFMON_WAITDEBUGEVENT_FAILED, GetLastError() );
  35. ExitProcess( 1 );
  36. }
  37. ProcessPfMonData();
  38. if ( fVerbose ) {
  39. if (DebugEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) {
  40. fprintf(stderr,"Debug exception event - Code: %x Address: %p Info: [%u] %x %x %x %x\n",
  41. DebugEvent.u.Exception.ExceptionRecord.ExceptionCode,
  42. DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress,
  43. DebugEvent.u.Exception.ExceptionRecord.NumberParameters,
  44. DebugEvent.u.Exception.ExceptionRecord.ExceptionInformation[ 0 ],
  45. DebugEvent.u.Exception.ExceptionRecord.ExceptionInformation[ 1 ],
  46. DebugEvent.u.Exception.ExceptionRecord.ExceptionInformation[ 2 ],
  47. DebugEvent.u.Exception.ExceptionRecord.ExceptionInformation[ 3 ]
  48. );
  49. }
  50. else {
  51. fprintf(stderr,"Debug %x event\n", DebugEvent.dwDebugEventCode);
  52. }
  53. }
  54. ContinueStatus = DebugEventHandler( &DebugEvent );
  55. if ( fVerbose ) {
  56. fprintf(stderr,"Continue Status %x\n", ContinueStatus);
  57. }
  58. if (!ContinueDebugEvent( DebugEvent.dwProcessId,
  59. DebugEvent.dwThreadId,
  60. ContinueStatus
  61. )
  62. ) {
  63. DeclareError( PFMON_CONTDEBUGEVENT_FAILED, GetLastError() );
  64. ExitProcess( 1 );
  65. }
  66. }
  67. while (!IsListEmpty( &ProcessListHead ));
  68. //
  69. // Drop back to old priority to interact with user.
  70. //
  71. SetPriorityClass( GetCurrentProcess(), OldPriority );
  72. }
  73. DWORD
  74. DebugEventHandler(
  75. LPDEBUG_EVENT DebugEvent
  76. )
  77. {
  78. DWORD ContinueStatus;
  79. PPROCESS_INFO Process;
  80. PTHREAD_INFO Thread;
  81. CONTEXT Context;
  82. PCONTEXT pContext;
  83. ContinueStatus = (DWORD)DBG_CONTINUE;
  84. if (FindProcessAndThreadForEvent( DebugEvent, &Process, &Thread )) {
  85. switch (DebugEvent->dwDebugEventCode) {
  86. case CREATE_PROCESS_DEBUG_EVENT:
  87. //
  88. // Create process event includes first thread of process
  89. // as well. Remember process and thread in our process tree
  90. //
  91. if (AddProcess( DebugEvent, &Process )) {
  92. AddModule( DebugEvent );
  93. AddThread( DebugEvent, Process, &Thread );
  94. }
  95. break;
  96. case EXIT_PROCESS_DEBUG_EVENT:
  97. //
  98. // Exit process event includes last thread of process
  99. // as well. Remove process and thread from our process tree
  100. //
  101. if (DeleteThread( Process, Thread )) {
  102. DeleteProcess( Process );
  103. }
  104. break;
  105. case CREATE_THREAD_DEBUG_EVENT:
  106. //
  107. // Create thread. Remember thread in our process tree.
  108. //
  109. AddThread( DebugEvent, Process, &Thread );
  110. break;
  111. case EXIT_THREAD_DEBUG_EVENT:
  112. //
  113. // Exit thread. Remove thread from our process tree.
  114. //
  115. DeleteThread( Process, Thread );
  116. break;
  117. case LOAD_DLL_DEBUG_EVENT:
  118. AddModule( DebugEvent );
  119. break;
  120. case UNLOAD_DLL_DEBUG_EVENT:
  121. break;
  122. case OUTPUT_DEBUG_STRING_EVENT:
  123. case RIP_EVENT:
  124. //
  125. // Ignore these
  126. //
  127. break;
  128. case EXCEPTION_DEBUG_EVENT:
  129. //
  130. // Assume we wont handle this exception
  131. //
  132. ContinueStatus = (DWORD)DBG_CONTINUE;
  133. switch (DebugEvent->u.Exception.ExceptionRecord.ExceptionCode) {
  134. //
  135. // Breakpoint exception.
  136. //
  137. case STATUS_BREAKPOINT:
  138. Context.ContextFlags = CONTEXT_FULL;
  139. if (!GetThreadContext( Thread->Handle, &Context )) {
  140. fprintf(stderr,"Failed to get context for thread %x (%p) - %u\n", Thread->Id, Thread->Handle, GetLastError());
  141. ExitProcess(1);
  142. }
  143. pContext = &Context;
  144. PROGRAM_COUNTER_TO_CONTEXT(pContext, (ULONG_PTR)((PCHAR)DebugEvent->u.Exception.ExceptionRecord.ExceptionAddress + BPSKIP));
  145. if (!SetThreadContext( Thread->Handle, &Context )) {
  146. fprintf(stderr,"Failed to set context for thread %x (%p) - %u\n", Thread->Id, Thread->Handle, GetLastError());
  147. ExitProcess(1);
  148. }
  149. break;
  150. default:
  151. ContinueStatus = (DWORD) DBG_EXCEPTION_NOT_HANDLED;
  152. if ( fVerbose ) {
  153. fprintf(stderr,"Unknown exception: %08x at %p\n",
  154. DebugEvent->u.Exception.ExceptionRecord.ExceptionCode,
  155. DebugEvent->u.Exception.ExceptionRecord.ExceptionAddress
  156. );
  157. }
  158. break;
  159. }
  160. break;
  161. default:
  162. break;
  163. }
  164. }
  165. return( ContinueStatus );
  166. }