[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:
SND\kernelnet_cp 2012-10-02 10:40:38 +00:00 committed by Mikhail I. Izmestev
parent 4adda326f5
commit 642bb01c57
13 changed files with 297 additions and 306 deletions

View File

@ -5,25 +5,64 @@
#include "stdafx.h" #include "stdafx.h"
#include "bpoint.h" #include "bpoint.h"
#include "dbgengine.h" #include "dbgengine.h"
#include "eventhandler.h"
/////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
namespace pykd { namespace pykd {
ULONG setSoftwareBp(ULONG64 offset, BpCallback &callback /*= BpCallback()*/) //////////////////////////////////////////////////////////////////////////////
ULONG setSoftwareBp(ULONG64 offset, python::object &callback/* = python::object() */)
{ {
offset = addr64( offset ); 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 ); 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();
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -6,47 +6,20 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include "pyaux.h"
namespace pykd { 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 } // end pykd namespace

View File

@ -66,9 +66,10 @@ void getStackTrace(std::vector<STACK_FRAME_DESC> &frames);
#define DEBUG_CALLBACK_METHODTYPE __cdecl #define DEBUG_CALLBACK_METHODTYPE __cdecl
enum DEBUG_CALLBACK_RESULT { enum DEBUG_CALLBACK_RESULT {
DebugCallbackBreak, DebugCallbackProceed = 0,
DebugCallbackProceed, DebugCallbackNoChange = 1,
DebugCallbackNoChange DebugCallbackBreak = 2,
DebugCallbackMax = 3
}; };
@ -78,7 +79,7 @@ struct DEBUG_EVENT_CALLBACK {
}; };
void eventRegisterCallbacks( const DEBUG_EVENT_CALLBACK *callbacks ); void eventRegisterCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
void eventRemoveCallbacks(); void eventRemoveCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
//breakpoints //breakpoints
ULONG breakPointSet( ULONG64 offset, bool hardware = false, ULONG size = 0, ULONG accessType = 0 ); ULONG breakPointSet( ULONG64 offset, bool hardware = false, ULONG size = 0, ULONG accessType = 0 );

View File

@ -28,9 +28,11 @@ WindbgGlobalSession::WindbgGlobalSession()
python::object main_namespace = main.attr("__dict__"); python::object main_namespace = main.attr("__dict__");
// äåëàåì àíàëîã from pykd import *
python::object pykd = boost::python::import( "pykd" ); python::object pykd = boost::python::import( "pykd" );
main_namespace["globalEventHandler"] = EventHandlerPtr( new EventHandlerImpl() );
// äåëàåì àíàëîã from pykd import *
python::dict pykd_namespace( pykd.attr("__dict__") ); python::dict pykd_namespace( pykd.attr("__dict__") );
python::list iterkeys( pykd_namespace.iterkeys() ); python::list iterkeys( pykd_namespace.iterkeys() );
@ -42,6 +44,13 @@ WindbgGlobalSession::WindbgGlobalSession()
main_namespace[ key ] = pykd_namespace[ key ]; 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(); pyState = PyEval_SaveThread();
} }
volatile LONG WindbgGlobalSession::sessionCount = 0; volatile LONG WindbgGlobalSession::sessionCount = 0;
@ -100,7 +109,6 @@ HRESULT
CALLBACK CALLBACK
py( PDEBUG_CLIENT4 client, PCSTR args ) py( PDEBUG_CLIENT4 client, PCSTR args )
{ {
WindbgGlobalSession::RestorePyState(); WindbgGlobalSession::RestorePyState();
PyThreadState *globalInterpreter = PyThreadState_Swap( NULL ); PyThreadState *globalInterpreter = PyThreadState_Swap( NULL );
@ -121,6 +129,10 @@ py( PDEBUG_CLIENT4 client, PCSTR args )
sys.attr("stderr") = python::object( DbgErr() ); sys.attr("stderr") = python::object( DbgErr() );
sys.attr("stdin") = python::object( DbgIn() ); sys.attr("stdin") = python::object( DbgIn() );
python::object pykd = python::import( "pykd" );
global["globalEventHandler"] = EventHandlerPtr( new EventHandlerImpl() );
// èìïîðòèðóåì ìîäóëü îáðàáîòêè èñêëþ÷åíèé ( íóæåí äëÿ âûâîäà traceback à ) // èìïîðòèðóåì ìîäóëü îáðàáîòêè èñêëþ÷åíèé ( íóæåí äëÿ âûâîäà traceback à )
python::object tracebackModule = python::import("traceback"); python::object tracebackModule = python::import("traceback");
@ -190,7 +202,6 @@ py( PDEBUG_CLIENT4 client, PCSTR args )
eprintln( sstr.str() ); eprintln( sstr.str() );
} }
} }
catch(...) catch(...)
{ {
@ -219,13 +230,6 @@ pycmd( PDEBUG_CLIENT4 client, PCSTR args )
try { 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( PyRun_String(
"__import__('code').InteractiveConsole(__import__('__main__').__dict__).interact()", "__import__('code').InteractiveConsole(__import__('__main__').__dict__).interact()",
Py_file_input, Py_file_input,

View File

@ -16,10 +16,42 @@ EventHandler::EventHandler()
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
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;
//}
//
//////////////////////////////////////////////////////////////////////////////////

View File

@ -5,6 +5,7 @@
#pragma once #pragma once
#include "dbgengine.h" #include "dbgengine.h"
#include "bpoint.h"
namespace pykd { namespace pykd {
@ -20,12 +21,93 @@ public:
private: 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; 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;
};
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////

View File

@ -12,37 +12,27 @@ class PyThreadStateSaver {
public: public:
PyThreadStateSaver() { PyThreadStateSaver( PyThreadState* s = NULL) {
m_index = TlsAlloc();
state = s;
} }
~PyThreadStateSaver() { ~PyThreadStateSaver() {
TlsFree( m_index );
} }
void saveState() { void saveState() {
//if ( !WindbgGlobalSession::isInit() ) state = PyEval_SaveThread();
TlsSetValue( m_index, PyEval_SaveThread() );
//else
// WindbgGlobalSession::SavePyState();
} }
void restoreState() { void restoreState() {
//if ( !WindbgGlobalSession::isInit() )
//{
PyThreadState* state = (PyThreadState*)TlsGetValue( m_index );
if ( state ) if ( state )
PyEval_RestoreThread( state ); PyEval_RestoreThread( state );
//}
//else
//{
// WindbgGlobalSession::RestorePyState();
//}
} }
private: private:
DWORD m_index; //DWORD m_index;
PyThreadState* state;
}; };

View File

@ -117,7 +117,8 @@ BOOST_PYTHON_MODULE( pykd )
"Get the page size for the currently executing processor context" ); "Get the page size for the currently executing processor context" );
// Manage target memory access // Manage target memory access
python::def( "addr64", &addr64,
"Extend address to 64 bits formats" );
python::def( "isValid", &isVaValid, python::def( "isValid", &isVaValid,
"Check if the virtual address is valid" ); "Check if the virtual address is valid" );
python::def( "compareMemory", &compareMemory, compareMemory_( python::args( "offset1", "offset2", "length", "phyAddr" ), python::def( "compareMemory", &compareMemory, compareMemory_( python::args( "offset1", "offset2", "length", "phyAddr" ),
@ -229,9 +230,9 @@ BOOST_PYTHON_MODULE( pykd )
"Set software breakpoint on executiont" ) ); "Set software breakpoint on executiont" ) );
python::def( "setBp", &setHardwareBp, setHardwareBp_( python::args( "offset", "size", "accsessType", "callback" ) , python::def( "setBp", &setHardwareBp, setHardwareBp_( python::args( "offset", "size", "accsessType", "callback" ) ,
"Set hardware breakpoint" ) ); "Set hardware breakpoint" ) );
python::def( "removeBp", &breakPointRemove, python::def( "removeBp", &removeBp,
"Remove breapoint by IDs" ); "Remove breapoint by IDs" );
python::def( "removeAllBp", &breakPointRemoveAll, python::def( "removeAllBp", &removeAllBp,
"Remove all breapoints" ); "Remove all breapoints" );
// custom types // custom types
@ -439,6 +440,12 @@ BOOST_PYTHON_MODULE( pykd )
.def( "ea", &Disasm::ea, "Return effective address for last disassembled instruction or 0" ) .def( "ea", &Disasm::ea, "Return effective address for last disassembled instruction or 0" )
.def( "reset", &Disasm::reset, "Reset current offset to begin" ); .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 // wrapper for standart python exceptions
python::register_exception_translator<PyException>( &PyException::exceptionTranslate ); python::register_exception_translator<PyException>( &PyException::exceptionTranslate );

View File

@ -60,3 +60,4 @@ namespace python = boost::python;
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <boost/variant.hpp> #include <boost/variant.hpp>
#include <boost/tokenizer.hpp> #include <boost/tokenizer.hpp>
#include <boost/thread/win32/recursive_mutex.hpp>

View File

@ -244,7 +244,7 @@ void debugBreak()
ULONG64 evaluate( const std::wstring &expression ) ULONG64 evaluate( const std::wstring &expression )
{ {
PyThreadState *pystate = PyEval_SaveThread(); PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
HRESULT hres; HRESULT hres;
ULONG64 value = 0; ULONG64 value = 0;
@ -829,6 +829,8 @@ void breakPointRemove( ULONG id )
void breakPointRemoveAll() void breakPointRemoveAll()
{ {
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
ULONG numberOfBps; ULONG numberOfBps;
do { do {
HRESULT hres = g_dbgEng->control->GetNumberBreakpoints(&numberOfBps); 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 ) void DebugEngine::registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks )
{ {
HRESULT hres; boost::recursive_mutex::scoped_lock l(m_handlerLock);
m_eventCallbacks = callbacks; m_handlers.push_back( DebugEventContext( callbacks, PyThreadStateSaver( PyThreadState_Get() ) ) );
hres = operator->()->client->SetEventCallbacks( &m_callbacks );
if ( S_OK != hres)
throw DbgException("IDebugClient::SetEventCallbacks", hres );
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
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 __in IDebugBreakpoint *bp
) )
{ {
DEBUG_EVENT_CALLBACK* eventCallback = const_cast<DEBUG_EVENT_CALLBACK*>( g_dbgEng.getCallbacks() );
ULONG id;
HRESULT hres; HRESULT hres;
ULONG id;
hres = bp->GetId( &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 ); return ConvertCallbackResult( result );
} }
@ -922,7 +943,6 @@ HRESULT STDMETHODCALLTYPE DebugEngine::DbgEventCallbacks::Breakpoint(
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
} // end pykd namespace } // end pykd namespace

View File

@ -12,8 +12,8 @@ namespace pykd {
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
class DebugEngine { class DebugEngine : private DebugBaseEventCallbacks
{
public: public:
struct DbgEngBind { struct DbgEngBind {
@ -26,22 +26,22 @@ public:
CComQIPtr<IDebugAdvanced2> advanced; CComQIPtr<IDebugAdvanced2> advanced;
CComQIPtr<IDebugRegisters2> registers; CComQIPtr<IDebugRegisters2> registers;
DbgEngBind( PDEBUG_CLIENT4 c ) DbgEngBind( PDEBUG_CLIENT4 client_, PDEBUG_EVENT_CALLBACKS callback )
{ {
client = c; client = client_;
control = c; control = client_;
system = c; system = client_;
symbols = c; symbols = client_;
dataspace = c; dataspace = client_;
advanced = c; advanced = client_;
registers = c; registers = client_;
client->SetEventCallbacks( callback );
} }
PyThreadStateSaver pystate; PyThreadStateSaver pystate;
}; };
class DbgEventCallbacks : public DebugBaseEventCallbacks
{
// IUnknown impls // IUnknown impls
STDMETHOD_(ULONG, AddRef)() { return 1; } STDMETHOD_(ULONG, AddRef)() { return 1; }
STDMETHOD_(ULONG, Release)() { return 1; } STDMETHOD_(ULONG, Release)() { return 1; }
@ -58,7 +58,6 @@ public:
STDMETHOD(Breakpoint)( STDMETHOD(Breakpoint)(
__in IDebugBreakpoint *bp __in IDebugBreakpoint *bp
); );
};
DbgEngBind* DbgEngBind*
operator->() operator->()
@ -72,36 +71,33 @@ public:
if ( FAILED( hres ) ) if ( FAILED( hres ) )
throw DbgException("DebugCreate failed"); throw DbgException("DebugCreate failed");
m_bind.reset(new DbgEngBind(client) ); m_bind.reset(new DbgEngBind(client, this) );
return m_bind.get(); return m_bind.get();
} }
void registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks ); void registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
void removeCallbacks(); void removeCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
const DEBUG_EVENT_CALLBACK* getCallbacks() const {
return m_eventCallbacks;
}
DebugEngine() :
m_callbacks()
{
g_eventHandler = new EventHandler();
}
~DebugEngine()
{
delete g_eventHandler;
g_eventHandler = NULL;
}
private: private:
std::auto_ptr<DbgEngBind> m_bind; 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;
}; };
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////

View File

@ -9,25 +9,25 @@ from pykd import *
def iat( moduleName, mask = "*" ): def iat( moduleName, mask = "*" ):
module = loadModule( moduleName ) mod = module( moduleName )
dprintln( "Module: " + moduleName + " base: %x" % module.begin() + " end: %x" % module.end() ) dprintln( "Module: " + moduleName + " base: %x" % mod.begin() + " end: %x" % mod.end() )
if isKernelDebugging(): if isKernelDebugging():
systemModule = loadModule( "nt" ) systemModule = module( "nt" )
else: else:
systemModule = loadModule( "ntdll" ) systemModule = module( "ntdll" )
if is64bitSystem(): 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: if ntHeader.OptionalHeader.Magic == 0x10b:
systemModule = loadModule( "ntdll32" ) 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 pSize = 4
else: else:
pSize = 8 pSize = 8
else: 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 pSize = 4
@ -37,7 +37,7 @@ def iat( moduleName, mask = "*" ):
if ntHeader.OptionalHeader.DataDirectory[12].Size == 0: if ntHeader.OptionalHeader.DataDirectory[12].Size == 0:
return 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 ): for i in range( 0, ntHeader.OptionalHeader.DataDirectory[12].Size / pSize ):

View File

@ -26,7 +26,7 @@ Work with NT Object tree manager
from pykd import * from pykd import *
nt = loadModule("nt") nt = module("nt")
def getTypeWin7(p): def getTypeWin7(p):
""" """