From e4c8bd3ff9ad03ea5cb767cf75e3a57e7da517e3 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Tue, 23 Dec 2014 10:00:43 +0000 Subject: [PATCH] [0.3.x] added : onDebugOutput callback [0.3.x] added : dbgCommand optional parameter suppressOutput git-svn-id: https://pykd.svn.codeplex.com/svn@89531 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/pydbgeng.h | 17 ++++++++++++----- pykd/pydbgio.h | 33 +++++++++++++++++++++++++++++++++ pykd/pyeventhandler.cpp | 22 ++++++++++++++++++++++ pykd/pyeventhandler.h | 1 + pykd/pykdver.h | 2 +- pykd/pymod.cpp | 31 +++++++++++++++++-------------- pykd/pythreadstate.h | 21 +++++++++++++++++++++ pykd/windbgext.cpp | 20 ++++++++++---------- 8 files changed, 117 insertions(+), 30 deletions(-) diff --git a/pykd/pydbgeng.h b/pykd/pydbgeng.h index de1aa72..0c16f8f 100644 --- a/pykd/pydbgeng.h +++ b/pykd/pydbgeng.h @@ -103,10 +103,19 @@ bool isKernelDebugging() } inline -std::wstring debugCommand( const std::wstring &command ) +python::object debugCommand( const std::wstring &command, bool suppressOutput = true) { - AutoRestorePyState pystate; - return kdlib::debugCommand(command); + std::wstring debugResult; + + { + AutoRestorePyState pystate; + debugResult = kdlib::debugCommand(command, suppressOutput); + } + + if (debugResult.size() > 0 ) + return python::object(debugResult); + + return python::object(); } /////////////////////////////////////////////////////////////////////////////// @@ -378,8 +387,6 @@ std::wstring callExtension( kdlib::EXTENSION_ID extId, const std::wstring comman /////////////////////////////////////////////////////////////////////////////// -std::wstring debugCommand( const std::wstring &command ); - python::object evaluate( const std::wstring &expression, bool cplusplus = false ); python::tuple getSourceLine( kdlib::MEMOFFSET_64 offset = 0 ); diff --git a/pykd/pydbgio.h b/pykd/pydbgio.h index 43130b9..b0d53c7 100644 --- a/pykd/pydbgio.h +++ b/pykd/pydbgio.h @@ -12,6 +12,16 @@ class DbgOut : public kdlib::windbg::WindbgOut { public: + virtual void write( const std::wstring& str ) { + AutoRestorePyState pystate; + kdlib::windbg::WindbgOut::write(str); + } + + virtual void writedml( const std::wstring& str ) { + AutoRestorePyState pystate; + kdlib::windbg::WindbgOut::writedml(str); + } + void flush() { } @@ -42,14 +52,24 @@ class SysDbgOut : public DbgOut { public: + SysDbgOut() { + m_state = PyThreadState_Get(); + } + virtual void write( const std::wstring& str) { + AutoSavePythonState pystate( &m_state ); python::object sys = python::import("sys"); sys.attr("stdout").attr("write")( str ); } virtual void writedml( const std::wstring& str) { + AutoSavePythonState pystate( &m_state ); write(str); } + +private: + + PyThreadState* m_state; }; /////////////////////////////////////////////////////////////////////////////// @@ -58,16 +78,26 @@ class SysDbgIn : public DbgIn { public: + SysDbgIn() { + m_state = PyThreadState_Get(); + } + virtual std::wstring readline() { + AutoSavePythonState pystate( &m_state ); python::object sys = python::import("sys"); return python::extract( sys.attr("stdin").attr("readline") ); } + +private: + + PyThreadState* m_state; }; /////////////////////////////////////////////////////////////////////////////// inline void dprint( const std::wstring &str, bool dml = false ) { + AutoRestorePyState pystate; kdlib::dprint(str,dml); } @@ -75,6 +105,7 @@ inline void dprint( const std::wstring &str, bool dml = false ) inline void dprintln( const std::wstring &str, bool dml = false ) { + AutoRestorePyState pystate; kdlib::dprintln(str,dml); } @@ -82,6 +113,7 @@ inline void dprintln( const std::wstring &str, bool dml = false ) inline void eprint( const std::wstring &str ) { + AutoRestorePyState pystate; kdlib::eprint(str); } @@ -89,6 +121,7 @@ inline void eprint( const std::wstring &str ) inline void eprintln( const std::wstring &str ) { + AutoRestorePyState pystate; kdlib::eprintln(str); } diff --git a/pykd/pyeventhandler.cpp b/pykd/pyeventhandler.cpp index 2d591fd..66e47b1 100644 --- a/pykd/pyeventhandler.cpp +++ b/pykd/pyeventhandler.cpp @@ -286,6 +286,28 @@ void EventHandler::onChangeLocalScope() ///////////////////////////////////////////////////////////////////////////////// +void EventHandler::onDebugOutput(const std::wstring& text) +{ + PyEval_RestoreThread( m_pystate ); + + try { + + python::override pythonHandler = get_override("onDebugOutput"); + if ( pythonHandler ) + { + pythonHandler(text); + } + } + catch (const python::error_already_set &) + { + printException(); + } + + m_pystate = PyEval_SaveThread(); +} + +///////////////////////////////////////////////////////////////////////////////// + Breakpoint::Breakpoint(kdlib::BreakpointPtr bp) { m_pystate = PyThreadState_Get(); diff --git a/pykd/pyeventhandler.h b/pykd/pyeventhandler.h index 890101f..ebdb7fa 100644 --- a/pykd/pyeventhandler.h +++ b/pykd/pyeventhandler.h @@ -35,6 +35,7 @@ public: virtual kdlib::DebugCallbackResult onModuleUnload( kdlib::MEMOFFSET_64 offset, const std::wstring &name ); virtual void onCurrentThreadChange(kdlib::THREAD_DEBUG_ID threadid); virtual void onChangeLocalScope(); + virtual void onDebugOutput(const std::wstring& text); private: diff --git a/pykd/pykdver.h b/pykd/pykdver.h index f91c3ed..a6d7d37 100644 --- a/pykd/pykdver.h +++ b/pykd/pykdver.h @@ -2,7 +2,7 @@ #define PYKD_VERSION_MAJOR 0 #define PYKD_VERSION_MINOR 3 #define PYKD_VERSION_SUBVERSION 0 -#define PYKD_VERSION_BUILDNO 14 +#define PYKD_VERSION_BUILDNO 15 #define __VER_STR2__(x) #x #define __VER_STR1__(x) __VER_STR2__(x) diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index cedef18..713cb3c 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -39,6 +39,7 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( detachProcess_, pykd::detachProcess, 0, 1 ); BOOST_PYTHON_FUNCTION_OVERLOADS( terminateProcess_, pykd::terminateProcess, 0, 1 ); BOOST_PYTHON_FUNCTION_OVERLOADS( attachKernel_, pykd::attachKernel, 0, 1 ); BOOST_PYTHON_FUNCTION_OVERLOADS( evaluate_, pykd::evaluate, 1, 2 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( debugCommand_, pykd::debugCommand, 1, 2 ); BOOST_PYTHON_FUNCTION_OVERLOADS( dprint_, pykd::dprint, 1, 2 ); BOOST_PYTHON_FUNCTION_OVERLOADS( dprintln_, pykd::dprintln, 1, 2 ); @@ -83,16 +84,22 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( Module_findSymbol, ModuleAdapter::findSymbol, 2 BOOST_PYTHON_FUNCTION_OVERLOADS( TypeInfo_ptrTo, TypeInfoAdapter::ptrTo, 1, 2 ); -pykd::SysDbgOut sysPykdOut; -pykd::SysDbgOut sysPykdErr; -pykd::SysDbgIn sysPykdIn; - namespace pykd { void initialize() { + pykd::SysDbgOut *sysPykdOut = new pykd::SysDbgOut(); + pykd::SysDbgOut *sysPykdErr = new pykd::SysDbgOut(); + pykd::SysDbgIn *sysPykdIn = new pykd::SysDbgIn(); + AutoRestorePyState pystate; + kdlib::initialize(); + + // использовать вместо консоли потоки из sys + kdlib::dbgout = sysPykdOut; + kdlib::dbgerr = sysPykdErr; + kdlib::dbgin = sysPykdIn; } void remote_initialize( const std::wstring& remoteOptions ) @@ -110,11 +117,6 @@ void uninitialize() BOOST_PYTHON_MODULE( pykd ) { - // использовать вместо консоли потоки из sys - kdlib::dbgout =&sysPykdOut; - kdlib::dbgerr = &sysPykdErr; - kdlib::dbgin = &sysPykdIn; - python::scope().attr("__version__") = pykdVersion; python::scope().attr("version") = pykdVersion; @@ -173,10 +175,10 @@ BOOST_PYTHON_MODULE( pykd ) python::def( "breakin", pykd::targetBreak, "Break into debugger" ); - python::def( "expr", pykd::evaluate, evaluate_( boost::python::args( "expression", "cplusplus" ), + python::def( "expr", pykd::evaluate, evaluate_( python::args( "expression", "cplusplus" ), "Evaluate windbg expression" ) ); - python::def( "dbgCommand", pykd::debugCommand, - "Run a debugger's command and return it's result as a string" ); + python::def( "dbgCommand", &pykd::debugCommand, + debugCommand_( python::args( "command", "suppressOutput"), "Run a debugger's command and return it's result as a string" ) ); python::def( "go", pykd::targetGo, "Go debugging" ); python::def( "step", pykd::targetStep, @@ -898,7 +900,9 @@ BOOST_PYTHON_MODULE( pykd ) "There is no return value" ) .def( "onChangeLocalScope", &EventHandler::onChangeLocalScope, "The current local scope has been changed.\n" - "There is no return value" ) + "There is no return value" ) + .def( "onDebugOutput", &EventHandler::onDebugOutput, + "Request debug output" ); // .def( "onSymbolsLoaded", &EventHandlerWrap::onSymbolsLoaded, // "Triggered debug symbols loaded. Parameter - module base or 0\n" @@ -908,7 +912,6 @@ BOOST_PYTHON_MODULE( pykd ) // "There is no return value"); ; - python::class_( "breakpoint", "class for CPU context representation", python::init()) .def( python::init() ) diff --git a/pykd/pythreadstate.h b/pykd/pythreadstate.h index c920777..9cc2233 100644 --- a/pykd/pythreadstate.h +++ b/pykd/pythreadstate.h @@ -30,4 +30,25 @@ private: PyThreadState* m_state; }; +class AutoSavePythonState +{ +public: + + explicit AutoSavePythonState(PyThreadState **state) { + PyEval_RestoreThread(*state); + m_state = state; + } + + ~AutoSavePythonState() { + *m_state = PyEval_SaveThread(); + + } + +private: + + PyThreadState** m_state; + + +}; + } \ No newline at end of file diff --git a/pykd/windbgext.cpp b/pykd/windbgext.cpp index 45d82d3..f895923 100644 --- a/pykd/windbgext.cpp +++ b/pykd/windbgext.cpp @@ -25,9 +25,9 @@ bool PykdExt::isInit() { extern "C" void initpykd(); -pykd::DbgOut pykdOut; -pykd::DbgOut pykdErr; -pykd::DbgIn pykdIn; +//pykd::DbgOut pykdOut; +//pykd::DbgOut pykdErr; +//pykd::DbgIn pykdIn; void PykdExt::setUp() @@ -58,16 +58,16 @@ void PykdExt::setUp() main_namespace[ key ] = pykd_namespace[ key ]; } - // перенаправление стандартных потоков ВВ - kdlib::dbgout =&pykdOut; - kdlib::dbgerr = &pykdErr; - kdlib::dbgin = &pykdIn; + //// перенаправление стандартных потоков ВВ + //kdlib::dbgout =&pykdOut; + //kdlib::dbgerr = &pykdErr; + //kdlib::dbgin = &pykdIn; python::object sys = python::import("sys"); - sys.attr("stdout") = python::object( &pykdOut ); - sys.attr("stderr") = python::object( &pykdErr ); - sys.attr("stdin") = python::object( &pykdIn ); + sys.attr("stdout") = python::object( pykd::DbgOut() ); + sys.attr("stderr") = python::object( pykd::DbgOut() ); + sys.attr("stdin") = python::object( pykd::DbgIn() ); python::list pathList(sys.attr("path"));