/*++ Copyright (c) 1992 Microsoft Corporation Module Name: debug.c Abstract: Main debug loop for pfmon Author: Mark Lucovsky (markl) 26-Jan-1995 Revision History: --*/ #include "pfmonp.h" DWORD DebugEventHandler( LPDEBUG_EVENT DebugEvent ); VOID DebugEventLoop( VOID ) { DEBUG_EVENT DebugEvent; DWORD ContinueStatus; DWORD OldPriority; // // We want to process debug events quickly // OldPriority = GetPriorityClass( GetCurrentProcess() ); SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ); do { retry_debug_wait: ProcessPfMonData(); if (!WaitForDebugEvent( &DebugEvent, 500 )) { if ( GetLastError() == ERROR_SEM_TIMEOUT ) { goto retry_debug_wait; } DeclareError( PFMON_WAITDEBUGEVENT_FAILED, GetLastError() ); ExitProcess( 1 ); } ProcessPfMonData(); if ( fVerbose ) { if (DebugEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { fprintf(stderr,"Debug exception event - Code: %x Address: %p Info: [%u] %x %x %x %x\n", DebugEvent.u.Exception.ExceptionRecord.ExceptionCode, DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress, DebugEvent.u.Exception.ExceptionRecord.NumberParameters, DebugEvent.u.Exception.ExceptionRecord.ExceptionInformation[ 0 ], DebugEvent.u.Exception.ExceptionRecord.ExceptionInformation[ 1 ], DebugEvent.u.Exception.ExceptionRecord.ExceptionInformation[ 2 ], DebugEvent.u.Exception.ExceptionRecord.ExceptionInformation[ 3 ] ); } else { fprintf(stderr,"Debug %x event\n", DebugEvent.dwDebugEventCode); } } ContinueStatus = DebugEventHandler( &DebugEvent ); if ( fVerbose ) { fprintf(stderr,"Continue Status %x\n", ContinueStatus); } if (!ContinueDebugEvent( DebugEvent.dwProcessId, DebugEvent.dwThreadId, ContinueStatus ) ) { DeclareError( PFMON_CONTDEBUGEVENT_FAILED, GetLastError() ); ExitProcess( 1 ); } } while (!IsListEmpty( &ProcessListHead )); // // Drop back to old priority to interact with user. // SetPriorityClass( GetCurrentProcess(), OldPriority ); } DWORD DebugEventHandler( LPDEBUG_EVENT DebugEvent ) { DWORD ContinueStatus; PPROCESS_INFO Process; PTHREAD_INFO Thread; CONTEXT Context; PCONTEXT pContext; ContinueStatus = (DWORD)DBG_CONTINUE; if (FindProcessAndThreadForEvent( DebugEvent, &Process, &Thread )) { switch (DebugEvent->dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: // // Create process event includes first thread of process // as well. Remember process and thread in our process tree // if (AddProcess( DebugEvent, &Process )) { AddModule( DebugEvent ); AddThread( DebugEvent, Process, &Thread ); } break; case EXIT_PROCESS_DEBUG_EVENT: // // Exit process event includes last thread of process // as well. Remove process and thread from our process tree // if (DeleteThread( Process, Thread )) { DeleteProcess( Process ); } break; case CREATE_THREAD_DEBUG_EVENT: // // Create thread. Remember thread in our process tree. // AddThread( DebugEvent, Process, &Thread ); break; case EXIT_THREAD_DEBUG_EVENT: // // Exit thread. Remove thread from our process tree. // DeleteThread( Process, Thread ); break; case LOAD_DLL_DEBUG_EVENT: AddModule( DebugEvent ); break; case UNLOAD_DLL_DEBUG_EVENT: break; case OUTPUT_DEBUG_STRING_EVENT: case RIP_EVENT: // // Ignore these // break; case EXCEPTION_DEBUG_EVENT: // // Assume we wont handle this exception // ContinueStatus = (DWORD)DBG_CONTINUE; switch (DebugEvent->u.Exception.ExceptionRecord.ExceptionCode) { // // Breakpoint exception. // case STATUS_BREAKPOINT: Context.ContextFlags = CONTEXT_FULL; if (!GetThreadContext( Thread->Handle, &Context )) { fprintf(stderr,"Failed to get context for thread %x (%p) - %u\n", Thread->Id, Thread->Handle, GetLastError()); ExitProcess(1); } pContext = &Context; PROGRAM_COUNTER_TO_CONTEXT(pContext, (ULONG_PTR)((PCHAR)DebugEvent->u.Exception.ExceptionRecord.ExceptionAddress + BPSKIP)); if (!SetThreadContext( Thread->Handle, &Context )) { fprintf(stderr,"Failed to set context for thread %x (%p) - %u\n", Thread->Id, Thread->Handle, GetLastError()); ExitProcess(1); } break; default: ContinueStatus = (DWORD) DBG_EXCEPTION_NOT_HANDLED; if ( fVerbose ) { fprintf(stderr,"Unknown exception: %08x at %p\n", DebugEvent->u.Exception.ExceptionRecord.ExceptionCode, DebugEvent->u.Exception.ExceptionRecord.ExceptionAddress ); } break; } break; default: break; } } return( ContinueStatus ); }