diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index bbed4cc..5f004f0 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -16,6 +16,8 @@ bool isDumpAnalyzing(); bool isKernelDebugging(); void debugGo(); +void debugStep(); +void debugStepIn(); void debugBreak(); ULONG64 evaluate( const std::wstring &expression ); diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 96420cc..cf25e60 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -21,6 +21,7 @@ #include "localvar.h" #include "win/dbgio.h" +#include "win/windbg.h" using namespace pykd; @@ -72,6 +73,8 @@ BOOST_PYTHON_MODULE( pykd ) "Check if it is a dump analyzing ( not living debuggee )" ); python::def( "isKernelDebugging", &isKernelDebugging, "Check if kernel dubugging is running" ); + python::def( "isWindbgExt", &WindbgGlobalSession::isInit, + "Check if script works in windbg context" ); python::def( "breakin", &debugBreak, "Break into debugger" ); @@ -79,6 +82,10 @@ BOOST_PYTHON_MODULE( pykd ) "Evaluate windbg expression" ); python::def( "go", &debugGo, "Go debugging" ); + python::def( "step", &debugStep, + "The target is executing a single instruction or--if that instruction is a subroutine call--subroutine" ); + python::def( "trace", &debugStepIn, + "The target is executing a single instruction" ); // Debug output python::def( "dprint", &pykd::dprint, dprint_( boost::python::args( "str", "dml" ), diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index 6de7deb..beaf65c 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -170,6 +170,62 @@ void debugGo() /////////////////////////////////////////////////////////////////////////////// +void debugStep() +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + + hres = g_dbgEng->control->SetExecutionStatus( DEBUG_STATUS_STEP_OVER ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::SetExecutionStatus failed" ); + + ULONG currentStatus; + + do { + hres = g_dbgEng->control->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::WaitForEvent failed" ); + + hres = g_dbgEng->control->GetExecutionStatus( ¤tStatus ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetExecutionStatus failed" ); + + } while( currentStatus != DEBUG_STATUS_BREAK && currentStatus != DEBUG_STATUS_NO_DEBUGGEE ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void debugStepIn() +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + + hres = g_dbgEng->control->SetExecutionStatus( DEBUG_STATUS_STEP_INTO ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::SetExecutionStatus failed" ); + + ULONG currentStatus; + + do { + hres = g_dbgEng->control->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::WaitForEvent failed" ); + + hres = g_dbgEng->control->GetExecutionStatus( ¤tStatus ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetExecutionStatus failed" ); + + } while( currentStatus != DEBUG_STATUS_BREAK && currentStatus != DEBUG_STATUS_NO_DEBUGGEE ); +} + +/////////////////////////////////////////////////////////////////////////////// + void debugBreak() { PyThreadState *pystate = PyEval_SaveThread();