[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 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 );

View File

@ -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();

View File

@ -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

View File

@ -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 );

View File

@ -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

View File

@ -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->()
{

View File

@ -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
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 )

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

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

View File

@ -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()

View File

@ -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(
@ -68,5 +70,5 @@ if __name__ == "__main__":
target.appPath = sys.argv[1]
target.moduleName = os.path.splitext(os.path.basename(target.appPath))[0]
unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( getTestSuite() )

View File

@ -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();

View File

@ -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>