mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-20 03:23:23 +08:00
254 lines
6.1 KiB
C++
254 lines
6.1 KiB
C++
#include "stdafx.h"
|
|
|
|
#include "kdlib\eventhandler.h"
|
|
|
|
#include "pyeventhandler.h"
|
|
#include "dbgexcept.h"
|
|
|
|
namespace pykd {
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
class SoftwareBreakpoint : public Breakpoint
|
|
{
|
|
public:
|
|
|
|
SoftwareBreakpoint( kdlib::MEMOFFSET_64 offset ) {
|
|
m_id = pykd::softwareBreakPointSet( offset );
|
|
}
|
|
|
|
~SoftwareBreakpoint() {
|
|
pykd::breakPointRemove( m_id );
|
|
}
|
|
|
|
private:
|
|
|
|
kdlib::BREAKPOINT_ID m_id;
|
|
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
class SoftwareBreakpointWithCallback : public Breakpoint, private kdlib::EventHandler
|
|
{
|
|
public:
|
|
|
|
SoftwareBreakpointWithCallback( kdlib::MEMOFFSET_64 offset, python::object &callback )
|
|
{
|
|
m_pystate = PyThreadState_Get();
|
|
m_callback = callback;
|
|
m_id = pykd::softwareBreakPointSet( offset );
|
|
}
|
|
|
|
~SoftwareBreakpointWithCallback()
|
|
{
|
|
try {
|
|
pykd::breakPointRemove( m_id );
|
|
} catch( kdlib::DbgException& )
|
|
{ }
|
|
}
|
|
|
|
private:
|
|
|
|
virtual kdlib::DebugCallbackResult onBreakpoint( kdlib::BREAKPOINT_ID bpId )
|
|
{
|
|
|
|
kdlib::DebugCallbackResult result;
|
|
|
|
if ( bpId != m_id )
|
|
return kdlib::DebugCallbackNoChange;
|
|
|
|
PyEval_RestoreThread( m_pystate );
|
|
|
|
try {
|
|
|
|
do {
|
|
|
|
python::object resObj = m_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);
|
|
|
|
} while( FALSE );
|
|
|
|
}
|
|
catch (const python::error_already_set &)
|
|
{
|
|
printException();
|
|
result = kdlib::DebugCallbackBreak;
|
|
}
|
|
|
|
m_pystate = PyEval_SaveThread();
|
|
|
|
return result;
|
|
}
|
|
|
|
kdlib::BREAKPOINT_ID m_id;
|
|
python::object m_callback;
|
|
PyThreadState* m_pystate;
|
|
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
BreakpointPtr Breakpoint::setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, python::object &callback )
|
|
{
|
|
if ( callback )
|
|
{
|
|
return BreakpointPtr( new SoftwareBreakpointWithCallback( offset, callback ) );
|
|
}
|
|
else
|
|
{
|
|
return BreakpointPtr( new SoftwareBreakpoint(offset) );
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
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;
|
|
}
|
|
|
|
python::object resObj = pythonHandler( 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);
|
|
|
|
} while( FALSE );
|
|
|
|
}
|
|
catch (const python::error_already_set &)
|
|
{
|
|
printException();
|
|
result = kdlib::DebugCallbackBreak;
|
|
}
|
|
|
|
m_pystate = PyEval_SaveThread();
|
|
|
|
return result;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void EventHandler::onExecutionStatusChange( kdlib::ExecutionStatus executionStatus )
|
|
{
|
|
PyEval_RestoreThread( m_pystate );
|
|
|
|
try {
|
|
|
|
python::override pythonHandler = get_override( "onExecutionStatusChange" );
|
|
if ( pythonHandler )
|
|
{
|
|
pythonHandler( executionStatus );
|
|
}
|
|
}
|
|
catch (const python::error_already_set &)
|
|
{
|
|
printException();
|
|
}
|
|
|
|
m_pystate = PyEval_SaveThread();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
kdlib::DebugCallbackResult EventHandler::onException( const kdlib::ExceptionInfo &exceptionInfo )
|
|
{
|
|
kdlib::DebugCallbackResult result = kdlib::DebugCallbackNoChange;
|
|
|
|
PyEval_RestoreThread( m_pystate );
|
|
|
|
try {
|
|
|
|
do {
|
|
|
|
python::override pythonHandler = get_override( "onException" );
|
|
if ( !pythonHandler )
|
|
{
|
|
result = kdlib::EventHandler::onException( exceptionInfo );
|
|
break;
|
|
}
|
|
|
|
python::object resObj = pythonHandler( exceptionInfo );
|
|
|
|
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;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
} // end namespace pykd
|