mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-19 19:13:22 +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 OnException( ExceptionInfoPtr exceptInfo ) = 0;
|
||||
virtual void onExecutionStatusChange( ULONG executionStatus ) = 0;
|
||||
virtual void onSymbolsLoaded(ULONG64 modBase) = 0;
|
||||
virtual void onSymbolsUnloaded(ULONG64 modBase OPTIONAL) = 0;
|
||||
};
|
||||
|
||||
enum EVENT_TYPE {
|
||||
|
@ -27,6 +27,8 @@ private:
|
||||
virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64 offset, const std::string &name ) = 0;
|
||||
virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) = 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 );
|
||||
}
|
||||
|
||||
virtual void onSymbolsLoaded(ULONG64 modBase) {
|
||||
void_handler("onSymbolsLoaded", modBase);
|
||||
}
|
||||
|
||||
virtual void onSymbolsUnloaded(ULONG64 modBase OPTIONAL) {
|
||||
void_handler("onSymbolsUnloaded", modBase);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
@ -3,15 +3,12 @@
|
||||
#include "module.h"
|
||||
#include "dbgexcept.h"
|
||||
#include "vardata.h"
|
||||
#include "symsessioncache.h"
|
||||
|
||||
namespace pykd {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Module::SymbolSessionCache Module::m_symSessionCache;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ModulePtr Module::loadModuleByName( const std::string &moduleName )
|
||||
{
|
||||
return ModulePtr( new Module( moduleName ) );
|
||||
@ -55,11 +52,9 @@ SymbolSessionPtr& Module::getSymSession()
|
||||
if (m_symSession)
|
||||
return m_symSession;
|
||||
|
||||
SymbolMapKey cacheKey = { m_name, m_size, m_timeDataStamp, m_checkSum };
|
||||
SymbolSessionCache::iterator found = m_symSessionCache.find( cacheKey );
|
||||
if ( found != m_symSessionCache.end() )
|
||||
SymCacheModuleKey cacheKey = { m_name, m_size, m_timeDataStamp, m_checkSum };
|
||||
if ( findSymCacheEntry( cacheKey, m_symSession ) )
|
||||
{
|
||||
m_symSession = found->second;
|
||||
if ( !m_symSession )
|
||||
throw SymbolException( "failed to load symbol file" );
|
||||
|
||||
@ -71,7 +66,7 @@ SymbolSessionPtr& Module::getSymSession()
|
||||
m_symSession = loadSymbolFile( m_base, m_imageName);
|
||||
if (m_symSession)
|
||||
{
|
||||
m_symSessionCache.insert( std::make_pair( cacheKey, m_symSession ) );
|
||||
insertSymCacheEntry( m_base, cacheKey, m_symSession );
|
||||
return m_symSession;
|
||||
}
|
||||
}
|
||||
@ -90,7 +85,7 @@ SymbolSessionPtr& Module::getSymSession()
|
||||
|
||||
if (m_symSession)
|
||||
{
|
||||
m_symSessionCache.insert( std::make_pair( cacheKey, m_symSession ) );
|
||||
insertSymCacheEntry( m_base, cacheKey, m_symSession );
|
||||
return m_symSession;
|
||||
}
|
||||
}
|
||||
@ -102,15 +97,14 @@ SymbolSessionPtr& Module::getSymSession()
|
||||
m_symSession = loadSymbolFromExports(m_base);
|
||||
if (m_symSession)
|
||||
{
|
||||
m_symSessionCache.insert( std::make_pair( cacheKey, m_symSession ) );
|
||||
insertSymCacheEntry( m_base, cacheKey, m_symSession );
|
||||
return m_symSession;
|
||||
}
|
||||
}
|
||||
catch(const DbgException&)
|
||||
{}
|
||||
|
||||
m_symSessionCache.insert( std::make_pair( cacheKey, SymbolSessionPtr() ) );
|
||||
|
||||
insertSymCacheEntry( m_base, cacheKey, SymbolSessionPtr() );
|
||||
throw SymbolException( "failed to load symbol file" );
|
||||
}
|
||||
|
||||
@ -137,8 +131,8 @@ SymbolPtr Module::getSymScope()
|
||||
|
||||
void Module::reloadSymbols()
|
||||
{
|
||||
SymbolMapKey cacheKey = { m_name, m_size, m_timeDataStamp, m_checkSum };
|
||||
m_symSessionCache.erase( cacheKey );
|
||||
SymCacheModuleKey cacheKey = { m_name, m_size, m_timeDataStamp, m_checkSum };
|
||||
eraseSymCacheEntry( cacheKey );
|
||||
|
||||
m_symSession.reset();
|
||||
getSymSession();
|
||||
|
@ -24,40 +24,6 @@ public:
|
||||
static
|
||||
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:
|
||||
|
||||
Module(const std::string &name );
|
||||
|
@ -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"
|
||||
@ -441,6 +441,10 @@
|
||||
RelativePath=".\stkframe.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\symsessioncache.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\typedvar.cpp"
|
||||
>
|
||||
@ -527,6 +531,10 @@
|
||||
RelativePath=".\symengine.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\symsessioncache.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\typedvar.h"
|
||||
>
|
||||
@ -581,6 +589,10 @@
|
||||
RelativePath=".\win\dbgio.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\win\dbgmod.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\win\lastevent.cpp"
|
||||
>
|
||||
|
@ -611,9 +611,15 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
.def( "onException", &EventHandlerWrap::OnException,
|
||||
"Triggered exception event. Parameter - exceptionInfo\n"
|
||||
"For ignore event method must return eventResult.noChange" )
|
||||
.def( "onExecutionStatusChange", &EventHandlerWrap::onExecutionStatusChange,
|
||||
.def( "onExecutionStatusChange", &EventHandlerWrap::onExecutionStatusChange,
|
||||
"Triggered execution status changed. Parameter - execution status.\n"
|
||||
"There is no return value" );
|
||||
"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");
|
||||
|
||||
// wrapper for standart python exceptions
|
||||
python::register_exception_translator<PyException>( &PyException::exceptionTranslate );
|
||||
|
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 <boost\algorithm\string\case_conv.hpp>
|
||||
#include <iomanip>
|
||||
|
||||
#include "win/dbgeng.h"
|
||||
#include "win/dbgio.h"
|
||||
#include "dbgexcept.h"
|
||||
#include "eventhandler.h"
|
||||
#include "symengine.h"
|
||||
|
||||
namespace pykd {
|
||||
|
||||
@ -346,7 +346,7 @@ ULONG64 evaluate( const std::wstring &expression )
|
||||
|
||||
if ( remainderIndex == expression.length() )
|
||||
value = debugValue.I32;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -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()
|
||||
{
|
||||
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(
|
||||
__in ULONG BufferSize )
|
||||
{
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "dbgexcept.h"
|
||||
#include "pyaux.h"
|
||||
#include "eventhandler.h"
|
||||
#include "symsessioncache.h"
|
||||
|
||||
#include <dbgeng.h>
|
||||
#include <dbghelp.h>
|
||||
@ -15,7 +16,6 @@ namespace pykd {
|
||||
class DebugEngine : private DebugBaseEventCallbacks, private IDebugInputCallbacks
|
||||
{
|
||||
public:
|
||||
|
||||
struct DbgEngBind {
|
||||
|
||||
CComQIPtr<IDebugClient4> client;
|
||||
@ -78,6 +78,7 @@ public:
|
||||
*Mask |= DEBUG_EVENT_UNLOAD_MODULE;
|
||||
*Mask |= DEBUG_EVENT_EXCEPTION;
|
||||
*Mask |= DEBUG_EVENT_CHANGE_ENGINE_STATE;
|
||||
*Mask |= DEBUG_EVENT_CHANGE_SYMBOL_STATE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -106,6 +107,10 @@ public:
|
||||
__in ULONG Flags,
|
||||
__in ULONG64 Argument );
|
||||
|
||||
STDMETHOD(ChangeSymbolState)(
|
||||
__in ULONG Flags,
|
||||
__in ULONG64 Argument );
|
||||
|
||||
|
||||
STDMETHOD(StartInput)(
|
||||
__in ULONG BufferSize );
|
||||
@ -117,12 +122,12 @@ public:
|
||||
void registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||
void removeCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||
|
||||
|
||||
DebugEngine() :
|
||||
previousExecutionStatus( DebugStatusNoChange )
|
||||
{}
|
||||
|
||||
private:
|
||||
|
||||
std::auto_ptr<DbgEngBind> m_bind;
|
||||
|
||||
struct DebugEventContext
|
||||
@ -150,4 +155,4 @@ extern DebugEngine g_dbgEng;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
};
|
||||
};
|
||||
|
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