DEBUG.C

/*++ 

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 );
}