diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index f908867..b0154d0 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -10,6 +10,7 @@ #include "dbgexcept.h" #include "module.h" #include "dbgio.h" +#include "dbgcmd.h" ///////////////////////////////////////////////////////////////////////////////// @@ -69,6 +70,10 @@ public: return Module( m_client, offset ); } + DbgExtensionPtr loadExtension( const std::wstring &extPath ) { + return DbgExtensionPtr( new DbgExtension( m_client, extPath ) ); + } + ULONG64 addr64( ULONG64 addr ); void dprint( const std::wstring &str, bool dml = false ); diff --git a/pykd/dbgcmd.cpp b/pykd/dbgcmd.cpp index 5c0ece6..a0bd083 100644 --- a/pykd/dbgcmd.cpp +++ b/pykd/dbgcmd.cpp @@ -32,6 +32,53 @@ std::string dbgCommand( const std::wstring &command ) ///////////////////////////////////////////////////////////////////////////////// +DbgExtension::DbgExtension( IDebugClient4 *client, const std::wstring &extPath ) : + DbgObject( client ) +{ + HRESULT hres; + + hres = m_control->AddExtensionWide( extPath.c_str(), 0, &m_handle ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::AddExtension failed" ); +} + +///////////////////////////////////////////////////////////////////////////////// + +DbgExtension::~DbgExtension() +{ + m_control->RemoveExtension( m_handle ); +} + +///////////////////////////////////////////////////////////////////////////////// + +std::string DbgExtension::call( const std::wstring &command, const std::wstring ¶ms ) +{ + HRESULT hres; + + OutputReader outReader( m_client ); + + PyThreadState *pystate = PyEval_SaveThread(); + + hres = m_control->CallExtensionWide( m_handle, command.c_str(), NULL ); + + PyEval_RestoreThread( pystate ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::CallExtension failed" ); + + return std::string( outReader.Line() ); +} + +///////////////////////////////////////////////////////////////////////////////// + +DbgExtensionPtr +loadExtension( const std::wstring &extPath ) +{ + return g_dbgClient->loadExtension( extPath ); +} + +///////////////////////////////////////////////////////////////////////////////// + } // end namespace pykd diff --git a/pykd/dbgcmd.h b/pykd/dbgcmd.h index c772573..00fe161 100644 --- a/pykd/dbgcmd.h +++ b/pykd/dbgcmd.h @@ -1,5 +1,8 @@ #pragma once +#include <string> + +#include "dbgobj.h" namespace pykd { @@ -10,6 +13,30 @@ dbgCommand( const std::wstring &command ); /////////////////////////////////////////////////////////////////////////////////// +class DbgExtension : private DbgObject { + +public: + + DbgExtension( IDebugClient4 *client, const std::wstring &extPath ); + + virtual ~DbgExtension(); + + std::string + call( const std::wstring &command, const std::wstring ¶m ); + +private: + + ULONG64 m_handle; + +}; + +typedef boost::shared_ptr<DbgExtension> DbgExtensionPtr; + +DbgExtensionPtr +loadExtension( const std::wstring &extPath ); + +/////////////////////////////////////////////////////////////////////////////////// + }; // end of namespace pykd diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 2789e74..a1e27d1 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -65,6 +65,8 @@ BOOST_PYTHON_MODULE( pykd ) "Attach debugger to a exsisting process" ) .def( "attachKernel", &pykd::DebugClient::attachKernel, "Attach debugger to a target's kernel" ) + .def ( "loadExt", &pykd::DebugClient::loadExtension, + "Load a debuger extension" ) .def( "loadModule", &pykd::DebugClient::loadModule, "Return instance of Module class" ) .def( "findModule", &pykd::DebugClient::findModule, @@ -86,6 +88,8 @@ BOOST_PYTHON_MODULE( pykd ) "Attach debugger to a exsisting process" ); python::def( "attachKernel", &pykd::attachKernel, "Attach debugger to a kernel target" ); + python::def( "loadExt", &pykd::loadExtension, + "Load a debuger extension" ); python::def( "loadModule", &pykd::loadModule, "Return instance of Module class" ); python::def( "findModule", &pykd::findModule, @@ -128,11 +132,15 @@ BOOST_PYTHON_MODULE( pykd ) .def("__getattr__", &pykd::Module::getSymbol, "Return address of the symbol" ); - boost::python::class_<DbgOut>( "dout", "dout", python::no_init ) - .def( "write", &DbgOut::write ); + python::class_<DbgOut>( "dout", "dout", python::no_init ) + .def( "write", &pykd::DbgOut::write ); - boost::python::class_<DbgIn>( "din", "din", python::no_init ) - .def( "readline", &DbgIn::readline ); + python::class_<DbgIn>( "din", "din", python::no_init ) + .def( "readline", &pykd::DbgIn::readline ); + + python::class_<DbgExtension, pykd::DbgExtensionPtr>("ext", python::no_init ) + .def( "call", &pykd::DbgExtension::call, + "Call debug extension command end return it's result as a string" ); python::def( "diaLoadPdb", &pyDia::GlobalScope::loadPdb, "Open pdb file for quering debug symbols. Return DiaSymbol of global scope"); diff --git a/test/scripts/basetest.py b/test/scripts/basetest.py index eeb7c7b..a218537 100644 --- a/test/scripts/basetest.py +++ b/test/scripts/basetest.py @@ -111,6 +111,7 @@ class BaseTest( unittest.TestCase ): """ Branch test: new API 0.1.x what must be available """ self.assertTrue( hasattr(pykd, 'createDbgClient') ) self.assertTrue( hasattr(pykd, 'diaLoadPdb') ) + self.assertTrue( hasattr(pykd, 'loadExt') ) self.assertTrue( hasattr(pykd, 'DiaException') ) self.assertTrue( hasattr(pykd, 'DiaScope') ) diff --git a/test/scripts/dbgcmd.py b/test/scripts/dbgcmd.py index 82aeeae..d68c81e 100644 --- a/test/scripts/dbgcmd.py +++ b/test/scripts/dbgcmd.py @@ -7,4 +7,7 @@ class DbgcmdTest( unittest.TestCase ): def testDbgCommand( self ): self.assertNotEqual( "", pykd.dbgCommand("lm") ) - + +# def testDbgExt( self ): +# #ext = pykd.loadExt( "ext" ) +# #self.assertNotEqual( "", ext.call("help", "") )