From f0127ccff35d14f17bb99a6155a1caa0877eb3c2 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 21 Sep 2011 15:53:02 +0000 Subject: [PATCH] [0.1.x] updated : Module class ( Class representing executable module ) git-svn-id: https://pykd.svn.codeplex.com/svn@69930 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgclient.cpp | 28 +++++++++- pykd/dbgclient.h | 21 +++++++ pykd/dbgexcept.cpp | 5 ++ pykd/dbgexcept.h | 11 ++++ pykd/dbgext.cpp | 47 ++++++++++++---- pykd/dbgmem.cpp | 49 +++++++++++++++++ pykd/dbgmem.h | 16 ++++++ pykd/dbgobj.h | 5 ++ pykd/module.cpp | 110 ++++++++++++++++++++++++++++++++++++- pykd/module.h | 13 +++-- pykd/pykd_2008.vcproj | 8 +++ test/scripts/moduletest.py | 18 ++++++ test/scripts/pykdtest.py | 10 ++-- 13 files changed, 317 insertions(+), 24 deletions(-) diff --git a/pykd/dbgclient.cpp b/pykd/dbgclient.cpp index 4a6d0c8..ebe09fe 100644 --- a/pykd/dbgclient.cpp +++ b/pykd/dbgclient.cpp @@ -3,7 +3,29 @@ #include "dbgclient.h" #include -using namespace pykd; + +namespace pykd { + +/////////////////////////////////////////////////////////////////////////////////// + +DebugClient primaryClient; +DebugClient *g_dbgClient = &primaryClient; + +void loadDump( const std::wstring &fileName ) { + g_dbgClient->loadDump( fileName ); +} + +void startProcess( const std::wstring &processName ) { + g_dbgClient->startProcess( processName ); +} + +void attachProcess( ULONG processId ) { + g_dbgClient->attachProcess( processId ); +} + +void attachKernel( const std::wstring ¶m ) { + g_dbgClient->attachKernel( param ); +} /////////////////////////////////////////////////////////////////////////////////// @@ -89,4 +111,6 @@ void DebugClient::attachKernel( const std::wstring ¶m ) throw DbgException( "IDebugClient5::AttachKernelWide failed" ); } -/////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file +/////////////////////////////////////////////////////////////////////////////////// + +}; // end of namespace pykd \ No newline at end of file diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index 04e6222..8e4c61d 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -33,6 +33,11 @@ public: return Module( m_client, moduleName ); } + Module findModule( ULONG64 offset ) { + return Module( m_client, offset ); + } + + ULONG64 addr64( ULONG64 addr ); private: @@ -43,6 +48,22 @@ private: ///////////////////////////////////////////////////////////////////////////////// +extern DebugClient *g_dbgClient; + +void loadDump( const std::wstring &fileName ); + +void startProcess( const std::wstring &processName ); + +void attachProcess( ULONG processId ); + +void attachKernel( const std::wstring ¶m ); + +Module loadModule( const std::string &moduleName ); + +Module findModule( ULONG64 offset ); + +///////////////////////////////////////////////////////////////////////////////// + }; // namespace pykd diff --git a/pykd/dbgexcept.cpp b/pykd/dbgexcept.cpp index 470b47b..63c1818 100644 --- a/pykd/dbgexcept.cpp +++ b/pykd/dbgexcept.cpp @@ -19,6 +19,11 @@ void DbgException::exceptionTranslate( const DbgException &e ) ///////////////////////////////////////////////////////////////////////////////// + + + + + //PyObject *eventExceptionType = NULL; //PyObject *typeExceptionType = NULL; //PyObject *memoryExceptionType = NULL; diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h index 5868049..02ce927 100644 --- a/pykd/dbgexcept.h +++ b/pykd/dbgexcept.h @@ -42,6 +42,17 @@ private: /////////////////////////////////////////////////////////////////////////////////// + + + + + + + + + + + // //class WaitEventException : public DbgException //{ diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 798140b..923fe67 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -89,11 +89,31 @@ static python::dict genDict(const pyDia::Symbol::ValueNameEntry srcValues[], siz BOOST_PYTHON_MODULE( pykd ) { python::class_("dbgClient", "Class representing a debugging session" ) - .def( "loadDump", &pykd::DebugClient::loadDump, "Load crash dump" ) - .def( "startProcess", &pykd::DebugClient::startProcess, "Start process for debugging" ) - .def( "attachProcess", &pykd::DebugClient::attachProcess, "Attach debugger to a exsisting process" ) - .def( "attachKernel", &pykd::DebugClient::attachKernel, "Attach debugger to a target's kernel" ) - .def( "loadModule", &pykd::DebugClient::loadModule, "Create instance of Module class" ); + .def( "loadDump", &pykd::DebugClient::loadDump, + "Load crash dump" ) + .def( "startProcess", &pykd::DebugClient::startProcess, + "Start process for debugging" ) + .def( "attachProcess", &pykd::DebugClient::attachProcess, + "Attach debugger to a exsisting process" ) + .def( "attachKernel", &pykd::DebugClient::attachKernel, + "Attach debugger to a target's kernel" ) + .def( "loadModule", &pykd::DebugClient::loadModule, + "Return instance of Module class" ) + .def( "findModule", &pykd::DebugClient::findModule, + "Return instance of the Module class which posseses specified address" ); + + boost::python::def( "loadDump", &loadDump, + "Load crash dump (only for console)"); + boost::python::def( "startProcess", &startProcess, + "Start process for debugging (only for console)"); + boost::python::def( "attachProcess", &attachProcess, + "Attach debugger to a exsisting process" ); + boost::python::def( "attachKernel", &attachKernel, + "Attach debugger to a kernel target" ); + boost::python::def( "loadModule", &loadModule, + "Return instance of Module class" ); + boost::python::def( "findModule", &findModule, + "Return instance of the Module class which posseses specified address" ); python::class_("module", "Class representing executable module", python::no_init ) .def("begin", &pykd::Module::getBase, @@ -103,7 +123,11 @@ BOOST_PYTHON_MODULE( pykd ) .def("size", &pykd::Module::getSize, "Return size of the module" ) .def("name", &pykd::Module::getName, - "Return name of the module" ); + "Return name of the module" ) + .def("pdb", &pykd::Module::getPdbName, + "Return the full path to the module's pdb file ( symbol information )" ) + .def("reload", &pykd::Module::reloadSymbols, + "(Re)load symbols for the module" ); python::def( "diaOpenPdb", &pyDia::GlobalScope::openPdb, "Open pdb file for quering debug symbols. Return DiaSymbol of global scope"); @@ -224,16 +248,19 @@ BOOST_PYTHON_MODULE( pykd ) genDict(pyDia::Symbol::basicTypeName, pyDia::Symbol::cntBasicTypeName); // exception: + // base exception - python::class_ dbgExceptionClass( "BaseException", + python::class_ dbgExceptionClass( "BaseException", "Pykd base exception class", python::no_init ); dbgExceptionClass .def( python::init( python::args("desc"), "constructor" ) ) - .def( "desc", &DbgException::getDesc, + .def( "desc", &pykd::DbgException::getDesc, "Get exception description" ) - .def( "__str__", &DbgException::print); - DbgException::setTypeObject( dbgExceptionClass.ptr() ); + .def( "__str__", &pykd::DbgException::print); + pykd::DbgException::setTypeObject( dbgExceptionClass.ptr() ); + boost::python::register_exception_translator( + &pykd::DbgException::exceptionTranslate ); // DIA exceptions python::class_ > diaException( diff --git a/pykd/dbgmem.cpp b/pykd/dbgmem.cpp index 52561dc..719791d 100644 --- a/pykd/dbgmem.cpp +++ b/pykd/dbgmem.cpp @@ -1,5 +1,54 @@ #include "stdafx.h" +#include "dbgclient.h" +#include "dbgexcept.h" + +namespace pykd { + +///////////////////////////////////////////////////////////////////////////////////// + +ULONG64 +DebugClient::addr64( ULONG64 addr) +{ + HRESULT hres; + + ULONG processorMode; + hres = m_control->GetActualProcessorType( &processorMode ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetEffectiveProcessorType failed" ); + + switch( processorMode ) + { + case IMAGE_FILE_MACHINE_I386: + if ( *( (ULONG*)&addr + 1 ) == 0 ) + return (ULONG64)(LONG)addr; + + case IMAGE_FILE_MACHINE_AMD64: + break; + + default: + throw DbgException( "Unknown processor type" ); + break; + } + + return addr; +} + +ULONG64 +addr64( ULONG64 addr) +{ + return g_dbgClient->addr64( addr ); +} + +///////////////////////////////////////////////////////////////////////////////////// + +}; // end of pykd + + + + + + //#include // //#include "dbgext.h" diff --git a/pykd/dbgmem.h b/pykd/dbgmem.h index 4d62b88..5927204 100644 --- a/pykd/dbgmem.h +++ b/pykd/dbgmem.h @@ -1,5 +1,21 @@ #pragma once +namespace pykd { + +/////////////////////////////////////////////////////////////////////////////////// + +ULONG64 +addr64( ULONG64 addr ); + +/////////////////////////////////////////////////////////////////////////////////// + +}; + + + + + + //#include // /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgobj.h b/pykd/dbgobj.h index 6875ca1..a06f0cd 100644 --- a/pykd/dbgobj.h +++ b/pykd/dbgobj.h @@ -25,6 +25,10 @@ protected: hres = client->QueryInterface( __uuidof(IDebugSymbols3), (void**)&m_symbols ); if ( FAILED( hres ) ) throw DbgException("QueryInterface IDebugSymbols3 failed"); + + hres = client->QueryInterface( __uuidof(IDebugAdvanced2), (void**)&m_advanced ); + if ( FAILED( hres ) ) + throw DbgException("QueryInterface IDebugAdvanced2 failed"); } virtual ~DbgObject() {}; @@ -32,6 +36,7 @@ protected: CComPtr m_client; CComPtr m_control; CComPtr m_symbols; + CComPtr m_advanced; }; diff --git a/pykd/module.cpp b/pykd/module.cpp index 4af45db..c5739bb 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -1,8 +1,22 @@ #include "stdafx.h" #include "module.h" +#include "dbgclient.h" +#include "dbgmem.h" -using namespace pykd; +namespace pykd { + +/////////////////////////////////////////////////////////////////////////////////// + +Module loadModule( const std::string &moduleName ) { + return g_dbgClient->loadModule( moduleName ); +}; + +/////////////////////////////////////////////////////////////////////////////////// + +Module findModule( ULONG64 offset ) { + return g_dbgClient->findModule( offset ); +} /////////////////////////////////////////////////////////////////////////////////// @@ -26,6 +40,100 @@ Module::Module( IDebugClient5 *client, const std::string& moduleName ) : DbgObje /////////////////////////////////////////////////////////////////////////////////// +Module::Module( IDebugClient5 *client, ULONG64 offset ) : DbgObject( client ) +{ + HRESULT hres; + + offset = addr64( offset ); + + ULONG moduleIndex; + hres = m_symbols->GetModuleByOffset( offset, 0, &moduleIndex, &m_base ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleByOffset failed" ); + + char moduleName[0x100]; + + hres = m_symbols->GetModuleNameString( + DEBUG_MODNAME_MODULE, + moduleIndex, + 0, + moduleName, + sizeof( moduleName ), + NULL ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleNameString failed" ); + + m_name = std::string( moduleName ); + + DEBUG_MODULE_PARAMETERS moduleParam = { 0 }; + hres = m_symbols->GetModuleParameters( 1, &m_base, 0, &moduleParam ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleParameters failed" ); + + m_size = moduleParam.Size; +} + +/////////////////////////////////////////////////////////////////////////////////// + +std::wstring +Module::getPdbName() +{ + HRESULT hres; + + IMAGEHLP_MODULEW64 moduleInfo = {}; + + hres = m_advanced->GetSymbolInformation( + DEBUG_SYMINFO_IMAGEHLP_MODULEW64, + m_base, + 0, + &moduleInfo, + sizeof(moduleInfo), + NULL, + NULL, + 0, + NULL ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" ); + + return std::wstring( moduleInfo.LoadedPdbName ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +void +Module::reloadSymbols() +{ + HRESULT hres; + + hres = m_symbols->Reload( "/f" ); + if ( FAILED( hres ) ) + throw DbgException("IDebugSymbols::Reload failed" ); + +} + +/////////////////////////////////////////////////////////////////////////////////// + +}; // end of namespace pykd + + + + + + + + + + + + + + +// // try reload module by entered name, "silent mode" +// OutputReader outputReader( dbgExt->client ); +// hres = dbgExt->symbols->Reload( reloadParam.c_str() ); + diff --git a/pykd/module.h b/pykd/module.h index 2df26f5..e571c88 100644 --- a/pykd/module.h +++ b/pykd/module.h @@ -14,6 +14,8 @@ public: Module( IDebugClient5 *client, const std::string& moduleName ); + Module( IDebugClient5 *client, ULONG64 offset ); + std::string getName() { return m_name; } @@ -30,6 +32,12 @@ public: return m_size; } + std::wstring + getPdbName(); + + void + reloadSymbols(); + private: std::string m_name; @@ -47,11 +55,6 @@ private: - - - - - //#include //#include // diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index 5f27921..2d8a601 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -361,6 +361,10 @@ RelativePath=".\dbgext.cpp" > + + @@ -423,6 +427,10 @@ RelativePath=".\dbgexcept.h" > + + diff --git a/test/scripts/moduletest.py b/test/scripts/moduletest.py index 96e72e4..3780ede 100644 --- a/test/scripts/moduletest.py +++ b/test/scripts/moduletest.py @@ -22,3 +22,21 @@ class ModuleTest( unittest.TestCase ): def testEnd( self ): self.assertEqual( target.module.size(), target.module.end() - target.module.begin() ) + + def testPdb( self ): + self.assertNotEqual( "", target.module.pdb() ); + + def testFindModule( self ): + + try: pykd.findModule( target.module.begin() - 0x10 ) + except pykd.BaseException: pass + #self.assertRaises( pykd.BaseException, pykd.findModule, target.module.begin() - 0x10 ) + + self.assertNotEqual( None, pykd.findModule( target.module.begin() ) ) + self.assertNotEqual( None, pykd.findModule( target.module.begin() + 0x10) ) + + try: pykd.findModule( target.module.end() ) + except pykd.BaseException: pass + + try: pykd.findModule( target.module.end() + 0x10) + except pykd.BaseException: pass diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py index 393a407..dbfb213 100644 --- a/test/scripts/pykdtest.py +++ b/test/scripts/pykdtest.py @@ -34,13 +34,11 @@ if __name__ == "__main__": target.moduleName = os.path.splitext(os.path.basename(targetAppPath))[0] print "\nTest module: %s" % targetAppPath - - dbg = pykd.dbgClient() - - dbg.startProcess( targetAppPath ) -# pykd.go() + + pykd.startProcess( targetAppPath ) - target.module = dbg.loadModule( target.moduleName ) + target.module = pykd.loadModule( target.moduleName ) + target.module.reload(); suite = getTestSuite()