210 lines
6.4 KiB
C
210 lines
6.4 KiB
C
|
/*++
|
||
|
|
||
|
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 );
|
||
|
}
|