diff --git a/pykd/bpoint.cpp b/pykd/bpoint.cpp index 7978d9e..bc0e0fe 100644 --- a/pykd/bpoint.cpp +++ b/pykd/bpoint.cpp @@ -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( main_namespace["globalEventHandler"] ); + EventHandlerImpl* handler = dynamic_cast( 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( main_namespace["globalEventHandler"] ); + EventHandlerImpl* handler = dynamic_cast( 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( main_namespace["globalEventHandler"] ); + EventHandlerImpl* handler = dynamic_cast( boost::get_pointer( eventHandler ) ); + handler->removeBpCallback( id ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void removeAllBp() +{ + // breakPointRemoveAll(); } /////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/bpoint.h b/pykd/bpoint.h index 04e698b..cb95b94 100644 --- a/pykd/bpoint.h +++ b/pykd/bpoint.h @@ -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 diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index 61f4813..950c2b3 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -66,9 +66,10 @@ void getStackTrace(std::vector &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 ); diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 1175826..1f9e2e3 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -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, diff --git a/pykd/eventhandler.cpp b/pykd/eventhandler.cpp index 6b6189c..05db8b8 100644 --- a/pykd/eventhandler.cpp +++ b/pykd/eventhandler.cpp @@ -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( 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(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 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; -//} -// -////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/eventhandler.h b/pykd/eventhandler.h index ef664f9..0fc9519 100644 --- a/pykd/eventhandler.h +++ b/pykd/eventhandler.h @@ -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 ) { - return DebugCallbackNoChange; - } + virtual DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE OnBreakpoint( ULONG bpId ) = 0; }; -extern EventHandler *g_eventHandler; +////////////////////////////////////////////////////////////////////////////////// + + +class EventHandlerWrap : public python::wrapper, public EventHandler +{ + +public: + + virtual DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE OnBreakpoint( ULONG Id ) { + return handler("onBreakpoint", Id); + } + +private: + + template + 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; + } +}; + +typedef boost::shared_ptr 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 BpMap; + + BpMap m_bpMap; +}; ////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/pyaux.h b/pykd/pyaux.h index 3f1a32b..33ee414 100644 --- a/pykd/pyaux.h +++ b/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; }; diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 4d21440..43a2859 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -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_( + "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::exceptionTranslate ); diff --git a/pykd/stdafx.h b/pykd/stdafx.h index 8367440..4309d3a 100644 --- a/pykd/stdafx.h +++ b/pykd/stdafx.h @@ -60,3 +60,4 @@ namespace python = boost::python; #include #include #include +#include diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index d0cfca0..148a013 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -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,22 +913,29 @@ ULONG ConvertCallbackResult( DEBUG_CALLBACK_RESULT result ) /////////////////////////////////////////////////////////////////////////////// -HRESULT STDMETHODCALLTYPE DebugEngine::DbgEventCallbacks::Breakpoint( +HRESULT STDMETHODCALLTYPE DebugEngine::Breakpoint( __in IDebugBreakpoint *bp ) { - DEBUG_EVENT_CALLBACK* eventCallback = const_cast( g_dbgEng.getCallbacks() ); - - ULONG id; - HRESULT hres; + 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 ); - return ConvertCallbackResult( result ); + DEBUG_CALLBACK_RESULT result = it->callback->OnBreakpoint( id ); + + if ( DebugCallbackNoChange != result ) + return ConvertCallbackResult( result ); } return DEBUG_STATUS_NO_CHANGE; @@ -922,7 +943,6 @@ HRESULT STDMETHODCALLTYPE DebugEngine::DbgEventCallbacks::Breakpoint( /////////////////////////////////////////////////////////////////////////////// - } // end pykd namespace diff --git a/pykd/win/dbgeng.h b/pykd/win/dbgeng.h index ccb2330..bfc1832 100644 --- a/pykd/win/dbgeng.h +++ b/pykd/win/dbgeng.h @@ -12,8 +12,8 @@ namespace pykd { /////////////////////////////////////////////////////////////////////////////////// -class DebugEngine { - +class DebugEngine : private DebugBaseEventCallbacks +{ public: struct DbgEngBind { @@ -26,39 +26,38 @@ public: CComQIPtr advanced; CComQIPtr 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; } + + // IDebugEventCallbacks impls + STDMETHOD(GetInterestMask)( + __out PULONG Mask + ) { - // IUnknown impls - STDMETHOD_(ULONG, AddRef)() { return 1; } - STDMETHOD_(ULONG, Release)() { return 1; } + *Mask = DEBUG_EVENT_BREAKPOINT; + return S_OK; + } - // IDebugEventCallbacks impls - STDMETHOD(GetInterestMask)( - __out PULONG Mask - ) - { - *Mask = DEBUG_EVENT_BREAKPOINT; - return S_OK; - } - - STDMETHOD(Breakpoint)( - __in IDebugBreakpoint *bp - ); - }; + 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 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(callback_) ), + pystate(pystate_) + {} + }; + + typedef std::list HandlerList; + + boost::recursive_mutex m_handlerLock; + HandlerList m_handlers; }; /////////////////////////////////////////////////////////////////////////////////// diff --git a/snippets/iat.py b/snippets/iat.py index 391bec5..11a00f3 100644 --- a/snippets/iat.py +++ b/snippets/iat.py @@ -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 ): diff --git a/snippets/ntobj.py b/snippets/ntobj.py index 5f2a9be..8ef9486 100644 --- a/snippets/ntobj.py +++ b/snippets/ntobj.py @@ -26,7 +26,7 @@ Work with NT Object tree manager from pykd import * -nt = loadModule("nt") +nt = module("nt") def getTypeWin7(p): """