mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-20 03:23:23 +08:00
[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:
parent
60963e6a9f
commit
df0be475c8
@ -109,6 +109,7 @@ struct DEBUG_EVENT_CALLBACK {
|
||||
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 OnException( ExceptionInfoPtr exceptInfo ) = 0;
|
||||
virtual void onExecutionStatusChange( ULONG executionStatus ) = 0;
|
||||
};
|
||||
|
||||
enum EVENT_TYPE {
|
||||
@ -133,6 +134,13 @@ EVENT_TYPE getLastEventType();
|
||||
ExceptionInfoPtr getLastExceptionInfo();
|
||||
|
||||
|
||||
enum EXECUTION_STATUS {
|
||||
DebugStatusNoChange = 0,
|
||||
DebugStatusGo = 1,
|
||||
DebugStatusBreak = 6,
|
||||
DebugStatusNoDebuggee = 7
|
||||
};
|
||||
|
||||
struct BUG_CHECK_DATA
|
||||
{
|
||||
ULONG code;
|
||||
@ -154,7 +162,9 @@ void breakPointRemoveAll();
|
||||
|
||||
// processes end threads
|
||||
ULONG64 getCurrentProcess();
|
||||
ULONG getCurrentProcessId();
|
||||
ULONG64 getImplicitThread();
|
||||
ULONG getCurrentThreadId();
|
||||
void setCurrentProcess( ULONG64 processAddr );
|
||||
void setImplicitThread( ULONG64 threadAddr );
|
||||
void getAllProcessThreads( std::vector<ULONG64> &threadsArray );
|
||||
|
@ -26,6 +26,7 @@ private:
|
||||
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 OnException( ExceptionInfoPtr exceptInfo ) = 0;
|
||||
virtual void onExecutionStatusChange( ULONG executionStatus ) = 0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
@ -52,15 +53,35 @@ public:
|
||||
return handler("onException", exceptInfo );
|
||||
}
|
||||
|
||||
virtual void onExecutionStatusChange( ULONG executionStatus ) {
|
||||
void_handler("onExecutionStatusChange", executionStatus );
|
||||
}
|
||||
|
||||
|
||||
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>
|
||||
DEBUG_CALLBACK_RESULT handler( const char* handlerName, Arg1Type arg1 )
|
||||
{
|
||||
if (python::override pythonHandler = get_override( handlerName ))
|
||||
{
|
||||
try {
|
||||
return pythonHandler(arg1);
|
||||
pythonHandler(arg1);
|
||||
}
|
||||
catch (const python::error_already_set &) {
|
||||
printException();
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define PYKD_VERSION_MAJOR 0
|
||||
#define PYKD_VERSION_MINOR 2
|
||||
#define PYKD_VERSION_SUBVERSION 0
|
||||
#define PYKD_VERSION_BUILDNO 17
|
||||
#define PYKD_VERSION_BUILDNO 18
|
||||
|
||||
|
||||
#define __VER_STR2__(x) #x
|
||||
|
@ -299,6 +299,12 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
"Set implicit thread for current process" );
|
||||
python::def( "getProcessThreads", &pysupport::getProcessThreads,
|
||||
"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
|
||||
python::def( "getSymbolPath", &getSymbolPath, "Returns current symbol path");
|
||||
@ -582,6 +588,13 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
.value("Break", DebugCallbackBreak)
|
||||
.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>(
|
||||
"eventHandler", "Base class for overriding and handling debug notifications" )
|
||||
.def( "onBreakpoint", &EventHandlerWrap::OnBreakpoint,
|
||||
@ -595,7 +608,10 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
"For ignore event method must return eventResult.noChange" )
|
||||
.def( "onException", &EventHandlerWrap::OnException,
|
||||
"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
|
||||
python::register_exception_translator<PyException>( &PyException::exceptionTranslate );
|
||||
|
@ -1235,14 +1235,6 @@ ULONG breakPointSet( ULONG64 offset, bool hardware, ULONG size, ULONG accessType
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
hres = bp->GetId(&breakId);
|
||||
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
|
||||
getCurrentProcess()
|
||||
{
|
||||
@ -1528,6 +1552,24 @@ getCurrentProcess()
|
||||
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
|
||||
@ -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 )
|
||||
{
|
||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||
@ -1673,8 +1731,6 @@ std::string callExtension( ULONG64 extHandle, const std::wstring command, const
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
} // end pykd namespace
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ public:
|
||||
*Mask |= DEBUG_EVENT_LOAD_MODULE;
|
||||
*Mask |= DEBUG_EVENT_UNLOAD_MODULE;
|
||||
*Mask |= DEBUG_EVENT_EXCEPTION;
|
||||
*Mask |= DEBUG_EVENT_CHANGE_ENGINE_STATE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -79,6 +80,10 @@ public:
|
||||
__in PEXCEPTION_RECORD64 Exception,
|
||||
__in ULONG FirstChance );
|
||||
|
||||
STDMETHOD(ChangeEngineState)(
|
||||
__in ULONG Flags,
|
||||
__in ULONG64 Argument );
|
||||
|
||||
DbgEngBind*
|
||||
operator->()
|
||||
{
|
||||
|
@ -6,15 +6,17 @@ import pykd
|
||||
import testutils
|
||||
|
||||
class ExceptionHandler(pykd.eventHandler):
|
||||
"""Track load/unload module implementation"""
|
||||
def __init__(self):
|
||||
pykd.eventHandler.__init__(self)
|
||||
self.accessViolationOccured = False
|
||||
|
||||
def onException(self, exceptInfo):
|
||||
"""Exception handler"""
|
||||
|
||||
self.accessViolationOccured = exceptInfo.ExceptionCode == 0xC0000005
|
||||
|
||||
print exceptInfo
|
||||
|
||||
if self.accessViolationOccured:
|
||||
self.param0 = exceptInfo.Parameters[0]
|
||||
self.param1 = exceptInfo.Parameters[1]
|
||||
@ -27,7 +29,7 @@ class EhExceptionTest(unittest.TestCase):
|
||||
|
||||
def testException(self):
|
||||
"""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 :
|
||||
exceptionHandler = ExceptionHandler()
|
||||
|
||||
@ -38,7 +40,7 @@ class EhExceptionTest(unittest.TestCase):
|
||||
|
||||
self.assertTrue( exceptionHandler.accessViolationOccured )
|
||||
self.assertEqual( exceptionHandler.param0, 1 ) # write
|
||||
self.assertEqual( exceptionHandler.param1, 6 ) # addr
|
||||
self.assertEqual( exceptionHandler.param1, 2 ) # addr
|
||||
|
||||
exceptInfo = pykd.lastException()
|
||||
self.assertEqual( exceptInfo.ExceptionCode, 0xC0000005 )
|
||||
|
36
test/scripts/ehstatustest.py
Normal file
36
test/scripts/ehstatustest.py
Normal 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 )
|
||||
|
@ -13,6 +13,9 @@ class handler( pykd.eventHandler ):
|
||||
self.counter += 1
|
||||
return pykd.DEBUG_STATUS_NO_CHANGE
|
||||
|
||||
def onExecutionStatusChange(self,status):
|
||||
print status
|
||||
|
||||
class EventTest( unittest.TestCase ):
|
||||
|
||||
def testDebugBreak( self ):
|
||||
|
@ -73,7 +73,7 @@ class ModuleTest( unittest.TestCase ):
|
||||
self.assertTrue( re.search('targetapp\\.cpp', fileName ) )
|
||||
self.assertEqual( 2, displacement )
|
||||
fileName, lineNo, displacement = pykd.getSourceLine()
|
||||
self.assertEqual( 663, lineNo )
|
||||
self.assertEqual( 673, lineNo )
|
||||
|
||||
def testEnumSymbols( self ):
|
||||
lst = target.module.enumSymbols()
|
||||
|
@ -22,6 +22,7 @@ import regtest
|
||||
import localstest
|
||||
import customtypestest
|
||||
import ehexcepttest
|
||||
import ehstatustest
|
||||
|
||||
class StartProcessWithoutParamsTest(unittest.TestCase):
|
||||
def testStart(self):
|
||||
@ -53,6 +54,7 @@ def getTestSuite( singleName = "" ):
|
||||
|
||||
unittest.TestLoader().loadTestsFromTestCase( localstest.LocalVarsTest ),
|
||||
unittest.TestLoader().loadTestsFromTestCase( ehexcepttest.EhExceptionTest ),
|
||||
unittest.TestLoader().loadTestsFromTestCase( ehstatustest.EhStatusTest ),
|
||||
] )
|
||||
else:
|
||||
return unittest.TestSuite(
|
||||
|
@ -602,6 +602,16 @@ int doExeptions()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int doChangeStatus()
|
||||
{
|
||||
__debugbreak();
|
||||
__debugbreak();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <map>
|
||||
|
||||
std::map<int, bool> g_map;
|
||||
@ -680,6 +690,9 @@ int _tmain(int argc, _TCHAR* argv[])
|
||||
|
||||
if ( !_tcsicmp(argv[1], _T("-testExceptions")) )
|
||||
return doExeptions();
|
||||
|
||||
if ( !_tcsicmp(argv[1], _T("-testChangeStatus")) )
|
||||
return doChangeStatus();
|
||||
}
|
||||
|
||||
__debugbreak();
|
||||
|
@ -550,12 +550,6 @@
|
||||
>
|
||||
</File>
|
||||
</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
|
||||
Name="scripts"
|
||||
>
|
||||
@ -587,6 +581,10 @@
|
||||
RelativePath="..\scripts\ehloadtest.py"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\scripts\ehstatustest.py"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\scripts\eventtest.py"
|
||||
>
|
||||
@ -640,6 +638,12 @@
|
||||
>
|
||||
</File>
|
||||
</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>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
Loading…
Reference in New Issue
Block a user