+ exception/breakpoint handling test for separate client
 + eventHandler catch python exception
   

git-svn-id: https://pykd.svn.codeplex.com/svn@73527 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2012-01-23 22:00:00 +00:00 committed by Mikhail I. Izmestev
parent bbd6dde6e9
commit 0107a6cb1f
6 changed files with 185 additions and 484 deletions

View File

@ -1,15 +1,18 @@
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//// Load/Unload module events // User-customizing debug event handler
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//
#include "stdafx.h" #include "stdafx.h"
#include "dbgevent.h" #include "dbgevent.h"
#include "dbgclient.h" #include "dbgclient.h"
////////////////////////////////////////////////////////////////////////////////
std::wstring fetchPythonExceptionStrings( python::object &tracebackModule );
namespace pykd { namespace pykd {
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
EventHandler::EventHandler() EventHandler::EventHandler()
{ {
@ -26,7 +29,7 @@ EventHandler::EventHandler()
m_parentClient = g_dbgClient; m_parentClient = g_dbgClient;
} }
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
EventHandler::EventHandler( DebugClientPtr &client ) EventHandler::EventHandler( DebugClientPtr &client )
{ {
@ -43,14 +46,14 @@ EventHandler::EventHandler( DebugClientPtr &client )
m_parentClient = client; m_parentClient = client;
} }
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
EventHandler::~EventHandler() EventHandler::~EventHandler()
{ {
m_handlerClient->SetEventCallbacks( NULL ); m_handlerClient->SetEventCallbacks( NULL );
} }
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
HRESULT EventHandler::GetInterestMask( HRESULT EventHandler::GetInterestMask(
__out PULONG Mask __out PULONG Mask
@ -67,79 +70,24 @@ HRESULT EventHandler::GetInterestMask(
return S_OK; return S_OK;
} }
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
HRESULT EventHandler::Breakpoint( HRESULT EventHandler::Breakpoint(
__in PDEBUG_BREAKPOINT Bp __in PDEBUG_BREAKPOINT Bp
) )
{ {
// boost::python::dict bpParameters; ULONG Id;
// HRESULT hres = Bp->GetId(&Id);
// HRESULT hres; if (S_OK == hres)
// ULONG Value = 0; {
// ULONG Value2 = 0; PyThread_StateSave pyThreadSave( m_parentClient->getThreadState() );
// ULONG64 Value64 = 0; return onBreakpoint(Id);
// 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;
boost::python::dict bpParameters; return DEBUG_STATUS_NO_CHANGE;
return onBreakpoint( bpParameters );
//onException(bpParameters);
//return S_OK;
} }
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
HRESULT EventHandler::Exception( HRESULT EventHandler::Exception(
__in PEXCEPTION_RECORD64 Exception, __in PEXCEPTION_RECORD64 Exception,
@ -151,7 +99,7 @@ HRESULT EventHandler::Exception(
// build list of parameters // build list of parameters
for (ULONG i = 0; i < Exception->NumberParameters; ++i) for (ULONG i = 0; i < Exception->NumberParameters; ++i)
exceptParams.append(Exception->ExceptionInformation[i]); exceptParams.append( Exception->ExceptionInformation[i] );
exceptData["Code"] = Exception->ExceptionCode; exceptData["Code"] = Exception->ExceptionCode;
exceptData["Flags"] = Exception->ExceptionFlags; exceptData["Flags"] = Exception->ExceptionFlags;
@ -165,7 +113,7 @@ HRESULT EventHandler::Exception(
return onException(exceptData); return onException(exceptData);
} }
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
HRESULT EventHandler::LoadModule( HRESULT EventHandler::LoadModule(
__in ULONG64 ImageFileHandle, __in ULONG64 ImageFileHandle,
@ -181,7 +129,7 @@ HRESULT EventHandler::LoadModule(
return onLoadModule( m_parentClient->loadModuleByOffset(BaseOffset) ); return onLoadModule( m_parentClient->loadModuleByOffset(BaseOffset) );
} }
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
HRESULT EventHandler::UnloadModule( HRESULT EventHandler::UnloadModule(
__in PCSTR ImageBaseName, __in PCSTR ImageBaseName,
@ -193,7 +141,7 @@ HRESULT EventHandler::UnloadModule(
return onUnloadModule( BaseOffset ); return onUnloadModule( BaseOffset );
} }
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
HRESULT EventHandler::SessionStatus( HRESULT EventHandler::SessionStatus(
__in ULONG Status __in ULONG Status
@ -205,7 +153,7 @@ HRESULT EventHandler::SessionStatus(
return S_OK; return S_OK;
} }
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
HRESULT EventHandler::ChangeDebuggeeState( HRESULT EventHandler::ChangeDebuggeeState(
__in ULONG Flags, __in ULONG Flags,
@ -218,229 +166,14 @@ HRESULT EventHandler::ChangeDebuggeeState(
return S_OK; return S_OK;
} }
/////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void EventHandlerWrap::onHandlerException()
{
// TODO: some logging, alerting....
}
////////////////////////////////////////////////////////////////////////////////
}; // end pykd namespace }; // end pykd namespace
//#include "dbgevent.h"
//#include "dbgio.h"
//#include "dbgexcept.h"
//#include "pyaux.h"
//
/////////////////////////////////////////////////////////////////////////////////////
//
//debugEvent::debugEvent()
//{
// HRESULT hres;
//
// hres = dbgExt->client->CreateClient( &m_debugClient );
// if ( FAILED( hres ) )
// throw DbgException( "IDebugClient::CreateClient" );
//
// hres = m_debugClient->SetEventCallbacks(this);
// if (FAILED(hres))
// throw DbgException( "IDebugClient::SetEventCallbacks" );
//}
//
/////////////////////////////////////////////////////////////////////////////////////
//
//debugEvent::~debugEvent()
//{
// m_debugClient->SetEventCallbacks( NULL );
//
// m_debugClient->Release();
//}
//
/////////////////////////////////////////////////////////////////////////////////////
//
//HRESULT debugEvent::GetInterestMask(
// __out PULONG Mask
//)
//{
// *Mask = 0;
//
// *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,
// __in ULONG ModuleSize,
// __in PCSTR ModuleName,
// __in PCSTR ImageName,
// __in ULONG CheckSum,
// __in ULONG TimeDateStamp
//)
//{
// std::auto_ptr<OutputReader> silentMode( new OutputReader(dbgExt->client) );
//
// ULONG64 moduleBase;
// ULONG moduleSize;
// std::string moduleName;
//
// queryModuleParams(BaseOffset, moduleName, moduleBase, moduleSize);
// dbgModuleClass module(moduleName, moduleBase, moduleSize);
// silentMode.reset();
//
// PyThread_StateSave pyThreadSave;
// return onLoadModule( module );
//}
//
/////////////////////////////////////////////////////////////////////////////////////
//
//HRESULT debugEvent::UnloadModule(
// __in PCSTR ImageBaseName,
// __in ULONG64 BaseOffset
//)
//{
// std::auto_ptr<OutputReader> silentMode( new OutputReader(dbgExt->client) );
//
// ULONG64 moduleBase;
// ULONG moduleSize;
// std::string moduleName;
//
// queryModuleParams(BaseOffset, moduleName, moduleBase, moduleSize);
// dbgModuleClass module(moduleName, moduleBase, moduleSize);
// silentMode.reset();
//
// PyThread_StateSave pyThreadSave;
// return onUnloadModule( module );
//}
//
/////////////////////////////////////////////////////////////////////////////////////
//
//HRESULT debugEvent::SessionStatus(
// __in ULONG Status
//)
//{
// PyThread_StateSave pyThreadSave;
// return onChangeSessionStatus( Status );
//}
//
/////////////////////////////////////////////////////////////////////////////////////
//
//HRESULT debugEvent::ChangeDebuggeeState(
// __in ULONG Flags,
// __in ULONG64 Argument
//)
//{
// PyThread_StateSave pyThreadSave;
// return onChangeDebugeeState();
//}
//
/////////////////////////////////////////////////////////////////////////////////////
//

View File

@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// user-customizing debug event handler // User-customizing debug event handler
///////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#pragma once #pragma once
@ -13,7 +13,7 @@
namespace pykd { namespace pykd {
///////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class EventHandler : public DebugBaseEventCallbacks class EventHandler : public DebugBaseEventCallbacks
{ {
@ -69,7 +69,7 @@ protected:
protected: protected:
virtual ULONG onBreakpoint(const python::dict &/*bpParameters*/) = 0; virtual ULONG onBreakpoint(ULONG Id) = 0;
virtual ULONG onException(const python::dict &/*exceptData*/) = 0; virtual ULONG onException(const python::dict &/*exceptData*/) = 0;
@ -88,7 +88,7 @@ protected:
DebugClientPtr m_parentClient; DebugClientPtr m_parentClient;
}; };
///////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class EventHandlerWrap : public python::wrapper<EventHandler>, public EventHandler class EventHandlerWrap : public python::wrapper<EventHandler>, public EventHandler
{ {
@ -101,8 +101,8 @@ public:
EventHandlerWrap( DebugClientPtr &client ) : EventHandler( client ) EventHandlerWrap( DebugClientPtr &client ) : EventHandler( client )
{} {}
ULONG onBreakpoint(const python::dict &bpParameters) { ULONG onBreakpoint(ULONG Id) {
return handler<const python::dict&>("onBreakpoint", bpParameters); return handler("onBreakpoint", Id);
} }
ULONG onException(const python::dict &exceptData) { ULONG onException(const python::dict &exceptData) {
@ -125,163 +125,41 @@ public:
return handler( "onChangeDebugeeState" ); return handler( "onChangeDebugeeState" );
} }
void onHandlerException();
private: private:
template<typename Arg1Type> template<typename Arg1Type>
ULONG handler( const char* handlerName, Arg1Type arg1 ) ULONG handler( const char* handlerName, Arg1Type arg1 )
{ {
if (python::override pythonHandler = get_override( handlerName )) if (python::override pythonHandler = get_override( handlerName ))
{
try {
return pythonHandler(arg1); return pythonHandler(arg1);
}
catch (const python::error_already_set &) {
onHandlerException();
}
}
return DEBUG_STATUS_NO_CHANGE; return DEBUG_STATUS_NO_CHANGE;
} }
ULONG handler( const char* handlerName ) ULONG handler( const char* handlerName )
{ {
if (python::override pythonHandler = get_override( handlerName )) if (python::override pythonHandler = get_override( handlerName ))
{
try {
return pythonHandler(); return pythonHandler();
}
catch (const python::error_already_set &) {
onHandlerException();
}
}
return DEBUG_STATUS_NO_CHANGE; return DEBUG_STATUS_NO_CHANGE;
} }
}; };
///////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
}; // end namespace pykd }; // end namespace pykd
//#include "dbgeventcb.h"
//#include "dbgmodule.h"
//#include "pyaux.h"
//
///////////////////////////////////////////////////////////////////////////////////
//
//class debugEvent : public DebugBaseEventCallbacks
//{
//public:
//
// 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 onUnloadModule(const dbgModuleClass &/* module */) = 0;
//
// virtual ULONG onChangeSessionStatus( ULONG status ) = 0;
//
// virtual ULONG onChangeDebugeeState() = 0;
//
//private:
//
// STDMETHOD_(ULONG, AddRef)() { return 1; }
// STDMETHOD_(ULONG, Release)() { return 1; }
//
// STDMETHOD(GetInterestMask)(
// __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,
// __in ULONG ModuleSize,
// __in PCSTR ModuleName,
// __in PCSTR ImageName,
// __in ULONG CheckSum,
// __in ULONG TimeDateStamp
// );
//
// STDMETHOD(UnloadModule)(
// __in PCSTR ImageBaseName,
// __in ULONG64 BaseOffset
// );
//
// STDMETHOD(SessionStatus)(
// __in ULONG Status
// );
//
// STDMETHOD(ChangeDebuggeeState)(
// __in ULONG Flags,
// __in ULONG64 Argument );
//
//private:
//
// IDebugClient *m_debugClient;
//};
//
///////////////////////////////////////////////////////////////////////////////////
//
//class debugEventWrap : public boost::python::wrapper<debugEvent>, public debugEvent
//{
//
//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 );
// }
//
// ULONG onUnloadModule(const dbgModuleClass &module) {
// return handler<const dbgModuleClass &>("onUnloadModule", module );
// }
//
// ULONG onChangeSessionStatus( ULONG status ) {
// return handler( "onChangeSessionStatus", status );
// }
//
// ULONG onChangeDebugeeState() {
// return handler( "onChangeDebugeeState" );
// }
//
//private:
//
// template<typename Arg1Type>
// ULONG handler( const char* handlerName, Arg1Type arg1 )
// {
// if (boost::python::override pythonHandler = get_override( handlerName ))
// return pythonHandler(arg1);
//
// return DEBUG_STATUS_NO_CHANGE;
// }
//
// ULONG handler( const char* handlerName )
// {
// if (boost::python::override pythonHandler = get_override( handlerName ))
// return pythonHandler();
//
// return DEBUG_STATUS_NO_CHANGE;
// }
//};
//
///////////////////////////////////////////////////////////////////////////////////

View File

@ -569,11 +569,7 @@ BOOST_PYTHON_MODULE( pykd )
.def( python::init<>() ) .def( python::init<>() )
.def( python::init<DebugClientPtr&>() ) .def( python::init<DebugClientPtr&>() )
.def( "onBreakpoint", &pykd::EventHandlerWrap::onBreakpoint, .def( "onBreakpoint", &pykd::EventHandlerWrap::onBreakpoint,
"Triggered breakpoint event. Parameter is dict:\n" "Triggered breakpoint event. Parameter is int: ID of breakpoint\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" ) "For ignore event method must return DEBUG_STATUS_NO_CHANGE value" )
.def( "onException", &pykd::EventHandlerWrap::onException, .def( "onException", &pykd::EventHandlerWrap::onException,
"Exception event. Parameter is dict:\n" "Exception event. Parameter is dict:\n"
@ -837,6 +833,30 @@ BOOST_PYTHON_MODULE( pykd )
DEF_PY_CONST_ULONG( DEBUG_USER_WINDOWS_SMALL_DUMP ); DEF_PY_CONST_ULONG( DEBUG_USER_WINDOWS_SMALL_DUMP );
DEF_PY_CONST_ULONG( DEBUG_USER_WINDOWS_DUMP ); DEF_PY_CONST_ULONG( DEBUG_USER_WINDOWS_DUMP );
// exception codes
DEF_PY_CONST_ULONG(EXCEPTION_ACCESS_VIOLATION);
DEF_PY_CONST_ULONG(EXCEPTION_DATATYPE_MISALIGNMENT);
DEF_PY_CONST_ULONG(EXCEPTION_BREAKPOINT);
DEF_PY_CONST_ULONG(EXCEPTION_SINGLE_STEP);
DEF_PY_CONST_ULONG(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
DEF_PY_CONST_ULONG(EXCEPTION_FLT_DENORMAL_OPERAND);
DEF_PY_CONST_ULONG(EXCEPTION_FLT_DIVIDE_BY_ZERO);
DEF_PY_CONST_ULONG(EXCEPTION_FLT_INEXACT_RESULT);
DEF_PY_CONST_ULONG(EXCEPTION_FLT_INVALID_OPERATION);
DEF_PY_CONST_ULONG(EXCEPTION_FLT_OVERFLOW);
DEF_PY_CONST_ULONG(EXCEPTION_FLT_STACK_CHECK);
DEF_PY_CONST_ULONG(EXCEPTION_FLT_UNDERFLOW);
DEF_PY_CONST_ULONG(EXCEPTION_INT_DIVIDE_BY_ZERO);
DEF_PY_CONST_ULONG(EXCEPTION_INT_OVERFLOW);
DEF_PY_CONST_ULONG(EXCEPTION_PRIV_INSTRUCTION);
DEF_PY_CONST_ULONG(EXCEPTION_IN_PAGE_ERROR);
DEF_PY_CONST_ULONG(EXCEPTION_ILLEGAL_INSTRUCTION);
DEF_PY_CONST_ULONG(EXCEPTION_NONCONTINUABLE_EXCEPTION);
DEF_PY_CONST_ULONG(EXCEPTION_STACK_OVERFLOW);
DEF_PY_CONST_ULONG(EXCEPTION_INVALID_DISPOSITION);
DEF_PY_CONST_ULONG(EXCEPTION_GUARD_PAGE);
DEF_PY_CONST_ULONG(EXCEPTION_INVALID_HANDLE);
// debug status // debug status
DEF_PY_CONST_ULONG(DEBUG_STATUS_NO_CHANGE); DEF_PY_CONST_ULONG(DEBUG_STATUS_NO_CHANGE);
DEF_PY_CONST_ULONG(DEBUG_STATUS_GO); DEF_PY_CONST_ULONG(DEBUG_STATUS_GO);
@ -1013,7 +1033,6 @@ py( PDEBUG_CLIENT4 client, PCSTR args )
for ( long i = 0; i < python::len(lst); ++i ) for ( long i = 0; i < python::len(lst); ++i )
sstr << std::wstring( python::extract<std::wstring>(lst[i]) ) << std::endl; sstr << std::wstring( python::extract<std::wstring>(lst[i]) ) << std::endl;
dbgClient->eprintln( sstr.str() ); dbgClient->eprintln( sstr.str() );
} }

View File

@ -0,0 +1,65 @@
"""Debug events handler: test exceptions and debug breaks"""
import unittest
import target
import pykd
class BreakExceptionHandler(pykd.eventHandler):
"""Track load/unload module implementation"""
def __init__(self, client):
pykd.eventHandler.__init__(self, client)
self.client = client
self.wasSecondChance = False
self.wasBreakpoint = False
self.bpLastModuleName = ""
self.bpCount = 0
self.firstChanceAccessAddresses = []
self.secondChanceAccessAddresses = []
def onBreakpoint(self, bpId):
"""Breakpoint handler"""
self.wasBreakpoint = True
return pykd.DEBUG_STATUS_NO_CHANGE
def onException(self, exceptParams):
"""Exception handler"""
self.wasSecondChance = not exceptParams["FirstChance"]
if exceptParams["Code"] == pykd.EXCEPTION_ACCESS_VIOLATION:
if self.wasSecondChance:
print exceptParams["Parameters"]
self.secondChanceAccessAddresses.append( exceptParams["Parameters"][1] )
else:
self.firstChanceAccessAddresses.append( exceptParams["Parameters"][1] )
elif exceptParams["Code"] == pykd.EXCEPTION_BREAKPOINT:
self.bpCount += 1
return pykd.DEBUG_STATUS_BREAK if self.wasSecondChance else pykd.DEBUG_STATUS_NO_CHANGE
class EhExceptionBreakpointTest(unittest.TestCase):
"""Unit tests of exceptions end breakpoint handling"""
def testBreakpointException(self):
"""Start new process and track exceptions/breakpoints"""
testClient = pykd.createDbgClient()
testClient.startProcess( target.appPath + " -testExceptions" )
testClient.dbgCommand( ".reload /f; bp targetapp!doExeptions" )
breakExceptionHandler = BreakExceptionHandler( testClient )
while not breakExceptionHandler.wasSecondChance:
testClient.go()
self.assertTrue( breakExceptionHandler.wasBreakpoint )
self.assertEqual( [2, 3], breakExceptionHandler.firstChanceAccessAddresses )
self.assertEqual( 2, breakExceptionHandler.bpCount ) # main and doExeptions
self.assertEqual( [3, ], breakExceptionHandler.secondChanceAccessAddresses )

View File

@ -26,6 +26,7 @@ import synsymtest
import ehloadtest import ehloadtest
import thrdctxtest import thrdctxtest
import localstest import localstest
import ehexcepttest
def getTestSuite( singleName = "" ): def getTestSuite( singleName = "" ):
if singleName == "": if singleName == "":
@ -43,7 +44,8 @@ def getTestSuite( singleName = "" ):
unittest.TestLoader().loadTestsFromTestCase( synsymtest.SynSymTest ), unittest.TestLoader().loadTestsFromTestCase( synsymtest.SynSymTest ),
unittest.TestLoader().loadTestsFromTestCase( thrdctxtest.ThreadContextTest ), unittest.TestLoader().loadTestsFromTestCase( thrdctxtest.ThreadContextTest ),
unittest.TestLoader().loadTestsFromTestCase( ehloadtest.EhLoadTest ), unittest.TestLoader().loadTestsFromTestCase( ehloadtest.EhLoadTest ),
unittest.TestLoader().loadTestsFromTestCase( localstest.LocalVarsTest ) unittest.TestLoader().loadTestsFromTestCase( localstest.LocalVarsTest ),
unittest.TestLoader().loadTestsFromTestCase( ehexcepttest.EhExceptionBreakpointTest )
] ) ] )
else: else:
return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) ) return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) )
@ -73,4 +75,4 @@ if __name__ == "__main__":
unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( suite ) unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( suite )
#raw_input("\npress return\n") # raw_input("\npress return\n")

View File

@ -416,6 +416,10 @@
RelativePath="..\scripts\diatest.py" RelativePath="..\scripts\diatest.py"
> >
</File> </File>
<File
RelativePath="..\scripts\ehexcepttest.py"
>
</File>
<File <File
RelativePath="..\scripts\ehloadtest.py" RelativePath="..\scripts\ehloadtest.py"
> >