[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:
SND\EreTIk_cp 2011-11-30 18:40:57 +00:00 committed by Mikhail I. Izmestev
parent 283f911a73
commit bc3259e916
16 changed files with 1018 additions and 27 deletions

View File

@ -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() {
HRESULT hres;
@ -315,4 +324,4 @@ ULONG ptrSize()
///////////////////////////////////////////////////////////////////////////////////
}; // end of namespace pykd
}; // end of namespace pykd

View File

@ -14,6 +14,8 @@
#include "pyaux.h"
#include "disasm.h"
#include "cpureg.h"
#include "inteventhandler.h"
#include "synsymbol.h"
/////////////////////////////////////////////////////////////////////////////////
@ -97,11 +99,11 @@ public:
void loadDump( const std::wstring &fileName );
Module loadModuleByName( const std::string &moduleName ) {
return Module( m_client, moduleName );
return Module( m_client, m_symSymbols, moduleName );
}
Module loadModuleByOffset( ULONG64 offset ) {
return Module( m_client, offset );
return Module( m_client, m_symSymbols, offset );
}
DbgExtensionPtr loadExtension( const std::wstring &extPath ) {
@ -191,6 +193,35 @@ public:
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:
template<typename T>
@ -200,7 +231,10 @@ private:
//python::list
//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;
};
@ -235,6 +269,38 @@ void setExecutionStatus( ULONG status );
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>
@ -331,4 +397,4 @@ void changeDebuggerStatus()
//
//extern dbgClient g_dbgClient;
//
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

View File

