[0.2.x] added : getCurrentProcessId routine ( Return PID of the current process ( user mode only ) )

[0.2.x] added : getCurrentThreadId routine ( Return TID of the current thread ( user mode only ) )
[0.2.x] added : eventHandler.onExecutionStatusChange method ( Triggered execution status changed )

git-svn-id: https://pykd.svn.codeplex.com/svn@82898 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\kernelnet_cp 2013-03-12 07:08:01 +00:00 committed by Mikhail I. Izmestev
parent 60963e6a9f
commit df0be475c8
13 changed files with 193 additions and 25 deletions

View File

@ -109,6 +109,7 @@ struct DEBUG_EVENT_CALLBACK {
virtual DEBUG_CALLBACK_RESULT OnModuleLoad( ULONG64 offset, const std::string &name ) = 0; virtual DEBUG_CALLBACK_RESULT OnModuleLoad( ULONG64 offset, const std::string &name ) = 0;
virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64 offset, const std::string &name ) = 0; virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64 offset, const std::string &name ) = 0;
virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) = 0; virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) = 0;
virtual void onExecutionStatusChange( ULONG executionStatus ) = 0;
}; };
enum EVENT_TYPE { enum EVENT_TYPE {
@ -133,6 +134,13 @@ EVENT_TYPE getLastEventType();
ExceptionInfoPtr getLastExceptionInfo(); ExceptionInfoPtr getLastExceptionInfo();
enum EXECUTION_STATUS {
DebugStatusNoChange = 0,
DebugStatusGo = 1,
DebugStatusBreak = 6,
DebugStatusNoDebuggee = 7
};
struct BUG_CHECK_DATA struct BUG_CHECK_DATA
{ {
ULONG code; ULONG code;
@ -154,7 +162,9 @@ void breakPointRemoveAll();
// processes end threads // processes end threads
ULONG64 getCurrentProcess(); ULONG64 getCurrentProcess();
ULONG getCurrentProcessId();
ULONG64 getImplicitThread(); ULONG64 getImplicitThread();
ULONG getCurrentThreadId();
void setCurrentProcess( ULONG64 processAddr ); void setCurrentProcess( ULONG64 processAddr );
void setImplicitThread( ULONG64 threadAddr ); void setImplicitThread( ULONG64 threadAddr );
void getAllProcessThreads( std::vector<ULONG64> &threadsArray ); void getAllProcessThreads( std::vector<ULONG64> &threadsArray );

View File

@ -26,6 +26,7 @@ private:
virtual DEBUG_CALLBACK_RESULT OnModuleLoad( ULONG64 offset, const std::string &name ) = 0; virtual DEBUG_CALLBACK_RESULT OnModuleLoad( ULONG64 offset, const std::string &name ) = 0;
virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64 offset, const std::string &name ) = 0; virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64 offset, const std::string &name ) = 0;
virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) = 0; virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) = 0;
virtual void onExecutionStatusChange( ULONG executionStatus ) = 0;
}; };
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
@ -52,15 +53,35 @@ public:
return handler("onException", exceptInfo ); return handler("onException", exceptInfo );
} }
virtual void onExecutionStatusChange( ULONG executionStatus ) {
void_handler("onExecutionStatusChange", executionStatus );
}
private: private:
template<typename Arg1Type>
void void_handler( const char* handlerName, Arg1Type arg1 )
{
if (python::override pythonHandler = get_override( handlerName ))
{
try {
pythonHandler(arg1);
}
catch (const python::error_already_set &) {
printException();
}
}
}
template<typename Arg1Type> template<typename Arg1Type>
DEBUG_CALLBACK_RESULT handler( const char* handlerName, Arg1Type arg1 ) DEBUG_CALLBACK_RESULT handler( const char* handlerName, Arg1Type arg1 )
{ {
if (python::override pythonHandler = get_override( handlerName )) if (python::override pythonHandler = get_override( handlerName ))
{ {
try { try {
return pythonHandler(arg1); pythonHandler(arg1);
} }
catch (const python::error_already_set &) { catch (const python::error_already_set &) {
printException(); printException();

View File

@ -2,7 +2,7 @@
#define PYKD_VERSION_MAJOR 0 #define PYKD_VERSION_MAJOR 0
#define PYKD_VERSION_MINOR 2 #define PYKD_VERSION_MINOR 2
#define PYKD_VERSION_SUBVERSION 0 #define PYKD_VERSION_SUBVERSION 0
#define PYKD_VERSION_BUILDNO 17 #define PYKD_VERSION_BUILDNO 18
#define __VER_STR2__(x) #x #define __VER_STR2__(x) #x

View File

@ -299,6 +299,12 @@ BOOST_PYTHON_MODULE( pykd )
"Set implicit thread for current process" ); "Set implicit thread for current process" );
python::def( "getProcessThreads", &pysupport::getProcessThreads, python::def( "getProcessThreads", &pysupport::getProcessThreads,
"Get all process's threads ( user mode only )" ); "Get all process's threads ( user mode only )" );
python::def( "getCurrentProcessId", &getCurrentProcessId,
"Return PID of the current process ( user mode only )" );
python::def( "getCurrentThreadId", &getCurrentThreadId,
"Return TID of the current thread ( user mode only )" );
// symbol path // symbol path
python::def( "getSymbolPath", &getSymbolPath, "Returns current symbol path"); python::def( "getSymbolPath", &getSymbolPath, "Returns current symbol path");
@ -582,6 +588,13 @@ BOOST_PYTHON_MODULE( pykd )
.value("Break", DebugCallbackBreak) .value("Break", DebugCallbackBreak)
.export_values(); .export_values();
python::enum_<EXECUTION_STATUS>("executionStatus", "Execution Status")
.value("NoChange", DebugStatusNoChange )
.value("Go", DebugStatusGo )
.value("Break", DebugStatusBreak )
.value("NoDebuggee", DebugStatusNoDebuggee )
.export_values();
python::class_<EventHandlerWrap, EventHandlerPtr, boost::noncopyable>( python::class_<EventHandlerWrap, EventHandlerPtr, boost::noncopyable>(
"eventHandler", "Base class for overriding and handling debug notifications" ) "eventHandler", "Base class for overriding and handling debug notifications" )
.def( "onBreakpoint", &EventHandlerWrap::OnBreakpoint, .def( "onBreakpoint", &EventHandlerWrap::OnBreakpoint,
@ -595,7 +608,10 @@ BOOST_PYTHON_MODULE( pykd )
"For ignore event method must return eventResult.noChange" ) "For ignore event method must return eventResult.noChange" )
.def( "onException", &EventHandlerWrap::OnException, .def( "onException", &EventHandlerWrap::OnException,
"Triggered exception event. Parameter - exceptionInfo\n" "Triggered exception event. Parameter - exceptionInfo\n"
"For ignore event method must return eventResult.noChange" ); "For ignore event method must return eventResult.noChange" )
.def( "onExecutionStatusChange", &EventHandlerWrap::onExecutionStatusChange,
"Triggered execution status changed. Parameter - execution status.\n"
"There is no return value" );
// wrapper for standart python exceptions // wrapper for standart python exceptions
python::register_exception_translator<PyException>( &PyException::exceptionTranslate ); python::register_exception_translator<PyException>( &PyException::exceptionTranslate );

View File

@ -1235,14 +1235,6 @@ ULONG breakPointSet( ULONG64 offset, bool hardware, ULONG size, ULONG accessType
throw DbgException("IDebugBreakpoint::GetFlags", hres); throw DbgException("IDebugBreakpoint::GetFlags", hres);
} }
bpFlags |= DEBUG_BREAKPOINT_ENABLED;
hres = bp->SetFlags(bpFlags);
if (S_OK != hres)
{
g_dbgEng->control->RemoveBreakpoint(bp);
throw DbgException("IDebugBreakpoint::SetFlags", hres);
}
if ( hardware ) if ( hardware )
{ {
HRESULT hres = bp->SetDataParameters(size, accessType); HRESULT hres = bp->SetDataParameters(size, accessType);
@ -1253,6 +1245,14 @@ ULONG breakPointSet( ULONG64 offset, bool hardware, ULONG size, ULONG accessType
} }
} }
bpFlags |= DEBUG_BREAKPOINT_ENABLED | DEBUG_BREAKPOINT_GO_ONLY;
hres = bp->SetFlags(bpFlags);
if (S_OK != hres)
{
g_dbgEng->control->RemoveBreakpoint(bp);
throw DbgException("IDebugBreakpoint::SetFlags", hres);
}
ULONG breakId; ULONG breakId;
hres = bp->GetId(&breakId); hres = bp->GetId(&breakId);
if (S_OK != hres) if (S_OK != hres)
@ -1513,6 +1513,30 @@ HRESULT STDMETHODCALLTYPE DebugEngine::Exception(
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE DebugEngine::ChangeEngineState(
__in ULONG Flags,
__in ULONG64 Argument )
{
boost::recursive_mutex::scoped_lock l(m_handlerLock);
HandlerList::iterator it = m_handlers.begin();
for ( ; it != m_handlers.end(); ++it )
{
if ( ( Flags & DEBUG_CES_EXECUTION_STATUS ) != 0 &&
( Argument & DEBUG_STATUS_INSIDE_WAIT ) == 0 )
{
PyThread_StateSave pyThreadSave( it->pystate );
it->callback->onExecutionStatusChange( (ULONG)Argument );
}
}
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
ULONG64 ULONG64
getCurrentProcess() getCurrentProcess()
{ {
@ -1528,6 +1552,24 @@ getCurrentProcess()
return processAddr; return processAddr;
} }
///////////////////////////////////////////////////////////////////////////////
ULONG getCurrentProcessId()
{
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
HRESULT hres;
ULONG pid;
hres = g_dbgEng->system->GetCurrentProcessSystemId( &pid );
if ( FAILED( hres ) )
throw DbgException( "IDebugSystemObjects2::GetCurrentProcessSystemId failed" );
return pid;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
ULONG64 ULONG64
@ -1547,6 +1589,22 @@ getImplicitThread()
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
ULONG getCurrentThreadId()
{
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
HRESULT hres;
ULONG tid;
hres = g_dbgEng->system->GetCurrentThreadSystemId( &tid );
if ( FAILED( hres ) )
throw DbgException( "IDebugSystemObjects2::GetCurrentThreadSystemId failed" );
return tid;
}
///////////////////////////////////////////////////////////////////////////////
void setCurrentProcess( ULONG64 processAddr ) void setCurrentProcess( ULONG64 processAddr )
{ {
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
@ -1673,8 +1731,6 @@ std::string callExtension( ULONG64 extHandle, const std::wstring command, const
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
} // end pykd namespace } // end pykd namespace

View File

@ -55,6 +55,7 @@ public:
*Mask |= DEBUG_EVENT_LOAD_MODULE; *Mask |= DEBUG_EVENT_LOAD_MODULE;
*Mask |= DEBUG_EVENT_UNLOAD_MODULE; *Mask |= DEBUG_EVENT_UNLOAD_MODULE;
*Mask |= DEBUG_EVENT_EXCEPTION; *Mask |= DEBUG_EVENT_EXCEPTION;
*Mask |= DEBUG_EVENT_CHANGE_ENGINE_STATE;
return S_OK; return S_OK;
} }
@ -79,6 +80,10 @@ public:
__in PEXCEPTION_RECORD64 Exception, __in PEXCEPTION_RECORD64 Exception,
__in ULONG FirstChance ); __in ULONG FirstChance );
STDMETHOD(ChangeEngineState)(
__in ULONG Flags,
__in ULONG64 Argument );
DbgEngBind* DbgEngBind*
operator->() operator->()
{ {

View File

@ -6,15 +6,17 @@ import pykd
import testutils import testutils
class ExceptionHandler(pykd.eventHandler): class ExceptionHandler(pykd.eventHandler):
"""Track load/unload module implementation"""
def __init__(self): def __init__(self):
pykd.eventHandler.__init__(self) pykd.eventHandler.__init__(self)
self.accessViolationOccured = False self.accessViolationOccured = False
def onException(self, exceptInfo): def onException(self, exceptInfo):
"""Exception handler""" """Exception handler"""
self.accessViolationOccured = exceptInfo.ExceptionCode == 0xC0000005 self.accessViolationOccured = exceptInfo.ExceptionCode == 0xC0000005
print exceptInfo
if self.accessViolationOccured: if self.accessViolationOccured:
self.param0 = exceptInfo.Parameters[0] self.param0 = exceptInfo.Parameters[0]
self.param1 = exceptInfo.Parameters[1] self.param1 = exceptInfo.Parameters[1]
@ -27,7 +29,7 @@ class EhExceptionTest(unittest.TestCase):
def testException(self): def testException(self):
"""Start new process and track exceptions""" """Start new process and track exceptions"""
_locProcessId = pykd.startProcess( target.appPath + " -testAccessViolation" ) _locProcessId = pykd.startProcess( target.appPath + " -testExceptions" )
with testutils.ContextCallIt( testutils.KillProcess(_locProcessId) ) as killStartedProcess : with testutils.ContextCallIt( testutils.KillProcess(_locProcessId) ) as killStartedProcess :
exceptionHandler = ExceptionHandler() exceptionHandler = ExceptionHandler()
@ -38,7 +40,7 @@ class EhExceptionTest(unittest.TestCase):
self.assertTrue( exceptionHandler.accessViolationOccured ) self.assertTrue( exceptionHandler.accessViolationOccured )
self.assertEqual( exceptionHandler.param0, 1 ) # write self.assertEqual( exceptionHandler.param0, 1 ) # write
self.assertEqual( exceptionHandler.param1, 6 ) # addr self.assertEqual( exceptionHandler.param1, 2 ) # addr
exceptInfo = pykd.lastException() exceptInfo = pykd.lastException()
self.assertEqual( exceptInfo.ExceptionCode, 0xC0000005 ) self.assertEqual( exceptInfo.ExceptionCode, 0xC0000005 )

View File

@ -0,0 +1,36 @@
"""Execution status event test"""
import unittest
import target
import pykd
import testutils
class StatusChangeHandler(pykd.eventHandler):
def __init__(self):
pykd.eventHandler.__init__(self)
self.breakCount = 0
def onExecutionStatusChange(self, executionStatus):
if executionStatus == pykd.executionStatus.Break:
self.breakCount = self.breakCount + 1
class EhStatusTest(unittest.TestCase):
"""Execution status event test"""
def testException(self):
"""Start new process and track exceptions"""
_locProcessId = pykd.startProcess( target.appPath + " -testChangeStatus" )
with testutils.ContextCallIt( testutils.KillProcess(_locProcessId) ) as killStartedProcess :
pykd.go() #skip initial break
statusChangeHandler = StatusChangeHandler()
pykd.go()
pykd.go()
self.assertEqual( 2, statusChangeHandler.breakCount )

View File

@ -13,6 +13,9 @@ class handler( pykd.eventHandler ):
self.counter += 1 self.counter += 1
return pykd.DEBUG_STATUS_NO_CHANGE return pykd.DEBUG_STATUS_NO_CHANGE
def onExecutionStatusChange(self,status):
print status
class EventTest( unittest.TestCase ): class EventTest( unittest.TestCase ):
def testDebugBreak( self ): def testDebugBreak( self ):

View File

@ -73,7 +73,7 @@ class ModuleTest( unittest.TestCase ):
self.assertTrue( re.search('targetapp\\.cpp', fileName ) ) self.assertTrue( re.search('targetapp\\.cpp', fileName ) )
self.assertEqual( 2, displacement ) self.assertEqual( 2, displacement )
fileName, lineNo, displacement = pykd.getSourceLine() fileName, lineNo, displacement = pykd.getSourceLine()
self.assertEqual( 663, lineNo ) self.assertEqual( 673, lineNo )
def testEnumSymbols( self ): def testEnumSymbols( self ):
lst = target.module.enumSymbols() lst = target.module.enumSymbols()

View File

@ -22,6 +22,7 @@ import regtest
import localstest import localstest
import customtypestest import customtypestest
import ehexcepttest import ehexcepttest
import ehstatustest
class StartProcessWithoutParamsTest(unittest.TestCase): class StartProcessWithoutParamsTest(unittest.TestCase):
def testStart(self): def testStart(self):
@ -53,6 +54,7 @@ def getTestSuite( singleName = "" ):
unittest.TestLoader().loadTestsFromTestCase( localstest.LocalVarsTest ), unittest.TestLoader().loadTestsFromTestCase( localstest.LocalVarsTest ),
unittest.TestLoader().loadTestsFromTestCase( ehexcepttest.EhExceptionTest ), unittest.TestLoader().loadTestsFromTestCase( ehexcepttest.EhExceptionTest ),
unittest.TestLoader().loadTestsFromTestCase( ehstatustest.EhStatusTest ),
] ) ] )
else: else:
return unittest.TestSuite( return unittest.TestSuite(

View File

@ -602,6 +602,16 @@ int doExeptions()
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int doChangeStatus()
{
__debugbreak();
__debugbreak();
return 0;
}
////////////////////////////////////////////////////////////////////////////////
#include <map> #include <map>
std::map<int, bool> g_map; std::map<int, bool> g_map;
@ -680,6 +690,9 @@ int _tmain(int argc, _TCHAR* argv[])
if ( !_tcsicmp(argv[1], _T("-testExceptions")) ) if ( !_tcsicmp(argv[1], _T("-testExceptions")) )
return doExeptions(); return doExeptions();
if ( !_tcsicmp(argv[1], _T("-testChangeStatus")) )
return doChangeStatus();
} }
__debugbreak(); __debugbreak();

View File

@ -550,12 +550,6 @@
> >
</File> </File>
</Filter> </Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<Filter <Filter
Name="scripts" Name="scripts"
> >
@ -587,6 +581,10 @@
RelativePath="..\scripts\ehloadtest.py" RelativePath="..\scripts\ehloadtest.py"
> >
</File> </File>
<File
RelativePath="..\scripts\ehstatustest.py"
>
</File>
<File <File
RelativePath="..\scripts\eventtest.py" RelativePath="..\scripts\eventtest.py"
> >
@ -640,6 +638,12 @@
> >
</File> </File>
</Filter> </Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>