From 0f9c2e1e2c290de0f32ce994f3bac6b9fb73de9b Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Mon, 9 Aug 2010 07:28:59 +0000 Subject: [PATCH] [+] added: dbgExtensionClass class for calling windbg extension command from python script git-svn-id: https://pykd.svn.codeplex.com/svn@53831 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgcallback.h | 176 +++++++++++++++++++++++++++++++++++++++++++++ pykd/dbgcmd.cpp | 60 ++++++++++++++++ pykd/dbgcmd.h | 23 +++++- pykd/dbgext.cpp | 7 ++ pykd/dbgstack.cpp | 45 ++++++++++++ pykd/dbgstack.h | 11 +++ pykd/dbgtype.cpp | 3 + pykd/pykd.vcproj | 8 +++ 8 files changed, 331 insertions(+), 2 deletions(-) create mode 100644 pykd/dbgcallback.h create mode 100644 pykd/dbgstack.cpp create mode 100644 pykd/dbgstack.h diff --git a/pykd/dbgcallback.h b/pykd/dbgcallback.h new file mode 100644 index 0000000..b8c4b17 --- /dev/null +++ b/pykd/dbgcallback.h @@ -0,0 +1,176 @@ +#pragma once + +#include "dbgext.h" +#include "dbgexcept.h" + +#include + +/////////////////////////////////////////////////////////////////////////////// + +// класс для перехвата вывода в отладчик + +class OutputReader : public IDebugOutputCallbacks { + +public: + + OutputReader( IDebugClient *debugClient ) + { + HRESULT hres; + + try { + + m_debugClient = debugClient; + m_debugClient->AddRef(); + + hres = m_debugClient->GetOutputCallbacks( &m_previousCallback ); + if ( FAILED( hres ) ) + { + throw hres; + } + + hres = m_debugClient->SetOutputCallbacks( this ); + if ( FAILED( hres ) ) + { + throw hres; + } + + } catch( ... ) + { + m_debugClient->Release(); + m_debugClient = NULL; + } + } + + ~OutputReader() + { + if ( m_debugClient ) + { + m_debugClient->SetOutputCallbacks( m_previousCallback ); + m_debugClient->Release(); + } + } + + const std::string& + Line() const { + return m_readLine; + } + +private: + + // IUnknown. + STDMETHOD(QueryInterface)( + __in REFIID InterfaceId, + __out PVOID* Interface ) { + return E_NOINTERFACE; + } + + STDMETHOD_(ULONG, AddRef)() { + return 1L; + } + + + STDMETHOD_(ULONG, Release)() { + return 0L; + } + + STDMETHOD(Output)( + __in ULONG Mask, + __in PCSTR Text ) + { + if ( Mask == DEBUG_OUTPUT_NORMAL ) + { + m_readLine += std::string( Text ); + } + + return S_OK; + } + +private: + + std::string m_readLine; + + IDebugClient *m_debugClient; + + IDebugOutputCallbacks *m_previousCallback; +}; + +/////////////////////////////////////////////////////////////////////////////// + +class InputReader : public IDebugInputCallbacks { + +public: + + InputReader( IDebugClient *debugClient ) + { + HRESULT hres; + + try { + + m_debugClient = debugClient; + m_debugClient->AddRef(); + + hres = m_debugClient->GetInputCallbacks( &m_previousCallback ); + if ( FAILED( hres ) ) + { + throw hres; + } + + hres = m_debugClient->SetInputCallbacks( this ); + if ( FAILED( hres ) ) + { + throw hres; + } + + } catch( ... ) + { + m_debugClient->Release(); + m_debugClient = NULL; + } + } + + ~InputReader() + { + if ( m_debugClient ) + { + m_debugClient->SetInputCallbacks( m_previousCallback ); + m_debugClient->Release(); + } + } + + +private: + + // IUnknown. + STDMETHOD(QueryInterface)( + __in REFIID InterfaceId, + __out PVOID* Interface ) { + return E_NOINTERFACE; + } + + STDMETHOD_(ULONG, AddRef)() { + return 1L; + } + + + STDMETHOD_(ULONG, Release)() { + return 0L; + } + + STDMETHOD( EndInput )() { + return S_OK; + } + + STDMETHOD( StartInput )( + IN ULONG BufferSize ) { + return S_OK; + } + +private: + + IDebugClient *m_debugClient; + + IDebugInputCallbacks *m_previousCallback; + +}; + +/////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgcmd.cpp b/pykd/dbgcmd.cpp index bc0cd5f..b63b0a4 100644 --- a/pykd/dbgcmd.cpp +++ b/pykd/dbgcmd.cpp @@ -35,3 +35,63 @@ dbgCommand( const std::string &command ) } /////////////////////////////////////////////////////////////////////////////// + +dbgExtensionClass::dbgExtensionClass( const char* path ) +{ + HRESULT hres; + + try { + + hres = dbgExt->control->AddExtension( path, 0, &m_handle ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::AddExtension failed" ); + + } + catch( std::exception &e ) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); + } + catch(...) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +dbgExtensionClass::~dbgExtensionClass() +{ + if ( m_handle ) + dbgExt->control->RemoveExtension( m_handle ); +} + +/////////////////////////////////////////////////////////////////////////////// + +std::string +dbgExtensionClass::call( const std::string &command, const std::string params ) +{ + HRESULT hres; + + try { + + OutputReader outReader( dbgExt->client ); + + hres = dbgExt->control->CallExtension( m_handle, command.c_str(), params.c_str() ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::CallExtension failed" ); + + return std::string( outReader.Line() ); + } + catch( std::exception &e ) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); + } + catch(...) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); + } + + return "error"; +} + +/////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgcmd.h b/pykd/dbgcmd.h index 24369d6..d6429ec 100644 --- a/pykd/dbgcmd.h +++ b/pykd/dbgcmd.h @@ -10,8 +10,27 @@ std::string dbgCommand( const std::string &command ); -void -dbgGoCommand(); +///////////////////////////////////////////////////////////////////////////////// + +class dbgExtensionClass { + +public: + + dbgExtensionClass() : + m_handle( NULL ) + {} + + dbgExtensionClass( const char* path ); + + ~dbgExtensionClass(); + + std::string + call( const std::string &command, const std::string param ); + +private: + + ULONG64 m_handle; +}; ///////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 00c25b0..7f30a05 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -24,6 +24,7 @@ #include "dbgexcept.h" #include "dbgsession.h" #include "dbgcallback.h" +#include "dbgstack.h" ///////////////////////////////////////////////////////////////////////////////// @@ -96,6 +97,7 @@ BOOST_PYTHON_MODULE( pykd ) boost::python::def( "ptrSignQWord", &loadByPtr<__int64> ); boost::python::def( "ptrPtr", &loadPtrByPtr ); boost::python::def( "compareMemory", &compareMemory ); + boost::python::def( "getStack", &getStack ); boost::python::class_( "typedVarClass" ) .def("getAddress", &typedVarClass::getAddress ); boost::python::class_( "dbgModuleClass" ) @@ -103,6 +105,11 @@ BOOST_PYTHON_MODULE( pykd ) .def("end", &dbgModuleClass::getEnd ) .def("name", &dbgModuleClass::getName ) .def("contain", &dbgModuleClass::contain ); + boost::python::class_( + "dbgExtensionClass", + "dbgExtensionClass", + boost::python::init( boost::python::args("path"), "__init__ dbgExtensionClass" ) ) + .def("call", &dbgExtensionClass::call ); } ///////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgstack.cpp b/pykd/dbgstack.cpp new file mode 100644 index 0000000..4b93562 --- /dev/null +++ b/pykd/dbgstack.cpp @@ -0,0 +1,45 @@ +#include "stdafx.h" + +#include "dbgext.h" +#include "dbgstack.h" +#include "dbgexcept.h" + +///////////////////////////////////////////////////////////////////////////////// + +boost::python::object +getStack( ULONG64 stackPtr ) +{ + HRESULT hres; + PDEBUG_STACK_FRAME frames = NULL; + + try { + + frames = new DEBUG_STACK_FRAME [ 1000 ]; + + ULONG filledFrames; + hres = dbgExt->control->GetStackTrace( stackPtr, stackPtr, stackPtr, frames, 1000, &filledFrames ); + + dbgExt->control->OutputStackTrace( DEBUG_OUTCTL_THIS_CLIENT, frames, filledFrames, DEBUG_STACK_FUNCTION_INFO | DEBUG_STACK_FRAME_ADDRESSES ); + + if ( frames ) + delete[] frames; + + return boost::python::object(); + + } + catch( std::exception &e ) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); + } + catch(...) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); + } + + if ( frames ) + delete[] frames; + + return boost::python::object(); +} + +///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgstack.h b/pykd/dbgstack.h new file mode 100644 index 0000000..05096b9 --- /dev/null +++ b/pykd/dbgstack.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +///////////////////////////////////////////////////////////////////////////////// + +boost::python::object +getStack( ULONG64 stackPtr ); + +///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgtype.cpp b/pykd/dbgtype.cpp index b8611c9..209e949 100644 --- a/pykd/dbgtype.cpp +++ b/pykd/dbgtype.cpp @@ -80,6 +80,9 @@ loadTypedVar( const std::string &moduleName, const std::string &typeName, ULONG6 HRESULT hres; try { + + if ( address == 0 ) + return boost::python::object(); ULONG64 moduleBase; diff --git a/pykd/pykd.vcproj b/pykd/pykd.vcproj index 47e8e3a..0f551a4 100644 --- a/pykd/pykd.vcproj +++ b/pykd/pykd.vcproj @@ -387,6 +387,10 @@ RelativePath=".\dbgsession.cpp" > + + @@ -485,6 +489,10 @@ RelativePath=".\dbgsession.h" > + +