mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-21 12:53:23 +08:00
[+] 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:
parent
77300508e7
commit
6e2d161966
@ -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;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
108
pykd/dbgmodevent.cpp
Normal 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
53
pykd/dbgmodevent.h
Normal 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);
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
@ -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 )
|
||||
{
|
||||
|
@ -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 );
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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
26
samples/goLoad.py
Normal 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" )
|
Loading…
Reference in New Issue
Block a user