mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-20 03:23:23 +08:00
[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:
parent
94bcc91f9c
commit
142dd21918
@ -5,6 +5,7 @@ namespace pykd {
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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 );
|
||||
bool isVaValid( ULONG64 addr );
|
||||
bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE );
|
||||
|
100
pykd/dia/diacallback.h
Normal file
100
pykd/dia/diacallback.h
Normal 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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -3,6 +3,8 @@
|
||||
#include "dbghelp.h"
|
||||
#include "dia/diawrapper.h"
|
||||
#include "win/utils.h"
|
||||
#include "dbgengine.h"
|
||||
#include "diacallback.h"
|
||||
|
||||
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;
|
||||
DiaDataSourcePtr dataSource;
|
||||
@ -130,9 +143,9 @@ SymbolSessionPtr loadSymbolFile(const std::string &filePath, ULONGLONG loadBase
|
||||
if ( S_OK != hres )
|
||||
throw DiaException("Call ::CoCreateInstance", hres);
|
||||
|
||||
hres = dataSource->loadDataFromPdb( toWStr(filePath) );
|
||||
hres = LoadDataImpl.load(*dataSource);
|
||||
if ( S_OK != hres )
|
||||
throw DiaException("Call IDiaDataSource::loadDataFromPdb", hres);
|
||||
throw DiaException("Call IDiaDataSource::loadDataXxx", hres);
|
||||
|
||||
DiaSessionPtr _session;
|
||||
hres = dataSource->openSession(&_session);
|
||||
@ -151,6 +164,119 @@ SymbolSessionPtr loadSymbolFile(const std::string &filePath, ULONGLONG loadBase
|
||||
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 )
|
||||
|
@ -22,7 +22,6 @@ Module::Module(const std::string &moduleName )
|
||||
{
|
||||
m_base = findModuleBase( moduleName );
|
||||
m_name = moduleName;
|
||||
m_symfile = getModuleSymbolFileName( m_base );
|
||||
m_imageName = getModuleImageName( m_base );
|
||||
m_timeDataStamp = getModuleTimeStamp( m_base );
|
||||
m_checkSum = getModuleCheckSum( m_base );
|
||||
@ -35,7 +34,6 @@ Module::Module(ULONG64 offset )
|
||||
{
|
||||
m_base = findModuleBase( addr64(offset) );
|
||||
m_name = getModuleName( m_base );
|
||||
m_symfile = getModuleSymbolFileName( m_base );
|
||||
m_imageName = getModuleImageName( m_base );
|
||||
m_timeDataStamp = getModuleTimeStamp( m_base );
|
||||
m_checkSum = getModuleCheckSum( m_base );
|
||||
@ -46,20 +44,15 @@ Module::Module(ULONG64 offset )
|
||||
|
||||
SymbolSessionPtr& Module::getSymSession()
|
||||
{
|
||||
do {
|
||||
|
||||
if ( m_symSession )
|
||||
return m_symSession;
|
||||
|
||||
if ( m_symfile.empty() )
|
||||
break;
|
||||
|
||||
m_symSession = loadSymbolFile( m_symfile, m_base );
|
||||
|
||||
} while( false );
|
||||
m_symSession = loadSymbolFile(m_base, m_imageName, m_symfile);
|
||||
|
||||
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;
|
||||
}
|
||||
@ -75,8 +68,8 @@ SymbolPtr& Module::getSymScope()
|
||||
|
||||
void Module::reloadSymbols()
|
||||
{
|
||||
m_symfile = getModuleSymbolFileName( m_base );
|
||||
m_symSession.reset();
|
||||
getSymSession();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -114,6 +107,8 @@ std::string Module::print()
|
||||
{
|
||||
std::stringstream sstr;
|
||||
|
||||
prepareSymbolFile();
|
||||
|
||||
sstr << "Module: " << m_name << std::endl;
|
||||
sstr << "Start: " << std::hex << m_base << " End: " << getEnd() << " Size: " << m_size << std::endl;
|
||||
sstr << "Image: " << m_imageName << std::endl;
|
||||
@ -248,6 +243,19 @@ std::string Module::getSourceFile( ULONG64 offset )
|
||||
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
|
||||
|
@ -46,7 +46,8 @@ public:
|
||||
return m_size;
|
||||
}
|
||||
|
||||
std::string getSymFile() const {
|
||||
std::string getSymFile() {
|
||||
prepareSymbolFile();
|
||||
return m_symfile;
|
||||
}
|
||||
|
||||
@ -116,6 +117,8 @@ private:
|
||||
|
||||
ULONG getRvaByName(const std::string &symName);
|
||||
|
||||
void prepareSymbolFile();
|
||||
|
||||
std::string m_name;
|
||||
std::string m_imageName;
|
||||
std::string m_symfile;
|
||||
|
@ -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"
|
||||
@ -609,6 +609,10 @@
|
||||
<Filter
|
||||
Name="dia"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\dia\diacallback.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dia\diadata.cpp"
|
||||
>
|
||||
|
@ -172,7 +172,14 @@ public:
|
||||
|
||||
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()
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
offset = addr64NoSafe( offset );
|
||||
@ -81,13 +78,24 @@ void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr )
|
||||
|
||||
DBG_UNREFERENCED_LOCAL_VARIABLE(nextAddress);
|
||||
|
||||
hres = g_dbgEng->dataspace->ReadVirtual( offset, buffer, length, NULL );
|
||||
hres = g_dbgEng->dataspace->ReadVirtual( offset, buffer, length, readed );
|
||||
}
|
||||
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 ) )
|
||||
throw MemoryException( offset, phyAddr );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user