+ eventHandler.onLoadModule
 + eventHandler.onUnloadModule
 ~ change eventHandler.onUnloadModule parameter: Module -> base addresss
 + test load/unload modules handling

git-svn-id: https://pykd.svn.codeplex.com/svn@72056 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2011-12-06 09:26:58 +00:00 committed by Mikhail I. Izmestev
parent 8e59db7fcc
commit 7889544689
12 changed files with 128 additions and 45 deletions

View File

@ -295,7 +295,12 @@ void DebugClient::waitForEvent()
} while( false ); } while( false );
if ( FAILED( hres ) ) if ( FAILED( hres ) )
{
if (E_UNEXPECTED == hres)
throw WaitEventException();
throw DbgException( "IDebugControl::WaitForEvent failed" ); throw DbgException( "IDebugControl::WaitForEvent failed" );
}
} }
void waitForEvent() void waitForEvent()
@ -317,6 +322,8 @@ ULONG DebugClient::ptrSize()
return S_OK == hres ? 8 : 4; return S_OK == hres ? 8 : 4;
} }
///////////////////////////////////////////////////////////////////////////////////
ULONG ptrSize() ULONG ptrSize()
{ {
return g_dbgClient->ptrSize(); return g_dbgClient->ptrSize();

View File

@ -222,6 +222,10 @@ public:
return m_symSymbols->removeByMask(moduleName, symName); return m_symSymbols->removeByMask(moduleName, symName);
} }
SynSymbolsPtr getSynSymbols() {
return m_symSymbols;
}
private: private:
template<typename T> template<typename T>

View File

@ -177,25 +177,8 @@ HRESULT EventHandler::LoadModule(
__in ULONG TimeDateStamp __in ULONG TimeDateStamp
) )
{ {
//PyThread_StateSave pyThreadSave( m_parentClient->getThreadState() ); PyThread_StateSave pyThreadSave( m_parentClient->getThreadState() );
return onLoadModule( m_parentClient->loadModuleByOffset(BaseOffset) );
//return onLoadModule( module );
//std::auto_ptr<OutputReader> silentMode( new OutputReader(dbgExt->client) );
//ULONG64 moduleBase;
//ULONG moduleSize;
//std::string moduleName;
//
//queryModuleParams(BaseOffset, moduleName, moduleBase, moduleSize);
//dbgModuleClass module(moduleName, moduleBase, moduleSize);
//silentMode.reset();
//PyThread_StateSave pyThreadSave;
//return onLoadModule( module );
return S_OK;
} }
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -205,19 +188,9 @@ HRESULT EventHandler::UnloadModule(
__in ULONG64 BaseOffset __in ULONG64 BaseOffset
) )
{ {
//std::auto_ptr<OutputReader> silentMode( new OutputReader(dbgExt->client) ); PyThread_StateSave pyThreadSave( m_parentClient->getThreadState() );
BaseOffset = m_parentClient->addr64(BaseOffset);
//ULONG64 moduleBase; return onUnloadModule( BaseOffset );
//ULONG moduleSize;
//std::string moduleName;
//
//queryModuleParams(BaseOffset, moduleName, moduleBase, moduleSize);
//dbgModuleClass module(moduleName, moduleBase, moduleSize);
//silentMode.reset();
//PyThread_StateSave pyThreadSave;
//return onUnloadModule( module );
return S_OK;
} }
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////

View File

@ -75,7 +75,7 @@ protected:
virtual ULONG onLoadModule(const Module &/* module */) = 0; virtual ULONG onLoadModule(const Module &/* module */) = 0;
virtual ULONG onUnloadModule(const Module &/* module */) = 0; virtual ULONG onUnloadModule(ULONG64 /*modBase*/) = 0;
virtual ULONG onChangeSessionStatus( ULONG status ) = 0; virtual ULONG onChangeSessionStatus( ULONG status ) = 0;
@ -113,8 +113,8 @@ public:
return handler<const Module&>("onLoadModule", module ); return handler<const Module&>("onLoadModule", module );
} }
ULONG onUnloadModule(const Module &module) { ULONG onUnloadModule(ULONG64 modBase) {
return handler<const Module&>("onUnloadModule", module ); return handler<ULONG64>("onUnloadModule", modBase );
} }
ULONG onChangeSessionStatus( ULONG status ) { ULONG onChangeSessionStatus( ULONG status ) {

View File

@ -7,6 +7,7 @@ namespace pykd {
PyObject *DbgException::baseExceptTypeObject = NULL; PyObject *DbgException::baseExceptTypeObject = NULL;
PyObject *MemoryException::memoryExceptionTypeObject = NULL; PyObject *MemoryException::memoryExceptionTypeObject = NULL;
PyObject *WaitEventException::waitEventExceptTypeObject = NULL;
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
@ -36,6 +37,16 @@ std::string buildExceptDesc(PCSTR routineName, HRESULT hres)
return sstream.str(); return sstream.str();
} }
/////////////////////////////////////////////////////////////////////////////////
void WaitEventException::exceptionTranslate( const WaitEventException &e )
{
python::object pyExcept(e);
PyErr_SetObject( waitEventExceptTypeObject, pyExcept.ptr() );
}
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
}; // end namespace pykd }; // end namespace pykd

