/*++
Copyright 1996 - 1997 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: %x 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 (%x) - %u\n", Thread->Id, Thread->Handle, GetLastError());
ExitProcess(1);
}
pContext = &Context;
CONTEXT_TO_PROGRAM_COUNTER(pContext) = (ULONG)((PCHAR)DebugEvent->u.Exception.ExceptionRecord.ExceptionAddress + BPSKIP);
if (!SetThreadContext( Thread->Handle, &Context )) {
fprintf(stderr,"Failed to set context for thread %x (%x) - %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 %08x\n",
DebugEvent->u.Exception.ExceptionRecord.ExceptionCode,
DebugEvent->u.Exception.ExceptionRecord.ExceptionAddress
);
}
break;
}
break;
default:
break;
}
}
return( ContinueStatus );
}