mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-21 12:53:23 +08:00
[0.2.x] workitem 11665 fixed: work with modules moved to separate module, add load/unload symbols debug events, work with symbol cache moved to separate module
git-svn-id: https://pykd.svn.codeplex.com/svn@83100 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
27fd6ad3b7
commit
342792bc91
@ -110,6 +110,8 @@ struct DEBUG_EVENT_CALLBACK {
|
|||||||
virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64 offset, const std::string &name ) = 0;
|
virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64 offset, const std::string &name ) = 0;
|
||||||
virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) = 0;
|
virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) = 0;
|
||||||
virtual void onExecutionStatusChange( ULONG executionStatus ) = 0;
|
virtual void onExecutionStatusChange( ULONG executionStatus ) = 0;
|
||||||
|
virtual void onSymbolsLoaded(ULONG64 modBase) = 0;
|
||||||
|
virtual void onSymbolsUnloaded(ULONG64 modBase OPTIONAL) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EVENT_TYPE {
|
enum EVENT_TYPE {
|
||||||
|
@ -27,6 +27,8 @@ private:
|
|||||||
virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64 offset, const std::string &name ) = 0;
|
virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64 offset, const std::string &name ) = 0;
|
||||||
virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) = 0;
|
virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) = 0;
|
||||||
virtual void onExecutionStatusChange( ULONG executionStatus ) = 0;
|
virtual void onExecutionStatusChange( ULONG executionStatus ) = 0;
|
||||||
|
virtual void onSymbolsLoaded(ULONG64 modBase) = 0;
|
||||||
|
virtual void onSymbolsUnloaded(ULONG64 modBase OPTIONAL) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -57,6 +59,13 @@ public:
|
|||||||
void_handler("onExecutionStatusChange", executionStatus );
|
void_handler("onExecutionStatusChange", executionStatus );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void onSymbolsLoaded(ULONG64 modBase) {
|
||||||
|
void_handler("onSymbolsLoaded", modBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void onSymbolsUnloaded(ULONG64 modBase OPTIONAL) {
|
||||||
|
void_handler("onSymbolsUnloaded", modBase);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -3,15 +3,12 @@
|
|||||||
#include "module.h"
|
#include "module.h"
|
||||||
#include "dbgexcept.h"
|
#include "dbgexcept.h"
|
||||||
#include "vardata.h"
|
#include "vardata.h"
|
||||||
|
#include "symsessioncache.h"
|
||||||
|
|
||||||
namespace pykd {
|
namespace pykd {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Module::SymbolSessionCache Module::m_symSessionCache;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ModulePtr Module::loadModuleByName( const std::string &moduleName )
|
ModulePtr Module::loadModuleByName( const std::string &moduleName )
|
||||||
{
|
{
|
||||||
return ModulePtr( new Module( moduleName ) );
|
return ModulePtr( new Module( moduleName ) );
|
||||||
@ -55,11 +52,9 @@ SymbolSessionPtr& Module::getSymSession()
|
|||||||
if (m_symSession)
|
if (m_symSession)
|
||||||
return m_symSession;
|
return m_symSession;
|
||||||
|
|
||||||
SymbolMapKey cacheKey = { m_name, m_size, m_timeDataStamp, m_checkSum };
|
SymCacheModuleKey cacheKey = { m_name, m_size, m_timeDataStamp, m_checkSum };
|
||||||
SymbolSessionCache::iterator found = m_symSessionCache.find( cacheKey );
|
if ( findSymCacheEntry( cacheKey, m_symSession ) )
|
||||||
if ( found != m_symSessionCache.end() )
|
|
||||||
{
|
{
|
||||||
m_symSession = found->second;
|
|
||||||
if ( !m_symSession )
|
if ( !m_symSession )
|
||||||
throw SymbolException( "failed to load symbol file" );
|
throw SymbolException( "failed to load symbol file" );
|
||||||
|
|
||||||
@ -71,7 +66,7 @@ SymbolSessionPtr& Module::getSymSession()
|
|||||||
m_symSession = loadSymbolFile( m_base, m_imageName);
|
m_symSession = loadSymbolFile( m_base, m_imageName);
|
||||||
if (m_symSession)
|
if (m_symSession)
|
||||||
{
|
{
|
||||||
m_symSessionCache.insert( std::make_pair( cacheKey, m_symSession ) );
|
insertSymCacheEntry( m_base, cacheKey, m_symSession );
|
||||||
return m_symSession;
|
return m_symSession;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,7 +85,7 @@ SymbolSessionPtr& Module::getSymSession()
|
|||||||
|
|
||||||
if (m_symSession)
|
if (m_symSession)
|
||||||
{
|
{
|
||||||
m_symSessionCache.insert( std::make_pair( cacheKey, m_symSession ) );
|
insertSymCacheEntry( m_base, cacheKey, m_symSession );
|
||||||
return m_symSession;
|
return m_symSession;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,15 +97,14 @@ SymbolSessionPtr& Module::getSymSession()
|
|||||||
m_symSession = loadSymbolFromExports(m_base);
|
m_symSession = loadSymbolFromExports(m_base);
|
||||||
if (m_symSession)
|
if (m_symSession)
|
||||||
{
|
{
|
||||||
m_symSessionCache.insert( std::make_pair( cacheKey, m_symSession ) );
|
insertSymCacheEntry( m_base, cacheKey, m_symSession );
|
||||||
return m_symSession;
|
return m_symSession;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(const DbgException&)
|
catch(const DbgException&)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
m_symSessionCache.insert( std::make_pair( cacheKey, SymbolSessionPtr() ) );
|
insertSymCacheEntry( m_base, cacheKey, SymbolSessionPtr() );
|
||||||
|
|
||||||
throw SymbolException( "failed to load symbol file" );
|
throw SymbolException( "failed to load symbol file" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,8 +131,8 @@ SymbolPtr Module::getSymScope()
|
|||||||
|
|
||||||
void Module::reloadSymbols()
|
void Module::reloadSymbols()
|
||||||
{
|
{
|
||||||
SymbolMapKey cacheKey = { m_name, m_size, m_timeDataStamp, m_checkSum };
|
SymCacheModuleKey cacheKey = { m_name, m_size, m_timeDataStamp, m_checkSum };
|
||||||
m_symSessionCache.erase( cacheKey );
|
eraseSymCacheEntry( cacheKey );
|
||||||
|
|
||||||
m_symSession.reset();
|
m_symSession.reset();
|
||||||
getSymSession();
|
getSymSession();
|
||||||
|
@ -24,40 +24,6 @@ public:
|
|||||||
static
|
static
|
||||||
ModulePtr loadModuleByOffset( ULONG64 offset );
|
ModulePtr loadModuleByOffset( ULONG64 offset );
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
struct SymbolMapKey{
|
|
||||||
std::string name;
|
|
||||||
ULONG size;
|
|
||||||
ULONG timeStamp;
|
|
||||||
ULONG checkSum;
|
|
||||||
|
|
||||||
bool operator < ( const SymbolMapKey& key ) const
|
|
||||||
{
|
|
||||||
if ( name < key.name )
|
|
||||||
return true;
|
|
||||||
if ( name > key.name )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ( size < key.size )
|
|
||||||
return true;
|
|
||||||
if ( size > key.size )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ( timeStamp < key.timeStamp )
|
|
||||||
return true;
|
|
||||||
if ( timeStamp > key.timeStamp )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return checkSum < key.checkSum;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::map<SymbolMapKey,SymbolSessionPtr> SymbolSessionCache;
|
|
||||||
static SymbolSessionCache m_symSessionCache;
|
|
||||||
|
|
||||||
SymbolSessionPtr getFromCache();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Module(const std::string &name );
|
Module(const std::string &name );
|
||||||
|
@ -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"
|
||||||
@ -441,6 +441,10 @@
|
|||||||
RelativePath=".\stkframe.cpp"
|
RelativePath=".\stkframe.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\symsessioncache.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\typedvar.cpp"
|
RelativePath=".\typedvar.cpp"
|
||||||
>
|
>
|
||||||
@ -527,6 +531,10 @@
|
|||||||
RelativePath=".\symengine.h"
|
RelativePath=".\symengine.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\symsessioncache.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\typedvar.h"
|
RelativePath=".\typedvar.h"
|
||||||
>
|
>
|
||||||
@ -581,6 +589,10 @@
|
|||||||
RelativePath=".\win\dbgio.h"
|
RelativePath=".\win\dbgio.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\win\dbgmod.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\win\lastevent.cpp"
|
RelativePath=".\win\lastevent.cpp"
|
||||||
>
|
>
|
||||||
|
@ -613,6 +613,12 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
"For ignore event method must return eventResult.noChange" )
|
"For ignore event method must return eventResult.noChange" )
|
||||||
.def( "onExecutionStatusChange", &EventHandlerWrap::onExecutionStatusChange,
|
.def( "onExecutionStatusChange", &EventHandlerWrap::onExecutionStatusChange,
|
||||||
"Triggered execution status changed. Parameter - execution status.\n"
|
"Triggered execution status changed. Parameter - execution status.\n"
|
||||||
|
"There is no return value" )
|
||||||
|
.def( "onSymbolsLoaded", &EventHandlerWrap::onSymbolsLoaded,
|
||||||
|
"Triggered debug symbols loaded. Parameter - module base\n"
|
||||||
|
"There is no return value")
|
||||||
|
.def( "onSymbolsUnloaded", &EventHandlerWrap::onSymbolsUnloaded,
|
||||||
|
"Triggered debug symbols unloaded. Parameter - module base or 0 (all modules)\n"
|
||||||
"There is no return value");
|
"There is no return value");
|
||||||
|
|
||||||
// wrapper for standart python exceptions
|
// wrapper for standart python exceptions
|
||||||
|
193
pykd/symsessioncache.cpp
Normal file
193
pykd/symsessioncache.cpp
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
//
|
||||||
|
// Cache of loaded executable module symbols:
|
||||||
|
// Map: module -> symbol session
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "dbgengine.h"
|
||||||
|
#include "symsessioncache.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class Impl : protected DEBUG_EVENT_CALLBACK {
|
||||||
|
public:
|
||||||
|
Impl();
|
||||||
|
~Impl();
|
||||||
|
|
||||||
|
bool find(const SymCacheModuleKey &cacheKey, SymbolSessionPtr &symSession);
|
||||||
|
|
||||||
|
void insert(ULONG64 modBase, const SymCacheModuleKey &cacheKey, SymbolSessionPtr symSession);
|
||||||
|
|
||||||
|
void erase(const SymCacheModuleKey &cacheKey);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// DEBUG_EVENT_CALLBACK:
|
||||||
|
virtual DEBUG_CALLBACK_RESULT OnBreakpoint( ULONG ) {
|
||||||
|
return DebugCallbackNoChange;
|
||||||
|
}
|
||||||
|
virtual DEBUG_CALLBACK_RESULT OnModuleLoad( ULONG64, const std::string & ) {
|
||||||
|
return DebugCallbackNoChange;
|
||||||
|
}
|
||||||
|
virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64, const std::string & );
|
||||||
|
virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr ) {
|
||||||
|
return DebugCallbackNoChange;
|
||||||
|
}
|
||||||
|
virtual void onExecutionStatusChange( ULONG ) {
|
||||||
|
}
|
||||||
|
virtual void onSymbolsLoaded(ULONG64 modBase) {
|
||||||
|
}
|
||||||
|
virtual void onSymbolsUnloaded(ULONG64 modBase OPTIONAL);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::map< ULONG64, SymCacheModuleKey > Base2Key;
|
||||||
|
Base2Key m_base2Key;
|
||||||
|
boost::recursive_mutex m_base2KeyLock;
|
||||||
|
|
||||||
|
typedef std::map< SymCacheModuleKey, SymbolSessionPtr > Key2Sym;
|
||||||
|
Key2Sym m_key2Sym;
|
||||||
|
boost::recursive_mutex m_key2SymLock;
|
||||||
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Impl::Impl()
|
||||||
|
{
|
||||||
|
eventRegisterCallbacks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
Impl::~Impl()
|
||||||
|
{
|
||||||
|
eventRemoveCallbacks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
DEBUG_CALLBACK_RESULT Impl::OnModuleUnload( ULONG64 modBase, const std::string & )
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock l(m_base2KeyLock);
|
||||||
|
if (modBase)
|
||||||
|
m_base2Key.erase(modBase);
|
||||||
|
else
|
||||||
|
m_base2Key.clear();
|
||||||
|
return DebugCallbackNoChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Impl::onSymbolsUnloaded(ULONG64 modBase)
|
||||||
|
{
|
||||||
|
if (!modBase)
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock l(m_key2SymLock);
|
||||||
|
m_key2Sym.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymCacheModuleKey cacheKey;
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock l(m_base2KeyLock);
|
||||||
|
Base2Key::const_iterator it = m_base2Key.find(modBase);
|
||||||
|
if (it == m_base2Key.end())
|
||||||
|
return;
|
||||||
|
cacheKey = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::recursive_mutex::scoped_lock l(m_key2SymLock);
|
||||||
|
m_key2Sym.erase(cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
Impl &getImpl()
|
||||||
|
{
|
||||||
|
// contruct after DebugEngine
|
||||||
|
static Impl g_Impl;
|
||||||
|
return g_Impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool findSymCacheEntry(const SymCacheModuleKey &cacheKey, SymbolSessionPtr &symSession)
|
||||||
|
{
|
||||||
|
return getImpl().find(cacheKey, symSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Impl::find(const SymCacheModuleKey &cacheKey, SymbolSessionPtr &symSession)
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock l(m_key2SymLock);
|
||||||
|
Key2Sym::const_iterator it = m_key2Sym.find(cacheKey);
|
||||||
|
if (it == m_key2Sym.end())
|
||||||
|
{
|
||||||
|
symSession.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
symSession = it->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void insertSymCacheEntry(ULONG64 modBase, const SymCacheModuleKey &cacheKey, SymbolSessionPtr symSession)
|
||||||
|
{
|
||||||
|
return getImpl().insert(modBase, cacheKey, symSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Impl::insert(ULONG64 modBase, const SymCacheModuleKey &cacheKey, SymbolSessionPtr symSession)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock l(m_base2KeyLock);
|
||||||
|
m_base2Key[modBase] = cacheKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock l(m_key2SymLock);
|
||||||
|
m_key2Sym[cacheKey] = symSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void eraseSymCacheEntry(const SymCacheModuleKey &cacheKey)
|
||||||
|
{
|
||||||
|
return getImpl().erase(cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Impl::erase(const SymCacheModuleKey &cacheKey)
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock l(m_key2SymLock);
|
||||||
|
m_key2Sym.erase(cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void clearSymCache()
|
||||||
|
{
|
||||||
|
return getImpl().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Impl::clear()
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock l(m_key2SymLock);
|
||||||
|
m_key2Sym.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
} // namespace pykd
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
59
pykd/symsessioncache.h
Normal file
59
pykd/symsessioncache.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// Cache of loaded executable module symbols:
|
||||||
|
// Map: module -> symbol session
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "symengine.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct SymCacheModuleKey {
|
||||||
|
std::string name;
|
||||||
|
ULONG size;
|
||||||
|
ULONG timeStamp;
|
||||||
|
ULONG checkSum;
|
||||||
|
|
||||||
|
bool operator < ( const SymCacheModuleKey& key ) const
|
||||||
|
{
|
||||||
|
if ( name < key.name )
|
||||||
|
return true;
|
||||||
|
if ( name > key.name )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( size < key.size )
|
||||||
|
return true;
|
||||||
|
if ( size > key.size )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( timeStamp < key.timeStamp )
|
||||||
|
return true;
|
||||||
|
if ( timeStamp > key.timeStamp )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return checkSum < key.checkSum;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool findSymCacheEntry(const SymCacheModuleKey &cacheKey, SymbolSessionPtr &symSession);
|
||||||
|
|
||||||
|
void insertSymCacheEntry(ULONG64 modBase, const SymCacheModuleKey &cacheKey, SymbolSessionPtr symSession);
|
||||||
|
|
||||||
|
void eraseSymCacheEntry(const SymCacheModuleKey &cacheKey);
|
||||||
|
|
||||||
|
void clearSymCache();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
} // namespace pykd
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
@ -1,12 +1,12 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
#include <boost\algorithm\string\case_conv.hpp>
|
#include <boost\algorithm\string\case_conv.hpp>
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
#include "win/dbgeng.h"
|
#include "win/dbgeng.h"
|
||||||
#include "win/dbgio.h"
|
#include "win/dbgio.h"
|
||||||
#include "dbgexcept.h"
|
#include "dbgexcept.h"
|
||||||
#include "eventhandler.h"
|
#include "eventhandler.h"
|
||||||
|
#include "symengine.h"
|
||||||
|
|
||||||
namespace pykd {
|
namespace pykd {
|
||||||
|
|
||||||
@ -370,310 +370,6 @@ std::string debugCommand( const std::wstring &command )
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ULONG64 findModuleBase( const std::string &moduleName )
|
|
||||||
{
|
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
ULONG64 base;
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &base );
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" );
|
|
||||||
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ULONG64 findModuleBase( ULONG64 offset )
|
|
||||||
{
|
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
ULONG64 base;
|
|
||||||
ULONG moduleIndex;
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetModuleByOffset( offset, 0, &moduleIndex, &base );
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugSymbol::GetModuleByOffset failed" );
|
|
||||||
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ULONG64 findModuleBySymbol( const std::string &symbolName )
|
|
||||||
{
|
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
ULONG64 base;
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetSymbolModule( ( std::string("!") + symbolName ).c_str(), &base );
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
{
|
|
||||||
std::stringstream sstr;
|
|
||||||
sstr << "failed to find module for symbol: " << symbolName;
|
|
||||||
throw SymbolException( sstr.str() );
|
|
||||||
}
|
|
||||||
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
std::string getModuleName( ULONG64 baseOffset )
|
|
||||||
{
|
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
|
|
||||||
char moduleName[0x100];
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetModuleNameString(
|
|
||||||
DEBUG_MODNAME_MODULE,
|
|
||||||
DEBUG_ANY_ID,
|
|
||||||
baseOffset,
|
|
||||||
moduleName,
|
|
||||||
sizeof( moduleName ),
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugSymbol::GetModuleNameString failed" );
|
|
||||||
|
|
||||||
return std::string( moduleName );
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
std::string getModuleImageName( ULONG64 baseOffset )
|
|
||||||
{
|
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
char imageName[0x100];
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetModuleNameString(
|
|
||||||
DEBUG_MODNAME_IMAGE,
|
|
||||||
DEBUG_ANY_ID,
|
|
||||||
baseOffset,
|
|
||||||
imageName,
|
|
||||||
sizeof( imageName ),
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugSymbol::GetModuleNameString failed" );
|
|
||||||
|
|
||||||
return std::string( imageName );
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ULONG getModuleSize( ULONG64 baseOffset )
|
|
||||||
{
|
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
DEBUG_MODULE_PARAMETERS moduleParam = { 0 };
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetModuleParameters( 1, &baseOffset, 0, &moduleParam );
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
|
|
||||||
|
|
||||||
return moduleParam.Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
std::string getModuleSymbolFileName( ULONG64 baseOffset )
|
|
||||||
{
|
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
IMAGEHLP_MODULEW64 moduleInfo = {};
|
|
||||||
|
|
||||||
hres = g_dbgEng->advanced->GetSymbolInformation(
|
|
||||||
DEBUG_SYMINFO_IMAGEHLP_MODULEW64,
|
|
||||||
baseOffset,
|
|
||||||
0,
|
|
||||||
&moduleInfo,
|
|
||||||
sizeof(moduleInfo),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" );
|
|
||||||
|
|
||||||
if (!*moduleInfo.LoadedPdbName)
|
|
||||||
{
|
|
||||||
std::wstringstream sstr;
|
|
||||||
sstr << L"/f \"" << moduleInfo.ImageName << L"\"";
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->ReloadWide( sstr.str().c_str() );
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException("IDebugSymbols::Reload failed" );
|
|
||||||
|
|
||||||
hres = g_dbgEng->advanced->GetSymbolInformation(
|
|
||||||
DEBUG_SYMINFO_IMAGEHLP_MODULEW64,
|
|
||||||
baseOffset,
|
|
||||||
0,
|
|
||||||
&moduleInfo,
|
|
||||||
sizeof(moduleInfo),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" );
|
|
||||||
}
|
|
||||||
|
|
||||||
char pdbName[ 256 ];
|
|
||||||
WideCharToMultiByte( CP_ACP, 0, moduleInfo.LoadedPdbName, 256, pdbName, 256, NULL, NULL );
|
|
||||||
|
|
||||||
return std::string( pdbName );
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ULONG getModuleTimeStamp( ULONG64 baseOffset )
|
|
||||||
{
|
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
DEBUG_MODULE_PARAMETERS moduleParam = { 0 };
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetModuleParameters( 1, &baseOffset, 0, &moduleParam );
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
|
|
||||||
|
|
||||||
return moduleParam.TimeDateStamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ULONG getModuleCheckSum( ULONG64 baseOffset )
|
|
||||||
{
|
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
DEBUG_MODULE_PARAMETERS moduleParam = { 0 };
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetModuleParameters( 1, &baseOffset, 0, &moduleParam );
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
|
|
||||||
|
|
||||||
return moduleParam.Checksum;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void getModuleFileVersion( ULONG64 baseOffset, USHORT &majorHigh, USHORT &majorLow, USHORT &minorHigh, USHORT &minorLow )
|
|
||||||
{
|
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
|
||||||
|
|
||||||
VS_FIXEDFILEINFO fileInfo={};
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetModuleVersionInformation(
|
|
||||||
DEBUG_ANY_ID,
|
|
||||||
baseOffset,
|
|
||||||
"\\",
|
|
||||||
(PVOID)&fileInfo,
|
|
||||||
sizeof(fileInfo),
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugSymbol2::GetModuleVersionInformation failed" );
|
|
||||||
|
|
||||||
majorHigh = HIWORD(fileInfo.dwFileVersionMS);
|
|
||||||
majorLow = LOWORD(fileInfo.dwFileVersionMS);
|
|
||||||
minorHigh = HIWORD(fileInfo.dwFileVersionLS);
|
|
||||||
minorLow = LOWORD(fileInfo.dwFileVersionLS);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
std::string getModuleVersionInfo( ULONG64 baseOffset, const std::string &value )
|
|
||||||
{
|
|
||||||
struct LANGANDCODEPAGE {
|
|
||||||
WORD wLanguage;
|
|
||||||
WORD wCodePage;
|
|
||||||
};
|
|
||||||
|
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
|
|
||||||
ULONG codePagesSize = 0;
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetModuleVersionInformation(
|
|
||||||
DEBUG_ANY_ID,
|
|
||||||
baseOffset,
|
|
||||||
"\\VarFileInfo\\Translation",
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
&codePagesSize );
|
|
||||||
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugSymbol2::GetModuleVersionInformation failed" );
|
|
||||||
|
|
||||||
size_t codePageNum = codePagesSize / sizeof(LANGANDCODEPAGE);
|
|
||||||
|
|
||||||
std::vector<LANGANDCODEPAGE> codePages(codePageNum);
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetModuleVersionInformation(
|
|
||||||
DEBUG_ANY_ID,
|
|
||||||
baseOffset,
|
|
||||||
"\\VarFileInfo\\Translation",
|
|
||||||
&codePages[0],
|
|
||||||
codePagesSize,
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
if ( FAILED( hres ) )
|
|
||||||
throw DbgException( "IDebugSymbol2::GetModuleVersionInformation failed" );
|
|
||||||
|
|
||||||
ULONG productNameLength = 0;
|
|
||||||
|
|
||||||
std::stringstream sstr;
|
|
||||||
sstr << "\\StringFileInfo\\" << std::hex
|
|
||||||
<< std::setw(4) << std::setfill('0') << codePages[0].wLanguage
|
|
||||||
<< std::setw(4) << std::setfill('0') << codePages[0].wCodePage
|
|
||||||
<< "\\" << value;
|
|
||||||
|
|
||||||
ULONG valueLength;
|
|
||||||
|
|
||||||
g_dbgEng->symbols->GetModuleVersionInformation(
|
|
||||||
DEBUG_ANY_ID,
|
|
||||||
baseOffset,
|
|
||||||
sstr.str().c_str(),
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
&valueLength );
|
|
||||||
|
|
||||||
std::vector<char> valueStr(valueLength);
|
|
||||||
|
|
||||||
hres = g_dbgEng->symbols->GetModuleVersionInformation(
|
|
||||||
DEBUG_ANY_ID,
|
|
||||||
baseOffset,
|
|
||||||
sstr.str().c_str(),
|
|
||||||
&valueStr[0],
|
|
||||||
valueLength,
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
if ( hres == S_OK )
|
|
||||||
return std::string( &valueStr[0] );
|
|
||||||
|
|
||||||
return "";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ULONG ptrSize()
|
ULONG ptrSize()
|
||||||
{
|
{
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
@ -1543,6 +1239,35 @@ HRESULT STDMETHODCALLTYPE DebugEngine::ChangeEngineState(
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DebugEngine::ChangeSymbolState(
|
||||||
|
__in ULONG Flags,
|
||||||
|
__in ULONG64 Argument )
|
||||||
|
{
|
||||||
|
HandlerList::iterator it;
|
||||||
|
|
||||||
|
if (Flags & DEBUG_CSS_LOADS)
|
||||||
|
{
|
||||||
|
for ( it = m_handlers.begin(); it != m_handlers.end(); ++it )
|
||||||
|
{
|
||||||
|
PyThread_StateSave pyThreadSave( it->pystate );
|
||||||
|
it->callback->onSymbolsLoaded( Argument );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Flags & DEBUG_CSS_UNLOADS)
|
||||||
|
{
|
||||||
|
for ( it = m_handlers.begin(); it != m_handlers.end(); ++it )
|
||||||
|
{
|
||||||
|
PyThread_StateSave pyThreadSave( it->pystate );
|
||||||
|
it->callback->onSymbolsUnloaded( Argument );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE DebugEngine::StartInput(
|
HRESULT STDMETHODCALLTYPE DebugEngine::StartInput(
|
||||||
__in ULONG BufferSize )
|
__in ULONG BufferSize )
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "dbgexcept.h"
|
#include "dbgexcept.h"
|
||||||
#include "pyaux.h"
|
#include "pyaux.h"
|
||||||
#include "eventhandler.h"
|
#include "eventhandler.h"
|
||||||
|
#include "symsessioncache.h"
|
||||||
|
|
||||||
#include <dbgeng.h>
|
#include <dbgeng.h>
|
||||||
#include <dbghelp.h>
|
#include <dbghelp.h>
|
||||||
@ -15,7 +16,6 @@ namespace pykd {
|
|||||||
class DebugEngine : private DebugBaseEventCallbacks, private IDebugInputCallbacks
|
class DebugEngine : private DebugBaseEventCallbacks, private IDebugInputCallbacks
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct DbgEngBind {
|
struct DbgEngBind {
|
||||||
|
|
||||||
CComQIPtr<IDebugClient4> client;
|
CComQIPtr<IDebugClient4> client;
|
||||||
@ -78,6 +78,7 @@ public:
|
|||||||
*Mask |= DEBUG_EVENT_UNLOAD_MODULE;
|
*Mask |= DEBUG_EVENT_UNLOAD_MODULE;
|
||||||
*Mask |= DEBUG_EVENT_EXCEPTION;
|
*Mask |= DEBUG_EVENT_EXCEPTION;
|
||||||
*Mask |= DEBUG_EVENT_CHANGE_ENGINE_STATE;
|
*Mask |= DEBUG_EVENT_CHANGE_ENGINE_STATE;
|
||||||
|
*Mask |= DEBUG_EVENT_CHANGE_SYMBOL_STATE;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +107,10 @@ public:
|
|||||||
__in ULONG Flags,
|
__in ULONG Flags,
|
||||||
__in ULONG64 Argument );
|
__in ULONG64 Argument );
|
||||||
|
|
||||||
|
STDMETHOD(ChangeSymbolState)(
|
||||||
|
__in ULONG Flags,
|
||||||
|
__in ULONG64 Argument );
|
||||||
|
|
||||||
|
|
||||||
STDMETHOD(StartInput)(
|
STDMETHOD(StartInput)(
|
||||||
__in ULONG BufferSize );
|
__in ULONG BufferSize );
|
||||||
@ -117,12 +122,12 @@ public:
|
|||||||
void registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
void registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||||
void removeCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
void removeCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||||
|
|
||||||
|
|
||||||
DebugEngine() :
|
DebugEngine() :
|
||||||
previousExecutionStatus( DebugStatusNoChange )
|
previousExecutionStatus( DebugStatusNoChange )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::auto_ptr<DbgEngBind> m_bind;
|
std::auto_ptr<DbgEngBind> m_bind;
|
||||||
|
|
||||||
struct DebugEventContext
|
struct DebugEventContext
|
||||||
|
359
pykd/win/dbgmod.cpp
Normal file
359
pykd/win/dbgmod.cpp
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
//
|
||||||
|
// Work with modules
|
||||||
|
//
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "dbgeng.h"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG64 findModuleBase( const std::string &moduleName )
|
||||||
|
{
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
|
HRESULT hres;
|
||||||
|
ULONG64 base;
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &base );
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugSymbol::GetModuleByModuleName failed" );
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG64 findModuleBase( ULONG64 offset )
|
||||||
|
{
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
|
HRESULT hres;
|
||||||
|
ULONG64 base;
|
||||||
|
ULONG moduleIndex;
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetModuleByOffset( offset, 0, &moduleIndex, &base );
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugSymbol::GetModuleByOffset failed" );
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG64 findModuleBySymbol( const std::string &symbolName )
|
||||||
|
{
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
|
HRESULT hres;
|
||||||
|
ULONG64 base;
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetSymbolModule( ( std::string("!") + symbolName ).c_str(), &base );
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
{
|
||||||
|
std::stringstream sstr;
|
||||||
|
sstr << "failed to find module for symbol: " << symbolName;
|
||||||
|
throw SymbolException( sstr.str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::string getModuleNameImpl( ULONG64 baseOffset )
|
||||||
|
{
|
||||||
|
HRESULT hres;
|
||||||
|
|
||||||
|
char moduleName[0x100];
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetModuleNameString(
|
||||||
|
DEBUG_MODNAME_MODULE,
|
||||||
|
DEBUG_ANY_ID,
|
||||||
|
baseOffset,
|
||||||
|
moduleName,
|
||||||
|
sizeof( moduleName ),
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugSymbol::GetModuleNameString failed" );
|
||||||
|
|
||||||
|
return std::string( moduleName );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getModuleName( ULONG64 baseOffset )
|
||||||
|
{
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
|
return getModuleNameImpl( baseOffset );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::string getModuleImageName( ULONG64 baseOffset )
|
||||||
|
{
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
|
HRESULT hres;
|
||||||
|
char imageName[0x100];
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetModuleNameString(
|
||||||
|
DEBUG_MODNAME_IMAGE,
|
||||||
|
DEBUG_ANY_ID,
|
||||||
|
baseOffset,
|
||||||
|
imageName,
|
||||||
|
sizeof( imageName ),
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugSymbol::GetModuleNameString failed" );
|
||||||
|
|
||||||
|
return std::string( imageName );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
ULONG getModuleSizeImpl( ULONG64 baseOffset )
|
||||||
|
{
|
||||||
|
HRESULT hres;
|
||||||
|
DEBUG_MODULE_PARAMETERS moduleParam = { 0 };
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetModuleParameters( 1, &baseOffset, 0, &moduleParam );
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
|
||||||
|
|
||||||
|
return moduleParam.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG getModuleSize( ULONG64 baseOffset )
|
||||||
|
{
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
|
return getModuleSizeImpl( baseOffset );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::string getModuleSymbolFileName( ULONG64 baseOffset )
|
||||||
|
{
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
|
HRESULT hres;
|
||||||
|
IMAGEHLP_MODULEW64 moduleInfo = {};
|
||||||
|
|
||||||
|
hres = g_dbgEng->advanced->GetSymbolInformation(
|
||||||
|
DEBUG_SYMINFO_IMAGEHLP_MODULEW64,
|
||||||
|
baseOffset,
|
||||||
|
0,
|
||||||
|
&moduleInfo,
|
||||||
|
sizeof(moduleInfo),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" );
|
||||||
|
|
||||||
|
if (!*moduleInfo.LoadedPdbName)
|
||||||
|
{
|
||||||
|
std::wstringstream sstr;
|
||||||
|
sstr << L"/f \"" << moduleInfo.ImageName << L"\"";
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->ReloadWide( sstr.str().c_str() );
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException("IDebugSymbols::Reload failed" );
|
||||||
|
|
||||||
|
hres = g_dbgEng->advanced->GetSymbolInformation(
|
||||||
|
DEBUG_SYMINFO_IMAGEHLP_MODULEW64,
|
||||||
|
baseOffset,
|
||||||
|
0,
|
||||||
|
&moduleInfo,
|
||||||
|
sizeof(moduleInfo),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" );
|
||||||
|
}
|
||||||
|
|
||||||
|
char pdbName[ 256 ];
|
||||||
|
WideCharToMultiByte( CP_ACP, 0, moduleInfo.LoadedPdbName, 256, pdbName, 256, NULL, NULL );
|
||||||
|
|
||||||
|
return std::string( pdbName );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace{
|
||||||
|
|
||||||
|
ULONG getModuleTimeStampImpl( ULONG64 baseOffset )
|
||||||
|
{
|
||||||
|
HRESULT hres;
|
||||||
|
DEBUG_MODULE_PARAMETERS moduleParam = { 0 };
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetModuleParameters( 1, &baseOffset, 0, &moduleParam );
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
|
||||||
|
|
||||||
|
return moduleParam.TimeDateStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG getModuleTimeStamp( ULONG64 baseOffset )
|
||||||
|
{
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
|
return getModuleTimeStampImpl( baseOffset );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
ULONG getModuleCheckSumImpl( ULONG64 baseOffset )
|
||||||
|
{
|
||||||
|
HRESULT hres;
|
||||||
|
DEBUG_MODULE_PARAMETERS moduleParam = { 0 };
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetModuleParameters( 1, &baseOffset, 0, &moduleParam );
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugSymbol::GetModuleParameters failed" );
|
||||||
|
|
||||||
|
return moduleParam.Checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG getModuleCheckSum( ULONG64 baseOffset )
|
||||||
|
{
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
|
return getModuleCheckSumImpl( baseOffset );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void getModuleFileVersion( ULONG64 baseOffset, USHORT &majorHigh, USHORT &majorLow, USHORT &minorHigh, USHORT &minorLow )
|
||||||
|
{
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
|
VS_FIXEDFILEINFO fileInfo={};
|
||||||
|
|
||||||
|
HRESULT hres;
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetModuleVersionInformation(
|
||||||
|
DEBUG_ANY_ID,
|
||||||
|
baseOffset,
|
||||||
|
"\\",
|
||||||
|
(PVOID)&fileInfo,
|
||||||
|
sizeof(fileInfo),
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugSymbol2::GetModuleVersionInformation failed" );
|
||||||
|
|
||||||
|
majorHigh = HIWORD(fileInfo.dwFileVersionMS);
|
||||||
|
majorLow = LOWORD(fileInfo.dwFileVersionMS);
|
||||||
|
minorHigh = HIWORD(fileInfo.dwFileVersionLS);
|
||||||
|
minorLow = LOWORD(fileInfo.dwFileVersionLS);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::string getModuleVersionInfo( ULONG64 baseOffset, const std::string &value )
|
||||||
|
{
|
||||||
|
struct LANGANDCODEPAGE {
|
||||||
|
WORD wLanguage;
|
||||||
|
WORD wCodePage;
|
||||||
|
};
|
||||||
|
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
|
HRESULT hres;
|
||||||
|
|
||||||
|
ULONG codePagesSize = 0;
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetModuleVersionInformation(
|
||||||
|
DEBUG_ANY_ID,
|
||||||
|
baseOffset,
|
||||||
|
"\\VarFileInfo\\Translation",
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&codePagesSize );
|
||||||
|
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugSymbol2::GetModuleVersionInformation failed" );
|
||||||
|
|
||||||
|
size_t codePageNum = codePagesSize / sizeof(LANGANDCODEPAGE);
|
||||||
|
|
||||||
|
std::vector<LANGANDCODEPAGE> codePages(codePageNum);
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetModuleVersionInformation(
|
||||||
|
DEBUG_ANY_ID,
|
||||||
|
baseOffset,
|
||||||
|
"\\VarFileInfo\\Translation",
|
||||||
|
&codePages[0],
|
||||||
|
codePagesSize,
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
throw DbgException( "IDebugSymbol2::GetModuleVersionInformation failed" );
|
||||||
|
|
||||||
|
ULONG productNameLength = 0;
|
||||||
|
|
||||||
|
std::stringstream sstr;
|
||||||
|
sstr << "\\StringFileInfo\\" << std::hex
|
||||||
|
<< std::setw(4) << std::setfill('0') << codePages[0].wLanguage
|
||||||
|
<< std::setw(4) << std::setfill('0') << codePages[0].wCodePage
|
||||||
|
<< "\\" << value;
|
||||||
|
|
||||||
|
ULONG valueLength;
|
||||||
|
|
||||||
|
g_dbgEng->symbols->GetModuleVersionInformation(
|
||||||
|
DEBUG_ANY_ID,
|
||||||
|
baseOffset,
|
||||||
|
sstr.str().c_str(),
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&valueLength );
|
||||||
|
|
||||||
|
std::vector<char> valueStr(valueLength);
|
||||||
|
|
||||||
|
hres = g_dbgEng->symbols->GetModuleVersionInformation(
|
||||||
|
DEBUG_ANY_ID,
|
||||||
|
baseOffset,
|
||||||
|
sstr.str().c_str(),
|
||||||
|
&valueStr[0],
|
||||||
|
valueLength,
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
if ( hres == S_OK )
|
||||||
|
return std::string( &valueStr[0] );
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
} // namespace pykd
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
Loading…
Reference in New Issue
Block a user