From 4e072f3ef55453a812129cd4f4d1d5b0044294ca Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Thu, 20 Oct 2011 06:33:44 +0000 Subject: [PATCH] [0.1.x] added : go routine [0.1.x] added : step routine [0.1.x] added : trace routine [0.1.x] added : waitForEvent routine ( Wait for events that breaks into the debugger ) [0.1.x] added : setExecutionStatus routine ( Requests that the debugger engine enter an executable state ) [0.1.x] added : getExecutionStatus routine ( Return information about the execution status of the debugger ) git-svn-id: https://pykd.svn.codeplex.com/svn@70639 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgclient.cpp | 60 +++++- pykd/dbgclient.h | 67 ++++++- pykd/dbgext.cpp | 43 ++++- pykd/module.cpp | 368 ------------------------------------- pykd/pyaux.h | 45 +++-- pykd/pykd_2008.vcproj | 4 + test/scripts/basetest.py | 3 + test/scripts/clienttest.py | 11 ++ 8 files changed, 204 insertions(+), 397 deletions(-) diff --git a/pykd/dbgclient.cpp b/pykd/dbgclient.cpp index 3675cb3..899860a 100644 --- a/pykd/dbgclient.cpp +++ b/pykd/dbgclient.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" +#include #include "dbgclient.h" -#include namespace pykd { @@ -70,6 +70,26 @@ python::tuple getDebuggeeType() /////////////////////////////////////////////////////////////////////////////////// +ULONG DebugClient::getExecutionStatus() +{ + ULONG currentStatus; + HRESULT hres; + + hres = m_control->GetExecutionStatus( ¤tStatus ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetExecutionStatus failed" ); + + return currentStatus; +} + +ULONG getExecutionStatus() +{ + return g_dbgClient->getExecutionStatus(); +} + +/////////////////////////////////////////////////////////////////////////////////// + bool DebugClient::isDumpAnalyzing() { HRESULT hres; @@ -190,6 +210,44 @@ void attachKernel( const std::wstring ¶m ) { g_dbgClient->attachKernel( param ); } +/////////////////////////////////////////////////////////////////////////////////// + +void DebugClient::setExecutionStatus( ULONG status ) +{ + HRESULT hres; + + hres = m_control->SetExecutionStatus( status ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::SetExecutionStatus failed" ); + +} + +void setExecutionStatus( ULONG status ) +{ + g_dbgClient->setExecutionStatus( status ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +void DebugClient::waitForEvent() +{ + HRESULT hres; + + do { + PyThread_StateRestore pyThreadRestore( m_pyThreadState ); + hres = m_control->WaitForEvent( 0, INFINITE ); + + } while( false ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::WaitForEvent failed" ); +} + +void waitForEvent() +{ + g_dbgClient->waitForEvent(); +} /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index dfc43b5..ae5f5ac 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -11,6 +11,7 @@ #include "module.h" #include "dbgio.h" #include "dbgcmd.h" +#include "pyaux.h" ///////////////////////////////////////////////////////////////////////////////// @@ -50,12 +51,15 @@ public: void attachKernel( const std::wstring ¶m ); - //createEventHandler(); - ULONG64 evaluate( const std::wstring &expression ); python::tuple getDebuggeeType(); + ULONG getExecutionStatus(); + + template + void changeDebuggerStatus(); + bool isKernelDebugging(); bool isDumpAnalyzing(); @@ -74,6 +78,14 @@ public: ULONG64 addr64( ULONG64 addr ); + DbgOut dout() { + return DbgOut( m_client ); + } + + DbgIn din() { + return DbgIn( m_client ); + } + void dprint( const std::wstring &str, bool dml = false ); void dprintln( const std::wstring &str, bool dml = false ); @@ -82,13 +94,9 @@ public: void eprintln( const std::wstring &str ); - DbgOut dout() { - return DbgOut( m_client ); - } - - DbgIn din() { - return DbgIn( m_client ); - } + void setExecutionStatus( ULONG status ); + + void waitForEvent(); public: @@ -110,6 +118,8 @@ public: private: DebugClient( IDebugClient4 *client ) : DbgObject( client ) {} + + PyThreadStateSaver m_pyThreadState; }; ///////////////////////////////////////////////////////////////////////////////// @@ -126,12 +136,51 @@ void attachKernel( const std::wstring ¶m ); python::tuple getDebuggeeType(); +ULONG getExecutionStatus(); + bool isKernelDebugging(); bool isDumpAnalyzing(); +void setExecutionStatus( ULONG status ); + +void waitForEvent(); + ///////////////////////////////////////////////////////////////////////////////// +template +void DebugClient::changeDebuggerStatus() +{ + HRESULT hres; + + hres = m_control->SetExecutionStatus( status ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::SetExecutionStatus failed" ); + + ULONG currentStatus; + + do { + + waitForEvent(); + + hres = m_control->GetExecutionStatus( ¤tStatus ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetExecutionStatus failed" ); + + } while( currentStatus != DEBUG_STATUS_BREAK && currentStatus != DEBUG_STATUS_NO_DEBUGGEE ); +} + +template +void changeDebuggerStatus() +{ + g_dbgClient->changeDebuggerStatus(); +} + +///////////////////////////////////////////////////////////////////////////////// + + }; // namespace pykd diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index e6ad6ae..8e8b9f3 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -72,6 +72,10 @@ BOOST_PYTHON_MODULE( pykd ) "Evaluate windbg expression" ) .def( "getDebuggeeType", &pykd::DebugClient::getDebuggeeType, "Return type of the debuggee" ) + .def( "getExecutionStatus", &pykd::DebugClient::getExecutionStatus, + "Return information about the execution status of the debugger" ) + .def( "go", &pykd::DebugClient::changeDebuggerStatus, + "Change debugger status to DEBUG_STATUS_GO" ) .def( "isDumpAnalyzing", &pykd::DebugClient::isDumpAnalyzing, "Check if it is a dump analyzing ( not living debuggee )" ) .def( "isKernelDebugging", &pykd::DebugClient::isKernelDebugging, @@ -87,7 +91,15 @@ BOOST_PYTHON_MODULE( pykd ) .def( "dprint", &pykd::DebugClient::dprint, "Print out string. If dml = True string is printed with dml highlighting ( only for windbg )" ) .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 )" ); + "Print out string and insert end of line symbol. If dml = True string is printed with dml highlighting ( only for windbg )" ) + .def( "setExecutionStatus", &pykd::DebugClient::setExecutionStatus, + "Requests that the debugger engine enter an executable state" ) + .def( "step", &pykd::DebugClient::changeDebuggerStatus, + "Change debugger status to DEBUG_STATUS_STEP_OVER" ) + .def( "trace", &pykd::DebugClient::changeDebuggerStatus, + "Change debugger status to DEBUG_STATUS_STEP_INTO" ) + .def( "waitForEvent", &pykd::DebugClient::waitForEvent, + "Wait for events that breaks into the debugger" ); python::def( "createDbgClient", (DebugClientPtr(*)())&pykd::DebugClient::createDbgClient, "create a new instance of the dbgClient class" ); @@ -103,6 +115,10 @@ BOOST_PYTHON_MODULE( pykd ) "Evaluate windbg expression" ); python::def( "getDebuggeeType", &pykd::getDebuggeeType, "Return type of the debuggee" ); + python::def( "getExecutionStatus", &pykd::getExecutionStatus, + "Return information about the execution status of the debugger" ); + python::def( "go", &pykd::changeDebuggerStatus, + "Change debugger status to DEBUG_STATUS_GO" ); python::def( "isDumpAnalyzing", &pykd::isDumpAnalyzing, "Check if it is a dump analyzing ( not living debuggee )" ); python::def( "isKernelDebugging", &pykd::isKernelDebugging, @@ -119,6 +135,14 @@ BOOST_PYTHON_MODULE( pykd ) "Print out string. If dml = True string is printed with dml highlighting ( only for windbg )" ) ); python::def( "dprintln", &pykd::dprintln, dprintln_( boost::python::args( "str", "dml" ), "Print out string and insert end of line symbol. If dml = True string is printed with dml highlighting ( only for windbg )" ) ); + python::def( "setExecutionStatus", &pykd::setExecutionStatus, + "Requests that the debugger engine enter an executable state" ); + python::def( "step", &pykd::changeDebuggerStatus, + "Change debugger status to DEBUG_STATUS_STEP_OVER" ); + python::def( "trace", &pykd::changeDebuggerStatus, + "Change debugger status to DEBUG_STATUS_STEP_INTO" ); + python::def( "waitForEvent", &pykd::waitForEvent, + "Wait for events that breaks into the debugger" ); python::class_("typeInfo", "Class representing typeInfo", python::no_init ) .def( "name", &pykd::TypeInfo::getName ) @@ -400,6 +424,22 @@ BOOST_PYTHON_MODULE( pykd ) DEF_PY_CONST_ULONG( DEBUG_USER_WINDOWS_PROCESS_SERVER ); DEF_PY_CONST_ULONG( DEBUG_USER_WINDOWS_SMALL_DUMP ); DEF_PY_CONST_ULONG( DEBUG_USER_WINDOWS_DUMP ); + + // debug status + DEF_PY_CONST_ULONG(DEBUG_STATUS_NO_CHANGE); + DEF_PY_CONST_ULONG(DEBUG_STATUS_GO); + DEF_PY_CONST_ULONG(DEBUG_STATUS_GO_HANDLED); + DEF_PY_CONST_ULONG(DEBUG_STATUS_GO_NOT_HANDLED); + DEF_PY_CONST_ULONG(DEBUG_STATUS_STEP_OVER); + DEF_PY_CONST_ULONG(DEBUG_STATUS_STEP_INTO); + DEF_PY_CONST_ULONG(DEBUG_STATUS_BREAK); + DEF_PY_CONST_ULONG(DEBUG_STATUS_NO_DEBUGGEE); + DEF_PY_CONST_ULONG(DEBUG_STATUS_STEP_BRANCH); + DEF_PY_CONST_ULONG(DEBUG_STATUS_RESTART_REQUESTED); + DEF_PY_CONST_ULONG(DEBUG_STATUS_REVERSE_GO); + DEF_PY_CONST_ULONG(DEBUG_STATUS_REVERSE_STEP_BRANCH); + DEF_PY_CONST_ULONG(DEBUG_STATUS_REVERSE_STEP_OVER); + DEF_PY_CONST_ULONG(DEBUG_STATUS_REVERSE_STEP_INTO); } #undef DEF_PY_CONST_ULONG @@ -600,7 +640,6 @@ pycmd( PDEBUG_CLIENT4 client, PCSTR args ) DebugClientPtr oldClient = DebugClient::setDbgClientCurrent( dbgClient ); WindbgGlobalSession::RestorePyState(); - ULONG mask = 0; client->GetOutputMask( &mask ); diff --git a/pykd/module.cpp b/pykd/module.cpp index 4345908..8bc9fa4 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -180,371 +180,3 @@ Module::getTypedVarByName( const std::string &symName ) }; // end of namespace pykd - - - - - - - - - - - - - -// // try reload module by entered name, "silent mode" -// OutputReader outputReader( dbgExt->client ); -// hres = dbgExt->symbols->Reload( reloadParam.c_str() ); - - - - - - - - - -//#include -// -//#include "dbgext.h" -//#include "dbgmem.h" -//#include "dbgmodule.h" -//#include "dbgexcept.h" -//#include "dbgsym.h" -//#include "dbgio.h" -//#include "dbgsynsym.h" -// -/////////////////////////////////////////////////////////////////////////////////// -// -//boost::python::object -//loadModule( const std::string &moduleName ) -//{ -// HRESULT hres; -// -// ULONG64 moduleBase; -// hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" ); -// -// DEBUG_MODULE_PARAMETERS moduleParam = { 0 }; -// hres = dbgExt->symbols->GetModuleParameters( 1, &moduleBase, 0, &moduleParam ); -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleParameters failed" ); -// -// -// return boost::python::object( dbgModuleClass( moduleName, moduleBase, moduleParam.Size ) ); -// -//} -// -/////////////////////////////////////////////////////////////////////////////////// -// -//void queryModuleParams( -// __in ULONG64 addr, -// __out std::string &name, -// __out ULONG64 &base, -// __out ULONG &size -//) -//{ -// addr = addr64( addr ); -// -// ULONG moduleIndex; -// HRESULT hres = -// dbgExt->symbols->GetModuleByOffset( addr, 0, &moduleIndex, &base); -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleByOffset failed" ); -// -// DEBUG_MODULE_PARAMETERS moduleParam = { 0 }; -// hres = dbgExt->symbols->GetModuleParameters( 1, &base, 0, &moduleParam ); -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleParameters failed" ); -// size = moduleParam.Size; -// -// ULONG moduleNameChars = 0; -// dbgExt->symbols->GetModuleNames( -// moduleIndex, -// 0, -// NULL, -// 0, -// NULL, -// NULL, -// 0, -// &moduleNameChars, -// NULL, -// 0, -// NULL ); -// name.resize(moduleNameChars + 1); -// hres = dbgExt->symbols->GetModuleNames( -// moduleIndex, -// 0, -// NULL, -// 0, -// NULL, -// &name[0], -// (ULONG)name.size(), -// NULL, -// NULL, -// 0, -// NULL ); -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::GetModuleNames failed" ); -//} -// -/////////////////////////////////////////////////////////////////////////////////// -// -//boost::python::object -//findModule( ULONG64 addr ) -//{ -// ULONG64 moduleBase; -// ULONG moduleSize; -// std::string moduleName; -// -// queryModuleParams(addr, moduleName, moduleBase, moduleSize); -// -// return boost::python::object( dbgModuleClass( moduleName, moduleBase, moduleSize ) ); -//} -// -/////////////////////////////////////////////////////////////////////////////////// -// -//dbgModuleClass::dbgModuleClass( const std::string &name, ULONG64 base, ULONG size ) : -// m_name( name ), -// m_base( addr64(base) ), -// m_end( addr64(base) + size ) -//{ -// reloadSymbols(); -// -// std::string pattern = name + "!*"; -// ULONG64 enumHandle = 0; -// -// HRESULT hres = dbgExt->symbols->StartSymbolMatch( pattern.c_str(), &enumHandle ); -// -// while( SUCCEEDED( hres ) ) -// { -// char nameBuf[0x100]; -// ULONG64 offset = 0; -// -// hres = -// dbgExt->symbols->GetNextSymbolMatch( -// enumHandle, -// nameBuf, -// sizeof( nameBuf ), -// NULL, -// &offset ); -// -// if ( FAILED( hres ) ) -// break; -// -// std::string symbolName( nameBuf ); -// -// symbolName.erase( 0, name.size() + 1 ); -// -// m_offsets.insert( std::make_pair( symbolName, offset ) ); -// } -// -// if ( enumHandle ) -// dbgExt->symbols->EndSymbolMatch( enumHandle ); -// -// memset( &m_debugInfo, 0, sizeof( m_debugInfo ) ); -// -// hres = dbgExt->advanced2->GetSymbolInformation( -// DEBUG_SYMINFO_IMAGEHLP_MODULEW64, -// base, -// 0, -// &m_debugInfo, -// sizeof( m_debugInfo ), -// NULL, -// NULL, -// 0, -// NULL ); -// -// if ( SUCCEEDED( hres ) ) -// getImagePath(); -//} -// -/////////////////////////////////////////////////////////////////////////////////// -// -//void -//dbgModuleClass::reloadSymbols() -//{ -// HRESULT hres; -// -// static const char *szReloadParam = "/f "; //"/f /s "; -// std::string reloadParam = szReloadParam; -// reloadParam += m_name; -// -// { -// // try reload module by entered name, "silent mode" -// OutputReader outputReader( dbgExt->client ); -// hres = dbgExt->symbols->Reload( reloadParam.c_str() ); -// } -// if ( FAILED( hres ) ) -// { -// // failed => try reload symbols by image file name -// char szImageName[MAX_PATH/2]; -// HRESULT hres2 = dbgExt->symbols2->GetModuleNameString( -// DEBUG_MODNAME_IMAGE, -// DEBUG_ANY_ID, -// m_base, -// szImageName, -// _countof(szImageName), -// NULL); -// if (SUCCEEDED(hres2)) -// { -// PCSTR szImageFileName = strrchr(szImageName, '\\'); -// if (!szImageFileName) -// szImageFileName = szImageName; -// else -// ++szImageFileName; -// -// reloadParam = szReloadParam; -// reloadParam += szImageFileName; -// hres = dbgExt->symbols->Reload( reloadParam.c_str() ); -// } -// } -// -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol::Reload failed" ); -//} -// -/////////////////////////////////////////////////////////////////////////////////// -// -//ULONG64 -//dbgModuleClass::getOffset( const std::string &symName ) -//{ -// OffsetMap::iterator offset = m_offsets.find( symName ); -// if ( offset != m_offsets.end() ) -// { -// return offset->second; -// } -// -// ModuleInfo moduleInfo(m_debugInfo); -// ULONG64 syntheticOffset = getSyntheticSymbol(moduleInfo, symName); -// -// if ( syntheticOffset == 0 ) -// throw DbgException( "failed to find offset for symbol" ); -// -// return syntheticOffset; -//} -// -/////////////////////////////////////////////////////////////////////////////////// -// -//bool dbgModuleClass::addSyntheticSymbol( -// ULONG64 offset, -// ULONG size, -// const std::string &symName -//) -//{ -// ModuleInfo moduleInfo(m_debugInfo); -// return ::addSyntheticSymbolForModule(offset, size, symName, moduleInfo); -//} -// -/////////////////////////////////////////////////////////////////////////////////// -// -//void dbgModuleClass::delAllSyntheticSymbols() -//{ -// ModuleInfo moduleInfo(m_debugInfo); -// ::delAllSyntheticSymbolsForModule(moduleInfo); -//} -// -/////////////////////////////////////////////////////////////////////////////////// -// -//ULONG dbgModuleClass::delSyntheticSymbol( -// ULONG64 offset -//) -//{ -// ModuleInfo moduleInfo(m_debugInfo); -// return ::delSyntheticSymbolForModule(offset, moduleInfo); -//} -// -/////////////////////////////////////////////////////////////////////////////////// -// -//ULONG dbgModuleClass::delSyntheticSymbolsMask( const std::string &symName ) -//{ -// return ::delSyntheticSymbolsMask(m_name, symName); -//} -// -/////////////////////////////////////////////////////////////////////////////////// -// -//void -//dbgModuleClass::getImagePath() -//{ -// HRESULT hres; -// -// ULONG pathSize = 0; -// hres = dbgExt->symbols3->GetSymbolPathWide( NULL, 0, &pathSize ); -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol3::GetImagePathWide failed" ); -// -// std::vector pathBuffer(pathSize); -// -// hres = dbgExt->symbols3->GetSymbolPathWide( &pathBuffer[0], pathSize, NULL ); -// if ( FAILED( hres ) ) -// throw DbgException( "IDebugSymbol3::GetImagePathWide failed" ); -// -// std::wstring symPath( &pathBuffer[0], pathSize ); -// -// std::wstring altName = m_debugInfo.CVData; -// altName = altName.substr( 0, altName.find_last_of(L".") ); -// -// std::wstring imageName = m_debugInfo.LoadedImageName; -// altName += imageName.substr( imageName.find_last_of(L".") ); -// -// for ( size_t offset = 0; offset < symPath.length(); ) -// { -// size_t newOffset = symPath.find( L";", offset ); -// std::wstring subPath = symPath.substr( offset, newOffset - offset ); -// -// std::wstringstream sstr; -// -// sstr << subPath << L"\\" << m_debugInfo.LoadedImageName << L"\\" << std::hex << -// m_debugInfo.TimeDateStamp << m_debugInfo.ImageSize << L"\\" << -// m_debugInfo.LoadedImageName; -// -// if( (_waccess( sstr.str().c_str(), 0 )) != -1 ) -// { -// m_imageFullName = sstr.str(); -// break; -// } -// -// -// std::wstringstream altstr; -// -// altstr << subPath << L"\\" << altName << L"\\" << std::hex << -// m_debugInfo.TimeDateStamp << m_debugInfo.ImageSize << L"\\" << -// altName; -// -// if( (_waccess( altstr.str().c_str(), 0 )) != -1 ) -// { -// m_imageFullName = altstr.str(); -// break; -// } -// -// if ( newOffset == std::wstring::npos ) -// break; -// -// offset = newOffset + 1; -// } -//} -// -//std::string -//dbgModuleClass::print() const -//{ -// const char * format_string(dbgExt->control->IsPointer64Bit() == S_OK ? -// "%1$016x %2$016x %3$20s %4$20s" : "%1$08x %2$08x %3$20s %4$20s"); -// boost::format fmt(format_string); -// std::vector v(MAX_PATH); -// ::WideCharToMultiByte( -// CP_ACP, -// 0, -// m_imageFullName.c_str(), -// -1, -// &v[0], -// (ULONG)v.size(), -// 0, -// 0); -// std::string fullname(&v[0]); -// fmt % m_base % (m_end - m_base) % m_name % fullname; -// return fmt.str(); -//} -// -/////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/pyaux.h b/pykd/pyaux.h index 8e85f5c..63a4385 100644 --- a/pykd/pyaux.h +++ b/pykd/pyaux.h @@ -2,6 +2,10 @@ #include +#include "windbg.h" + +namespace pykd { + /////////////////////////////////////////////////////////////////////////////// class PyThreadStateSaver { @@ -17,14 +21,14 @@ public: } void saveState() { - if ( !isWindbgExt() ) + if ( !WindbgGlobalSession::isInit() ) TlsSetValue( m_index, PyEval_SaveThread() ); else WindbgGlobalSession::SavePyState(); } void restoreState() { - if ( !isWindbgExt() ) + if ( !WindbgGlobalSession::isInit() ) { PyThreadState* state = (PyThreadState*)TlsGetValue( m_index ); if ( state ) @@ -41,33 +45,33 @@ private: DWORD m_index; }; -extern PyThreadStateSaver g_pyThreadState; - - -//typedef PyThreadState *PyThreadStatePtr; -//extern __declspec( thread ) PyThreadStatePtr ptrPyThreadState; // --> call back // { PyThread_StateSave state( winext->getThreadState() ); // do_callback(); // } // -// Если колбек был вызван и при этом у текщего потока сохранен контекст ( был вызов setExecutionStatus ) -// то перед выполнением питоновского кода нужно восстановить контекст, а после возврата управления, -// снова сохранить его +// Если был вызван колбек то перед выполнением питоновского кода нужно восстановить контекст, +// а после возврата управления, снова сохранить его class PyThread_StateSave { public: - PyThread_StateSave() + PyThread_StateSave( PyThreadStateSaver &threadState) : + m_threadState( threadState ) { - g_pyThreadState.restoreState(); + m_threadState.restoreState(); } ~PyThread_StateSave() { - g_pyThreadState.saveState(); + m_threadState.saveState(); } + +private: + + PyThreadStateSaver &m_threadState; + }; // { PyThread_StateRestore state; @@ -78,13 +82,20 @@ class PyThread_StateRestore { public: - PyThread_StateRestore() { - g_pyThreadState.saveState(); + PyThread_StateRestore(PyThreadStateSaver &threadState) : + m_threadState( threadState ) + { + m_threadState.saveState(); } ~PyThread_StateRestore() { - g_pyThreadState.restoreState(); + m_threadState.restoreState(); } +private: + + PyThreadStateSaver &m_threadState; }; -/////////////////////////////////////////////////////////////////////////////// \ No newline at end of file +///////////////////////////////////////////////////////////////////////////////// + +}; //end namespace pykd \ No newline at end of file diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index 6012948..8885a94 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -495,6 +495,10 @@ RelativePath=".\module.h" > + + diff --git a/test/scripts/basetest.py b/test/scripts/basetest.py index 7d12959..9e1d1cf 100644 --- a/test/scripts/basetest.py +++ b/test/scripts/basetest.py @@ -112,7 +112,10 @@ class BaseTest( unittest.TestCase ): self.assertTrue( hasattr(pykd, 'createDbgClient') ) self.assertTrue( hasattr(pykd, 'diaLoadPdb') ) self.assertTrue( hasattr(pykd, 'getDebuggeeType' ) ) + self.assertTrue( hasattr(pykd, 'getExecutionStatus' ) ) self.assertTrue( hasattr(pykd, 'loadExt') ) + self.assertTrue( hasattr(pykd, 'setExecutionStatus') ) + self.assertTrue( hasattr(pykd, 'waitForEvent') ) self.assertTrue( hasattr(pykd, 'DiaException') ) self.assertTrue( hasattr(pykd, 'DiaScope') ) diff --git a/test/scripts/clienttest.py b/test/scripts/clienttest.py index c7e656a..50aac4d 100644 --- a/test/scripts/clienttest.py +++ b/test/scripts/clienttest.py @@ -15,4 +15,15 @@ class DbgClientTest( unittest.TestCase ): def testIsDumpAnalyzing( self ): self.assertFalse( pykd.isDumpAnalyzing() ) + + def testExecutionStatus( self ): + self.assertEqual( pykd.DEBUG_STATUS_BREAK, pykd.getExecutionStatus() ) + pykd.setExecutionStatus( pykd.DEBUG_STATUS_GO ) + pykd.waitForEvent() + self.assertEqual( pykd.DEBUG_STATUS_BREAK, pykd.getExecutionStatus() ) + + + + +