mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-20 03:23:23 +08:00
[0.3.x] refactored : supported new breakpoint model for kdlibcpp
git-svn-id: https://pykd.svn.codeplex.com/svn@87821 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
782db1ba38
commit
5aa47e8201
@ -18,6 +18,8 @@ BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
int a;
|
||||
a = 10;
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -7,189 +7,6 @@
|
||||
|
||||
namespace pykd {
|
||||
|
||||
pykd::InternalEventHandler *globalEventHandler = NULL;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
InternalEventHandler::~InternalEventHandler()
|
||||
{
|
||||
breakPointRemoveAll();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
kdlib::BREAKPOINT_ID InternalEventHandler::setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, python::object &callback )
|
||||
{
|
||||
kdlib::BREAKPOINT_ID id;
|
||||
kdlib::PROCESS_DEBUG_ID processId;
|
||||
|
||||
boost::recursive_mutex::scoped_lock l(m_breakPointLock);
|
||||
|
||||
do {
|
||||
AutoRestorePyState pystate;
|
||||
id = kdlib::softwareBreakPointSet(offset);
|
||||
processId = kdlib::getCurrentProcessId();
|
||||
} while(false);
|
||||
|
||||
m_breakPointMap[id] = Breakpoint(id, processId, callback);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
kdlib::BREAKPOINT_ID InternalEventHandler::setHardwareBreakpoint( kdlib::MEMOFFSET_64 offset, size_t size, kdlib::ACCESS_TYPE accessType, python::object &callback )
|
||||
{
|
||||
kdlib::BREAKPOINT_ID id;
|
||||
kdlib::PROCESS_DEBUG_ID processId;
|
||||
|
||||
boost::recursive_mutex::scoped_lock l(m_breakPointLock);
|
||||
|
||||
do {
|
||||
AutoRestorePyState pystate;
|
||||
id = kdlib::hardwareBreakPointSet(offset,size,accessType);
|
||||
processId = kdlib::getCurrentProcessId();
|
||||
} while(false);
|
||||
|
||||
m_breakPointMap[id] = Breakpoint(id, processId, callback);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void InternalEventHandler::breakPointRemove(kdlib::BREAKPOINT_ID bpId)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock l(m_breakPointLock);
|
||||
|
||||
BreakpointMap::iterator it = m_breakPointMap.find(bpId);
|
||||
|
||||
if ( it != m_breakPointMap.end() )
|
||||
{
|
||||
m_breakPointMap.erase(it);
|
||||
|
||||
try {
|
||||
AutoRestorePyState pystate;
|
||||
kdlib::breakPointRemove(bpId);
|
||||
} catch(kdlib::DbgException&)
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void InternalEventHandler::breakPointRemoveAll()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock l(m_breakPointLock);
|
||||
|
||||
BreakpointMap::iterator it;
|
||||
|
||||
for ( it = m_breakPointMap.begin(); it != m_breakPointMap.end(); ++it )
|
||||
{
|
||||
try {
|
||||
AutoRestorePyState pystate;
|
||||
kdlib::breakPointRemove(it->first);
|
||||
} catch(kdlib::DbgException&)
|
||||
{}
|
||||
}
|
||||
|
||||
m_breakPointMap.clear();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
kdlib::DebugCallbackResult InternalEventHandler::onBreakpoint( kdlib::BREAKPOINT_ID bpId )
|
||||
{
|
||||
kdlib::DebugCallbackResult result = kdlib::DebugCallbackNoChange;
|
||||
|
||||
boost::recursive_mutex::scoped_lock l(m_breakPointLock);
|
||||
|
||||
BreakpointMap::iterator it = m_breakPointMap.find(bpId);
|
||||
if ( it != m_breakPointMap.end() )
|
||||
{
|
||||
PyEval_RestoreThread( m_pystate );
|
||||
|
||||
do {
|
||||
|
||||
python::object &callback = it->second.getCallback();
|
||||
|
||||
if ( !callback )
|
||||
{
|
||||
result = kdlib::DebugCallbackBreak;
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
python::object resObj = callback( bpId );
|
||||
|
||||
if ( resObj.is_none() )
|
||||
{
|
||||
result = kdlib::DebugCallbackNoChange;
|
||||
break;
|
||||
}
|
||||
|
||||
int retVal = python::extract<int>( resObj );
|
||||
|
||||
if ( retVal >= kdlib::DebugCallbackMax )
|
||||
{
|
||||
result = kdlib::DebugCallbackBreak;
|
||||
break;
|
||||
}
|
||||
|
||||
result = kdlib::DebugCallbackResult(retVal);
|
||||
|
||||
}
|
||||
catch (const python::error_already_set &)
|
||||
{
|
||||
printException();
|
||||
result = kdlib::DebugCallbackBreak;
|
||||
}
|
||||
|
||||
} while( false);
|
||||
|
||||
m_pystate = PyEval_SaveThread();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = kdlib::DebugCallbackNoChange;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
kdlib::DebugCallbackResult InternalEventHandler::onProcessExit( kdlib::PROCESS_DEBUG_ID processId, kdlib::ProcessExitReason reason, unsigned long exitCode )
|
||||
{
|
||||
|
||||
boost::recursive_mutex::scoped_lock l(m_breakPointLock);
|
||||
|
||||
BreakpointMap::iterator it = m_breakPointMap.begin();
|
||||
|
||||
while( it != m_breakPointMap.end() )
|
||||
{
|
||||
if ( it->second.getProcessId() == processId )
|
||||
{
|
||||
kdlib::breakPointRemove(it->first);
|
||||
|
||||
PyEval_RestoreThread( m_pystate );
|
||||
|
||||
m_breakPointMap.erase(it);
|
||||
|
||||
m_pystate = PyEval_SaveThread();
|
||||
|
||||
it = m_breakPointMap.begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
return kdlib::DebugCallbackNoChange;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EventHandler::EventHandler()
|
||||
@ -425,5 +242,147 @@ kdlib::DebugCallbackResult EventHandler::onModuleUnload( kdlib::MEMOFFSET_64 of
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CallbackBreakpoint : public kdlib::BaseBreakpoint
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
static kdlib::BREAKPOINT_ID setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, python::object &callback);
|
||||
static kdlib::BREAKPOINT_ID setHardwareBreakpoint( kdlib::MEMOFFSET_64 offset, size_t size, kdlib::ACCESS_TYPE accessType, python::object &callback );
|
||||
static void removeBreakpoint( kdlib::BREAKPOINT_ID id );
|
||||
|
||||
private:
|
||||
|
||||
virtual kdlib::DebugCallbackResult onHit();
|
||||
|
||||
python::object m_callback;
|
||||
PyThreadState* m_pystate;
|
||||
|
||||
typedef std::map<kdlib::BREAKPOINT_ID, CallbackBreakpoint*> BreakpointMap;
|
||||
static boost::recursive_mutex m_breakpointLock;
|
||||
static BreakpointMap m_breakpointMap;
|
||||
};
|
||||
|
||||
CallbackBreakpoint::BreakpointMap CallbackBreakpoint::m_breakpointMap;
|
||||
boost::recursive_mutex CallbackBreakpoint::m_breakpointLock;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
kdlib::BREAKPOINT_ID CallbackBreakpoint::setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, python::object &callback)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock l(m_breakpointLock);
|
||||
|
||||
CallbackBreakpoint *bp = new CallbackBreakpoint();
|
||||
bp->m_pystate = PyThreadState_Get();
|
||||
bp->m_callback = callback;
|
||||
bp->set(offset);
|
||||
|
||||
m_breakpointMap[bp->m_id] = bp;
|
||||
|
||||
return bp->m_id;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
kdlib::BREAKPOINT_ID CallbackBreakpoint::setHardwareBreakpoint( kdlib::MEMOFFSET_64 offset, size_t size, kdlib::ACCESS_TYPE accessType, python::object &callback )
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock l(m_breakpointLock);
|
||||
|
||||
CallbackBreakpoint *bp = new CallbackBreakpoint();
|
||||
bp->m_pystate = PyThreadState_Get();
|
||||
bp->m_callback = callback;
|
||||
bp->set(offset,size,accessType);
|
||||
|
||||
m_breakpointMap[bp->m_id] = bp;
|
||||
|
||||
return bp->m_id;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CallbackBreakpoint::removeBreakpoint( kdlib::BREAKPOINT_ID id )
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock l(m_breakpointLock);
|
||||
|
||||
BreakpointMap::iterator it = m_breakpointMap.find(id);
|
||||
if ( it != m_breakpointMap.end() )
|
||||
m_breakpointMap.erase(it);
|
||||
|
||||
kdlib::breakPointRemove(id);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
kdlib::DebugCallbackResult CallbackBreakpoint::onHit()
|
||||
{
|
||||
kdlib::DebugCallbackResult result = kdlib::DebugCallbackNoChange;
|
||||
|
||||
PyEval_RestoreThread( m_pystate );
|
||||
|
||||
try {
|
||||
|
||||
do {
|
||||
|
||||
if ( !m_callback )
|
||||
{
|
||||
result = kdlib::DebugCallbackBreak;
|
||||
break;
|
||||
}
|
||||
|
||||
python::object resObj = m_callback();
|
||||
|
||||
if ( resObj.is_none() )
|
||||
{
|
||||
result = kdlib::DebugCallbackNoChange;
|
||||
break;
|
||||
}
|
||||
|
||||
int retVal = python::extract<int>( resObj );
|
||||
|
||||
if ( retVal >= kdlib::DebugCallbackMax )
|
||||
{
|
||||
result = kdlib::DebugCallbackBreak;
|
||||
break;
|
||||
}
|
||||
|
||||
result = kdlib::DebugCallbackResult(retVal);
|
||||
|
||||
} while( FALSE );
|
||||
|
||||
}
|
||||
catch (const python::error_already_set &)
|
||||
{
|
||||
printException();
|
||||
result = kdlib::DebugCallbackBreak;
|
||||
}
|
||||
|
||||
m_pystate = PyEval_SaveThread();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
kdlib::BREAKPOINT_ID setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, python::object &callback)
|
||||
{
|
||||
return CallbackBreakpoint::setSoftwareBreakpoint(offset,callback);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
kdlib::BREAKPOINT_ID setHardwareBreakpoint( kdlib::MEMOFFSET_64 offset, size_t size, kdlib::ACCESS_TYPE accessType,python::object &callback)
|
||||
{
|
||||
return CallbackBreakpoint::setHardwareBreakpoint(offset, size, accessType,callback);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void breakPointRemove( kdlib::BREAKPOINT_ID id )
|
||||
{
|
||||
CallbackBreakpoint::removeBreakpoint(id);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
} // end namespace pykd
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "kdlib/dbgengine.h"
|
||||
#include "kdlib/eventhandler.h"
|
||||
#include "kdlib/breakpoint.h"
|
||||
|
||||
#include "boost/shared_ptr.hpp"
|
||||
#include "boost/noncopyable.hpp"
|
||||
@ -40,98 +41,33 @@ private:
|
||||
PyThreadState* m_pystate;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Breakpoint
|
||||
{
|
||||
public:
|
||||
|
||||
Breakpoint()
|
||||
{}
|
||||
|
||||
Breakpoint(
|
||||
kdlib::BREAKPOINT_ID& bpId,
|
||||
kdlib::PROCESS_DEBUG_ID& targetId,
|
||||
python::object& callback
|
||||
) : m_bpId(bpId), m_processId(targetId), m_callback(callback)
|
||||
{}
|
||||
|
||||
kdlib::BREAKPOINT_ID getId() const {
|
||||
return m_bpId;
|
||||
}
|
||||
|
||||
kdlib::PROCESS_DEBUG_ID getProcessId() const {
|
||||
return m_processId;
|
||||
}
|
||||
|
||||
python::object& getCallback() {
|
||||
return m_callback;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
kdlib::BREAKPOINT_ID m_bpId;
|
||||
kdlib::PROCESS_DEBUG_ID m_processId;
|
||||
python::object m_callback;
|
||||
};
|
||||
|
||||
class InternalEventHandler: public kdlib::EventHandler
|
||||
{
|
||||
public:
|
||||
|
||||
InternalEventHandler() {
|
||||
m_pystate = PyThreadState_Get();
|
||||
}
|
||||
|
||||
~InternalEventHandler();
|
||||
|
||||
kdlib::BREAKPOINT_ID setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, python::object &callback = python::object() );
|
||||
|
||||
kdlib::BREAKPOINT_ID setHardwareBreakpoint( kdlib::MEMOFFSET_64 offset, size_t size = 0, kdlib::ACCESS_TYPE accessType = 0, python::object &callback = python::object() );
|
||||
|
||||
void breakPointRemove(kdlib::BREAKPOINT_ID bpId);
|
||||
|
||||
void breakPointRemoveAll();
|
||||
|
||||
private:
|
||||
|
||||
virtual kdlib::DebugCallbackResult onBreakpoint( kdlib::BREAKPOINT_ID bpId );
|
||||
|
||||
virtual kdlib::DebugCallbackResult onProcessExit( kdlib::PROCESS_DEBUG_ID processid, kdlib::ProcessExitReason reason, unsigned long exitCode );
|
||||
|
||||
private:
|
||||
|
||||
PyThreadState* m_pystate;
|
||||
|
||||
typedef std::map<kdlib::BREAKPOINT_ID, Breakpoint> BreakpointMap;
|
||||
boost::recursive_mutex m_breakPointLock;
|
||||
BreakpointMap m_breakPointMap;
|
||||
|
||||
};
|
||||
|
||||
extern pykd::InternalEventHandler *globalEventHandler;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline kdlib::BREAKPOINT_ID setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, python::object &callback = python::object() )
|
||||
{
|
||||
return globalEventHandler->setSoftwareBreakpoint(offset, callback);
|
||||
}
|
||||
kdlib::BREAKPOINT_ID setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, python::object &callback = python::object() );
|
||||
kdlib::BREAKPOINT_ID setHardwareBreakpoint( kdlib::MEMOFFSET_64 offset, size_t size, kdlib::ACCESS_TYPE accessType,python::object &callback = python::object()) ;
|
||||
void breakPointRemove( kdlib::BREAKPOINT_ID id );
|
||||
|
||||
inline kdlib::BREAKPOINT_ID setHardwareBreakpoint( kdlib::MEMOFFSET_64 offset, size_t size = 0, kdlib::ACCESS_TYPE accessType = 0, python::object &callback = python::object() )
|
||||
{
|
||||
return globalEventHandler->setHardwareBreakpoint( offset, size, accessType, callback);
|
||||
}
|
||||
|
||||
inline void breakPointRemove( kdlib::BREAKPOINT_ID id )
|
||||
{
|
||||
globalEventHandler->breakPointRemove(id);
|
||||
}
|
||||
|
||||
inline void breakPointRemoveAll()
|
||||
{
|
||||
globalEventHandler->breakPointRemoveAll();
|
||||
}
|
||||
//class Breakpoint : public kdlib::BaseBreakpoint {
|
||||
//
|
||||
//public:
|
||||
//
|
||||
// static kdlib::BreakpointPtr setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset )
|
||||
// static kdlib::BreakpointPtr setHardwareBreakpoint( kdlib::MEMOFFSET_64 offset, size_t size, kdlib::ACCESS_TYPE accessType );
|
||||
// static void breakPointRemove( kdlib::BREAKPOINT_ID id );
|
||||
//
|
||||
// ~Breakpoint();
|
||||
//
|
||||
//protected:
|
||||
//
|
||||
// static BreakpointMap m_breakpointMap;
|
||||
// static boost::recursive_mutex m_breakpointLock;
|
||||
//
|
||||
// kdlib::BREAKPOINT_ID m_id;
|
||||
//
|
||||
// PyThreadState* m_pystate;
|
||||
//
|
||||
//};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -92,14 +92,10 @@ namespace pykd {
|
||||
void initialize()
|
||||
{
|
||||
kdlib::initialize();
|
||||
|
||||
globalEventHandler = new InternalEventHandler();
|
||||
}
|
||||
|
||||
void uninitialize()
|
||||
{
|
||||
delete globalEventHandler;
|
||||
|
||||
kdlib::uninitialize();
|
||||
}
|
||||
|
||||
@ -364,8 +360,6 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
"Set hardware breakpoint" ) );
|
||||
python::def( "removeBp", pykd::breakPointRemove,
|
||||
"Remove breapoint by IDs" );
|
||||
python::def( "removeAllBp", &breakPointRemoveAll,
|
||||
"Remove all breapoints" );
|
||||
|
||||
// processes and threads
|
||||
python::def ( "getNumberProcesses", pykd::getNumberProcesses,
|
||||
@ -640,9 +634,10 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
.add_static_property( "VoidPtr", &BaseTypesEnum::getVoidPtr )
|
||||
;
|
||||
|
||||
//python::class_<Breakpoint, BreakpointPtr, boost::noncopyable>( "breakpoint",
|
||||
//python::class_<kdlib::Breakpoint, kdlib::BreakpointPtr, boost::noncopyable>( "breakpoint",
|
||||
// "class for breakpoint representation", python::no_init )
|
||||
// .def("__init__", python::make_constructor(Breakpoint::setSoftwareBreakpoint) )
|
||||
// .def("__init__", python::make_constructor(pykd::Breakpoint::setSoftwareBreakpoint) )
|
||||
// .def("__init__", python::make_constructor(pykd::Breakpoint::setHardwareBreakpoint) )
|
||||
// ;
|
||||
|
||||
python::class_<kdlib::StackFrame, kdlib::StackFramePtr, boost::noncopyable>( "stackFrame",
|
||||
|
@ -9,22 +9,14 @@ class callCounter(object):
|
||||
def __init__(self,func):
|
||||
self.count = 0
|
||||
self.func = func
|
||||
def __call__(self,val):
|
||||
def __call__(self):
|
||||
self.count = self.count+1
|
||||
return self.func(val)
|
||||
return self.func()
|
||||
|
||||
|
||||
class breakpoint(object):
|
||||
def __init__(self, offset, callback):
|
||||
self.id = pykd.setBp(offset,callback)
|
||||
def __del__(self):
|
||||
pykd.removeBp(self.id)
|
||||
|
||||
|
||||
def stopOnBreak(id):
|
||||
def stopOnBreak():
|
||||
return pykd.eventResult.Break
|
||||
|
||||
def continueOnBreak(id):
|
||||
def continueOnBreak():
|
||||
return pykd.eventResult.Proceed
|
||||
|
||||
|
||||
@ -65,7 +57,7 @@ class BreakpointTest( unittest.TestCase ):
|
||||
|
||||
breakCount = callCounter(stopOnBreak)
|
||||
|
||||
bp = breakpoint( targetModule.CdeclFunc, breakCount )
|
||||
bp = pykd.setBp( targetModule.CdeclFunc, breakCount )
|
||||
|
||||
self.assertEqual( pykd.Break, pykd.go() )
|
||||
|
||||
@ -80,7 +72,7 @@ class BreakpointTest( unittest.TestCase ):
|
||||
|
||||
breakCount = callCounter(continueOnBreak)
|
||||
|
||||
bp = breakpoint( targetModule.CdeclFunc, breakCount )
|
||||
bp = pykd.setBp( targetModule.CdeclFunc, breakCount )
|
||||
|
||||
self.assertEqual( pykd.NoDebuggee, pykd.go() )
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user