diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 6894df3..f083c0a 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -151,6 +151,7 @@ BOOST_PYTHON_MODULE( pykd ) boost::python::def( "setCurrentProcess", &setCurrentProcess ); boost::python::def( "getProcessorMode", &getProcessorMode ); boost::python::def( "setProcessorMode", &setProcessorMode ); + boost::python::def( "addSynSymbol", &addSyntheticSymbol ); boost::python::class_<typeClass, boost::shared_ptr<typeClass> >( "typeClass" ) .def("sizeof", &typeClass::size ) .def("offset", &typeClass::getOffset ) @@ -164,6 +165,7 @@ BOOST_PYTHON_MODULE( pykd ) .def("contain", &dbgModuleClass::contain ) .def("image", &dbgModuleClass::getImageSymbolName ) .def("pdb", &dbgModuleClass::getPdbName ) + .def("addSynSymbol", &dbgModuleClass::addSyntheticSymbol ) .def("__getattr__", &dbgModuleClass::getOffset ); boost::python::class_<dbgExtensionClass>( "ext", diff --git a/pykd/dbgext.h b/pykd/dbgext.h index 3dc4c5d..1fd6a8e 100644 --- a/pykd/dbgext.h +++ b/pykd/dbgext.h @@ -14,8 +14,8 @@ struct DbgExt { IDebugRegisters *registers; IDebugSymbols *symbols; - IDebugSymbols2 *symbols2; - IDebugSymbols3 *symbols3; + IDebugSymbols2 *symbols2; + IDebugSymbols3 *symbols3; IDebugDataSpaces *dataSpaces; IDebugDataSpaces4 *dataSpaces4; diff --git a/pykd/dbgmodule.cpp b/pykd/dbgmodule.cpp index a02882b..39b2659 100644 --- a/pykd/dbgmodule.cpp +++ b/pykd/dbgmodule.cpp @@ -224,7 +224,18 @@ dbgModuleClass::getOffset( const std::string &symName ) return offset->second; } - return 0; + return 0; +} + +///////////////////////////////////////////////////////////////////////////////// + +void dbgModuleClass::addSyntheticSymbol( + ULONG64 offset, + ULONG size, + const std::string &symName +) +{ + ::addSyntheticSymbol(m_base + offset, size, symName); } ///////////////////////////////////////////////////////////////////////////////// @@ -306,4 +317,31 @@ dbgModuleClass::getImagePath() delete[] pathBuffer; } -///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file +///////////////////////////////////////////////////////////////////////////////// + +void +addSyntheticSymbol( ULONG64 addr, ULONG size, const std::string &symName ) +{ + try + { + HRESULT hres = + dbgExt->symbols3->AddSyntheticSymbol( + addr, + size, + symName.c_str(), + DEBUG_ADDSYNTHSYM_DEFAULT, + NULL); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol3::AddSyntheticSymbol failed" ); + } + catch( std::exception &e ) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); + } + catch(...) + { + dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); + } +} + +///////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgmodule.h b/pykd/dbgmodule.h index b90ea03..e86dd60 100644 --- a/pykd/dbgmodule.h +++ b/pykd/dbgmodule.h @@ -15,20 +15,20 @@ public: dbgModuleClass() : m_base( 0 ), m_end( 0 ) - {} - + {} + dbgModuleClass( const std::string &name, ULONG64 base, ULONG size ); ULONG64 getBegin() const { return m_base; - } - + } + ULONG64 getEnd() const { return m_end; } - + bool contain( ULONG64 addr ) const { if ( *( (ULONG*)&addr + 1 ) == 0 ) @@ -36,34 +36,36 @@ public: return m_base <= addr && addr <= m_end; } - + std::string getName() const { return m_name; - } - + } + void reloadSymbols(); - + ULONG64 getOffset( const std::string &symName ); - + std::wstring getImageSymbolName() const { return m_imageFullName; } - + std::wstring getPdbName() const { return std::wstring( m_debugInfo.LoadedPdbName ); } - - + + void + addSyntheticSymbol( ULONG64 offset, ULONG size, const std::string &symName ); + private: ULONG64 m_base; - ULONG64 m_end; + ULONG64 m_end; std::string m_name; @@ -87,4 +89,7 @@ loadModule( const std::string &moduleName ); boost::python::object findModule( ULONG64 addr ); +void +addSyntheticSymbol( ULONG64 addr, ULONG size, const std::string &symName ); + ///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/samples/synimp.py b/samples/synimp.py new file mode 100644 index 0000000..ad51270 --- /dev/null +++ b/samples/synimp.py @@ -0,0 +1,54 @@ +# +# Add synthetic symbols for module by imports +# + +from pykd import * +import sys + +def addSymSymbolsByImports(dbgModule): + if isKernelDebugging(): + systemModule = loadModule( "nt" ) + else: + systemModule = loadModule( "ntdll" ) + + if is64bitSystem(): + ntHeader = typedVar( systemModule.name(), "_IMAGE_NT_HEADERS64", dbgModule.begin() + ptrDWord( dbgModule.begin() + 0x3c ) ) + if ntHeader.OptionalHeader.Magic == 0x10b: + systemModule = loadModule( "ntdll32" ) + ntHeader = typedVar( systemModule.name(), "_IMAGE_NT_HEADERS", dbgModule.begin() + ptrDWord( dbgModule.begin() + 0x3c ) ) + pSize = 4 + else: + pSize = 8 + else: + ntHeader = typedVar( systemModule.name(), "_IMAGE_NT_HEADERS", dbgModule.begin() + ptrDWord( dbgModule.begin() + 0x3c ) ) + pSize = 4 + + if ntHeader.OptionalHeader.DataDirectory[12].Size == 0: + return + + iatAddr = dbgModule.begin() + ntHeader.OptionalHeader.DataDirectory[12].VirtualAddress; + + for i in range( 0, ntHeader.OptionalHeader.DataDirectory[12].Size / pSize ): + pIatEtry = iatAddr + i*pSize; + + if ( pSize == 4 ): + iatEntry = ptrDWord( pIatEtry ) + else: + iatEntry = ptrQWord( pIatEtry ) + + if iatEntry != 0: + symbolName = findSymbol( iatEntry ) + addSynSymbol(pIatEtry, pSize, "_imp_" + symbolName) + +if __name__ == "__main__": + + if not isSessionStart(): + print "Script is launch out of WinDBG" + quit(0) + + argc = len(sys.argv) + if (2 == argc): + addSymSymbolsByImports(findModule(expr(sys.argv[1]))) + else: + dprintln("Invalid command line") + dprintln("Usage: " + sys.argv[0] + " module_address")