From 5ef445611cf7aa77ad26081dcff18cd64fbde310 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Mon, 10 Oct 2011 11:19:12 +0000 Subject: [PATCH] [0.1.x] added : !pycmd implementation git-svn-id: https://pykd.svn.codeplex.com/svn@70280 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgclient.cpp | 41 +------------ pykd/dbgclient.h | 38 +++++++++--- pykd/dbgext.cpp | 28 ++++++--- pykd/dbgio.cpp | 12 +++- pykd/dbgio.h | 143 ++++++++++++++++++++++++++++++++++++++++++++- pykd/dbgobj.h | 11 ++-- pykd/module.cpp | 4 +- pykd/module.h | 4 +- 8 files changed, 212 insertions(+), 69 deletions(-) diff --git a/pykd/dbgclient.cpp b/pykd/dbgclient.cpp index f65439b..a9f5409 100644 --- a/pykd/dbgclient.cpp +++ b/pykd/dbgclient.cpp @@ -8,7 +8,7 @@ namespace pykd { /////////////////////////////////////////////////////////////////////////////////// -DebugClientPtr g_dbgClient( DebugClient::createDbgClient() ); +DebugClientPtr g_dbgClient; //( DebugClient::createDbgClient() ); void loadDump( const std::wstring &fileName ) { g_dbgClient->loadDump( fileName ); @@ -37,43 +37,6 @@ DebugClientPtr DebugClient::setDbgClientCurrent( DebugClientPtr newDbgClient ) /////////////////////////////////////////////////////////////////////////////////// -DebugClient::DebugClient() -{ - HRESULT hres; - hres = DebugCreate( __uuidof(IDebugClient5), (void **)&m_client ); - if ( FAILED( hres ) ) - throw DbgException("DebugCreate failed"); - - hres = m_client->QueryInterface( __uuidof(IDebugControl4), (void**)&m_control ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugControl4 failed"); - - hres = m_client->QueryInterface( __uuidof(IDebugSymbols3), (void**)&m_symbols ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugSymbols3 failed"); -} - -/////////////////////////////////////////////////////////////////////////////////// - -DebugClient::DebugClient( IDebugClient4 *client ) -{ - HRESULT hres; - - hres = client->QueryInterface( __uuidof(IDebugClient5), (void**)&m_client ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugControl4 failed"); - - hres = client->QueryInterface( __uuidof(IDebugControl4), (void**)&m_control ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugControl4 failed"); - - hres = client->QueryInterface( __uuidof(IDebugSymbols3), (void**)&m_symbols ); - if ( FAILED( hres ) ) - throw DbgException("QueryInterface IDebugSymbols3 failed"); -} - -/////////////////////////////////////////////////////////////////////////////////// - void DebugClient::loadDump( const std::wstring &fileName ) { HRESULT hres; @@ -133,7 +96,7 @@ void DebugClient::attachKernel( const std::wstring ¶m ) { HRESULT hres; - hres = m_client->AttachKernelWide( DEBUG_ATTACH_KERNEL_CONNECTION, param.c_str() ); + hres = m_client5->AttachKernelWide( DEBUG_ATTACH_KERNEL_CONNECTION, param.c_str() ); if ( FAILED( hres ) ) throw DbgException( "IDebugClient5::AttachKernelWide failed" ); } diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index 9f8530d..7f3a9db 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -6,6 +6,7 @@ #include +#include "dbgobj.h" #include "dbgexcept.h" #include "module.h" #include "dbgio.h" @@ -21,7 +22,7 @@ typedef boost::shared_ptr DebugClientPtr; ///////////////////////////////////////////////////////////////////////////////// -class DebugClient { +class DebugClient : private DbgObject { public: @@ -29,7 +30,15 @@ public: static DebugClientPtr createDbgClient() { - return DebugClientPtr( new DebugClient() ); + + HRESULT hres; + CComPtr client = NULL; + + hres = DebugCreate( __uuidof(IDebugClient4), (void **)&client ); + if ( FAILED( hres ) ) + throw DbgException("DebugCreate failed"); + + return createDbgClient( client ); } static @@ -74,15 +83,26 @@ public: return DbgIn( m_client ); } +public: + + CComPtr& + client() { + return m_client; + } + + CComPtr& + client5() { + return m_client5; + } + + CComPtr& + control() { + return m_control; + } + private: - DebugClient(); - - DebugClient( IDebugClient4 *client ); - - CComPtr m_client; - CComPtr m_control; - CComPtr m_symbols; + DebugClient( IDebugClient4 *client ) : DbgObject( client ) {} }; ///////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index c982c0e..75624de 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -73,8 +73,8 @@ BOOST_PYTHON_MODULE( pykd ) .def( "dprintln", &pykd::DebugClient::dprintln, "Print out string and insert end of line symbol. If dml = True string is printed with dml highlighting ( only for windbg )" ); -// python::def( "createDbgClient", pykd::DebugClient::createDbgClient, -// "create a new instance of the dbgClient class" ); + python::def( "createDbgClient", (DebugClientPtr(*)())&pykd::DebugClient::createDbgClient, + "create a new instance of the dbgClient class" ); python::def( "loadDump", &pykd::loadDump, "Load crash dump (only for console)"); python::def( "startProcess", &pykd::startProcess, @@ -392,15 +392,13 @@ py( PDEBUG_CLIENT4 client, PCSTR args ) try { // получаем достпу к глобальному мапу ( нужен для вызова exec_file ) - boost::python::object main = python::import("__main__"); + python::object main = python::import("__main__"); - boost::python::object global(main.attr("__dict__")); + python::object global(main.attr("__dict__")); - boost::python::import( "pykd" ); - // настраиваем ввод/вывод ( чтобы в скрипте можно было писать print ) - boost::python::object sys = boost::python::import("sys"); + python::object sys = python::import("sys"); sys.attr("stdout") = python::object( dbgClient->dout() ); sys.attr("stdin") = python::object( dbgClient->din() ); @@ -514,7 +512,21 @@ pycmd( PDEBUG_CLIENT4 client, PCSTR args ) try { - + // перенаправление стандартных потоков ВВ + python::object sys = python::import("sys"); + + sys.attr("stdout") = python::object( DbgOut( client ) ); + sys.attr("stdin") = python::object( DbgIn( client ) ); + + client->SetOutputMask( DEBUG_OUTPUT_NORMAL ); + //client->SetInputCallbacks( NULL ); + + PyRun_String( + "__import__('code').InteractiveConsole(__import__('__main__').__dict__).interact()", + Py_file_input, + WindbgGlobalSession::global().ptr(), + WindbgGlobalSession::global().ptr() + ); } catch(...) { diff --git a/pykd/dbgio.cpp b/pykd/dbgio.cpp index 2f350cc..5b47d2a 100644 --- a/pykd/dbgio.cpp +++ b/pykd/dbgio.cpp @@ -94,8 +94,9 @@ DbgOut::write( const std::wstring &str ) { for ( size_t i = 0; i < str.size() / 100 + 1; ++i ) { - m_control->OutputWide( - DEBUG_OUTPUT_ERROR, + m_control->ControlledOutputWide( + DEBUG_OUTCTL_AMBIENT_TEXT, + DEBUG_OUTPUT_NORMAL, L"%ws", str.substr( i*100, min( str.size() - i*100, 100 ) ).c_str() ); @@ -112,7 +113,12 @@ DbgOut::write( const std::wstring &str ) std::string DbgIn::readline() { - return ""; + char str[0x100]; + ULONG inputSize = 0; + + m_control->Input( str, sizeof(str), &inputSize ); + + return std::string( str ) + "\n"; } /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgio.h b/pykd/dbgio.h index 7447171..51d770c 100644 --- a/pykd/dbgio.h +++ b/pykd/dbgio.h @@ -1,6 +1,7 @@ #pragma once #include "dbgobj.h" +#include namespace pykd { @@ -20,7 +21,7 @@ class DbgOut : private DbgObject { public: - DbgOut( IDebugClient5 *client ) : DbgObject( client ) + DbgOut( IDebugClient4 *client ) : DbgObject( client ) {} void @@ -33,7 +34,7 @@ class DbgIn : private DbgObject { public: - DbgIn( IDebugClient5 *client ) : DbgObject( client ) + DbgIn( IDebugClient4 *client ) : DbgObject( client ) {} std::string @@ -42,4 +43,142 @@ public: ///////////////////////////////////////////////////////////////////////////////// +// класс для перехвата вывода в отладчик + +class OutputReader : private DbgObject, public IDebugOutputCallbacks, private boost::noncopyable { + +public: + + explicit OutputReader( IDebugClient4 *client ) : DbgObject( client ) + { + HRESULT hres; + + hres = m_client->GetOutputCallbacks( &m_previousCallback ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugClient::GetOutputCallbacks failed" ); + + hres = m_client->SetOutputCallbacks( this ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugClient::GetOutputCallbacks failed" ); + + } + + ~OutputReader() + { + if ( m_previousCallback ) + m_client->SetOutputCallbacks( m_previousCallback ); + } + + 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; + + CComPtr m_previousCallback; +}; + +/////////////////////////////////////////////////////////////////////////////////// +// +//class InputReader : public IDebugInputCallbacks, private DbgObject, private boost::noncopyable { +// +//public: +// +// explicit InputReader( IDebugClient4 *debugClient ) : DbgObject( debugClient ) +// { +// HRESULT hres; +// +// hres = m_client->GetInputCallbacks( &m_previousCallback ); +// if ( FAILED( hres ) ) +// throw DbgException( "IDebugClient::GetInputCallbacks failed" ); +// +// hres = m_client->SetInputCallbacks( this ); +// if ( FAILED( hres ) ) +// throw DbgException( "IDebugClient::SetInputCallbacks failed" ); +// } +// +// ~InputReader() +// { +// if ( m_previousCallback ) +// m_client->SetInputCallbacks( m_previousCallback ); +// } +// +// +//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 ) { +// +// std::vector buf(BufferSize); +// +// ULONG inputSize; +// +// m_control->Input( &buf[0], BufferSize, &inputSize ); +// +// m_control->ReturnInput( &buf[0] ); +// +// return S_OK; +// } +// +//private: +// +// CComPtr m_previousCallback; +// +//}; + +///////////////////////////////////////////////////////////////////////////////// + }; \ No newline at end of file diff --git a/pykd/dbgobj.h b/pykd/dbgobj.h index a06f0cd..f8e1dc4 100644 --- a/pykd/dbgobj.h +++ b/pykd/dbgobj.h @@ -11,12 +11,14 @@ class DbgObject { protected: - DbgObject( IDebugClient5 *client ) { + DbgObject( IDebugClient4 *client ) { + + m_client = client; HRESULT hres; - hres = client->QueryInterface( __uuidof(IDebugClient5), (void **)&m_client ); + hres = client->QueryInterface( __uuidof(IDebugClient5), (void **)&m_client5 ); if ( FAILED( hres ) ) - throw DbgException("DebugCreate failed"); + throw DbgException("QueryInterface IDebugClient5 failed"); hres = client->QueryInterface( __uuidof(IDebugControl4), (void**)&m_control ); if ( FAILED( hres ) ) @@ -33,7 +35,8 @@ protected: virtual ~DbgObject() {}; - CComPtr m_client; + CComPtr m_client5; + CComPtr m_client; CComPtr m_control; CComPtr m_symbols; CComPtr m_advanced; diff --git a/pykd/module.cpp b/pykd/module.cpp index 9ebb13b..c35ad13 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -20,7 +20,7 @@ Module findModule( ULONG64 offset ) { /////////////////////////////////////////////////////////////////////////////////// -Module::Module( IDebugClient5 *client, const std::string& moduleName ) : DbgObject( client ) +Module::Module( IDebugClient4 *client, const std::string& moduleName ) : DbgObject( client ) { HRESULT hres; @@ -55,7 +55,7 @@ Module::Module( IDebugClient5 *client, const std::string& moduleName ) : DbgObje /////////////////////////////////////////////////////////////////////////////////// -Module::Module( IDebugClient5 *client, ULONG64 offset ) : DbgObject( client ) +Module::Module( IDebugClient4 *client, ULONG64 offset ) : DbgObject( client ) { HRESULT hres; diff --git a/pykd/module.h b/pykd/module.h index 51fcbec..34e704c 100644 --- a/pykd/module.h +++ b/pykd/module.h @@ -14,9 +14,9 @@ class Module : private DbgObject { public: - Module( IDebugClient5 *client, const std::string& moduleName ); + Module( IDebugClient4 *client, const std::string& moduleName ); - Module( IDebugClient5 *client, ULONG64 offset ); + Module( IDebugClient4 *client, ULONG64 offset ); std::string getName() { return m_name;