mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-21 12:53:23 +08:00
[0.2.x] added : EventHandler class and breakpoints callback
git-svn-id: https://pykd.svn.codeplex.com/svn@79970 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
4adda326f5
commit
642bb01c57
@ -5,25 +5,64 @@
|
||||
#include "stdafx.h"
|
||||
#include "bpoint.h"
|
||||
#include "dbgengine.h"
|
||||
#include "eventhandler.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace pykd {
|
||||
|
||||
ULONG setSoftwareBp(ULONG64 offset, BpCallback &callback /*= BpCallback()*/)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG setSoftwareBp(ULONG64 offset, python::object &callback/* = python::object() */)
|
||||
{
|
||||
offset = addr64( offset );
|
||||
|
||||
return breakPointSet( offset );
|
||||
ULONG id = breakPointSet( offset );
|
||||
|
||||
python::object main = boost::python::import("__main__");
|
||||
python::dict main_namespace( main.attr("__dict__") );
|
||||
EventHandlerPtr eventHandler = python::extract<EventHandlerPtr>( main_namespace["globalEventHandler"] );
|
||||
EventHandlerImpl* handler = dynamic_cast<EventHandlerImpl*>( boost::get_pointer( eventHandler ) );
|
||||
handler->addBpCallback( id, callback );
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG setHardwareBp(ULONG64 offset, ULONG size, ULONG accessType, BpCallback &callback /*= BpCallback()*/ )
|
||||
ULONG setHardwareBp(ULONG64 offset, ULONG size, ULONG accessType, python::object &callback/* = python::object() */ )
|
||||
{
|
||||
offset = addr64( offset );
|
||||
|
||||
return breakPointSet( offset, true, size, accessType );
|
||||
ULONG id = breakPointSet( offset, true, size, accessType );
|
||||
|
||||
python::object main = boost::python::import("__main__");
|
||||
python::dict main_namespace( main.attr("__dict__") );
|
||||
EventHandlerPtr eventHandler = python::extract<EventHandlerPtr>( main_namespace["globalEventHandler"] );
|
||||
EventHandlerImpl* handler = dynamic_cast<EventHandlerImpl*>( boost::get_pointer( eventHandler ) );
|
||||
handler->addBpCallback( id, callback );
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void removeBp( ULONG id )
|
||||
{
|
||||
breakPointRemove( id );
|
||||
|
||||
python::object main = boost::python::import("__main__");
|
||||
python::dict main_namespace( main.attr("__dict__") );
|
||||
EventHandlerPtr eventHandler = python::extract<EventHandlerPtr>( main_namespace["globalEventHandler"] );
|
||||
EventHandlerImpl* handler = dynamic_cast<EventHandlerImpl*>( boost::get_pointer( eventHandler ) );
|
||||
handler->removeBpCallback( id );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void removeAllBp()
|
||||
{
|
||||
// breakPointRemoveAll();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -6,47 +6,20 @@
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pyaux.h"
|
||||
|
||||
namespace pykd {
|
||||
|
||||
typedef python::object BpCallback;
|
||||
ULONG setSoftwareBp(ULONG64 offset, python::object &callback = python::object() );
|
||||
|
||||
ULONG setSoftwareBp(ULONG64 offset, BpCallback &callback = BpCallback() );
|
||||
ULONG setHardwareBp(ULONG64 offset, ULONG size, ULONG accessType, python::object &callback = python::object() );
|
||||
|
||||
ULONG setHardwareBp(ULONG64 offset, ULONG size, ULONG accessType, BpCallback &callback = BpCallback());
|
||||
void removeBp( ULONG id );
|
||||
|
||||
void removeAllBp();
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//inline BPOINT_ID setSoftwareBp(ULONG64 addr, BpCallback &callback = BpCallback()) {
|
||||
// return g_dbgClient->setSoftwareBp(addr, callback);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//inline BPOINT_ID setHardwareBp(ULONG64 addr, ULONG size, ULONG accessType, BpCallback &callback = BpCallback()) {
|
||||
// return g_dbgClient->setHardwareBp(addr, size, accessType, callback);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//inline python::list getAllBp() {
|
||||
// return g_dbgClient->getAllBp();
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//inline void removeBp(BPOINT_ID Id) {
|
||||
// return g_dbgClient->removeBp(Id);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//inline void removeAllBp() {
|
||||
// return g_dbgClient->removeAllBp();
|
||||
//}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // end pykd namespace
|
||||
|
||||
|
@ -66,9 +66,10 @@ void getStackTrace(std::vector<STACK_FRAME_DESC> &frames);
|
||||
#define DEBUG_CALLBACK_METHODTYPE __cdecl
|
||||
|
||||
enum DEBUG_CALLBACK_RESULT {
|
||||
DebugCallbackBreak,
|
||||
DebugCallbackProceed,
|
||||
DebugCallbackNoChange
|
||||
DebugCallbackProceed = 0,
|
||||
DebugCallbackNoChange = 1,
|
||||
DebugCallbackBreak = 2,
|
||||
DebugCallbackMax = 3
|
||||
};
|
||||
|
||||
|
||||
@ -78,7 +79,7 @@ struct DEBUG_EVENT_CALLBACK {
|
||||
};
|
||||
|
||||
void eventRegisterCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||
void eventRemoveCallbacks();
|
||||
void eventRemoveCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||
|
||||
//breakpoints
|
||||
ULONG breakPointSet( ULONG64 offset, bool hardware = false, ULONG size = 0, ULONG accessType = 0 );
|
||||
|
@ -28,9 +28,11 @@ WindbgGlobalSession::WindbgGlobalSession()
|
||||
|
||||
python::object main_namespace = main.attr("__dict__");
|
||||
|
||||
// äåëàåì àíàëîã from pykd import *
|
||||
python::object pykd = boost::python::import( "pykd" );
|
||||
|
||||
main_namespace["globalEventHandler"] = EventHandlerPtr( new EventHandlerImpl() );
|
||||
|
||||
// äåëàåì àíàëîã from pykd import *
|
||||
python::dict pykd_namespace( pykd.attr("__dict__") );
|
||||
|
||||
python::list iterkeys( pykd_namespace.iterkeys() );
|
||||
@ -42,6 +44,13 @@ WindbgGlobalSession::WindbgGlobalSession()
|
||||
main_namespace[ key ] = pykd_namespace[ key ];
|
||||
}
|
||||
|
||||
// ïåðåíàïðàâëåíèå ñòàíäàðòíûõ ïîòîêîâ ÂÂ
|
||||
python::object sys = python::import("sys");
|
||||
|
||||
sys.attr("stdout") = python::object( DbgOut() );
|
||||
sys.attr("stderr") = python::object( DbgErr() );
|
||||
sys.attr("stdin") = python::object( DbgIn() );
|
||||
|
||||
pyState = PyEval_SaveThread();
|
||||
}
|
||||
volatile LONG WindbgGlobalSession::sessionCount = 0;
|
||||
@ -100,7 +109,6 @@ HRESULT
|
||||
CALLBACK
|
||||
py( PDEBUG_CLIENT4 client, PCSTR args )
|
||||
{
|
||||
|
||||
WindbgGlobalSession::RestorePyState();
|
||||
|
||||
PyThreadState *globalInterpreter = PyThreadState_Swap( NULL );
|
||||
@ -121,6 +129,10 @@ py( PDEBUG_CLIENT4 client, PCSTR args )
|
||||
sys.attr("stderr") = python::object( DbgErr() );
|
||||
sys.attr("stdin") = python::object( DbgIn() );
|
||||
|
||||
python::object pykd = python::import( "pykd" );
|
||||
|
||||
global["globalEventHandler"] = EventHandlerPtr( new EventHandlerImpl() );
|
||||
|
||||
// èìïîðòèðóåì ìîäóëü îáðàáîòêè èñêëþ÷åíèé ( íóæåí äëÿ âûâîäà traceback à )
|
||||
python::object tracebackModule = python::import("traceback");
|
||||
|
||||
@ -190,7 +202,6 @@ py( PDEBUG_CLIENT4 client, PCSTR args )
|
||||
|
||||
eprintln( sstr.str() );
|
||||
}
|
||||
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@ -219,13 +230,6 @@ pycmd( PDEBUG_CLIENT4 client, PCSTR args )
|
||||
|
||||
try {
|
||||
|
||||
// ïåðåíàïðàâëåíèå ñòàíäàðòíûõ ïîòîêîâ ÂÂ
|
||||
python::object sys = python::import("sys");
|
||||
|
||||
sys.attr("stdout") = python::object( DbgOut() );
|
||||
sys.attr("stderr") = python::object( DbgErr() );
|
||||
sys.attr("stdin") = python::object( DbgIn() );
|
||||
|
||||
PyRun_String(
|
||||
"__import__('code').InteractiveConsole(__import__('__main__').__dict__).interact()",
|
||||
Py_file_input,
|
||||
|
@ -16,10 +16,42 @@ EventHandler::EventHandler()
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
EventHandler::~EventHandler()
|
||||
{
|
||||
eventRemoveCallbacks();
|
||||
eventRemoveCallbacks( this );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE EventHandlerImpl::OnBreakpoint( ULONG bpId )
|
||||
{
|
||||
BpMap::iterator foundIt = m_bpMap.find( bpId );
|
||||
if ( foundIt == m_bpMap.end() )
|
||||
return DebugCallbackNoChange;
|
||||
|
||||
python::object bpcallback = foundIt->second;
|
||||
|
||||
if ( bpcallback.is_none() )
|
||||
return DebugCallbackBreak;
|
||||
|
||||
try {
|
||||
|
||||
python::object resObj = bpcallback( bpId );
|
||||
|
||||
if ( resObj.is_none() )
|
||||
return DebugCallbackProceed;
|
||||
|
||||
ULONG retVal = python::extract<ULONG>( resObj );
|
||||
|
||||
if ( retVal >= DebugCallbackMax )
|
||||
return DebugCallbackBreak;
|
||||
|
||||
return DEBUG_CALLBACK_RESULT(retVal);
|
||||
}
|
||||
catch (const python::error_already_set &) {
|
||||
}
|
||||
|
||||
return DebugCallbackBreak;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -46,158 +78,4 @@ EventHandler::~EventHandler()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//InternalDbgEventHandler::InternalDbgEventHandler(
|
||||
// IDebugClient4 *client,
|
||||
// DebugClient *parentClient,
|
||||
// SynSymbolsPtr synSymbols,
|
||||
// BpCallbackMap &bpCallbacks
|
||||
//) : m_parentClient(parentClient)
|
||||
// , m_synSymbols(synSymbols)
|
||||
// , m_bpCallbacks(bpCallbacks)
|
||||
//{
|
||||
// HRESULT hres = client->CreateClient(&m_client);
|
||||
// if (FAILED(hres))
|
||||
// throw DbgException("Call IDebugClient::CreateClient failed");
|
||||
//
|
||||
// hres = m_client->QueryInterface(__uuidof(IDebugControl), (void**)&m_control);
|
||||
// if ( FAILED( hres ) )
|
||||
// throw DbgException("QueryInterface IDebugControl failed");
|
||||
//
|
||||
// m_client->SetEventCallbacks(this);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//InternalDbgEventHandler::~InternalDbgEventHandler()
|
||||
//{
|
||||
// m_control->Release();
|
||||
// m_client->Release();
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//HRESULT InternalDbgEventHandler::GetInterestMask(
|
||||
// __out PULONG Mask
|
||||
//)
|
||||
//{
|
||||
// *Mask =
|
||||
// DEBUG_EVENT_BREAKPOINT |
|
||||
// DEBUG_EVENT_CHANGE_ENGINE_STATE |
|
||||
// DEBUG_EVENT_CHANGE_SYMBOL_STATE;
|
||||
//
|
||||
// return S_OK;
|
||||
//}
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//HRESULT InternalDbgEventHandler::ChangeSymbolState(
|
||||
// __in ULONG Flags,
|
||||
// __in ULONG64 Argument
|
||||
//)
|
||||
//{
|
||||
// HRESULT hres = S_OK;
|
||||
//
|
||||
// if (DEBUG_CSS_LOADS & Flags)
|
||||
// hres = symLoaded(Argument);
|
||||
//
|
||||
// return hres;
|
||||
//}
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//HRESULT InternalDbgEventHandler::ChangeEngineState(
|
||||
// __in ULONG Flags,
|
||||
// __in ULONG64 Argument
|
||||
//)
|
||||
//{
|
||||
// HRESULT hres = S_OK;
|
||||
//
|
||||
// if (DEBUG_CES_BREAKPOINTS & Flags)
|
||||
// hres = bpChanged(static_cast<BPOINT_ID>(Argument));
|
||||
//
|
||||
// return hres;
|
||||
//}
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//HRESULT InternalDbgEventHandler::Breakpoint(IDebugBreakpoint *bp)
|
||||
//{
|
||||
// BPOINT_ID Id;
|
||||
// HRESULT hres = bp->GetId(&Id);
|
||||
// if (S_OK == hres)
|
||||
// {
|
||||
// boost::recursive_mutex::scoped_lock mapBpLock(*m_bpCallbacks.m_lock);
|
||||
// BpCallbackMapIml::iterator it = m_bpCallbacks.m_map.find(Id);
|
||||
// if (it != m_bpCallbacks.m_map.end())
|
||||
// {
|
||||
// PyThread_StateSave pyThreadSave( m_parentClient->getThreadState() );
|
||||
//
|
||||
// try {
|
||||
//
|
||||
// python::object resObj = it->second(Id);
|
||||
//
|
||||
// if (resObj.is_none())
|
||||
// return DEBUG_STATUS_NO_CHANGE;
|
||||
//
|
||||
// python::extract<HRESULT> getRetCode( resObj );
|
||||
// if (getRetCode.check())
|
||||
// return getRetCode();
|
||||
// }
|
||||
// catch (const python::error_already_set &) {
|
||||
// // TODO: some logging, alerting...
|
||||
// return DEBUG_STATUS_BREAK;
|
||||
// }
|
||||
// // TODO: python code return invalid value
|
||||
// // some logging, alerting...
|
||||
// return DEBUG_STATUS_BREAK;
|
||||
// }
|
||||
// }
|
||||
// return DEBUG_STATUS_NO_CHANGE;
|
||||
//}
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//HRESULT InternalDbgEventHandler::symLoaded(
|
||||
// __in ULONG64 ModuleAddress
|
||||
//)
|
||||
//{
|
||||
// if (!ModuleAddress)
|
||||
// {
|
||||
// // f.e. is case ".reload /f image.exe", if for image.exe no symbols
|
||||
// m_synSymbols->restoreAll();
|
||||
// return S_OK;
|
||||
// }
|
||||
//
|
||||
// m_synSymbols->restoreForModule(ModuleAddress);
|
||||
// return S_OK;
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//HRESULT InternalDbgEventHandler::bpChanged(BPOINT_ID Id)
|
||||
//{
|
||||
// if (DEBUG_ANY_ID == Id)
|
||||
// return S_OK;
|
||||
//
|
||||
// IDebugBreakpoint *bp;
|
||||
// HRESULT hres = m_control->GetBreakpointById(Id, &bp);
|
||||
// if (E_NOINTERFACE == hres)
|
||||
// {
|
||||
// // breakpoint was removed
|
||||
// boost::recursive_mutex::scoped_lock mapBpLock(*m_bpCallbacks.m_lock);
|
||||
// m_bpCallbacks.m_map.erase(Id);
|
||||
// }
|
||||
//
|
||||
// return S_OK;
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "dbgengine.h"
|
||||
#include "bpoint.h"
|
||||
|
||||
namespace pykd {
|
||||
|
||||
@ -20,12 +21,93 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
virtual DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE OnBreakpoint( ULONG bpId ) {
|
||||
virtual DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE OnBreakpoint( ULONG bpId ) = 0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class EventHandlerWrap : public python::wrapper<EventHandler>, public EventHandler
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE OnBreakpoint( ULONG Id ) {
|
||||
return handler("onBreakpoint", Id);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename Arg1Type>
|
||||
DEBUG_CALLBACK_RESULT handler( const char* handlerName, Arg1Type arg1 )
|
||||
{
|
||||
if (python::override pythonHandler = get_override( handlerName ))
|
||||
{
|
||||
try {
|
||||
return pythonHandler(arg1);
|
||||
}
|
||||
catch (const python::error_already_set &) {
|
||||
//onHandlerException();
|
||||
}
|
||||
}
|
||||
return DebugCallbackNoChange;
|
||||
}
|
||||
|
||||
DEBUG_CALLBACK_RESULT handler( const char* handlerName )
|
||||
{
|
||||
if (python::override pythonHandler = get_override( handlerName ))
|
||||
{
|
||||
try {
|
||||
return pythonHandler();
|
||||
}
|
||||
catch (const python::error_already_set &) {
|
||||
//onHandlerException();
|
||||
}
|
||||
}
|
||||
|
||||
return DebugCallbackNoChange;
|
||||
}
|
||||
};
|
||||
|
||||
extern EventHandler *g_eventHandler;
|
||||
typedef boost::shared_ptr<EventHandlerWrap> EventHandlerPtr;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class EventHandlerImpl : public EventHandlerWrap
|
||||
{
|
||||
public:
|
||||
void addBpCallback( ULONG id, python::object &callback )
|
||||
{
|
||||
m_bpMap.insert( std::make_pair( id, callback ) );
|
||||
}
|
||||
|
||||
void removeBpCallback( ULONG id )
|
||||
{
|
||||
BpMap::iterator foundIt = m_bpMap.find( id );
|
||||
if ( foundIt != m_bpMap.end() )
|
||||
m_bpMap.erase( foundIt );
|
||||
}
|
||||
|
||||
virtual ~EventHandlerImpl()
|
||||
{
|
||||
while( !m_bpMap.empty() )
|
||||
{
|
||||
BpMap::iterator it = m_bpMap.begin();
|
||||
breakPointRemove( it->first );
|
||||
m_bpMap.erase( it );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
virtual DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE OnBreakpoint( ULONG bpId );
|
||||
|
||||
private:
|
||||
|
||||
typedef std::map<ULONG, python::object> BpMap;
|
||||
|
||||
BpMap m_bpMap;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
22
pykd/pyaux.h
22
pykd/pyaux.h
@ -12,37 +12,27 @@ class PyThreadStateSaver {
|
||||
|
||||
public:
|
||||
|
||||
PyThreadStateSaver() {
|
||||
m_index = TlsAlloc();
|
||||
PyThreadStateSaver( PyThreadState* s = NULL) {
|
||||
|
||||
state = s;
|
||||
}
|
||||
|
||||
~PyThreadStateSaver() {
|
||||
TlsFree( m_index );
|
||||
}
|
||||
|
||||
void saveState() {
|
||||
//if ( !WindbgGlobalSession::isInit() )
|
||||
TlsSetValue( m_index, PyEval_SaveThread() );
|
||||
//else
|
||||
// WindbgGlobalSession::SavePyState();
|
||||
state = PyEval_SaveThread();
|
||||
}
|
||||
|
||||
void restoreState() {
|
||||
//if ( !WindbgGlobalSession::isInit() )
|
||||
//{
|
||||
PyThreadState* state = (PyThreadState*)TlsGetValue( m_index );
|
||||
if ( state )
|
||||
PyEval_RestoreThread( state );
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// WindbgGlobalSession::RestorePyState();
|
||||
//}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
DWORD m_index;
|
||||
//DWORD m_index;
|
||||
PyThreadState* state;
|
||||
};
|
||||
|
||||
|
||||
|
@ -117,7 +117,8 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
"Get the page size for the currently executing processor context" );
|
||||
|
||||
// Manage target memory access
|
||||
|
||||
python::def( "addr64", &addr64,
|
||||
"Extend address to 64 bits formats" );
|
||||
python::def( "isValid", &isVaValid,
|
||||
"Check if the virtual address is valid" );
|
||||
python::def( "compareMemory", &compareMemory, compareMemory_( python::args( "offset1", "offset2", "length", "phyAddr" ),
|
||||
@ -229,9 +230,9 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
"Set software breakpoint on executiont" ) );
|
||||
python::def( "setBp", &setHardwareBp, setHardwareBp_( python::args( "offset", "size", "accsessType", "callback" ) ,
|
||||
"Set hardware breakpoint" ) );
|
||||
python::def( "removeBp", &breakPointRemove,
|
||||
python::def( "removeBp", &removeBp,
|
||||
"Remove breapoint by IDs" );
|
||||
python::def( "removeAllBp", &breakPointRemoveAll,
|
||||
python::def( "removeAllBp", &removeAllBp,
|
||||
"Remove all breapoints" );
|
||||
|
||||
// custom types
|
||||
@ -439,6 +440,12 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
.def( "ea", &Disasm::ea, "Return effective address for last disassembled instruction or 0" )
|
||||
.def( "reset", &Disasm::reset, "Reset current offset to begin" );
|
||||
|
||||
python::class_<EventHandlerWrap, EventHandlerPtr, boost::noncopyable>(
|
||||
"eventHandler", "Base class for overriding and handling debug notifications", python::no_init )
|
||||
.def( "onBreakpoint", &EventHandlerWrap::OnBreakpoint,
|
||||
"Triggered breakpoint event. Parameter is int: ID of breakpoint\n"
|
||||
"For ignore event method must return DEBUG_STATUS_NO_CHANGE value" );
|
||||
|
||||
// wrapper for standart python exceptions
|
||||
python::register_exception_translator<PyException>( &PyException::exceptionTranslate );
|
||||
|
||||
|
@ -60,3 +60,4 @@ namespace python = boost::python;
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/thread/win32/recursive_mutex.hpp>
|
||||
|
@ -244,7 +244,7 @@ void debugBreak()
|
||||
|
||||
ULONG64 evaluate( const std::wstring &expression )
|
||||
{
|
||||
PyThreadState *pystate = PyEval_SaveThread();
|
||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||
|
||||
HRESULT hres;
|
||||
ULONG64 value = 0;
|
||||
@ -829,6 +829,8 @@ void breakPointRemove( ULONG id )
|
||||
|
||||
void breakPointRemoveAll()
|
||||
{
|
||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||
|
||||
ULONG numberOfBps;
|
||||
do {
|
||||
HRESULT hres = g_dbgEng->control->GetNumberBreakpoints(&numberOfBps);
|
||||
@ -860,20 +862,32 @@ void eventRegisterCallbacks( const DEBUG_EVENT_CALLBACK *callbacks )
|
||||
|
||||
void DebugEngine::registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks )
|
||||
{
|
||||
HRESULT hres;
|
||||
boost::recursive_mutex::scoped_lock l(m_handlerLock);
|
||||
|
||||
m_eventCallbacks = callbacks;
|
||||
|
||||
hres = operator->()->client->SetEventCallbacks( &m_callbacks );
|
||||
|
||||
if ( S_OK != hres)
|
||||
throw DbgException("IDebugClient::SetEventCallbacks", hres );
|
||||
m_handlers.push_back( DebugEventContext( callbacks, PyThreadStateSaver( PyThreadState_Get() ) ) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void eventRemoveCallbacks()
|
||||
void eventRemoveCallbacks( const DEBUG_EVENT_CALLBACK *callback )
|
||||
{
|
||||
g_dbgEng.removeCallbacks( callback );
|
||||
}
|
||||
|
||||
void DebugEngine::removeCallbacks( const DEBUG_EVENT_CALLBACK *callback )
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock l(m_handlerLock);
|
||||
|
||||
HandlerList::iterator it = m_handlers.begin();
|
||||
|
||||
for ( ; it != m_handlers.end(); ++it )
|
||||
{
|
||||
if ( it->callback == callback )
|
||||
{
|
||||
m_handlers.erase( it );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -899,21 +913,28 @@ ULONG ConvertCallbackResult( DEBUG_CALLBACK_RESULT result )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HRESULT STDMETHODCALLTYPE DebugEngine::DbgEventCallbacks::Breakpoint(
|
||||
HRESULT STDMETHODCALLTYPE DebugEngine::Breakpoint(
|
||||
__in IDebugBreakpoint *bp
|
||||
)
|
||||
{
|
||||
DEBUG_EVENT_CALLBACK* eventCallback = const_cast<DEBUG_EVENT_CALLBACK*>( g_dbgEng.getCallbacks() );
|
||||
|
||||
ULONG id;
|
||||
HRESULT hres;
|
||||
ULONG id;
|
||||
|
||||
hres = bp->GetId( &id );
|
||||
if ( FAILED( hres ) )
|
||||
return DEBUG_STATUS_NO_CHANGE;
|
||||
|
||||
if ( hres == S_OK )
|
||||
boost::recursive_mutex::scoped_lock l(m_handlerLock);
|
||||
|
||||
HandlerList::iterator it = m_handlers.begin();
|
||||
|
||||
for ( ; it != m_handlers.end(); ++it )
|
||||
{
|
||||
DEBUG_CALLBACK_RESULT result = eventCallback->OnBreakpoint( id );
|
||||
PyThread_StateSave pyThreadSave( it->pystate );
|
||||
|
||||
DEBUG_CALLBACK_RESULT result = it->callback->OnBreakpoint( id );
|
||||
|
||||
if ( DebugCallbackNoChange != result )
|
||||
return ConvertCallbackResult( result );
|
||||
}
|
||||
|
||||
@ -922,7 +943,6 @@ HRESULT STDMETHODCALLTYPE DebugEngine::DbgEventCallbacks::Breakpoint(
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
} // end pykd namespace
|
||||
|
||||
|
||||
|
@ -12,8 +12,8 @@ namespace pykd {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DebugEngine {
|
||||
|
||||
class DebugEngine : private DebugBaseEventCallbacks
|
||||
{
|
||||
public:
|
||||
|
||||
struct DbgEngBind {
|
||||
@ -26,22 +26,22 @@ public:
|
||||
CComQIPtr<IDebugAdvanced2> advanced;
|
||||
CComQIPtr<IDebugRegisters2> registers;
|
||||
|
||||
DbgEngBind( PDEBUG_CLIENT4 c )
|
||||
DbgEngBind( PDEBUG_CLIENT4 client_, PDEBUG_EVENT_CALLBACKS callback )
|
||||
{
|
||||
client = c;
|
||||
control = c;
|
||||
system = c;
|
||||
symbols = c;
|
||||
dataspace = c;
|
||||
advanced = c;
|
||||
registers = c;
|
||||
client = client_;
|
||||
control = client_;
|
||||
system = client_;
|
||||
symbols = client_;
|
||||
dataspace = client_;
|
||||
advanced = client_;
|
||||
registers = client_;
|
||||
|
||||
client->SetEventCallbacks( callback );
|
||||
}
|
||||
|
||||
PyThreadStateSaver pystate;
|
||||
};
|
||||
|
||||
class DbgEventCallbacks : public DebugBaseEventCallbacks
|
||||
{
|
||||
// IUnknown impls
|
||||
STDMETHOD_(ULONG, AddRef)() { return 1; }
|
||||
STDMETHOD_(ULONG, Release)() { return 1; }
|
||||
@ -58,7 +58,6 @@ public:
|
||||
STDMETHOD(Breakpoint)(
|
||||
__in IDebugBreakpoint *bp
|
||||
);
|
||||
};
|
||||
|
||||
DbgEngBind*
|
||||
operator->()
|
||||
@ -72,36 +71,33 @@ public:
|
||||
if ( FAILED( hres ) )
|
||||
throw DbgException("DebugCreate failed");
|
||||
|
||||
m_bind.reset(new DbgEngBind(client) );
|
||||
m_bind.reset(new DbgEngBind(client, this) );
|
||||
|
||||
return m_bind.get();
|
||||
}
|
||||
|
||||
void registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||
void removeCallbacks();
|
||||
const DEBUG_EVENT_CALLBACK* getCallbacks() const {
|
||||
return m_eventCallbacks;
|
||||
}
|
||||
|
||||
DebugEngine() :
|
||||
m_callbacks()
|
||||
{
|
||||
g_eventHandler = new EventHandler();
|
||||
}
|
||||
|
||||
~DebugEngine()
|
||||
{
|
||||
delete g_eventHandler;
|
||||
g_eventHandler = NULL;
|
||||
}
|
||||
void removeCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||
|
||||
private:
|
||||
|
||||
std::auto_ptr<DbgEngBind> m_bind;
|
||||
|
||||
DbgEventCallbacks m_callbacks;
|
||||
struct DebugEventContext
|
||||
{
|
||||
DEBUG_EVENT_CALLBACK* callback;
|
||||
PyThreadStateSaver pystate;
|
||||
|
||||
const DEBUG_EVENT_CALLBACK *m_eventCallbacks;
|
||||
DebugEventContext( const DEBUG_EVENT_CALLBACK* callback_, PyThreadStateSaver &pystate_ ) :
|
||||
callback( const_cast<DEBUG_EVENT_CALLBACK*>(callback_) ),
|
||||
pystate(pystate_)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef std::list<DebugEventContext> HandlerList;
|
||||
|
||||
boost::recursive_mutex m_handlerLock;
|
||||
HandlerList m_handlers;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -9,25 +9,25 @@ from pykd import *
|
||||
|
||||
def iat( moduleName, mask = "*" ):
|
||||
|
||||
module = loadModule( moduleName )
|
||||
dprintln( "Module: " + moduleName + " base: %x" % module.begin() + " end: %x" % module.end() )
|
||||
mod = module( moduleName )
|
||||
dprintln( "Module: " + moduleName + " base: %x" % mod.begin() + " end: %x" % mod.end() )
|
||||
|
||||
if isKernelDebugging():
|
||||
systemModule = loadModule( "nt" )
|
||||
systemModule = module( "nt" )
|
||||
else:
|
||||
systemModule = loadModule( "ntdll" )
|
||||
systemModule = module( "ntdll" )
|
||||
|
||||
|
||||
if is64bitSystem():
|
||||
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS64", module.begin() + ptrDWord( module.begin() + 0x3c ) )
|
||||
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS64", mod.begin() + ptrDWord( mod.begin() + 0x3c ) )
|
||||
if ntHeader.OptionalHeader.Magic == 0x10b:
|
||||
systemModule = loadModule( "ntdll32" )
|
||||
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS", module.begin() + ptrDWord( module.begin() + 0x3c ) )
|
||||
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS", mod.begin() + ptrDWord( mod.begin() + 0x3c ) )
|
||||
pSize = 4
|
||||
else:
|
||||
pSize = 8
|
||||
else:
|
||||
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS", module.begin() + ptrDWord( module.begin() + 0x3c ) )
|
||||
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS", mod.begin() + ptrDWord( mod.begin() + 0x3c ) )
|
||||
pSize = 4
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ def iat( moduleName, mask = "*" ):
|
||||
if ntHeader.OptionalHeader.DataDirectory[12].Size == 0:
|
||||
return
|
||||
|
||||
iatAddr = module.begin() + ntHeader.OptionalHeader.DataDirectory[12].VirtualAddress;
|
||||
iatAddr = mod.begin() + ntHeader.OptionalHeader.DataDirectory[12].VirtualAddress;
|
||||
|
||||
for i in range( 0, ntHeader.OptionalHeader.DataDirectory[12].Size / pSize ):
|
||||
|
||||
|
@ -26,7 +26,7 @@ Work with NT Object tree manager
|
||||
|
||||
from pykd import *
|
||||
|
||||
nt = loadModule("nt")
|
||||
nt = module("nt")
|
||||
|
||||
def getTypeWin7(p):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user