mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-21 04:13:22 +08:00
[0.1.x] add: synthetic symbols implementation
git-svn-id: https://pykd.svn.codeplex.com/svn@71929 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
283f911a73
commit
bc3259e916
@ -12,6 +12,15 @@ DebugClientPtr g_dbgClient( DebugClient::createDbgClient() );
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
DebugClient::DebugClient( IDebugClient4 *client )
|
||||||
|
: DbgObject( client )
|
||||||
|
, m_symSymbols( new SyntheticSymbols(*m_symbols, *this) )
|
||||||
|
, m_internalDbgEventHandler(client, m_symSymbols)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
DebugClientPtr DebugClient::createDbgClient() {
|
DebugClientPtr DebugClient::createDbgClient() {
|
||||||
|
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
@ -315,4 +324,4 @@ ULONG ptrSize()
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
}; // end of namespace pykd
|
}; // end of namespace pykd
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include "pyaux.h"
|
#include "pyaux.h"
|
||||||
#include "disasm.h"
|
#include "disasm.h"
|
||||||
#include "cpureg.h"
|
#include "cpureg.h"
|
||||||
|
#include "inteventhandler.h"
|
||||||
|
#include "synsymbol.h"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -97,11 +99,11 @@ public:
|
|||||||
void loadDump( const std::wstring &fileName );
|
void loadDump( const std::wstring &fileName );
|
||||||
|
|
||||||
Module loadModuleByName( const std::string &moduleName ) {
|
Module loadModuleByName( const std::string &moduleName ) {
|
||||||
return Module( m_client, moduleName );
|
return Module( m_client, m_symSymbols, moduleName );
|
||||||
}
|
}
|
||||||
|
|
||||||
Module loadModuleByOffset( ULONG64 offset ) {
|
Module loadModuleByOffset( ULONG64 offset ) {
|
||||||
return Module( m_client, offset );
|
return Module( m_client, m_symSymbols, offset );
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgExtensionPtr loadExtension( const std::wstring &extPath ) {
|
DbgExtensionPtr loadExtension( const std::wstring &extPath ) {
|
||||||
@ -191,6 +193,35 @@ public:
|
|||||||
return m_pyThreadState;
|
return m_pyThreadState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addSyntheticSymbol(
|
||||||
|
ULONG64 addr,
|
||||||
|
ULONG size,
|
||||||
|
const std::string &symName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return m_symSymbols->add(addr, size, symName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void delAllSyntheticSymbols()
|
||||||
|
{
|
||||||
|
return m_symSymbols->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG delSyntheticSymbol(
|
||||||
|
ULONG64 addr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return m_symSymbols->remove(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG delSyntheticSymbolsMask(
|
||||||
|
const std::string &moduleName,
|
||||||
|
const std::string &symName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return m_symSymbols->removeByMask(moduleName, symName);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -200,7 +231,10 @@ private:
|
|||||||
//python::list
|
//python::list
|
||||||
//loadArray( ULONG64 offset, ULONG count, bool phyAddr );
|
//loadArray( ULONG64 offset, ULONG count, bool phyAddr );
|
||||||
|
|
||||||
DebugClient( IDebugClient4 *client ) : DbgObject( client ) {}
|
SynSymbolsPtr m_symSymbols; // DebugClient is creator
|
||||||
|
InternalDbgEventHandler m_internalDbgEventHandler;
|
||||||
|
|
||||||
|
DebugClient( IDebugClient4 *client );
|
||||||
|
|
||||||
PyThreadStateSaver m_pyThreadState;
|
PyThreadStateSaver m_pyThreadState;
|
||||||
};
|
};
|
||||||
@ -235,6 +269,38 @@ void setExecutionStatus( ULONG status );
|
|||||||
|
|
||||||
void waitForEvent();
|
void waitForEvent();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Synthetic symbols global finctions:
|
||||||
|
|
||||||
|
inline void addSyntheticSymbol(
|
||||||
|
ULONG64 addr,
|
||||||
|
ULONG size,
|
||||||
|
const std::string &symName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return g_dbgClient->addSyntheticSymbol(addr, size, symName);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void delAllSyntheticSymbols()
|
||||||
|
{
|
||||||
|
return g_dbgClient->delAllSyntheticSymbols();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ULONG delSyntheticSymbol(
|
||||||
|
ULONG64 addr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return g_dbgClient->delSyntheticSymbol(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ULONG delSyntheticSymbolsMask(
|
||||||
|
const std::string &moduleName,
|
||||||
|
const std::string &symName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return g_dbgClient->delSyntheticSymbolsMask(moduleName, symName);
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<ULONG status>
|
template<ULONG status>
|
||||||
@ -331,4 +397,4 @@ void changeDebuggerStatus()
|
|||||||
//
|
//
|
||||||
//extern dbgClient g_dbgClient;
|
//extern dbgClient g_dbgClient;
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -234,7 +234,15 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
.def( "trace", &pykd::DebugClient::changeDebuggerStatus<DEBUG_STATUS_STEP_INTO>,
|
.def( "trace", &pykd::DebugClient::changeDebuggerStatus<DEBUG_STATUS_STEP_INTO>,
|
||||||
"Change debugger status to DEBUG_STATUS_STEP_INTO" )
|
"Change debugger status to DEBUG_STATUS_STEP_INTO" )
|
||||||
.def( "waitForEvent", &pykd::DebugClient::waitForEvent,
|
.def( "waitForEvent", &pykd::DebugClient::waitForEvent,
|
||||||
"Wait for events that breaks into the debugger" );
|
"Wait for events that breaks into the debugger" )
|
||||||
|
.def( "addSynSymbol", &pykd::DebugClient::addSyntheticSymbol,
|
||||||
|
"Add new synthetic symbol for virtual address" )
|
||||||
|
.def( "delAllSynSymbols", &pykd::DebugClient::delAllSyntheticSymbols,
|
||||||
|
"Delete all synthetic symbol for all modules")
|
||||||
|
.def( "delSynSymbol", &pykd::DebugClient::delSyntheticSymbol,
|
||||||
|
"Delete synthetic symbols by virtual address" )
|
||||||
|
.def( "delSynSymbolsMask", &pykd::DebugClient::delSyntheticSymbolsMask,
|
||||||
|
"Delete synthetic symbols by mask of module and symbol name");
|
||||||
|
|
||||||
python::def( "addr64", &addr64,
|
python::def( "addr64", &addr64,
|
||||||
"Extend address to 64 bits formats" );
|
"Extend address to 64 bits formats" );
|
||||||
@ -318,6 +326,16 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
"Read an signed mashine's word wide integer from the target memory" );
|
"Read an signed mashine's word wide integer from the target memory" );
|
||||||
python::def( "ptrPtr", &ptrPtr,
|
python::def( "ptrPtr", &ptrPtr,
|
||||||
"Read an pointer value from the target memory" );
|
"Read an pointer value from the target memory" );
|
||||||
|
|
||||||
|
boost::python::def( "addSynSymbol", &addSyntheticSymbol,
|
||||||
|
"Add new synthetic symbol for virtual address" );
|
||||||
|
boost::python::def( "delAllSynSymbols", &delAllSyntheticSymbols,
|
||||||
|
"Delete all synthetic symbol for all modules");
|
||||||
|
boost::python::def( "delSynSymbol", &delSyntheticSymbol,
|
||||||
|
"Delete synthetic symbols by virtual address" );
|
||||||
|
boost::python::def( "delSynSymbolsMask", &delSyntheticSymbolsMask,
|
||||||
|
"Delete synthetic symbols by mask of module and symbol name");
|
||||||
|
|
||||||
python::def( "loadExt", &pykd::loadExtension,
|
python::def( "loadExt", &pykd::loadExtension,
|
||||||
"Load a debuger extension" );
|
"Load a debuger extension" );
|
||||||
python::def( "loadModule", &loadModuleByName,
|
python::def( "loadModule", &loadModuleByName,
|
||||||
@ -610,6 +628,8 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
// wrapper for standart python exceptions
|
// wrapper for standart python exceptions
|
||||||
python::register_exception_translator<pykd::PyException>( &PyException::exceptionTranslate );
|
python::register_exception_translator<pykd::PyException>( &PyException::exceptionTranslate );
|
||||||
|
|
||||||
|
#define _DECL_BASE_EXCEPT_STR .def( "__str__", &pykd::DbgException::print )
|
||||||
|
|
||||||
// base exception
|
// base exception
|
||||||
python::class_<pykd::DbgException> dbgExceptionClass( "BaseException",
|
python::class_<pykd::DbgException> dbgExceptionClass( "BaseException",
|
||||||
"Pykd base exception class",
|
"Pykd base exception class",
|
||||||
@ -618,17 +638,17 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
.def( python::init<std::string>( python::args("desc"), "constructor" ) )
|
.def( python::init<std::string>( python::args("desc"), "constructor" ) )
|
||||||
.def( "desc", &pykd::DbgException::getDesc,
|
.def( "desc", &pykd::DbgException::getDesc,
|
||||||
"Get exception description" )
|
"Get exception description" )
|
||||||
.def( "__str__", &pykd::DbgException::print);
|
_DECL_BASE_EXCEPT_STR;
|
||||||
pykd::DbgException::setTypeObject( dbgExceptionClass.ptr() );
|
pykd::DbgException::setTypeObject( dbgExceptionClass.ptr() );
|
||||||
python::register_exception_translator<pykd::DbgException>(
|
python::register_exception_translator<pykd::DbgException>(
|
||||||
&pykd::DbgException::exceptionTranslate );
|
&pykd::DbgException::exceptionTranslate );
|
||||||
|
|
||||||
// DIA exceptions
|
// DIA exceptions
|
||||||
python::class_<pyDia::Exception, python::bases<DbgException> > diaException(
|
python::class_<pyDia::Exception, python::bases<DbgException> > diaException(
|
||||||
"DiaException", "Debug interface access exception",
|
"DiaException", "Debug interface access exception", python::no_init);
|
||||||
python::no_init );
|
|
||||||
diaException
|
diaException
|
||||||
.def( "hres", &pyDia::Exception::getRes );
|
.def( "hres", &pyDia::Exception::getRes )
|
||||||
|
_DECL_BASE_EXCEPT_STR;
|
||||||
pyDia::Exception::setTypeObject( diaException.ptr() );
|
pyDia::Exception::setTypeObject( diaException.ptr() );
|
||||||
python::register_exception_translator<pyDia::Exception>(
|
python::register_exception_translator<pyDia::Exception>(
|
||||||
&pyDia::Exception::exceptionTranslate );
|
&pyDia::Exception::exceptionTranslate );
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <dbgeng.h>
|
#include <dbgeng.h>
|
||||||
#include "dbgexcept.h"
|
#include "dbgexcept.h"
|
||||||
|
#include "synsymbol.h"
|
||||||
|
|
||||||
namespace pykd {
|
namespace pykd {
|
||||||
|
|
||||||
@ -11,7 +12,8 @@ class DbgObject {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
DbgObject( IDebugClient4 *client ) {
|
DbgObject( IDebugClient4 *client )
|
||||||
|
{
|
||||||
|
|
||||||
m_client = client;
|
m_client = client;
|
||||||
|
|
||||||
@ -38,7 +40,7 @@ protected:
|
|||||||
|
|
||||||
hres = client->QueryInterface( __uuidof(IDebugRegisters2), (void**)&m_registers );
|
hres = client->QueryInterface( __uuidof(IDebugRegisters2), (void**)&m_registers );
|
||||||
if ( FAILED( hres ) )
|
if ( FAILED( hres ) )
|
||||||
throw DbgException("QueryInterface IDebugDataSpaces failed");
|
throw DbgException("QueryInterface IDebugDataSpaces failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~DbgObject() {};
|
virtual ~DbgObject() {};
|
||||||
@ -50,7 +52,6 @@ protected:
|
|||||||
CComPtr<IDebugAdvanced2> m_advanced;
|
CComPtr<IDebugAdvanced2> m_advanced;
|
||||||
CComPtr<IDebugDataSpaces4> m_dataSpaces;
|
CComPtr<IDebugDataSpaces4> m_dataSpaces;
|
||||||
CComPtr<IDebugRegisters2> m_registers;
|
CComPtr<IDebugRegisters2> m_registers;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
76
pykd/inteventhandler.cpp
Normal file
76
pykd/inteventhandler.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "inteventhandler.h"
|
||||||
|
#include "dbgexcept.h"
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
InternalDbgEventHandler::InternalDbgEventHandler(
|
||||||
|
IDebugClient4 *client,
|
||||||
|
SynSymbolsPtr synSymbols
|
||||||
|
) : m_synSymbols(synSymbols)
|
||||||
|
{
|
||||||
|
HRESULT hres = client->CreateClient(&m_client);
|
||||||
|
if (FAILED(hres))
|
||||||
|
throw DbgException("Call IDebugClient::CreateClient failed");
|
||||||
|
|
||||||
|
m_client->SetEventCallbacks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
InternalDbgEventHandler::~InternalDbgEventHandler()
|
||||||
|
{
|
||||||
|
m_client->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
HRESULT InternalDbgEventHandler::GetInterestMask(
|
||||||
|
__out PULONG Mask
|
||||||
|
)
|
||||||
|
{
|
||||||
|
*Mask =
|
||||||
|
DEBUG_EVENT_CHANGE_SYMBOL_STATE;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
HRESULT InternalDbgEventHandler::ChangeSymbolState(
|
||||||
|
__in ULONG Flags,
|
||||||
|
__in ULONG64 Argument
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HRESULT hres = S_OK;
|
||||||
|
|
||||||
|
if (DEBUG_CSS_LOADS & Flags)
|
||||||
|
hres = symLoaded(Argument);
|
||||||
|
|
||||||
|
return hres;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
HRESULT InternalDbgEventHandler::symLoaded(
|
||||||
|
__in ULONG64 ModuleAddress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!ModuleAddress)
|
||||||
|
{
|
||||||
|
// f.e. is case ".reload /f image.exe", if for image.exe no symbols
|
||||||
|
m_synSymbols->restoreAll();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_synSymbols->restoreForModule(ModuleAddress);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
}; // namespace pykd
|
45
pykd/inteventhandler.h
Normal file
45
pykd/inteventhandler.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// Internal debug event handler
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <DbgEng.h>
|
||||||
|
#include "synsymbol.h"
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
class InternalDbgEventHandler : public DebugBaseEventCallbacks {
|
||||||
|
public:
|
||||||
|
|
||||||
|
InternalDbgEventHandler(
|
||||||
|
IDebugClient4 *client,
|
||||||
|
SynSymbolsPtr synSymbols
|
||||||
|
);
|
||||||
|
~InternalDbgEventHandler();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// IUnknown impls
|
||||||
|
STDMETHOD_(ULONG, AddRef)() { return 1; }
|
||||||
|
STDMETHOD_(ULONG, Release)() { return 1; }
|
||||||
|
|
||||||
|
// IDebugEventCallbacks impls
|
||||||
|
STDMETHOD(GetInterestMask)(
|
||||||
|
__out PULONG Mask
|
||||||
|
);
|
||||||
|
|
||||||
|
STDMETHOD(ChangeSymbolState)(
|
||||||
|
__in ULONG Flags,
|
||||||
|
__in ULONG64 Argument
|
||||||
|
);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
HRESULT symLoaded(__in ULONG64 ModuleAddress);
|
||||||
|
|
||||||
|
IDebugClient *m_client;
|
||||||
|
SynSymbolsPtr m_synSymbols;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace pykd
|
@ -20,7 +20,9 @@ Module loadModuleByOffset( ULONG64 offset ) {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Module::Module( IDebugClient4 *client, const std::string& moduleName ) : DbgObject( client )
|
Module::Module( IDebugClient4 *client, SynSymbolsPtr synSymbols, const std::string& moduleName )
|
||||||
|
: DbgObject( client )
|
||||||
|
, m_synSymbols(synSymbols)
|
||||||
{
|
{
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
@ -36,6 +38,8 @@ Module::Module( IDebugClient4 *client, const std::string& moduleName ) : DbgObje
|
|||||||
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
|
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
|
||||||
|
|
||||||
m_size = moduleParam.Size;
|
m_size = moduleParam.Size;
|
||||||
|
m_timeDataStamp = moduleParam.TimeDateStamp;
|
||||||
|
m_checkSumm = moduleParam.Checksum;
|
||||||
|
|
||||||
char imageName[0x100];
|
char imageName[0x100];
|
||||||
|
|
||||||
@ -55,7 +59,9 @@ Module::Module( IDebugClient4 *client, const std::string& moduleName ) : DbgObje
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Module::Module( IDebugClient4 *client, ULONG64 offset ) : DbgObject( client )
|
Module::Module( IDebugClient4 *client, SynSymbolsPtr synSymbols, ULONG64 offset )
|
||||||
|
: DbgObject( client )
|
||||||
|
, m_synSymbols(synSymbols)
|
||||||
{
|
{
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
@ -102,6 +108,8 @@ Module::Module( IDebugClient4 *client, ULONG64 offset ) : DbgObject( client )
|
|||||||
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
|
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
|
||||||
|
|
||||||
m_size = moduleParam.Size;
|
m_size = moduleParam.Size;
|
||||||
|
m_timeDataStamp = moduleParam.TimeDateStamp;
|
||||||
|
m_checkSumm = moduleParam.Checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -198,5 +206,18 @@ Module::getTypedVarByAddr( ULONG64 addr )
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG Module::getRvaByName(const std::string &symName)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
pyDia::SymbolPtr sym = getDia()->getChildByName( symName );
|
||||||
|
return sym->getRva();
|
||||||
|
}
|
||||||
|
catch (const pyDia::Exception &) {
|
||||||
|
}
|
||||||
|
return (ULONG)m_synSymbols->getRvaByName(m_timeDataStamp, m_checkSumm, symName);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
}; // end of namespace pykd
|
}; // end of namespace pykd
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "diawrapper.h"
|
#include "diawrapper.h"
|
||||||
#include "typeinfo.h"
|
#include "typeinfo.h"
|
||||||
#include "typedvar.h"
|
#include "typedvar.h"
|
||||||
|
#include "synsymbol.h"
|
||||||
|
|
||||||
namespace pykd {
|
namespace pykd {
|
||||||
|
|
||||||
@ -15,9 +16,9 @@ class Module : private DbgObject {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Module( IDebugClient4 *client, const std::string& moduleName );
|
Module( IDebugClient4 *client, SynSymbolsPtr synSymbols, const std::string& moduleName );
|
||||||
|
|
||||||
Module( IDebugClient4 *client, ULONG64 offset );
|
Module( IDebugClient4 *client, SynSymbolsPtr synSymbols, ULONG64 offset );
|
||||||
|
|
||||||
std::string getName() {
|
std::string getName() {
|
||||||
return m_name;
|
return m_name;
|
||||||
@ -47,16 +48,12 @@ public:
|
|||||||
|
|
||||||
ULONG64
|
ULONG64
|
||||||
getSymbol( const std::string &symbolname ) {
|
getSymbol( const std::string &symbolname ) {
|
||||||
pyDia::SymbolPtr sym = getDia()->getChildByName( symbolname );
|
return m_base + getRvaByName(symbolname);
|
||||||
|
|
||||||
return m_base + sym->getRva();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
getSymbolRva( const std::string &symbolname ) {
|
getSymbolRva( const std::string &symbolname ) {
|
||||||
pyDia::SymbolPtr sym = getDia()->getChildByName( symbolname );
|
return getRvaByName(symbolname);
|
||||||
|
|
||||||
return sym->getRva();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeInfoPtr getTypeByName( const std::string &typeName ) {
|
TypeInfoPtr getTypeByName( const std::string &typeName ) {
|
||||||
@ -73,6 +70,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
ULONG getRvaByName(const std::string &symName);
|
||||||
|
|
||||||
pyDia::GlobalScopePtr& getDia() {
|
pyDia::GlobalScopePtr& getDia() {
|
||||||
if (!m_dia)
|
if (!m_dia)
|
||||||
m_dia = pyDia::GlobalScope::loadPdb( getPdbName() );
|
m_dia = pyDia::GlobalScope::loadPdb( getPdbName() );
|
||||||
@ -84,7 +83,12 @@ private:
|
|||||||
std::string m_imageName;
|
std::string m_imageName;
|
||||||
ULONG64 m_base;
|
ULONG64 m_base;
|
||||||
ULONG m_size;
|
ULONG m_size;
|
||||||
|
|
||||||
pyDia::GlobalScopePtr m_dia;
|
pyDia::GlobalScopePtr m_dia;
|
||||||
|
|
||||||
|
ULONG m_timeDataStamp;
|
||||||
|
ULONG m_checkSumm;
|
||||||
|
SynSymbolsPtr m_synSymbols;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="windows-1251"?>
|
<?xml version="1.0" encoding="windows-1251"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="9,00"
|
Version="9.00"
|
||||||
Name="pykd"
|
Name="pykd"
|
||||||
ProjectGUID="{FE961905-666F-4908-A212-961465F46F13}"
|
ProjectGUID="{FE961905-666F-4908-A212-961465F46F13}"
|
||||||
RootNamespace="pykd"
|
RootNamespace="pykd"
|
||||||
@ -401,6 +401,10 @@
|
|||||||
RelativePath=".\disasm.cpp"
|
RelativePath=".\disasm.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\inteventhandler.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\module.cpp"
|
RelativePath=".\module.cpp"
|
||||||
>
|
>
|
||||||
@ -445,6 +449,14 @@
|
|||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\synsymbol.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\synsymhelpers.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\typedvar.cpp"
|
RelativePath=".\typedvar.cpp"
|
||||||
>
|
>
|
||||||
@ -511,6 +523,10 @@
|
|||||||
RelativePath=".\intbase.h"
|
RelativePath=".\intbase.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\inteventhandler.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\module.h"
|
RelativePath=".\module.h"
|
||||||
>
|
>
|
||||||
@ -527,6 +543,14 @@
|
|||||||
RelativePath=".\stdafx.h"
|
RelativePath=".\stdafx.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\synsymbol.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\synsymhelpers.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\typedvar.h"
|
RelativePath=".\typedvar.h"
|
||||||
>
|
>
|
||||||
|
248
pykd/synsymbol.cpp
Normal file
248
pykd/synsymbol.cpp
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
|
#include "dbgmem.h"
|
||||||
|
#include "dbgexcept.h"
|
||||||
|
#include "dbgclient.h"
|
||||||
|
#include "synsymhelpers.h"
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
SyntheticSymbols::SyntheticSymbols(
|
||||||
|
IDebugSymbols3 &symbols,
|
||||||
|
DebugClient &dbgClient
|
||||||
|
) : m_symbols(symbols)
|
||||||
|
, m_dbgClient(dbgClient)
|
||||||
|
{
|
||||||
|
m_allSymbolsLock.reset(new boost::recursive_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void SyntheticSymbols::add(
|
||||||
|
ULONG64 addr,
|
||||||
|
ULONG size,
|
||||||
|
const std::string &symName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
addr = m_dbgClient.addr64(addr);
|
||||||
|
|
||||||
|
// add new synthetic symbol to debug engine
|
||||||
|
DEBUG_MODULE_AND_ID dbgModuleAndId = { 0 };
|
||||||
|
HRESULT hres =
|
||||||
|
m_symbols.AddSyntheticSymbol(
|
||||||
|
addr,
|
||||||
|
size,
|
||||||
|
symName.c_str(),
|
||||||
|
DEBUG_ADDSYNTHSYM_DEFAULT,
|
||||||
|
&dbgModuleAndId);
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException(buildExceptDesc("IDebugSymbols3::AddSyntheticSymbol", hres));
|
||||||
|
|
||||||
|
// add/update symbol for target module (in internal map)
|
||||||
|
SymbolsScopedLock lock(*m_allSymbolsLock);
|
||||||
|
|
||||||
|
ModSymbols &modSymbols =
|
||||||
|
m_allSymbols[SynSymHelper(m_symbols).modByBase(dbgModuleAndId.ModuleBase)];
|
||||||
|
SymbolData &symData = modSymbols[addr - dbgModuleAndId.ModuleBase];
|
||||||
|
|
||||||
|
symData.m_name = symName;
|
||||||
|
symData.m_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG SyntheticSymbols::remove(ULONG64 addr)
|
||||||
|
{
|
||||||
|
addr = m_dbgClient.addr64(addr);
|
||||||
|
|
||||||
|
SynSymHelper synSymHelper(m_symbols);
|
||||||
|
|
||||||
|
// find target module
|
||||||
|
ULONG64 moduleBase;
|
||||||
|
SymbolsScopedLock lock(*m_allSymbolsLock);
|
||||||
|
AllSymbols::iterator itModSymbols =
|
||||||
|
m_allSymbols.find(synSymHelper.modByOffset(addr, moduleBase));
|
||||||
|
if (itModSymbols == m_allSymbols.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// remove symbol from internal map
|
||||||
|
itModSymbols->second.erase(addr - moduleBase);
|
||||||
|
|
||||||
|
// remove symbol from debug engine
|
||||||
|
return synSymHelper.removeSyntheticSymbols(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG SyntheticSymbols::removeByMask(
|
||||||
|
const std::string &moduleName,
|
||||||
|
const std::string &symName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SynSymHelper synSymHelper(m_symbols);
|
||||||
|
|
||||||
|
std::vector<DEBUG_MODULE_AND_ID> dbgSymbols;
|
||||||
|
HRESULT hres =
|
||||||
|
synSymHelper.getSymbolsByMaks(
|
||||||
|
moduleName + "!" + symName,
|
||||||
|
dbgSymbols);
|
||||||
|
if (FAILED(hres))
|
||||||
|
throw DbgException(buildExceptDesc("IDebugSymbols3::GetSymbolEntriesByName", hres));
|
||||||
|
|
||||||
|
if (dbgSymbols.empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ULONG removed = 0;
|
||||||
|
|
||||||
|
SymbolsScopedLock lock(*m_allSymbolsLock);
|
||||||
|
for (ULONG i =0; i < dbgSymbols.size(); ++i)
|
||||||
|
{
|
||||||
|
DEBUG_SYMBOL_ENTRY dbgSymbolInfo;
|
||||||
|
HRESULT hres =
|
||||||
|
m_symbols.GetSymbolEntryInformation(
|
||||||
|
&dbgSymbols[i],
|
||||||
|
&dbgSymbolInfo);
|
||||||
|
if (FAILED(hres))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// try find modules in internal map
|
||||||
|
AllSymbols::iterator itModSymbols =
|
||||||
|
m_allSymbols.find(synSymHelper.modByBase(dbgSymbolInfo.ModuleBase));
|
||||||
|
if (itModSymbols == m_allSymbols.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// try find symbol
|
||||||
|
ModSymbols::iterator itSymbol =
|
||||||
|
itModSymbols->second.find(dbgSymbolInfo.Offset - dbgSymbolInfo.ModuleBase);
|
||||||
|
if (itSymbol == itModSymbols->second.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// remove from debug engine
|
||||||
|
if (synSymHelper.removeSyntheticSymbols(dbgSymbols[i]))
|
||||||
|
++removed;
|
||||||
|
|
||||||
|
// remove from internal map
|
||||||
|
itModSymbols->second.erase(itSymbol);
|
||||||
|
|
||||||
|
if (itModSymbols->second.empty())
|
||||||
|
m_allSymbols.erase(itModSymbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void SyntheticSymbols::clear()
|
||||||
|
{
|
||||||
|
SymbolsScopedLock lock(*m_allSymbolsLock);
|
||||||
|
|
||||||
|
// clean symbols from debug engine
|
||||||
|
forEachLoadedModule( SynSymRemoveAll(m_symbols) );
|
||||||
|
|
||||||
|
// clean internal map
|
||||||
|
m_allSymbols.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void SyntheticSymbols::restoreForModule(ULONG64 moduleBase)
|
||||||
|
{
|
||||||
|
SymbolsScopedLock lock(*m_allSymbolsLock);
|
||||||
|
|
||||||
|
SynSymRestore restorer(m_symbols);
|
||||||
|
AllSymbols::iterator itFoundModule =
|
||||||
|
m_allSymbols.find( restorer.modByBase(moduleBase) );
|
||||||
|
if (itFoundModule == m_allSymbols.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
forEachFromModule(moduleBase, itFoundModule->second, restorer);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void SyntheticSymbols::restoreAll()
|
||||||
|
{
|
||||||
|
SymbolsScopedLock lock(*m_allSymbolsLock);
|
||||||
|
|
||||||
|
// clean symbols from debug engine
|
||||||
|
forEachLoadedModule( SynSymRestore(m_symbols) );
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG64 SyntheticSymbols::getRvaByName(
|
||||||
|
ULONG timeDataStamp,
|
||||||
|
ULONG checkSumm,
|
||||||
|
const std::string &symName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SymbolsScopedLock lock(*m_allSymbolsLock);
|
||||||
|
AllSymbols::iterator itFoundModule =
|
||||||
|
m_allSymbols.find( ModuleId(timeDataStamp, checkSumm) );
|
||||||
|
if (itFoundModule == m_allSymbols.end())
|
||||||
|
throw DbgException("Synthetic symbol is not found");
|
||||||
|
|
||||||
|
|
||||||
|
ModSymbols::iterator itSynSymbol = itFoundModule->second.begin();
|
||||||
|
while (itSynSymbol != itFoundModule->second.end())
|
||||||
|
{
|
||||||
|
if (boost::iequals(symName, itSynSymbol->second.m_name))
|
||||||
|
return itSynSymbol->first;
|
||||||
|
|
||||||
|
++itSynSymbol;
|
||||||
|
}
|
||||||
|
throw DbgException("Synthetic symbol is not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void SyntheticSymbols::forEachFromModule(
|
||||||
|
ULONG64 moduleBase,
|
||||||
|
const ModSymbols &modSymbols,
|
||||||
|
ISynSymForEach &forEach
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ModSymbols::const_iterator itSynSymbol = modSymbols.begin();
|
||||||
|
while (itSynSymbol != modSymbols.end())
|
||||||
|
{
|
||||||
|
forEach.symbol(moduleBase, itSynSymbol->first, itSynSymbol->second);
|
||||||
|
++itSynSymbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void SyntheticSymbols::forEachLoadedModule(ISynSymForEach &forEach)
|
||||||
|
{
|
||||||
|
// for loaded and unloaded modules...
|
||||||
|
std::vector<DEBUG_MODULE_PARAMETERS> dbgModules;
|
||||||
|
if (!SUCCEEDED(forEach.getAllModules(dbgModules)) || dbgModules.empty())
|
||||||
|
{
|
||||||
|
SymbolsScopedLock lock(*m_allSymbolsLock);
|
||||||
|
m_allSymbols.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<DEBUG_MODULE_PARAMETERS>::iterator itModule = dbgModules.begin();
|
||||||
|
while (itModule != dbgModules.end())
|
||||||
|
{
|
||||||
|
// ...do it!
|
||||||
|
AllSymbols::const_iterator itFoundModule =
|
||||||
|
m_allSymbols.find( ModuleId(*itModule) );
|
||||||
|
if (itFoundModule != m_allSymbols.end())
|
||||||
|
forEachFromModule(itModule->Base, itFoundModule->second, forEach);
|
||||||
|
|
||||||
|
++itModule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
}; // namespace pykd
|
144
pykd/synsymbol.h
Normal file
144
pykd/synsymbol.h
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
//
|
||||||
|
// Synthetic symbol
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dbgexcept.h"
|
||||||
|
#include <DbgEng.h>
|
||||||
|
#include <map>
|
||||||
|
#include <boost\thread\win32\recursive_mutex.hpp>
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
interface ISynSymForEach;
|
||||||
|
class DebugClient;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class SyntheticSymbols {
|
||||||
|
public:
|
||||||
|
SyntheticSymbols(
|
||||||
|
IDebugSymbols3 &symbols,
|
||||||
|
DebugClient &dbgClient
|
||||||
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Python API:
|
||||||
|
|
||||||
|
// add new synthetic symbol
|
||||||
|
void add(
|
||||||
|
ULONG64 addr,
|
||||||
|
ULONG size,
|
||||||
|
const std::string &symName
|
||||||
|
);
|
||||||
|
|
||||||
|
// remove synthetic symbols by address
|
||||||
|
ULONG remove(ULONG64 addr);
|
||||||
|
|
||||||
|
// remove synthetic symbols by module and symbol names
|
||||||
|
ULONG removeByMask(
|
||||||
|
const std::string &moduleName,
|
||||||
|
const std::string &symName
|
||||||
|
);
|
||||||
|
|
||||||
|
// remove all synthetic symbols from all modules
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Debug event callback manager API:
|
||||||
|
|
||||||
|
void restoreForModule(ULONG64 moduleBase);
|
||||||
|
void restoreAll();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Module API:
|
||||||
|
|
||||||
|
ULONG64 getRvaByName(
|
||||||
|
ULONG timeDataStamp,
|
||||||
|
ULONG checkSumm,
|
||||||
|
const std::string &symName
|
||||||
|
);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// unique module ID
|
||||||
|
struct ModuleId {
|
||||||
|
ULONG m_timeDataStamp;
|
||||||
|
ULONG m_checkSumm;
|
||||||
|
|
||||||
|
ModuleId(ULONG timeDataStamp, ULONG checkSumm)
|
||||||
|
: m_timeDataStamp(timeDataStamp)
|
||||||
|
, m_checkSumm(checkSumm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ModuleId(const DEBUG_MODULE_PARAMETERS &dbgModuleParameters)
|
||||||
|
: m_timeDataStamp(dbgModuleParameters.TimeDateStamp)
|
||||||
|
, m_checkSumm(dbgModuleParameters.Checksum)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator == (const ModuleId &rhs) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
m_timeDataStamp == rhs.m_timeDataStamp &&
|
||||||
|
m_checkSumm == rhs.m_checkSumm;
|
||||||
|
}
|
||||||
|
bool operator < (const ModuleId &rhs) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
m_timeDataStamp < rhs.m_timeDataStamp &&
|
||||||
|
m_checkSumm < rhs.m_checkSumm;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// symbol data
|
||||||
|
struct SymbolData {
|
||||||
|
std::string m_name;
|
||||||
|
ULONG m_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
// synthetic symbols of one module: offset -> name+size
|
||||||
|
typedef ULONG64 SYM_OFFSET;
|
||||||
|
typedef std::map<SYM_OFFSET, SymbolData> ModSymbols;
|
||||||
|
|
||||||
|
// synthetic symbols of all modules
|
||||||
|
typedef std::map<ModuleId, ModSymbols> AllSymbols;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// lock of static map
|
||||||
|
typedef boost::shared_ptr<boost::recursive_mutex> SymbolsLock;
|
||||||
|
typedef boost::recursive_mutex::scoped_lock SymbolsScopedLock;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// execute for all symbols from modules
|
||||||
|
void forEachFromModule(
|
||||||
|
ULONG64 moduleBase,
|
||||||
|
const ModSymbols &modSymbols,
|
||||||
|
ISynSymForEach &forEach
|
||||||
|
);
|
||||||
|
|
||||||
|
// execute for all symbols all loaded modules
|
||||||
|
void forEachLoadedModule(ISynSymForEach &forEach);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
SymbolsLock m_allSymbolsLock;
|
||||||
|
AllSymbols m_allSymbols;
|
||||||
|
|
||||||
|
DebugClient &m_dbgClient;
|
||||||
|
IDebugSymbols3 &m_symbols;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<SyntheticSymbols> SynSymbolsPtr;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
}; // namespace pykd
|
152
pykd/synsymhelpers.cpp
Normal file
152
pykd/synsymhelpers.cpp
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
|
||||||
|
#include <stdafx.h>
|
||||||
|
|
||||||
|
#include "dbgexcept.h"
|
||||||
|
#include "synsymhelpers.h"
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool SynSymHelper::removeSyntheticSymbols(
|
||||||
|
const DEBUG_MODULE_AND_ID &dbgSymbols
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return SUCCEEDED(
|
||||||
|
m_symbols.RemoveSyntheticSymbol(
|
||||||
|
const_cast<DEBUG_MODULE_AND_ID *>(&dbgSymbols)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG SynSymHelper::removeSyntheticSymbols(
|
||||||
|
const std::vector<DEBUG_MODULE_AND_ID> &arrSymbols
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG countOfRemoved = 0;
|
||||||
|
for (ULONG i = 0; i < arrSymbols.size(); ++i)
|
||||||
|
{
|
||||||
|
if (removeSyntheticSymbols(arrSymbols[i]))
|
||||||
|
++countOfRemoved;
|
||||||
|
}
|
||||||
|
return countOfRemoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG SynSymHelper::removeSyntheticSymbols(ULONG64 addr)
|
||||||
|
{
|
||||||
|
ULONG entries = 0;
|
||||||
|
m_symbols.GetSymbolEntriesByOffset(addr, 0, NULL, NULL, 0, &entries);
|
||||||
|
if (!entries)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
std::vector<DEBUG_MODULE_AND_ID> arrSymbols(entries);
|
||||||
|
HRESULT hres = m_symbols.GetSymbolEntriesByOffset(
|
||||||
|
addr,
|
||||||
|
0,
|
||||||
|
&arrSymbols[0],
|
||||||
|
NULL,
|
||||||
|
(ULONG)arrSymbols.size(),
|
||||||
|
NULL);
|
||||||
|
if (SUCCEEDED(hres))
|
||||||
|
return removeSyntheticSymbols(arrSymbols);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
SyntheticSymbols::ModuleId SynSymHelper::modByBase(ULONG64 moduleBase)
|
||||||
|
{
|
||||||
|
DEBUG_MODULE_PARAMETERS dbgModuleParameters;
|
||||||
|
HRESULT hres =
|
||||||
|
m_symbols.GetModuleParameters(
|
||||||
|
1,
|
||||||
|
&moduleBase,
|
||||||
|
0,
|
||||||
|
&dbgModuleParameters);
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException(buildExceptDesc("IDebugSymbols3::GetModuleParameters", hres));
|
||||||
|
|
||||||
|
return SyntheticSymbols::ModuleId(dbgModuleParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
SyntheticSymbols::ModuleId SynSymHelper::modByOffset(
|
||||||
|
ULONG64 moduleOffset,
|
||||||
|
ULONG64 &moduleBase
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HRESULT hres =
|
||||||
|
m_symbols.GetModuleByOffset(moduleOffset, 0, NULL, &moduleBase);
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException(buildExceptDesc("IDebugSymbols3::GetModuleByOffset", hres));
|
||||||
|
|
||||||
|
return modByBase(moduleBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
HRESULT SynSymHelper::getAllModules(
|
||||||
|
std::vector<DEBUG_MODULE_PARAMETERS> &dbgModules
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG nLoaded;
|
||||||
|
ULONG nUnloaded;
|
||||||
|
HRESULT hres = m_symbols.GetNumberModules(&nLoaded, &nUnloaded);
|
||||||
|
if (FAILED(hres))
|
||||||
|
return hres;
|
||||||
|
|
||||||
|
if (!nLoaded && !nUnloaded)
|
||||||
|
{
|
||||||
|
dbgModules.clear();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgModules.resize(nLoaded + nUnloaded);
|
||||||
|
return
|
||||||
|
m_symbols.GetModuleParameters(
|
||||||
|
nLoaded + nUnloaded,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&dbgModules[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
HRESULT SynSymHelper::getSymbolsByMaks(
|
||||||
|
const std::string &symMask,
|
||||||
|
std::vector<DEBUG_MODULE_AND_ID> &dbgSymbols
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG entries = 0;
|
||||||
|
m_symbols.GetSymbolEntriesByName(
|
||||||
|
symMask.c_str(),
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&entries);
|
||||||
|
if (!entries)
|
||||||
|
{
|
||||||
|
dbgSymbols.clear();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgSymbols.resize(entries);
|
||||||
|
|
||||||
|
return
|
||||||
|
m_symbols.GetSymbolEntriesByName(
|
||||||
|
symMask.c_str(),
|
||||||
|
0,
|
||||||
|
&dbgSymbols[0],
|
||||||
|
entries,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
}; // namespace pykd
|
107
pykd/synsymhelpers.h
Normal file
107
pykd/synsymhelpers.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
//
|
||||||
|
// Synthetic symbol helpers
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "synsymbol.h"
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class SynSymHelper {
|
||||||
|
public:
|
||||||
|
SynSymHelper(IDebugSymbols3 &symbols) : m_symbols(symbols) {}
|
||||||
|
|
||||||
|
// remove array of synthetic symbols from debug engine
|
||||||
|
bool removeSyntheticSymbols(
|
||||||
|
const DEBUG_MODULE_AND_ID &dbgSymbols
|
||||||
|
);
|
||||||
|
ULONG removeSyntheticSymbols(
|
||||||
|
const std::vector<DEBUG_MODULE_AND_ID> &arrSymbols
|
||||||
|
);
|
||||||
|
ULONG removeSyntheticSymbols(ULONG64 addr);
|
||||||
|
|
||||||
|
// buid ModuleId by base of image
|
||||||
|
SyntheticSymbols::ModuleId modByBase(ULONG64 moduleBase);
|
||||||
|
|
||||||
|
// buid ModuleId by offset in image
|
||||||
|
SyntheticSymbols::ModuleId modByOffset(
|
||||||
|
ULONG64 moduleOffset,
|
||||||
|
ULONG64 &moduleBase
|
||||||
|
);
|
||||||
|
|
||||||
|
// get array of all modules
|
||||||
|
HRESULT getAllModules(std::vector<DEBUG_MODULE_PARAMETERS> &dbgModules);
|
||||||
|
|
||||||
|
// get symbols by mask
|
||||||
|
HRESULT getSymbolsByMaks(
|
||||||
|
const std::string &symMask,
|
||||||
|
std::vector<DEBUG_MODULE_AND_ID> &dbgSymbols
|
||||||
|
);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
IDebugSymbols3 &m_symbols;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Enumerator all synthetic symbols for loaded modules
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
interface ISynSymForEach : public SynSymHelper {
|
||||||
|
ISynSymForEach(IDebugSymbols3 &symbols) : SynSymHelper(symbols) {}
|
||||||
|
|
||||||
|
virtual void symbol(
|
||||||
|
const ULONG64 moduleBase,
|
||||||
|
SyntheticSymbols::SYM_OFFSET offset,
|
||||||
|
const SyntheticSymbols::SymbolData &symData
|
||||||
|
) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Remove symbols from loaded modules
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
class SynSymRemoveAll : public ISynSymForEach
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SynSymRemoveAll(IDebugSymbols3 &symbols) : ISynSymForEach(symbols) {}
|
||||||
|
|
||||||
|
virtual void symbol(
|
||||||
|
const ULONG64 moduleBase,
|
||||||
|
SyntheticSymbols::SYM_OFFSET offset,
|
||||||
|
const SyntheticSymbols::SymbolData &/*symData*/
|
||||||
|
) override
|
||||||
|
{
|
||||||
|
removeSyntheticSymbols(moduleBase + offset);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Restore symbols for loaded modules
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
class SynSymRestore : public ISynSymForEach
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SynSymRestore(IDebugSymbols3 &symbols) : ISynSymForEach(symbols) {}
|
||||||
|
|
||||||
|
virtual void symbol(
|
||||||
|
const ULONG64 moduleBase,
|
||||||
|
SyntheticSymbols::SYM_OFFSET offset,
|
||||||
|
const SyntheticSymbols::SymbolData &symData
|
||||||
|
) override
|
||||||
|
{
|
||||||
|
m_symbols.AddSyntheticSymbol(
|
||||||
|
moduleBase + offset,
|
||||||
|
symData.m_size,
|
||||||
|
symData.m_name.c_str(),
|
||||||
|
DEBUG_ADDSYNTHSYM_DEFAULT,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
}; // namespace pykd
|
@ -22,6 +22,7 @@ import eventtest
|
|||||||
import typedvar
|
import typedvar
|
||||||
import memtest
|
import memtest
|
||||||
import intbase
|
import intbase
|
||||||
|
import synsymtest
|
||||||
|
|
||||||
def getTestSuite( singleName = "" ):
|
def getTestSuite( singleName = "" ):
|
||||||
if singleName == "":
|
if singleName == "":
|
||||||
@ -36,6 +37,7 @@ 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 )
|
||||||
] )
|
] )
|
||||||
else:
|
else:
|
||||||
return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) )
|
return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) )
|
||||||
@ -58,5 +60,5 @@ if __name__ == "__main__":
|
|||||||
#suite = getTestSuite( "typedvar.TypedVarTest.testStruct" )
|
#suite = getTestSuite( "typedvar.TypedVarTest.testStruct" )
|
||||||
|
|
||||||
unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( suite )
|
unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( suite )
|
||||||
|
|
||||||
#a = raw_input("\npress return\n")
|
a = raw_input("\npress return\n")
|
68
test/scripts/synsymtest.py
Normal file
68
test/scripts/synsymtest.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
"""Synthetic symbols tests"""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import target
|
||||||
|
import pykd
|
||||||
|
|
||||||
|
class SynSymTest(unittest.TestCase):
|
||||||
|
"""Unit tests of synthetic symbols"""
|
||||||
|
|
||||||
|
def testAdd(self):
|
||||||
|
"""Add new synthetic symbol"""
|
||||||
|
pykd.addSynSymbol(
|
||||||
|
target.module.offset("FuncWithName0")-1, 1, "synSym1")
|
||||||
|
self.assertEqual(
|
||||||
|
target.module.offset("FuncWithName0")-1,
|
||||||
|
target.module.offset("synSym1"))
|
||||||
|
|
||||||
|
def testDel(self):
|
||||||
|
"""Remove synthetic symbol"""
|
||||||
|
pykd.addSynSymbol(
|
||||||
|
target.module.offset("FuncWithName0")-2, 1, "synSym2")
|
||||||
|
self.assertEqual(
|
||||||
|
pykd.delSynSymbol( target.module.offset("synSym2") ), 1 )
|
||||||
|
|
||||||
|
exceptionOccurred = True
|
||||||
|
try:
|
||||||
|
target.module.rva("synSym2")
|
||||||
|
exceptionOccurred = False
|
||||||
|
except pykd.BaseException:
|
||||||
|
pass
|
||||||
|
self.assertTrue(exceptionOccurred)
|
||||||
|
|
||||||
|
def testDelAll(self):
|
||||||
|
"""Remove all synthetic symbols"""
|
||||||
|
pykd.addSynSymbol(
|
||||||
|
target.module.offset("FuncWithName0")-3, 1, "synSym3")
|
||||||
|
pykd.delAllSynSymbols()
|
||||||
|
|
||||||
|
exceptionOccurred = True
|
||||||
|
try:
|
||||||
|
target.module.rva("synSym3")
|
||||||
|
exceptionOccurred = False
|
||||||
|
except pykd.BaseException:
|
||||||
|
pass
|
||||||
|
self.assertTrue(exceptionOccurred)
|
||||||
|
|
||||||
|
def testDelByMask(self):
|
||||||
|
"""Remove synthetic symbol by mask"""
|
||||||
|
pykd.addSynSymbol(
|
||||||
|
target.module.offset("FuncWithName0")-4, 1, "synSym4")
|
||||||
|
self.assertTrue( pykd.delSynSymbolsMask( "*", "synSym4" ) >= 1 )
|
||||||
|
|
||||||
|
exceptionOccurred = True
|
||||||
|
try:
|
||||||
|
target.module.rva("synSym4")
|
||||||
|
exceptionOccurred = False
|
||||||
|
except pykd.BaseException:
|
||||||
|
pass
|
||||||
|
self.assertTrue(exceptionOccurred)
|
||||||
|
|
||||||
|
def testReload(self):
|
||||||
|
"""Restore synthetic symbols after reload module symbols"""
|
||||||
|
pykd.addSynSymbol(
|
||||||
|
target.module.offset("FuncWithName0")-5, 1, "synSym5")
|
||||||
|
target.module.reload()
|
||||||
|
self.assertEqual(
|
||||||
|
target.module.offset("FuncWithName0")-5,
|
||||||
|
target.module.offset("synSym5"))
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="windows-1251"?>
|
<?xml version="1.0" encoding="windows-1251"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="9,00"
|
Version="9.00"
|
||||||
Name="targetapp"
|
Name="targetapp"
|
||||||
ProjectGUID="{C6254E16-AB8E-41EE-887D-31458E93FC68}"
|
ProjectGUID="{C6254E16-AB8E-41EE-887D-31458E93FC68}"
|
||||||
RootNamespace="targetapp"
|
RootNamespace="targetapp"
|
||||||
@ -440,6 +440,10 @@
|
|||||||
RelativePath="..\scripts\regtest.py"
|
RelativePath="..\scripts\regtest.py"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\scripts\synsymtest.py"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\scripts\target.py"
|
RelativePath="..\scripts\target.py"
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user