diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index fe8c167..4cfabcb 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -89,6 +89,8 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( getLocals_, getLocals, 0, 1 ); BOOST_PYTHON_FUNCTION_OVERLOADS( setSoftwareBp_, setSoftwareBp, 1, 2 ); BOOST_PYTHON_FUNCTION_OVERLOADS( setHardwareBp_, setHardwareBp, 3, 4 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( pyDia_GlobalScope_loadExe, pyDia::GlobalScope::loadExe, 1, 2 ); + BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadChars, DebugClient::loadChars, 2, 3 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadWChars, DebugClient::loadWChars, 2, 3 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadBytes, DebugClient::loadBytes, 2, 3 ); @@ -672,6 +674,8 @@ BOOST_PYTHON_MODULE( pykd ) python::def( "diaLoadPdb", &pyDia::GlobalScope::loadPdb, "Open pdb file for querying debug symbols. Return DiaSymbol of global scope"); + python::def( "diaLoadExe", &pyDia::GlobalScope::loadExe, pyDia_GlobalScope_loadExe( python::args( "fileName", "searchPath" ) , + "Load the debug symbols associated with the executable file. Return DiaSymbol of global scope") ); python::class_( "DiaSymbol", "class wrapper for MS DIA Symbol", python::no_init ) diff --git a/pykd/diacallback.h b/pykd/diacallback.h new file mode 100644 index 0000000..8386ba5 --- /dev/null +++ b/pykd/diacallback.h @@ -0,0 +1,93 @@ +// +// DIA load callback +// + +#pragma once + +namespace pyDia { + +class LoadCallback : public IDiaLoadCallback2 { + int m_nRefCount; +public: + LoadCallback() : m_nRefCount(1) {} + + ULONG STDMETHODCALLTYPE AddRef() { + m_nRefCount++; + return m_nRefCount; + } + ULONG STDMETHODCALLTYPE Release() { + if ( (--m_nRefCount) == 0 ) + delete this; + return m_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 + ) + { + DBG_UNREFERENCED_PARAMETER(dbgPath); + DBG_UNREFERENCED_PARAMETER(resultCode); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE NotifyOpenPDB( + LPCOLESTR pdbPath, + HRESULT resultCode + ) + { + DBG_UNREFERENCED_PARAMETER(pdbPath); + DBG_UNREFERENCED_PARAMETER(resultCode); + 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; + } +}; + +} diff --git a/pykd/diawrapper.cpp b/pykd/diawrapper.cpp index bf9e0fd..a43c7e9 100644 --- a/pykd/diawrapper.cpp +++ b/pykd/diawrapper.cpp @@ -2,6 +2,7 @@ #include "stdafx.h" #include "diawrapper.h" +#include "diacallback.h" #include "utils.h" namespace pyDia { @@ -386,6 +387,57 @@ GlobalScope::GlobalScope( //////////////////////////////////////////////////////////////////////////////// GlobalScopePtr GlobalScope::loadPdb(const std::string &filePath) +{ + class CLoaderFromPdb : public IScopeDataLoader { + public: + CLoaderFromPdb(const std::string &filePath) : m_filePath(filePath) {} + + virtual void loadData(IDiaDataSource *_scope) override { + HRESULT hres = _scope->loadDataFromPdb( toWStr(m_filePath) ); + if ( S_OK != hres ) + throw Exception("Call IDiaDataSource::loadDataFromPdb", hres); + } + + private: + const std::string &m_filePath; + } loaderFromPdb(filePath); + + return loadImpl(loaderFromPdb); +} + +//////////////////////////////////////////////////////////////////////////////// + +GlobalScopePtr GlobalScope::loadExe(const std::string &filePath, PCSTR searchPath /*= NULL*/) +{ + if (!searchPath) + searchPath = "SRV**\\\\symbols\\symbols"; + + class CLoaderForExe : public IScopeDataLoader { + public: + CLoaderForExe(const std::string &filePath, PCSTR searchPath) + : m_filePath(filePath), m_searchPath(searchPath) + { + } + + virtual void loadData(IDiaDataSource *_scope) override { + LoadCallback loadCallback; + HRESULT hres = + _scope->loadDataForExe( toWStr(m_filePath), toWStr(m_searchPath), &loadCallback ); + if ( S_OK != hres ) + throw Exception("Call IDiaDataSource::loadDataForExe", hres); + } + + private: + const std::string &m_filePath; + const std::string m_searchPath; + } loaderForExe(filePath, searchPath); + + return loadImpl(loaderForExe); +} + +//////////////////////////////////////////////////////////////////////////////// + +GlobalScopePtr GlobalScope::loadImpl(IScopeDataLoader &ScopeDataLoader) { DiaDataSourcePtr _scope; @@ -394,9 +446,7 @@ GlobalScopePtr GlobalScope::loadPdb(const std::string &filePath) if ( S_OK != hres ) throw Exception("Call ::CoCreateInstance", hres); - hres = _scope->loadDataFromPdb( toWStr(filePath) ); - if ( S_OK != hres ) - throw Exception("Call IDiaDataSource::loadDataFromPdb", hres); + ScopeDataLoader.loadData(_scope); DiaSessionPtr _session; hres = _scope->openSession(&_session); diff --git a/pykd/diawrapper.h b/pykd/diawrapper.h index e0fc09c..da49df3 100644 --- a/pykd/diawrapper.h +++ b/pykd/diawrapper.h @@ -232,6 +232,7 @@ public: // GlobalScope factory static GlobalScopePtr loadPdb(const std::string &filePath); + static GlobalScopePtr loadExe(const std::string &filePath, PCSTR searchPath = NULL); // RVA -> Symbol python::tuple findByRva( @@ -253,6 +254,11 @@ public: SymbolPtr getSymbolById(ULONG symId); private: + interface IScopeDataLoader { + virtual ~IScopeDataLoader() {} + virtual void loadData(IDiaDataSource *_scope) = 0; + }; + static GlobalScopePtr loadImpl(IScopeDataLoader &ScopeDataLoader); GlobalScope( __inout DiaDataSourcePtr &_scope, diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index 30db6c7..d4f0bac 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -543,6 +543,10 @@ RelativePath=".\defctxi386.h" > + +