[0.3.x] added : event handler

git-svn-id: https://pykd.svn.codeplex.com/svn@84101 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\kernelnet_cp 2013-06-18 06:46:43 +00:00 committed by Mikhail I. Izmestev
parent 7373b0226b
commit 0b3beb39a2
4 changed files with 180 additions and 6 deletions

View File

@ -118,5 +118,46 @@ BreakpointPtr Breakpoint::setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, pyt
///////////////////////////////////////////////////////////////////////////////
EventHandler::EventHandler()
{
m_pystate = PyThreadState_Get();
}
///////////////////////////////////////////////////////////////////////////////
kdlib::DebugCallbackResult EventHandler::onBreakpoint( kdlib::BREAKPOINT_ID bpId )
{
kdlib::DebugCallbackResult result = kdlib::DebugCallbackNoChange;
PyEval_RestoreThread( m_pystate );
try {
do {
python::override pythonHandler = get_override( "onBreakpoint" );
if ( !pythonHandler )
{
result = kdlib::EventHandler::onBreakpoint( bpId );
break;
}
return pythonHandler(bpId );
} while( FALSE );
}
catch (const python::error_already_set &)
{
printException();
result = kdlib::DebugCallbackBreak;
}
m_pystate = PyEval_SaveThread();
return result;
}
///////////////////////////////////////////////////////////////////////////////
} // end namespace pykd

View File

@ -1,10 +1,13 @@
#pragma once
#include "kdlib/dbgengine.h"
#include "kdlib/eventhandler.h"
#include "boost/shared_ptr.hpp"
#include "boost/noncopyable.hpp"
#include "boost/python/object.hpp"
#include "boost/python/wrapper.hpp"
namespace python = boost::python;
namespace pykd {
@ -30,4 +33,22 @@ protected:
///////////////////////////////////////////////////////////////////////////////
class EventHandler;
typedef boost::shared_ptr<EventHandler> EventHandlerPtr;
class EventHandler : public python::wrapper<kdlib::EventHandler>, public kdlib::EventHandler
{
public:
EventHandler();
virtual kdlib::DebugCallbackResult onBreakpoint( kdlib::BREAKPOINT_ID bpId );
private:
PyThreadState* m_pystate;
};
///////////////////////////////////////////////////////////////////////////////
} // end namespace pykd

View File

@ -634,11 +634,11 @@ BOOST_PYTHON_MODULE( pykd )
.value("NoDebuggee", kdlib::DebugStatusNoDebuggee )
.export_values();
//python::class_<EventHandler, EventHandlerPtr, boost::noncopyable>(
// "eventHandler", "Base class for overriding and handling debug notifications" )
// .def( "onBreakpoint", &EventHandler::OnBreakpoint,
// "Triggered breakpoint event. Parameter is int: ID of breakpoint\n"
// "For ignore event method must return eventResult.noChange" )
python::class_<EventHandler, EventHandlerPtr, boost::noncopyable>(
"eventHandler", "Base class for overriding and handling debug notifications" )
.def( "onBreakpoint", &EventHandler::onBreakpoint,
"Triggered breakpoint event. Parameter is int: ID of breakpoint\n"
"For ignore event method must return eventResult.noChange" )
// .def( "onModuleLoad", &EventHandlerWrap::OnModuleLoad,
// "Triggered module load event. Parameter are long: module base, string: module name\n"
// "For ignore event method must return eventResult.noChange" )
@ -657,7 +657,7 @@ BOOST_PYTHON_MODULE( pykd )
// .def( "onSymbolsUnloaded", &EventHandlerWrap::onSymbolsUnloaded,
// "Triggered debug symbols unloaded. Parameter - module base or 0 (all modules)\n"
// "There is no return value");
;
python::register_exception_translator<kdlib::IndexException>( &ExceptionTranslator::indexTranslate );

112
test/scripts/breakpoint.py Normal file
View File

@ -0,0 +1,112 @@
""" breakpoints """
import unittest
import pykd
import target
import testutils
class callCounter:
def __init__(self,func):
self.count = 0
self.func = func
def __call__(self,val):
self.count = self.count+1
return self.func(val)
def stopOnBreak(id):
return pykd.Break
def continueOnBreak(id):
return pykd.NoChange
class BreakpointTest( unittest.TestCase ):
def testNoBreakpoint(self):
processId = pykd.startProcess( target.appPath + " breakhandlertest" )
with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess :
pykd.go()
self.assertEqual( pykd.NoDebuggee, pykd.go() )
def testSetBp(self):
processId = pykd.startProcess( target.appPath + " breakhandlertest" )
targetModule = pykd.module( target.moduleName )
targetModule.reload()
with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess :
pykd.go()
pykd.setBp( targetModule.CdeclFunc )
self.assertEqual( pykd.Break, pykd.go() )
def testRemoveBp(self):
processId = pykd.startProcess( target.appPath + " breakhandlertest" )
targetModule = pykd.module( target.moduleName )
targetModule.reload()
with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess :
pykd.go()
bpid = pykd.setBp( targetModule.CdeclFunc )
pykd.removeBp( bpid )
self.assertEqual( pykd.NoDebuggee, pykd.go() )
def testBreakCallback(self):
processId = pykd.startProcess( target.appPath + " breakhandlertest" )
targetModule = pykd.module( target.moduleName )
targetModule.reload()
with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess :
pykd.go()
breakCount = callCounter(stopOnBreak)
bp = pykd.breakpoint( targetModule.CdeclFunc, breakCount )
self.assertEqual( pykd.Break, pykd.go() )
self.assertEqual( 1, breakCount.count )
def testNoBreakCallback(self):
processId = pykd.startProcess( target.appPath + " breakhandlertest" )
targetModule = pykd.module( target.moduleName )
targetModule.reload()
with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess :
pykd.go()
breakCount = callCounter(continueOnBreak)
bp = pykd.breakpoint( targetModule.CdeclFunc, breakCount )
self.assertEqual( pykd.NoDebuggee, pykd.go() )
self.assertEqual( 1, breakCount.count )
def testBreakpointHandler(self):
class BreakpointHandler( pykd.eventHandler ):
def __init__(self):
super(BreakpointHandler, self).__init__()
self.count = 0
def onBreakpoint( self, bpid_):
self.count = self.count + 1
processId = pykd.startProcess( target.appPath + " breakhandlertest" )
targetModule = pykd.module( target.moduleName )
targetModule.reload()
with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess :
pykd.go()
handler = BreakpointHandler()
pykd.setBp( targetModule.CdeclFunc )
self.assertEqual( pykd.Break, pykd.go() )
self.assertEqual( 1, handler.count )