[+] WaitEventException : none of the targets could generate events

[+] Breakpoint debug event
[+] Exception debug event
[+] watchDog.py - demo for debugEvent::onException and WaitEventException

git-svn-id: https://pykd.svn.codeplex.com/svn@69518 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2011-09-02 16:38:27 +00:00
parent 5ac233a473
commit 8596f87b72
7 changed files with 313 additions and 52 deletions

View File

@ -30,7 +30,12 @@ setExecutionStatus()
} }
if ( FAILED( hres ) ) if ( FAILED( hres ) )
{
if (E_UNEXPECTED == hres)
throw WaitEventException();
throw DbgException( "IDebugControl::WaitForEvent failed" ); throw DbgException( "IDebugControl::WaitForEvent failed" );
}
hres = dbgExt->control->GetExecutionStatus( &currentStatus ); hres = dbgExt->control->GetExecutionStatus( &currentStatus );

View File

@ -43,12 +43,110 @@ HRESULT debugEvent::GetInterestMask(
*Mask |= DEBUG_EVENT_LOAD_MODULE; *Mask |= DEBUG_EVENT_LOAD_MODULE;
*Mask |= DEBUG_EVENT_UNLOAD_MODULE; *Mask |= DEBUG_EVENT_UNLOAD_MODULE;
*Mask |= DEBUG_EVENT_SESSION_STATUS; *Mask |= DEBUG_EVENT_SESSION_STATUS;
*Mask |= DEBUG_EVENT_EXCEPTION;
*Mask |= DEBUG_EVENT_BREAKPOINT;
return S_OK; return S_OK;
} }
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
HRESULT debugEvent::Breakpoint(
__in PDEBUG_BREAKPOINT Bp
)
{
boost::python::dict bpParameters;
HRESULT hres;
ULONG Value = 0;
ULONG Value2 = 0;
ULONG64 Value64 = 0;
std::string str;
#define _ADD_BP_ULONG(x) \
hres = Bp->Get##x(&Value); \
BOOST_ASSERT( SUCCEEDED( hres ) || hres == E_NOINTERFACE ); \
if (SUCCEEDED( hres )) \
bpParameters[#x] = Value;
#define _ADD_BP_ULONG2(x, n1, n2) \
hres = Bp->Get##x(&Value, &Value2); \
BOOST_ASSERT( SUCCEEDED( hres ) || hres == E_NOINTERFACE ); \
if (SUCCEEDED( hres )) \
{ \
bpParameters[n1] = Value; bpParameters[n2] = Value2; \
}
#define _ADD_BP_ULONG64(x) \
hres = Bp->Get##x(&Value64); \
BOOST_ASSERT( SUCCEEDED( hres ) || hres == E_NOINTERFACE ); \
if (SUCCEEDED( hres )) \
bpParameters[#x] = Value64;
#define _ADD_BP_STR(x) \
Value = 0; \
Bp->Get##x(NULL, 0, &Value); \
if (Value) \
{ \
str.resize(Value + 1); \
BOOST_VERIFY( SUCCEEDED( \
Bp->Get##x(&str[0], (ULONG)str.size(), NULL) \
) ); \
if (!str.empty()) bpParameters[#x] = str.c_str(); \
}
_ADD_BP_ULONG(Id);
_ADD_BP_ULONG2(Type, "BreakType", "ProcType");
_ADD_BP_ULONG(Flags);
_ADD_BP_ULONG64(Offset);
_ADD_BP_ULONG2(DataParameters, "Size", "AccessType");
_ADD_BP_ULONG(PassCount);
_ADD_BP_ULONG(CurrentPassCount);
_ADD_BP_ULONG(MatchThreadId);
_ADD_BP_STR(Command);
_ADD_BP_STR(OffsetExpression);
#undef _ADD_BP_ULONG
#undef _ADD_BP_ULONG2
#undef _ADD_BP_ULONG64
#undef _ADD_BP_STR
PyThread_StateSave pyThreadSave;
return onException(bpParameters);
}
///////////////////////////////////////////////////////////////////////////////////
HRESULT debugEvent::Exception(
__in PEXCEPTION_RECORD64 Exception,
__in ULONG FirstChance
)
{
boost::python::list exceptParams;
boost::python::dict exceptData;
// build list of parameters
for (ULONG i = 0; i < Exception->NumberParameters; ++i)
exceptParams.append(Exception->ExceptionInformation[i]);
// build dict of exception data
#define _ADD_EXCEPTION_ENTRY(x) exceptData[#x] = Exception->Exception##x
_ADD_EXCEPTION_ENTRY(Code);
_ADD_EXCEPTION_ENTRY(Flags);
_ADD_EXCEPTION_ENTRY(Record);
_ADD_EXCEPTION_ENTRY(Address);
#undef _ADD_EXCEPTION_ENTRY
exceptData["Parameters"] = exceptParams;
exceptData["FirstChance"] = (0 != FirstChance);
PyThread_StateSave pyThreadSave;
return onException(exceptData);
}
///////////////////////////////////////////////////////////////////////////////////
HRESULT debugEvent::LoadModule( HRESULT debugEvent::LoadModule(
__in ULONG64 ImageFileHandle, __in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset, __in ULONG64 BaseOffset,

View File

@ -16,6 +16,10 @@ public:
virtual ~debugEvent(); virtual ~debugEvent();
virtual ULONG onBreakpoint(boost::python::dict &/*bpParameters*/) = 0;
virtual ULONG onException(boost::python::dict &/*exceptData*/) = 0;
virtual ULONG onLoadModule(const dbgModuleClass &/* module */) = 0; virtual ULONG onLoadModule(const dbgModuleClass &/* module */) = 0;
virtual ULONG onUnloadModule(const dbgModuleClass &/* module */) = 0; virtual ULONG onUnloadModule(const dbgModuleClass &/* module */) = 0;
@ -33,6 +37,16 @@ private:
__out PULONG Mask __out PULONG Mask
); );
STDMETHOD(Breakpoint)(
__in PDEBUG_BREAKPOINT Bp
);
STDMETHOD(Exception)(
__in PEXCEPTION_RECORD64 Exception,
__in ULONG FirstChance
);
STDMETHOD(LoadModule)( STDMETHOD(LoadModule)(
__in ULONG64 ImageFileHandle, __in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset, __in ULONG64 BaseOffset,
@ -68,6 +82,13 @@ class debugEventWrap : public boost::python::wrapper<debugEvent>, public debugEv
public: public:
ULONG onBreakpoint(boost::python::dict &bpParameters) {
return handler<boost::python::dict &>("onBreakpoint", bpParameters);
}
ULONG onException(boost::python::dict &exceptData) {
return handler<boost::python::dict &>("onException", exceptData);
}
ULONG onLoadModule(const dbgModuleClass &module) { ULONG onLoadModule(const dbgModuleClass &module) {
return handler<const dbgModuleClass &>("onLoadModule", module ); return handler<const dbgModuleClass &>("onLoadModule", module );

View File

@ -6,6 +6,7 @@
// òèïû èñêëþ÷åíèé // òèïû èñêëþ÷åíèé
PyObject *baseExceptionType = NULL; PyObject *baseExceptionType = NULL;
PyObject *eventExceptionType = NULL;
PyObject *typeExceptionType = NULL; PyObject *typeExceptionType = NULL;
PyObject *memoryExceptionType = NULL; PyObject *memoryExceptionType = NULL;
@ -22,6 +23,15 @@ void DbgException::exceptionTranslate( const DbgException &e )
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
void WaitEventException::exceptionTranslate( const WaitEventException &e )
{
boost::python::object pyExcept(e);
PyErr_SetObject( eventExceptionType, pyExcept.ptr());
}
/////////////////////////////////////////////////////////////////////////////////
void TypeException::exceptionTranslate( const TypeException &e ) void TypeException::exceptionTranslate( const TypeException &e )
{ {
boost::python::object pyExcept(e); boost::python::object pyExcept(e);

View File

@ -10,19 +10,29 @@ class DbgException : public std::exception
public: public:
DbgException( const std::string &desc ) : DbgException( const std::string &desc ) :
std::exception( desc.c_str() ) std::exception( desc.c_str() )
{} {}
const char* getDesc() const { const char* getDesc() const {
return what(); return what();
} }
static static
void void
exceptionTranslate(const DbgException &e ); exceptionTranslate(const DbgException &e );
}; };
class WaitEventException : public DbgException
{
public:
WaitEventException()
: DbgException( "none of the targets could generate events" )
{
}
static void exceptionTranslate(const WaitEventException &e);
};
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
class TypeException : public DbgException class TypeException : public DbgException
@ -114,6 +124,7 @@ private:
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
extern PyObject *baseExceptionType; extern PyObject *baseExceptionType;
extern PyObject *eventExceptionType;
extern PyObject *typeExceptionType; extern PyObject *typeExceptionType;
extern PyObject *memoryExceptionType; extern PyObject *memoryExceptionType;

View File

@ -355,11 +355,24 @@ BOOST_PYTHON_MODULE( pykd )
boost::python::class_<debugEventWrap, boost::noncopyable>( "debugEvent", boost::python::class_<debugEventWrap, boost::noncopyable>( "debugEvent",
"Base class for debug events handlers" ) "Base class for debug events handlers" )
.def( "onBreakpoint", &debugEventWrap::onBreakpoint,
"Triggered breakpoint event. Parameter is dict:\n"
"{\"Id\":int, \"BreakType\":int, \"ProcType\":int, \"Flags\":int, \"Offset\":int,"
" \"Size\":int, \"AccessType\":int, \"PassCount\":int, \"CurrentPassCount\":int,"
" \"MatchThreadId\":int, \"Command\":str, \"OffsetExpression\":str}\n"
"Detailed information: http://msdn.microsoft.com/en-us/library/ff539284(VS.85).aspx \n"
"For ignore event method must return DEBUG_STATUS_NO_CHANGE value" )
.def( "onException", &debugEventWrap::onException,
"Exception event. Parameter is dict:\n"
"{\"Code\":int, \"Flags\":int, \"Record\":int, \"Address\":int,"
" \"Parameters\":list_of_int, \"FirstChance\":bool}\n"
"Detailed information: http://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx \n"
"For ignore event method must return DEBUG_STATUS_NO_CHANGE value" )
.def( "onLoadModule", &debugEventWrap::onLoadModule, .def( "onLoadModule", &debugEventWrap::onLoadModule,
"Load module event. Parameter is instance of dbgModuleClass. " "Load module event. Parameter is instance of dbgModuleClass.\n"
"For ignore event method must return DEBUG_STATUS_NO_CHANGE value" ) "For ignore event method must return DEBUG_STATUS_NO_CHANGE value" )
.def( "onUnloadModule", &debugEventWrap::onUnloadModule, .def( "onUnloadModule", &debugEventWrap::onUnloadModule,
"Unload module event. Parameter is instance of dbgModuleClass. " "Unload module event. Parameter is instance of dbgModuleClass.\n"
"For ignore event method must return DEBUG_STATUS_NO_CHANGE value" ); "For ignore event method must return DEBUG_STATUS_NO_CHANGE value" );
boost::python::class_<disasm>("disasm", "Class disassemble a processor instructions", boost::python::no_init ) boost::python::class_<disasm>("disasm", "Class disassemble a processor instructions", boost::python::no_init )
@ -384,6 +397,10 @@ BOOST_PYTHON_MODULE( pykd )
.def( "desc", &DbgException::getDesc, .def( "desc", &DbgException::getDesc,
"Get exception description" ); "Get exception description" );
boost::python::class_<WaitEventException, boost::python::bases<DbgException> > waitExceptionClass( "WaitEventException",
"Type exception class",
boost::python::no_init );
boost::python::class_<TypeException, boost::python::bases<DbgException> > typeExceptionClass( "TypeException", boost::python::class_<TypeException, boost::python::bases<DbgException> > typeExceptionClass( "TypeException",
"Type exception class", "Type exception class",
boost::python::no_init ); boost::python::no_init );
@ -398,10 +415,12 @@ BOOST_PYTHON_MODULE( pykd )
"Return target address" ); "Return target address" );
baseExceptionType = dbgExceptionClass.ptr(); baseExceptionType = dbgExceptionClass.ptr();
eventExceptionType = waitExceptionClass.ptr();
typeExceptionType = typeExceptionClass.ptr(); typeExceptionType = typeExceptionClass.ptr();
memoryExceptionType = memoryExceptionClass.ptr(); memoryExceptionType = memoryExceptionClass.ptr();
boost::python::register_exception_translator<DbgException>( &DbgException::exceptionTranslate ); boost::python::register_exception_translator<DbgException>( &DbgException::exceptionTranslate );
boost::python::register_exception_translator<WaitEventException>( &WaitEventException::exceptionTranslate );
boost::python::register_exception_translator<TypeException>( &TypeException::exceptionTranslate ); boost::python::register_exception_translator<TypeException>( &TypeException::exceptionTranslate );
boost::python::register_exception_translator<IndexException>( &IndexException::translate); boost::python::register_exception_translator<IndexException>( &IndexException::translate);
boost::python::register_exception_translator<MemoryException>( &MemoryException::translate ); boost::python::register_exception_translator<MemoryException>( &MemoryException::translate );

97
samples/watchDog.py Normal file
View File

@ -0,0 +1,97 @@
"""
Exception watchdog
"""
from pykd import *
import sys
# known exception codes
knownExcepCodes = {
0xc0000005 : "EXCEPTION_ACCESS_VIOLATION",
0x80000002 : "EXCEPTION_DATATYPE_MISALIGNMENT",
0x80000003 : "EXCEPTION_BREAKPOINT",
0x80000004 : "EXCEPTION_SINGLE_STEP",
0xc000008c : "EXCEPTION_ARRAY_BOUNDS_EXCEEDED",
0xc000008d : "EXCEPTION_FLT_DENORMAL_OPERAND",
0xc000008e : "EXCEPTION_FLT_DIVIDE_BY_ZERO",
0xc000008f : "EXCEPTION_FLT_INEXACT_RESULT",
0xc0000090 : "EXCEPTION_FLT_INVALID_OPERATION",
0xc0000091 : "EXCEPTION_FLT_OVERFLOW",
0xc0000092 : "EXCEPTION_FLT_STACK_CHECK",
0xc0000093 : "EXCEPTION_FLT_UNDERFLOW",
0xc0000094 : "EXCEPTION_INT_DIVIDE_BY_ZERO",
0xc0000095 : "EXCEPTION_INT_OVERFLOW",
0xc0000096 : "EXCEPTION_PRIV_INSTRUCTION",
0xc0000006 : "EXCEPTION_IN_PAGE_ERROR",
0xc000001d : "EXCEPTION_ILLEGAL_INSTRUCTION",
0xc0000025 : "EXCEPTION_NONCONTINUABLE_EXCEPTION",
0xc00000fd : "EXCEPTION_STACK_OVERFLOW",
0xc0000026 : "EXCEPTION_INVALID_DISPOSITION",
0x80000001 : "EXCEPTION_GUARD_PAGE",
0xc0000008 : "EXCEPTION_INVALID_HANDLE",
0xc0000194 : "EXCEPTION_POSSIBLE_DEADLOCK",
0xc000013a : "CONTROL_C_EXIT"
};
class ExceptionHandler(debugEvent):
def onException(self, exceptData):
dprintln("\n *** shit happens")
exceptCode = exceptData["Code"]
dprint("Exception code : ")
if exceptCode in knownExcepCodes:
dprintln( knownExcepCodes[exceptCode] )
else:
dprintln( "0x%08x" % exceptCode )
dprint("Exception flags : ")
exceptFlags = exceptData["Flags"]
if exceptFlags:
if exceptFlags & NONCONTINUABLE_EXCEPTION:
exceptFlags &= ~NONCONTINUABLE_EXCEPTION
dprint( "NONCONTINUABLE " )
if exceptFlags:
dprintln( "| 0x%02x" % exceptFlags)
else:
dprintln( "" )
else:
dprintln( "0" )
dprintln("Exception record : 0x%X" % exceptData["Record"])
exceptAddr = exceptData["Address"]
dprintln("\nException address : 0x%X" % exceptAddr)
dprintln( dbgCommand("ln 0x%X" % exceptAddr) )
if len( exceptData["Parameters"] ):
dprintln("Parameters : ")
for param in exceptData["Parameters"]:
dprintln("\t0x%X" % param)
dprintln("\nFirst chance : " + str( exceptData["FirstChance"] ))
dprintln( "\n " + dbgCommand( "r" ) )
dbgCommand( ".reload" )
dprintln( dbgCommand( "kb" ) )
return DEBUG_STATUS_BREAK
if __name__ == '__main__':
if len(sys.argv) != 1:
startComamnd = ""
for i in range(1, len(sys.argv)):
startComamnd += sys.argv[i] + " "
startProcess(startComamnd)
exceptionHandler = ExceptionHandler()
try:
go()
except WaitEventException:
dprintln("none of the targets could generate events")