[0.2.x] ~load symbols by RVA-read executable

git-svn-id: https://pykd.svn.codeplex.com/svn@80112 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2012-10-09 07:21:49 +00:00 committed by Mikhail I. Izmestev
parent 94bcc91f9c
commit 142dd21918
8 changed files with 285 additions and 28 deletions

View File

@ -5,6 +5,7 @@ namespace pykd {
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
ULONG64 addr64( ULONG64 offset ); ULONG64 addr64( ULONG64 offset );
HRESULT readMemoryImpl(ULONG64 offset, PVOID buffer, ULONG length, ULONG *readed = NULL, bool phyAddr = false);
void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr = FALSE ); void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr = FALSE );
bool isVaValid( ULONG64 addr ); bool isVaValid( ULONG64 addr );
bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE ); bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE );

100
pykd/dia/diacallback.h Normal file
View File

@ -0,0 +1,100 @@
//
// DIA load callback
//
#pragma once
namespace pykd {
class DiaLoadCallback2 : public IDiaLoadCallback2 {
int m_nRefCount;
std::string *m_openedSymbolFile;
public:
DiaLoadCallback2(std::string *openedSymbolFile = NULL)
: m_nRefCount(1), m_openedSymbolFile(openedSymbolFile)
{
}
ULONG STDMETHODCALLTYPE AddRef() {
m_nRefCount++;
return m_nRefCount;
}
ULONG STDMETHODCALLTYPE Release() {
const int nRefCount = (--m_nRefCount);
if (!nRefCount)
delete this;
return nRefCount;
}
HRESULT STDMETHODCALLTYPE QueryInterface( REFIID rid, void **ppUnk ) {
if ( ppUnk == NULL )
return E_INVALIDARG;
if (rid == __uuidof( IDiaLoadCallback2 ) )
*ppUnk = (IDiaLoadCallback2 *)this;
else if (rid == __uuidof( IDiaLoadCallback ) )
*ppUnk = (IDiaLoadCallback *)this;
else if (rid == __uuidof( IUnknown ) )
*ppUnk = (IUnknown *)this;
else
*ppUnk = NULL;
if ( *ppUnk != NULL ) {
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE NotifyDebugDir(
BOOL fExecutable,
DWORD cbData,
BYTE data[]
)
{
DBG_UNREFERENCED_PARAMETER(fExecutable);
DBG_UNREFERENCED_PARAMETER(cbData);
DBG_UNREFERENCED_PARAMETER(data);
return S_OK;
}
HRESULT STDMETHODCALLTYPE NotifyOpenDBG(
LPCOLESTR dbgPath,
HRESULT resultCode
)
{
if (S_OK == resultCode && m_openedSymbolFile)
*m_openedSymbolFile = autoBstr::asStr((BSTR)dbgPath);
return S_OK;
}
HRESULT STDMETHODCALLTYPE NotifyOpenPDB(
LPCOLESTR pdbPath,
HRESULT resultCode
)
{
if (S_OK == resultCode && m_openedSymbolFile)
*m_openedSymbolFile = autoBstr::asStr((BSTR)pdbPath);
return S_OK;
}
HRESULT STDMETHODCALLTYPE RestrictRegistryAccess() {
return S_OK;
}
HRESULT STDMETHODCALLTYPE RestrictSymbolServerAccess() {
return S_OK;
}
HRESULT STDMETHODCALLTYPE RestrictOriginalPathAccess() {
return S_OK;
}
HRESULT STDMETHODCALLTYPE RestrictReferencePathAccess() {
return S_OK;
}
HRESULT STDMETHODCALLTYPE RestrictDBGAccess() {
return S_OK;
}
HRESULT STDMETHODCALLTYPE RestrictSystemRootAccess() {
return S_OK;
}
};
}

View File

@ -3,6 +3,8 @@
#include "dbghelp.h" #include "dbghelp.h"
#include "dia/diawrapper.h" #include "dia/diawrapper.h"
#include "win/utils.h" #include "win/utils.h"
#include "dbgengine.h"
#include "diacallback.h"
namespace pykd { namespace pykd {
@ -120,7 +122,18 @@ std::string DiaException::makeFullDesc(const std::string &desc, HRESULT hres, ID
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
SymbolSessionPtr loadSymbolFile(const std::string &filePath, ULONGLONG loadBase ) interface IDiaLoadDataImpl
{
virtual ~IDiaLoadDataImpl() {}
virtual HRESULT load(__inout IDiaDataSource &DiaDataSource) = 0;
};
////////////////////////////////////////////////////////////////////////////////
static SymbolSessionPtr loadDebugSymbols(
IDiaLoadDataImpl &LoadDataImpl,
ULONGLONG loadBase
)
{ {
HRESULT hres; HRESULT hres;
DiaDataSourcePtr dataSource; DiaDataSourcePtr dataSource;
@ -130,9 +143,9 @@ SymbolSessionPtr loadSymbolFile(const std::string &filePath, ULONGLONG loadBase
if ( S_OK != hres ) if ( S_OK != hres )
throw DiaException("Call ::CoCreateInstance", hres); throw DiaException("Call ::CoCreateInstance", hres);
hres = dataSource->loadDataFromPdb( toWStr(filePath) ); hres = LoadDataImpl.load(*dataSource);
if ( S_OK != hres ) if ( S_OK != hres )
throw DiaException("Call IDiaDataSource::loadDataFromPdb", hres); throw DiaException("Call IDiaDataSource::loadDataXxx", hres);
DiaSessionPtr _session; DiaSessionPtr _session;
hres = dataSource->openSession(&_session); hres = dataSource->openSession(&_session);
@ -151,6 +164,119 @@ SymbolSessionPtr loadSymbolFile(const std::string &filePath, ULONGLONG loadBase
return SymbolSessionPtr( new DiaSession( _session, _globalScope ) ); return SymbolSessionPtr( new DiaSession( _session, _globalScope ) );
} }
////////////////////////////////////////////////////////////////////////////////
SymbolSessionPtr loadSymbolFile(const std::string &filePath, ULONGLONG loadBase )
{
struct LoadDataFromPdb : IDiaLoadDataImpl, boost::noncopyable
{
const std::string &m_filePath;
LoadDataFromPdb(const std::string &filePath) : m_filePath(filePath) {}
virtual HRESULT load(__inout IDiaDataSource &dataSource) override
{
return dataSource.loadDataFromPdb( toWStr(m_filePath) );
}
};
LoadDataFromPdb loadDataFromPdb(filePath);
return loadDebugSymbols(loadDataFromPdb, loadBase);
}
//////////////////////////////////////////////////////////////////////////////////
SymbolSessionPtr loadSymbolFile(
__in ULONGLONG loadBase,
__in const std::string &executable,
__out std::string &loadedSymbolFile,
__in_opt std::string symbolSearchPath /*= std::string()*/
)
{
if (symbolSearchPath.empty())
symbolSearchPath = getSymbolPath();
class ReadExeAtRVACallback : public IDiaReadExeAtRVACallback
{
ULONGLONG m_loadBase;
int m_nRefCount;
CComPtr< IDiaLoadCallback2 > m_diaLoadCallback2;
public:
ReadExeAtRVACallback(ULONGLONG loadBase, std::string &openedSymbolFile)
: m_loadBase(loadBase), m_nRefCount(1), m_diaLoadCallback2(new DiaLoadCallback2(&openedSymbolFile))
{
}
ULONG STDMETHODCALLTYPE AddRef() {
m_nRefCount++;
return m_nRefCount;
}
ULONG STDMETHODCALLTYPE Release() {
const int nRefCount = (--m_nRefCount);
if (!nRefCount)
delete this;
return nRefCount;
}
HRESULT STDMETHODCALLTYPE QueryInterface( REFIID rid, void **ppUnk ) {
if ( ppUnk == NULL )
return E_INVALIDARG;
if (rid == __uuidof(IDiaReadExeAtRVACallback))
{
*ppUnk = this;
return S_OK;
}
return m_diaLoadCallback2->QueryInterface(rid, ppUnk);
}
virtual HRESULT STDMETHODCALLTYPE ReadExecutableAtRVA(
/* [in] */ DWORD relativeVirtualAddress,
/* [in] */ DWORD cbData,
/* [out] */ DWORD *pcbData,
/* [size_is][out] */ BYTE *pbData
) override
{
return
readMemoryImpl(
m_loadBase + relativeVirtualAddress,
pbData,
cbData,
pcbData);
}
};
struct LoadDataForExeByRva : IDiaLoadDataImpl, boost::noncopyable
{
ULONGLONG m_loadBase;
const std::string &m_executable;
const std::string &m_symbolSearchPath;
std::string m_openedSymbolFile;
LoadDataForExeByRva(ULONGLONG loadBase, const std::string &executable, std::string symbolSearchPath)
: m_loadBase(loadBase), m_executable(executable), m_symbolSearchPath(symbolSearchPath)
{
}
HRESULT STDMETHODCALLTYPE load(__inout IDiaDataSource &dataSource) override
{
CComPtr< IUnknown > readExeAtRVACallback(new ReadExeAtRVACallback(m_loadBase, m_openedSymbolFile) );
return
dataSource.loadDataForExe(
toWStr(m_executable),
toWStr(m_symbolSearchPath),
readExeAtRVACallback);
}
};
LoadDataForExeByRva loadDataForExeByRva(loadBase, executable, symbolSearchPath);
SymbolSessionPtr symSession = loadDebugSymbols(loadDataForExeByRva, loadBase);
loadedSymbolFile = loadDataForExeByRva.m_openedSymbolFile;
return symSession;
}
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
std::string getBasicTypeName( ULONG basicType ) std::string getBasicTypeName( ULONG basicType )

View File

@ -22,7 +22,6 @@ Module::Module(const std::string &moduleName )
{ {
m_base = findModuleBase( moduleName ); m_base = findModuleBase( moduleName );
m_name = moduleName; m_name = moduleName;
m_symfile = getModuleSymbolFileName( m_base );
m_imageName = getModuleImageName( m_base ); m_imageName = getModuleImageName( m_base );
m_timeDataStamp = getModuleTimeStamp( m_base ); m_timeDataStamp = getModuleTimeStamp( m_base );
m_checkSum = getModuleCheckSum( m_base ); m_checkSum = getModuleCheckSum( m_base );
@ -35,7 +34,6 @@ Module::Module(ULONG64 offset )
{ {
m_base = findModuleBase( addr64(offset) ); m_base = findModuleBase( addr64(offset) );
m_name = getModuleName( m_base ); m_name = getModuleName( m_base );
m_symfile = getModuleSymbolFileName( m_base );
m_imageName = getModuleImageName( m_base ); m_imageName = getModuleImageName( m_base );
m_timeDataStamp = getModuleTimeStamp( m_base ); m_timeDataStamp = getModuleTimeStamp( m_base );
m_checkSum = getModuleCheckSum( m_base ); m_checkSum = getModuleCheckSum( m_base );
@ -46,20 +44,15 @@ Module::Module(ULONG64 offset )
SymbolSessionPtr& Module::getSymSession() SymbolSessionPtr& Module::getSymSession()
{ {
do { m_symSession = loadSymbolFile(m_base, m_imageName, m_symfile);
if ( m_symSession )
return m_symSession;
if ( m_symfile.empty() )
break;
m_symSession = loadSymbolFile( m_symfile, m_base );
} while( false );
if ( !m_symSession ) if ( !m_symSession )
throw SymbolException( "failed to find symbol file" ); {
m_symfile = getModuleSymbolFileName(m_base);
m_symSession = loadSymbolFile(m_symfile, m_base);
if (m_symSession)
throw SymbolException( "failed to load symbol file" );
}
return m_symSession; return m_symSession;
} }
@ -75,8 +68,8 @@ SymbolPtr& Module::getSymScope()
void Module::reloadSymbols() void Module::reloadSymbols()
{ {
m_symfile = getModuleSymbolFileName( m_base );
m_symSession.reset(); m_symSession.reset();
getSymSession();
} }
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
@ -114,6 +107,8 @@ std::string Module::print()
{ {
std::stringstream sstr; std::stringstream sstr;
prepareSymbolFile();
sstr << "Module: " << m_name << std::endl; sstr << "Module: " << m_name << std::endl;
sstr << "Start: " << std::hex << m_base << " End: " << getEnd() << " Size: " << m_size << std::endl; sstr << "Start: " << std::hex << m_base << " End: " << getEnd() << " Size: " << m_size << std::endl;
sstr << "Image: " << m_imageName << std::endl; sstr << "Image: " << m_imageName << std::endl;
@ -248,6 +243,19 @@ std::string Module::getSourceFile( ULONG64 offset )
return fileName; return fileName;
} }
void Module::prepareSymbolFile()
{
try
{
// load symbols for modules, if need
getSymSession();
}
catch (const SymbolException &e)
{
DBG_UNREFERENCED_LOCAL_VARIABLE(e);
}
}
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
}; // end of namespace pykd }; // end of namespace pykd

View File

@ -46,7 +46,8 @@ public:
return m_size; return m_size;
} }
std::string getSymFile() const { std::string getSymFile() {
prepareSymbolFile();
return m_symfile; return m_symfile;
} }
@ -116,6 +117,8 @@ private:
ULONG getRvaByName(const std::string &symName); ULONG getRvaByName(const std::string &symName);
void prepareSymbolFile();
std::string m_name; std::string m_name;
std::string m_imageName; std::string m_imageName;
std::string m_symfile; std::string m_symfile;

View File

@ -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"
@ -609,6 +609,10 @@
<Filter <Filter
Name="dia" Name="dia"
> >
<File
RelativePath=".\dia\diacallback.h"
>
</File>
<File <File
RelativePath=".\dia\diadata.cpp" RelativePath=".\dia\diadata.cpp"
> >

View File

@ -172,7 +172,14 @@ public:
std::string getBasicTypeName( ULONG basicType ); std::string getBasicTypeName( ULONG basicType );
SymbolSessionPtr loadSymbolFile(const std::string &filePath, ULONGLONG loadBase = 0); SymbolSessionPtr loadSymbolFile(const std::string &filePath, ULONGLONG loadBase = 0);
SymbolSessionPtr loadSymbolFile(
__in ULONGLONG loadBase,
__in const std::string &executable,
__out std::string &loadedSymbolFile,
__in_opt std::string symbolSearchPath = std::string()
);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -65,12 +65,9 @@ bool isVaValid( ULONG64 addr )
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr ) HRESULT readMemoryImpl(ULONG64 offset, PVOID buffer, ULONG length, ULONG *readed, bool phyAddr)
{ {
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); HRESULT hres;
HRESULT hres;
if ( phyAddr == false ) if ( phyAddr == false )
{ {
offset = addr64NoSafe( offset ); offset = addr64NoSafe( offset );
@ -81,13 +78,24 @@ void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr )
DBG_UNREFERENCED_LOCAL_VARIABLE(nextAddress); DBG_UNREFERENCED_LOCAL_VARIABLE(nextAddress);
hres = g_dbgEng->dataspace->ReadVirtual( offset, buffer, length, NULL ); hres = g_dbgEng->dataspace->ReadVirtual( offset, buffer, length, readed );
} }
else else
{ {
hres = g_dbgEng->dataspace->ReadPhysical( offset, buffer, length, NULL ); hres = g_dbgEng->dataspace->ReadPhysical( offset, buffer, length, readed );
} }
return hres;
}
///////////////////////////////////////////////////////////////////////////////////
void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr )
{
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
HRESULT hres = readMemoryImpl(offset, buffer, length, NULL, phyAddr);
if ( FAILED( hres ) ) if ( FAILED( hres ) )
throw MemoryException( offset, phyAddr ); throw MemoryException( offset, phyAddr );
} }