View File

@ -116,6 +116,25 @@ private:
std::string buildExceptDesc(PCSTR routineName, HRESULT hres); std::string buildExceptDesc(PCSTR routineName, HRESULT hres);
///////////////////////////////////////////////////////////////////////////////////
class WaitEventException : public DbgException
{
public:
WaitEventException()
: DbgException( "None of the targets could generate events" )
{
}
static void exceptionTranslate(const WaitEventException &e);
static void setTypeObject(PyObject *p) {
waitEventExceptTypeObject = p;
}
private:
static PyObject *waitEventExceptTypeObject;
};
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
}; // namespace pykd }; // namespace pykd

View File

@ -448,10 +448,10 @@ BOOST_PYTHON_MODULE( pykd )
"Detailed information: http://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx \n" "Detailed information: http://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx \n"
"For ignore event method must return DEBUG_STATUS_NO_CHANGE value" ) "For ignore event method must return DEBUG_STATUS_NO_CHANGE value" )
.def( "onLoadModule", &pykd::EventHandlerWrap::onLoadModule, .def( "onLoadModule", &pykd::EventHandlerWrap::onLoadModule,
"Load module event. Parameter is instance of dbgModuleClass.\n" "Load module event. Parameter is instance of module.\n"
"For ignore event method must return DEBUG_STATUS_NO_CHANGE value" ) "For ignore event method must return DEBUG_STATUS_NO_CHANGE value" )
.def( "onUnloadModule", &pykd::EventHandlerWrap::onUnloadModule, .def( "onUnloadModule", &pykd::EventHandlerWrap::onUnloadModule,
"Unload module event. Parameter is instance of dbgModuleClass.\n" "Unload module event. Parameter is base address of unloaded module.\n"
"For ignore event method must return DEBUG_STATUS_NO_CHANGE value" ); "For ignore event method must return DEBUG_STATUS_NO_CHANGE value" );
python::class_<Disasm>("disasm", "Class disassemble a processor instructions" ) python::class_<Disasm>("disasm", "Class disassemble a processor instructions" )
@ -662,6 +662,15 @@ BOOST_PYTHON_MODULE( pykd )
python::register_exception_translator<pykd::MemoryException>( python::register_exception_translator<pykd::MemoryException>(
&pykd::MemoryException::exceptionTranslate ); &pykd::MemoryException::exceptionTranslate );
// Wait debug event exception
python::class_<WaitEventException, python::bases<DbgException> > waitEventException(
"WaitEventException", "Debug interface access exception", python::no_init);
waitEventException
_DECL_BASE_EXCEPT_STR;
WaitEventException::setTypeObject( waitEventException.ptr() );
python::register_exception_translator<WaitEventException>(
&WaitEventException::exceptionTranslate );
DEF_PY_CONST_ULONG( DEBUG_CLASS_UNINITIALIZED ); DEF_PY_CONST_ULONG( DEBUG_CLASS_UNINITIALIZED );
DEF_PY_CONST_ULONG( DEBUG_CLASS_KERNEL ); DEF_PY_CONST_ULONG( DEBUG_CLASS_KERNEL );
DEF_PY_CONST_ULONG( DEBUG_CLASS_USER_WINDOWS ); DEF_PY_CONST_ULONG( DEBUG_CLASS_USER_WINDOWS );

View File

