[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:
SND\EreTIk_cp 2013-03-28 18:28:42 +00:00 committed by Mikhail I. Izmestev
parent 27fd6ad3b7
commit 342792bc91
11 changed files with 691 additions and 361 deletions

View File

@ -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 {

View File

@ -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:

View File

@ -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();

View File

@ -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 );

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"
@ -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"
>

View File

@ -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
View 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
View 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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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 )
{

View File

@ -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
View 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
///////////////////////////////////////////////////////////////////////////////