@ -234,7 +234,15 @@ BOOST_PYTHON_MODULE( pykd )
.def( "trace", &pykd::DebugClient::changeDebuggerStatus<DEBUG_STATUS_STEP_INTO>,
"Change debugger status to DEBUG_STATUS_STEP_INTO" )
.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,
"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" );
python::def( "ptrPtr", &ptrPtr,
"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,
"Load a debuger extension" );
python::def( "loadModule", &loadModuleByName,
@ -610,6 +628,8 @@ BOOST_PYTHON_MODULE( pykd )
// wrapper for standart python exceptions
python::register_exception_translator<pykd::PyException>( &PyException::exceptionTranslate );
#define _DECL_BASE_EXCEPT_STR .def( "__str__", &pykd::DbgException::print )
// base exception
python::class_<pykd::DbgException> dbgExceptionClass( "BaseException",
"Pykd base exception class",
@ -618,17 +638,17 @@ BOOST_PYTHON_MODULE( pykd )
.def( python::init<std::string>( python::args("desc"), "constructor" ) )
.def( "desc", &pykd::DbgException::getDesc,
"Get exception description" )
.def( "__str__", &pykd::DbgException::print);
_DECL_BASE_EXCEPT_STR;
pykd::DbgException::setTypeObject( dbgExceptionClass.ptr() );
python::register_exception_translator<pykd::DbgException>(
&pykd::DbgException::exceptionTranslate );
// DIA exceptions
python::class_<pyDia::Exception, python::bases<DbgException> > diaException(
"DiaException", "Debug interface access exception",
python::no_init );
"DiaException", "Debug interface access exception", python::no_init);
diaException
.def( "hres", &pyDia::Exception::getRes );
.def( "hres", &pyDia::Exception::getRes )
_DECL_BASE_EXCEPT_STR;
pyDia::Exception::setTypeObject( diaException.ptr() );
python::register_exception_translator<pyDia::Exception>(
&pyDia::Exception::exceptionTranslate );

View File

@ -2,6 +2,7 @@
#include <dbgeng.h>
#include "dbgexcept.h"
#include "synsymbol.h"
namespace pykd {
@ -11,7 +12,8 @@ class DbgObject {
protected:
DbgObject( IDebugClient4 *client ) {
DbgObject( IDebugClient4 *client )
{
m_client = client;
@ -38,7 +40,7 @@ protected:
hres = client->QueryInterface( __uuidof(IDebugRegisters2), (void**)&m_registers );
if ( FAILED( hres ) )
throw DbgException("QueryInterface IDebugDataSpaces failed");
throw DbgException("QueryInterface IDebugDataSpaces failed");
}
virtual ~DbgObject() {};
@ -50,7 +52,6 @@ protected:
CComPtr<IDebugAdvanced2> m_advanced;
CComPtr<IDebugDataSpaces4> m_dataSpaces;
CComPtr<IDebugRegisters2> m_registers;
};

76
pykd/inteventhandler.cpp Normal file
View 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
View 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

View File

@ -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;
@ -36,6 +38,8 @@ Module::Module( IDebugClient4 *client, const std::string& moduleName ) : DbgObje
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
m_size = moduleParam.Size;
m_timeDataStamp = moduleParam.TimeDateStamp;
m_checkSumm = moduleParam.Checksum;
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;
@ -102,6 +108,8 @@ Module::Module( IDebugClient4 *client, ULONG64 offset ) : DbgObject( client )
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
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

View File

@ -6,6 +6,7 @@
#include "diawrapper.h"
#include "typeinfo.h"
#include "typedvar.h"
#include "synsymbol.h"
namespace pykd {
@ -15,9 +16,9 @@ class Module : private DbgObject {
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() {
return m_name;
@ -47,16 +48,12 @@ public:
ULONG64
getSymbol( const std::string &symbolname ) {
pyDia::SymbolPtr sym = getDia()->getChildByName( symbolname );
return m_base + sym->getRva();
return m_base + getRvaByName(symbolname);
}
ULONG
getSymbolRva( const std::string &symbolname ) {
pyDia::SymbolPtr sym = getDia()->getChildByName( symbolname );
return sym->getRva();
return getRvaByName(symbolname);
}
TypeInfoPtr getTypeByName( const std::string &typeName ) {
@ -73,6 +70,8 @@ public:
private:
ULONG getRvaByName(const std::string &symName);
pyDia::GlobalScopePtr& getDia() {
if (!m_dia)
m_dia = pyDia::GlobalScope::loadPdb( getPdbName() );
@ -84,7 +83,12 @@ private:
std::string m_imageName;
ULONG64 m_base;
ULONG m_size;
pyDia::GlobalScopePtr m_dia;
ULONG m_timeDataStamp;
ULONG m_checkSumm;
SynSymbolsPtr m_synSymbols;
};
///////////////////////////////////////////////////////////////////////////////////

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Version="9.00"
Name="pykd"
ProjectGUID="{FE961905-666F-4908-A212-961465F46F13}"
RootNamespace="pykd"
@ -401,6 +401,10 @@
RelativePath=".\disasm.cpp"
>
</File>
<File
RelativePath=".\inteventhandler.cpp"
>
</File>
<File
RelativePath=".\module.cpp"
>
@ -445,6 +449,14 @@
/>
</FileConfiguration>
</File>
<File
RelativePath=".\synsymbol.cpp"
>
</File>
<File
RelativePath=".\synsymhelpers.cpp"
>
</File>
<File
RelativePath=".\typedvar.cpp"
>
@ -511,6 +523,10 @@
RelativePath=".\intbase.h"
>
</File>
<File
RelativePath=".\inteventhandler.h"
>
</File>
<File
RelativePath=".\module.h"
>
@ -527,6 +543,14 @@
RelativePath=".\stdafx.h"
>
</File>
<File
RelativePath=".\synsymbol.h"
>
</File>
<File
RelativePath=".\synsymhelpers.h"
>
</File>
<File
RelativePath=".\typedvar.h"
>

248
pykd/synsymbol.cpp Normal file
View 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
View 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
View 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
View 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

View File

@ -22,6 +22,7 @@ import eventtest
import typedvar
import memtest
import intbase
import synsymtest
def getTestSuite( singleName = "" ):
if singleName == "":
@ -36,6 +37,7 @@ def getTestSuite( singleName = "" ):
unittest.TestLoader().loadTestsFromTestCase( eventtest.EventTest ),
unittest.TestLoader().loadTestsFromTestCase( memtest.MemoryTest ),
unittest.TestLoader().loadTestsFromTestCase( intbase.IntBaseTest ),
unittest.TestLoader().loadTestsFromTestCase( synsymtest.SynSymTest )
] )
else:
return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) )
@ -58,5 +60,5 @@ if __name__ == "__main__":
#suite = getTestSuite( "typedvar.TypedVarTest.testStruct" )
unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( suite )
#a = raw_input("\npress return\n")
a = raw_input("\npress return\n")

View 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"))

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Version="9.00"
Name="targetapp"
ProjectGUID="{C6254E16-AB8E-41EE-887D-31458E93FC68}"
RootNamespace="targetapp"
@ -440,6 +440,10 @@
RelativePath="..\scripts\regtest.py"
>
</File>
<File
RelativePath="..\scripts\synsymtest.py"
>
</File>
<File
RelativePath="..\scripts\target.py"
>