@ -0,0 +1,51 @@
"""Debug events handler: test [un-]load modules notification"""
import unittest
import target
import pykd
import fnmatch
class ModuleLoadHandler(pykd.eventHandler):
"""Track load/unload module implementation"""
def __init__(self, client, moduleMask):
pykd.eventHandler.__init__(self, client)
self.moduleMask = moduleMask.lower()
self.wasLoad = 0
self.wasUnload = False
def onLoadModule(self, module):
"""Load module handler"""
if ( fnmatch.fnmatch(module.name().lower(), self.moduleMask) ):
self.wasLoad = module.begin()
return pykd.DEBUG_STATUS_NO_CHANGE
def onUnloadModule(self, modBase):
"""Unload module handler"""
if ( self.wasLoad and (self.wasLoad == modBase) ):
self.wasUnload = True
return pykd.DEBUG_STATUS_NO_CHANGE
class EhLoadTest(unittest.TestCase):
"""Unit tests of [un-]load modules notification"""
def testLoadUnload(self):
"""Start new process and track loading and unloading modules"""
testClient = pykd.createDbgClient()
testClient.startProcess( target.appPath + " -testLoadUnload" )
modLoadHandler = ModuleLoadHandler( testClient, "*Iphlpapi*" )
try:
while True:
testClient.go()
except pykd.WaitEventException:
pass
self.assertTrue(modLoadHandler.wasLoad)
self.assertTrue(modLoadHandler.wasUnload)

View File

@ -23,6 +23,7 @@ import typedvar
import memtest import memtest
import intbase import intbase
import synsymtest import synsymtest
import ehloadtest
def getTestSuite( singleName = "" ): def getTestSuite( singleName = "" ):
if singleName == "": if singleName == "":
@ -37,7 +38,8 @@ def getTestSuite( singleName = "" ):
unittest.TestLoader().loadTestsFromTestCase( eventtest.EventTest ), unittest.TestLoader().loadTestsFromTestCase( eventtest.EventTest ),
unittest.TestLoader().loadTestsFromTestCase( memtest.MemoryTest ), unittest.TestLoader().loadTestsFromTestCase( memtest.MemoryTest ),
unittest.TestLoader().loadTestsFromTestCase( intbase.IntBaseTest ), unittest.TestLoader().loadTestsFromTestCase( intbase.IntBaseTest ),
unittest.TestLoader().loadTestsFromTestCase( synsymtest.SynSymTest ) unittest.TestLoader().loadTestsFromTestCase( synsymtest.SynSymTest ),
unittest.TestLoader().loadTestsFromTestCase( ehloadtest.EhLoadTest )
] ) ] )
else: else:
return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) ) return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) )
@ -45,12 +47,12 @@ def getTestSuite( singleName = "" ):
if __name__ == "__main__": if __name__ == "__main__":
targetAppPath = sys.argv[1] target.appPath = sys.argv[1]
target.moduleName = os.path.splitext(os.path.basename(targetAppPath))[0] target.moduleName = os.path.splitext(os.path.basename(target.appPath))[0]
print "\nTest module: %s" % targetAppPath print "\nTest module: %s" % target.appPath
pykd.startProcess( targetAppPath ) pykd.startProcess( target.appPath )
target.module = pykd.loadModule( target.moduleName ) target.module = pykd.loadModule( target.moduleName )
target.module.reload(); target.module.reload();

View File

@ -4,4 +4,5 @@
module = None module = None
moduleName = None moduleName = None
dbgext = None dbgext = None
appPath = None

View File

@ -159,6 +159,7 @@ void FuncWithName1(int a)
int doLoadUnload() int doLoadUnload()
{ {
__debugbreak();
HMODULE hmod = ::LoadLibrary( _T("iphlpapi.dll") ); HMODULE hmod = ::LoadLibrary( _T("iphlpapi.dll") );
if (hmod) if (hmod)
::FreeLibrary(hmod); ::FreeLibrary(hmod);
@ -172,6 +173,9 @@ int _tmain(int argc, _TCHAR* argv[])
{ {
try try
{ {
// Let test scripts to execute
__debugbreak();
if (2 == argc) if (2 == argc)
{ {
// run with parameters // run with parameters
@ -179,8 +183,6 @@ int _tmain(int argc, _TCHAR* argv[])
return doLoadUnload(); return doLoadUnload();
} }
// Let test scripts to execute
__debugbreak();
__debugbreak(); __debugbreak();
__debugbreak(); __debugbreak();
__debugbreak(); __debugbreak();

View File

@ -416,6 +416,10 @@
RelativePath="..\scripts\diatest.py" RelativePath="..\scripts\diatest.py"
> >
</File> </File>
<File
RelativePath="..\scripts\ehloadtest.py"
>
</File>
<File <File
RelativePath="..\scripts\eventtest.py" RelativePath="..\scripts\eventtest.py"
> >