[+] add callback for load/unload modules

git-svn-id: https://pykd.svn.codeplex.com/svn@65709 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2011-05-22 23:55:20 +00:00
parent 77300508e7
commit 6e2d161966
10 changed files with 364 additions and 69 deletions

View File

@ -7,6 +7,7 @@
#include "dbgmodule.h"
#include "dbgsynsym.h"
#include "dbgcmd.h"
#include "dbgmodevent.h"
///////////////////////////////////////////////////////////////////////////////////
@ -51,7 +52,11 @@ HRESULT DbgEventCallbacksManager::GetInterestMask(
__out PULONG Mask
)
{
*Mask = DEBUG_EVENT_CHANGE_SYMBOL_STATE | DEBUG_EVENT_BREAKPOINT;
*Mask =
DEBUG_EVENT_CHANGE_SYMBOL_STATE |
DEBUG_EVENT_BREAKPOINT |
DEBUG_EVENT_LOAD_MODULE |
DEBUG_EVENT_UNLOAD_MODULE;
return S_OK;
}
@ -66,8 +71,7 @@ HRESULT DbgEventCallbacksManager::ChangeSymbolState(
{
if (Argument)
{
DEBUG_MODULE_PARAMETERS dbgModuleParameters={};
DEBUG_MODULE_PARAMETERS dbgModuleParameters;
HRESULT hres = dbgExt->symbols3->GetModuleParameters(
1,
&Argument,
@ -77,7 +81,6 @@ HRESULT DbgEventCallbacksManager::ChangeSymbolState(
if (SUCCEEDED(hres))
{
ModuleInfo moduleInfo(dbgModuleParameters);
restoreSyntheticSymbolForModule(moduleInfo);
}
@ -104,3 +107,41 @@ HRESULT DbgEventCallbacksManager::Breakpoint(
///////////////////////////////////////////////////////////////////////////////////
HRESULT DbgEventCallbacksManager::LoadModule(
__in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in PCSTR ModuleName,
__in PCSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp
)
{
try
{
return moduleEvents::onLoadModule(BaseOffset);
}
catch (std::exception &)
{
}
return DEBUG_STATUS_NO_CHANGE;
}
///////////////////////////////////////////////////////////////////////////////////
HRESULT DbgEventCallbacksManager::UnloadModule(
__in PCSTR ImageBaseName,
__in ULONG64 BaseOffset
)
{
try
{
return moduleEvents::onUnloadModule(BaseOffset);
}
catch (std::exception &)
{
}
return DEBUG_STATUS_NO_CHANGE;
}
///////////////////////////////////////////////////////////////////////////////////

View File

@ -36,8 +36,22 @@ private:
__in PDEBUG_BREAKPOINT Bp
);
private:
STDMETHOD(LoadModule)(
__in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in PCSTR ModuleName,
__in PCSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp
);
STDMETHOD(UnloadModule)(
__in PCSTR ImageBaseName,
__in ULONG64 BaseOffset
);
private:
IDebugClient *m_debugClient;
};

View File

@ -28,6 +28,7 @@
#include "dbgprocess.h"
#include "dbgsynsym.h"
#include "dbgclient.h"
#include "dbgmodevent.h"
//////////////////////////////////////////////////////////////////////////////
@ -287,6 +288,15 @@ BOOST_PYTHON_MODULE( pykd )
.def( "__str__", &dbgBreakpointClass::print,
"Return a nice string represention of the breakpoint class" );
boost::python::class_<moduleEventsWrap, boost::noncopyable>( "modEvents",
"Class for processing of events: loading and unloading modules" )
.def( "onLoad", &moduleEvents::onLoad, &moduleEventsWrap::onLoadDef,
"Load module event. Parameter is instance of dbgModuleClass. "
"For ignore event method must return DEBUG_STATUS_NO_CHANGE value" )
.def( "onUnload", &moduleEvents::onUnload, &moduleEventsWrap::onUnloadDef,
"Unload module event. Parameter is instance of dbgModuleClass. "
"For ignore event method must return DEBUG_STATUS_NO_CHANGE value" );
// debug status
_DEF_PY_CONST(DEBUG_STATUS_NO_CHANGE);
_DEF_PY_CONST(DEBUG_STATUS_GO);

108
pykd/dbgmodevent.cpp Normal file
View File

@ -0,0 +1,108 @@
/////////////////////////////////////////////////////////////////////////////////
// Load/Unload module events
/////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "dbgeng.h"
#include "dbgmodule.h"
#include "dbgmodevent.h"
/////////////////////////////////////////////////////////////////////////////////
moduleEvents::modCallbacksColl moduleEvents::modCallbacks;
moduleEvents::modCallbacksLock moduleEvents::modCallbacksMtx;
/////////////////////////////////////////////////////////////////////////////////
moduleEvents::moduleEvents()
{
modCallbacksScopedLock lock(modCallbacksMtx);
modCallbacks.insert(this);
}
/////////////////////////////////////////////////////////////////////////////////
moduleEvents::~moduleEvents()
{
modCallbacksScopedLock lock(modCallbacksMtx);
modCallbacks.erase(this);
}
/////////////////////////////////////////////////////////////////////////////////
ULONG moduleEvents::onLoadModule(__in ULONG64 addr)
{
modCallbacksScopedLock lock(modCallbacksMtx);
if (modCallbacks.empty())
return DEBUG_STATUS_NO_CHANGE;
ULONG64 moduleBase;
ULONG moduleSize;
std::string moduleName;
queryModuleParams(addr, moduleName, moduleBase, moduleSize);
dbgModuleClass module(moduleName, moduleBase, moduleSize);
modCallbacksColl::iterator itCallback = modCallbacks.begin();
while (itCallback != modCallbacks.end())
{
const ULONG retValue = (*itCallback)->onLoad(module);
if (DEBUG_STATUS_NO_CHANGE != retValue)
return retValue;
++itCallback;
}
return DEBUG_STATUS_NO_CHANGE;
}
/////////////////////////////////////////////////////////////////////////////////
ULONG moduleEvents::onUnloadModule(__in ULONG64 addr)
{
modCallbacksScopedLock lock(modCallbacksMtx);
if (modCallbacks.empty())
return DEBUG_STATUS_NO_CHANGE;
ULONG64 moduleBase;
ULONG moduleSize;
std::string moduleName;
queryModuleParams(addr, moduleName, moduleBase, moduleSize);
dbgModuleClass module(moduleName, moduleBase, moduleSize);
modCallbacksColl::iterator itCallback = modCallbacks.begin();
while (itCallback != modCallbacks.end())
{
const ULONG retValue = (*itCallback)->onUnload(module);
if (DEBUG_STATUS_NO_CHANGE != retValue)
return retValue;
++itCallback;
}
return DEBUG_STATUS_NO_CHANGE;
}
/////////////////////////////////////////////////////////////////////////////////
ULONG moduleEventsWrap::onLoad(
const dbgModuleClass &module
)
{
if (boost::python::override override = get_override("onLoad"))
return override(module);
return moduleEvents::onLoad(module);
}
/////////////////////////////////////////////////////////////////////////////////
ULONG moduleEventsWrap::onUnload(
const dbgModuleClass &module
)
{
if (boost::python::override override = get_override("onUnload"))
return override(module);
return moduleEvents::onUnload(module);
}
/////////////////////////////////////////////////////////////////////////////////

53
pykd/dbgmodevent.h Normal file
View File

@ -0,0 +1,53 @@
/////////////////////////////////////////////////////////////////////////////////
// Load/Unload module events
/////////////////////////////////////////////////////////////////////////////////
#include <set>
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
interface moduleEvents
{
moduleEvents();
virtual ~moduleEvents();
virtual ULONG onLoad(const dbgModuleClass &/* module */)
{
return DEBUG_STATUS_NO_CHANGE;
}
virtual ULONG onUnload(const dbgModuleClass &/* module */)
{
return DEBUG_STATUS_NO_CHANGE;
}
static ULONG onLoadModule(__in ULONG64 addr);
static ULONG onUnloadModule(__in ULONG64 addr);
private:
typedef std::set<moduleEvents *> modCallbacksColl;
static modCallbacksColl modCallbacks;
typedef boost::interprocess::interprocess_recursive_mutex modCallbacksLock;
static modCallbacksLock modCallbacksMtx;
typedef boost::interprocess::scoped_lock<modCallbacksLock> modCallbacksScopedLock;
};
// python wrapper for moduleEvents
struct moduleEventsWrap : moduleEvents, boost::python::wrapper<moduleEvents>
{
ULONG onLoad(const dbgModuleClass &module);
ULONG onLoadDef(const dbgModuleClass &module)
{
return moduleEvents::onLoad(module);
}
ULONG onUnload(const dbgModuleClass &module);
ULONG onUnloadDef(const dbgModuleClass &module)
{
return moduleEvents::onUnload(module);
}
};
/////////////////////////////////////////////////////////////////////////////////

View File

@ -47,50 +47,71 @@ loadModule( const std::string &moduleName )
/////////////////////////////////////////////////////////////////////////////////
boost::python::object
findModule( ULONG64 addr )
void queryModuleParams(
__in ULONG64 addr,
__out std::string &name,
__out ULONG64 &base,
__out ULONG &size
)
{
HRESULT hres;
addr = addr64( addr );
try {
ULONG moduleIndex;
ULONG64 moduleBase;
hres = dbgExt->symbols->GetModuleByOffset( addr, 0, &moduleIndex, &moduleBase );
HRESULT hres =
dbgExt->symbols->GetModuleByOffset( addr, 0, &moduleIndex, &base);
if ( FAILED( hres ) )
{
return boost::python::object();
}
throw DbgException( "IDebugSymbol::GetModuleByOffset failed" );
DEBUG_MODULE_PARAMETERS moduleParam = { 0 };
hres = dbgExt->symbols->GetModuleParameters( 1, &moduleBase, 0, &moduleParam );
hres = dbgExt->symbols->GetModuleParameters( 1, &base, 0, &moduleParam );
if ( FAILED( hres ) )
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
size = moduleParam.Size;
char moduleName[0x100];
hres =
ULONG moduleNameChars = 0;
dbgExt->symbols->GetModuleNames(
moduleIndex,
0,
NULL,
0,
NULL,
moduleName,
sizeof( moduleName ),
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" );
}
return boost::python::object( dbgModuleClass( moduleName, moduleBase, moduleParam.Size ) );
/////////////////////////////////////////////////////////////////////////////////
boost::python::object
findModule( ULONG64 addr )
{
try {
ULONG64 moduleBase;
ULONG moduleSize;
std::string moduleName;
queryModuleParams(addr, moduleName, moduleBase, moduleSize);
return
boost::python::object(
dbgModuleClass( moduleName, moduleBase, moduleSize )
);
}
catch( std::exception &e )
{

View File

@ -162,6 +162,14 @@ private:
boost::python::object
loadModule( const std::string &moduleName );
// query module parameters (for construct dbgModuleClass) by virtual address
// error : DbgException exception
void queryModuleParams(
__in ULONG64 addr,
__out std::string &name,
__out ULONG64 &base,
__out ULONG &size
);
boost::python::object
findModule( ULONG64 addr );

View File

@ -376,6 +376,10 @@
RelativePath=".\dbgmem.cpp"
>
</File>
<File
RelativePath=".\dbgmodevent.cpp"
>
</File>
<File
RelativePath=".\dbgmodule.cpp"
>
@ -494,6 +498,10 @@
RelativePath=".\dbgmem.h"
>
</File>
<File
RelativePath=".\dbgmodevent.h"
>
</File>
<File
RelativePath=".\dbgmodule.h"
>

View File

@ -78,7 +78,6 @@
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
Profile="true"
/>
<Tool
Name="VCALinkTool"
@ -159,7 +158,6 @@
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="17"
Profile="true"
/>
<Tool
Name="VCALinkTool"
@ -367,6 +365,10 @@
RelativePath=".\dbgmem.cpp"
>
</File>
<File
RelativePath=".\dbgmodevent.cpp"
>
</File>
<File
RelativePath=".\dbgmodule.cpp"
>
@ -485,6 +487,10 @@
RelativePath=".\dbgmem.h"
>
</File>
<File
RelativePath=".\dbgmodevent.h"
>
</File>
<File
RelativePath=".\dbgmodule.h"
>

26
samples/goLoad.py Normal file
View File

@ -0,0 +1,26 @@
"""
Wait (execute) for load target module
"""
from pykd import *
import fnmatch
import sys
class modLoad(modEvents):
def __init__(self, mask):
modEvents.__init__(self)
self.mask = mask
def onLoad(self, module):
if fnmatch.fnmatch( module.name(), self.mask ):
return DEBUG_STATUS_BREAK
return DEBUG_STATUS_NO_CHANGE
if __name__ == "__main__":
if len(sys.argv) == 2:
loadHandler = modLoad( sys.argv[1] )
go()
else:
dprintln( "Wait (execute) for load target module\nInvalid command line" )
dprintln( "Using" + sys.argv[0] + " <MOD_FILE_NAME>" )
dprintln( "\tMOD_FILE_NAME - name of target module with wildcard" )