[+] 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,8 +30,13 @@ setExecutionStatus()
}
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::WaitForEvent failed" );
{
if (E_UNEXPECTED == hres)
throw WaitEventException();
throw DbgException( "IDebugControl::WaitForEvent failed" );
}
hres = dbgExt->control->GetExecutionStatus( &currentStatus );
if ( FAILED( hres ) )

View File

@ -43,12 +43,110 @@ HRESULT debugEvent::GetInterestMask(
*Mask |= DEBUG_EVENT_LOAD_MODULE;
*Mask |= DEBUG_EVENT_UNLOAD_MODULE;
*Mask |= DEBUG_EVENT_SESSION_STATUS;
*Mask |= DEBUG_EVENT_EXCEPTION;
*Mask |= DEBUG_EVENT_BREAKPOINT;
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(
__in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset,

View File

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

View File

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

View File

@ -10,17 +10,27 @@ class DbgException : public std::exception
public:
DbgException( const std::string &desc ) :
std::exception( desc.c_str() )
{}
std::exception( desc.c_str() )
{}
const char* getDesc() const {
return what();
}
static
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);
};
/////////////////////////////////////////////////////////////////////////////////
@ -40,7 +50,7 @@ public:
static
void
exceptionTranslate(const TypeException &e );
};
/////////////////////////////////////////////////////////////////////////////////
@ -114,6 +124,7 @@ private:
/////////////////////////////////////////////////////////////////////////////////
extern PyObject *baseExceptionType;
extern PyObject *eventExceptionType;
extern PyObject *typeExceptionType;
extern PyObject *memoryExceptionType;

View File

@ -352,14 +352,27 @@ BOOST_PYTHON_MODULE( pykd )
"Remove a breakpoint set before" )
.def( "__str__", &dbgBreakpointClass::print,
"Return a nice string represention of the breakpoint class" );
boost::python::class_<debugEventWrap, boost::noncopyable>( "debugEvent",
"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,
"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" )
.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" );
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,
"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",
"Type exception class",
boost::python::no_init );
@ -396,13 +413,15 @@ BOOST_PYTHON_MODULE( pykd )
.def( boost::python::init<ULONG64>( boost::python::args("targetAddress"), "constructor" ) )
.def( "getAddress", &MemoryException::getAddress,
"Return target address" );
baseExceptionType = dbgExceptionClass.ptr();
eventExceptionType = waitExceptionClass.ptr();
typeExceptionType = typeExceptionClass.ptr();
memoryExceptionType = memoryExceptionClass.ptr();
boost::python::register_exception_translator<DbgException>( &DbgException::exceptionTranslate );
boost::python::register_exception_translator<TypeException>( &TypeException::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<IndexException>( &IndexException::translate);
boost::python::register_exception_translator<MemoryException>( &MemoryException::translate );
@ -411,83 +430,83 @@ BOOST_PYTHON_MODULE( pykd )
"intBase")
.def( boost::python::init<>() )
.def( boost::python::init<ULONG64>( boost::python::args("value"), "constructor" ) )
.def( "value", &intBase::value )
.def( int_( boost::python::self ) )
//.def( boost::python::self = long() )
//.def( boost::python::self = long() )
.def( boost::python::self + long() )
.def( long() + boost::python::self )
.def( boost::python::self += long() )
.def( boost::python::self + boost::python::self )
.def( boost::python::self += boost::python::self )
.def( boost::python::self += boost::python::self )
.def( boost::python::self - long() )
.def( long() - boost::python::self )
.def( boost::python::self -= long() )
.def( boost::python::self - boost::python::self )
.def( boost::python::self -= boost::python::self )
.def( boost::python::self * long() )
.def( long() * boost::python::self )
.def( boost::python::self *= long() )
.def( boost::python::self * boost::python::self )
.def( boost::python::self *= boost::python::self )
.def( boost::python::self / long() )
.def( long() / boost::python::self )
.def( boost::python::self /= long() )
.def( boost::python::self / boost::python::self )
.def( boost::python::self /= boost::python::self )
.def( boost::python::self /= boost::python::self )
.def( boost::python::self % long() )
.def( long() % boost::python::self )
.def( boost::python::self %= long() )
.def( boost::python::self % boost::python::self )
.def( boost::python::self %= boost::python::self )
.def( boost::python::self %= boost::python::self )
.def( boost::python::self & long() )
.def( long() & boost::python::self )
.def( boost::python::self &= long() )
.def( boost::python::self & boost::python::self )
.def( boost::python::self &= boost::python::self )
.def( boost::python::self &= boost::python::self )
.def( boost::python::self | long() )
.def( long() | boost::python::self )
.def( boost::python::self |= long() )
.def( boost::python::self | boost::python::self )
.def( boost::python::self |= boost::python::self )
.def( boost::python::self |= boost::python::self )
.def( boost::python::self ^ long() )
.def( long() ^ boost::python::self )
.def( boost::python::self ^= long() )
.def( boost::python::self ^ boost::python::self )
.def( boost::python::self ^= boost::python::self )
.def( boost::python::self ^= boost::python::self )
.def( boost::python::self << long() )
.def( boost::python::self <<= long() )
.def( boost::python::self >> long() )
.def( boost::python::self >>= long() )
.def( boost::python::self < long() )
.def( boost::python::self < boost::python::self )
.def( boost::python::self <= long() )
.def( boost::python::self <= boost::python::self )
.def( boost::python::self < long() )
.def( boost::python::self < boost::python::self )
.def( boost::python::self <= long() )
.def( boost::python::self <= boost::python::self )
.def( boost::python::self == long() )
.def( boost::python::self == boost::python::self )
.def( boost::python::self >= long() )
.def( boost::python::self >= boost::python::self )
.def( boost::python::self > long() )
.def( boost::python::self > boost::python::self )
.def( boost::python::self != long() )
.def( boost::python::self != boost::python::self )
.def( boost::python::self == boost::python::self )
.def( boost::python::self >= long() )
.def( boost::python::self >= boost::python::self )
.def( boost::python::self > long() )
.def( boost::python::self > boost::python::self )
.def( boost::python::self != long() )
.def( boost::python::self != boost::python::self )
.def( ~boost::python::self )
.def( !boost::python::self )

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")