From 3d7f2990280213dd9b0dbb1346cde694dad45b7e Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Thu, 25 Apr 2013 17:39:09 +0000 Subject: [PATCH] [0.2.x] ~ workitem/11723: find symbol by name ("public" pdb) - enum types by mask git-svn-id: https://pykd.svn.codeplex.com/svn@83473 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dia/diadecls.h | 2 +- pykd/dia/diaload.cpp | 12 ++++- pykd/dia/diapubsymcache.cpp | 84 +++++++++++++++++++++++++++++++++ pykd/dia/diapubsymcache.h | 31 ++++++++++++ pykd/dia/diasession.cpp | 24 ++++++++++ pykd/dia/diasession.h | 11 ++--- pykd/dia/diasymbol.cpp | 91 +++++++++++++++++++++++++----------- pykd/dia/diasymbol.h | 17 ++----- pykd/dia/symexport.cpp | 10 +++- pykd/module.cpp | 57 +++++++++++++--------- pykd/module.h | 6 ++- pykd/pykd_2008.vcproj | 8 ++++ pykd/python/pymod.cpp | 7 +-- pykd/symengine.h | 9 +++- pykd/typeinfo.cpp | 4 +- test/scripts/moduletest.py | 21 +++------ test/scripts/mspdbtest.py | 1 + test/scripts/typedvar.py | 42 ++++++++--------- test/targetapp/targetapp.cpp | 12 +++++ 19 files changed, 329 insertions(+), 120 deletions(-) create mode 100644 pykd/dia/diapubsymcache.cpp create mode 100644 pykd/dia/diapubsymcache.h diff --git a/pykd/dia/diadecls.h b/pykd/dia/diadecls.h index 0e89e0a..3d47ac5 100644 --- a/pykd/dia/diadecls.h +++ b/pykd/dia/diadecls.h @@ -1,12 +1,12 @@ #pragma once #include +#include #include "symengine.h" #include "dia\diaexcept.h" - namespace pykd { ////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dia/diaload.cpp b/pykd/dia/diaload.cpp index 9d14e01..62ff9f3 100644 --- a/pykd/dia/diaload.cpp +++ b/pykd/dia/diaload.cpp @@ -30,12 +30,14 @@ interface IDataProvider ////////////////////////////////////////////////////////////////////////////////// // Load debug symbols using DIA -static SymbolSessionPtr createSession( +SymbolSessionPtr createSession( IDataProvider &DataProvider, ULONGLONG loadBase, const std::string &symbolFileName ) { + const CTime startTime = CTime::GetCurrentTime(); + HRESULT hres; DiaDataSourcePtr dataSource; @@ -62,7 +64,13 @@ static SymbolSessionPtr createSession( if ( S_OK != hres ) throw DiaException("Call IDiaSymbol::get_globalScope", hres); - return SymbolSessionPtr( new DiaSession( _session, _globalScope, symbolFileName ) ); + return SymbolSessionPtr( + new DiaSession( + _session, + _globalScope, + symbolFileName, + (CTime::GetCurrentTime() - startTime).GetTotalSeconds() ) + ); } ////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dia/diapubsymcache.cpp b/pykd/dia/diapubsymcache.cpp new file mode 100644 index 0000000..efa262f --- /dev/null +++ b/pykd/dia/diapubsymcache.cpp @@ -0,0 +1,84 @@ + +#include "stdafx.h" + +#include +#include "dbghelp.h" + +#include "dia\diadecls.h" +#include "dia\diapubsymcache.h" + +#include "win\utils.h" + +namespace pykd { + +////////////////////////////////////////////////////////////////////////////// + +DiaPublicSymbolCache::DiaPublicSymbolCache(DiaSymbolPtr globalScope) +{ + const CTime startTime = CTime::GetCurrentTime(); + + DiaEnumSymbolsPtr publicSymbols; + HRESULT hres = + globalScope->findChildren( + ::SymTagPublicSymbol, + NULL, + nsNone, + &publicSymbols); + if (S_OK != hres) + throw DiaException("Call IDiaSymbol::findChildren", hres); + + std::set< std::string > ambiguousSymbols; + + DiaSymbolPtr currentSym; + ULONG celt; + while ( SUCCEEDED(publicSymbols->Next(1, ¤tSym, &celt)) && (celt == 1) ) + { + struct ClearSymbol : boost::noncopyable + { + DiaSymbolPtr &m_sym; + ClearSymbol(DiaSymbolPtr &sym) : m_sym(sym) {} + ~ClearSymbol() { m_sym = NULL; } + } clearSymbol(currentSym); + + BSTR bstrTemp; + hres = currentSym->get_name(&bstrTemp); + if (hres != S_OK) + continue; + std::string name = autoBstr(bstrTemp).asStr(); + + hres = currentSym->get_undecoratedNameEx(UNDNAME_NAME_ONLY, &bstrTemp); + if (hres != S_OK) + continue; + std::string undecoratedName = autoBstr(bstrTemp).asStr(); + + if (undecoratedName.empty() || undecoratedName == name) + continue; + + if (ambiguousSymbols.find(undecoratedName) != ambiguousSymbols.end()) + continue; + + if (m_impl.find(undecoratedName) != m_impl.end()) + { + ambiguousSymbols.insert(undecoratedName); + m_impl.erase(undecoratedName); + } + + m_impl[undecoratedName] = currentSym; + } + + m_buildTimeInSeconds = + (CTime::GetCurrentTime() - startTime).GetTotalSeconds(); +} + +////////////////////////////////////////////////////////////////////////////// + +DiaSymbolPtr DiaPublicSymbolCache::lookup(const std::string &name) const +{ + Impl::const_iterator it = m_impl.find(name); + return (it != m_impl.end()) ? it->second : DiaSymbolPtr(); +} + +/////////////////////////////////////////////////////////////////////////////// + +}; // pykd namespace end + diff --git a/pykd/dia/diapubsymcache.h b/pykd/dia/diapubsymcache.h new file mode 100644 index 0000000..f08d0d5 --- /dev/null +++ b/pykd/dia/diapubsymcache.h @@ -0,0 +1,31 @@ + +#pragma once + +namespace pykd { + +////////////////////////////////////////////////////////////////////////////// + +class DiaPublicSymbolCache : boost::noncopyable +{ +public: + DiaPublicSymbolCache(DiaSymbolPtr globalScope); + + // Lookup entry by name + // Sta. + DiaSymbolPtr lookup(const std::string &name) const; + + LONGLONG getBuildTimeInSeconds() const { + return m_buildTimeInSeconds; + } + +private: + typedef std::map< std::string, DiaSymbolPtr > Impl; + Impl m_impl; + + LONGLONG m_buildTimeInSeconds; +}; +typedef boost::shared_ptr< DiaPublicSymbolCache > DiaPublicSymbolCachePtr; + +////////////////////////////////////////////////////////////////////////////// + +} // end pykd namespace diff --git a/pykd/dia/diasession.cpp b/pykd/dia/diasession.cpp index 019babf..37e3f4e 100644 --- a/pykd/dia/diasession.cpp +++ b/pykd/dia/diasession.cpp @@ -9,6 +9,17 @@ namespace pykd { ////////////////////////////////////////////////////////////////////////////// +DiaSession::DiaSession( IDiaSession* session, IDiaSymbol *globalScope, const std::string symbolFile, LONGLONG loadSeconds ) + : m_globalScope( globalScope ) + , m_globalSymbol( DiaSymbol::fromGlobalScope( globalScope ) ) + , m_session( session ) + , m_symbolFileName( symbolFile ) + , m_loadSeconds(loadSeconds) +{ +} + +////////////////////////////////////////////////////////////////////////////// + SymbolPtr DiaSession::findByRva( ULONG rva, ULONG symTag, LONG* pdisplacement ) { DiaSymbolPtr child; @@ -74,4 +85,17 @@ void DiaSession::getSourceLine( ULONG64 offset, std::string &fileName, ULONG &li /////////////////////////////////////////////////////////////////////////////// +std::string DiaSession::getBuildDescription() const +{ + std::stringstream sstr; + sstr << "Load : "; + sstr << std::dec << m_loadSeconds; + sstr << " sec"; + + const std::string globalScopeDesc = m_globalSymbol->getBuildDescription(); + return !globalScopeDesc.empty() ? sstr.str() + ", " + globalScopeDesc : sstr.str(); +} + +/////////////////////////////////////////////////////////////////////////////// + }; // pykd namespace end diff --git a/pykd/dia/diasession.h b/pykd/dia/diasession.h index 7c2918d..256e387 100644 --- a/pykd/dia/diasession.h +++ b/pykd/dia/diasession.h @@ -12,12 +12,7 @@ class DiaSession : public SymbolSession { public: - DiaSession( IDiaSession* session, IDiaSymbol *globalScope, const std::string symbolFile ) : - m_globalScope( globalScope ), - m_globalSymbol( DiaSymbol::fromGlobalScope( globalScope ) ), - m_session( session ), - m_symbolFileName( symbolFile ) - {} + DiaSession( IDiaSession* session, IDiaSymbol *globalScope, const std::string symbolFile, LONGLONG loadSeconds ); virtual SymbolPtr getSymbolScope() { return m_globalSymbol; @@ -31,6 +26,8 @@ public: return m_symbolFileName; } + virtual std::string getBuildDescription() const; + private: ULONG findRvaByName( const std::string &name ); @@ -39,7 +36,7 @@ private: SymbolPtr m_globalSymbol; DiaSessionPtr m_session; std::string m_symbolFileName; - + LONGLONG m_loadSeconds; }; //////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dia/diasymbol.cpp b/pykd/dia/diasymbol.cpp index bd8c0d0..29798fb 100644 --- a/pykd/dia/diasymbol.cpp +++ b/pykd/dia/diasymbol.cpp @@ -47,49 +47,50 @@ SymbolPtr DiaSymbol::fromGlobalScope( IDiaSymbol *_symbol ) if (!machineType) machineType = IMAGE_FILE_MACHINE_I386; - return SymbolPtr( new DiaSymbol(DiaSymbolPtr(_symbol), machineType) ); + std::auto_ptr< DiaSymbol > globalScope( new DiaSymbol(DiaSymbolPtr(_symbol), machineType) ); + globalScope->m_publicSymbols.reset( new DiaPublicSymbolCache( _symbol ) ); + return SymbolPtr( globalScope.release() ); } ////////////////////////////////////////////////////////////////////////////////// -SymbolPtrList DiaSymbol::findChildren( - ULONG symTag, - const std::string &name, - bool caseSensitive - ) +SymbolPtrList DiaSymbol::findChildren(ULONG symTag, const std::string &name) { DiaEnumSymbolsPtr symbols; HRESULT hres; - if ( name.empty() ) - { - hres = m_symbol->findChildren( - static_cast(symTag), - NULL, - (caseSensitive ? nsCaseSensitive : nsCaseInsensitive) | nsfUndecoratedName | nsfRegularExpression, - &symbols); + const bool bFindAllNames = ( name.empty() || name == "*" ); + if ( bFindAllNames ) + { + hres = + m_symbol->findChildren( + static_cast(symTag), + NULL, + nsNone, + &symbols); } else { - hres = m_symbol->findChildren( - static_cast(symTag), + hres = + m_symbol->findChildren( + static_cast(symTag), toWStr(name), - (caseSensitive ? nsCaseSensitive : nsCaseInsensitive) | nsfUndecoratedName | nsfRegularExpression, + nsRegularExpression, &symbols); } if (S_OK != hres) - throw DiaException("Call IDiaSymbol::findChildren", hres); + throw DiaException("IDiaSymbol::findChildren", hres); SymbolPtrList childList; DiaSymbolPtr child; - ULONG celt; + ULONG celt = 0; while ( SUCCEEDED(symbols->Next(1, &child, &celt)) && (celt == 1) ) { childList.push_back( SymbolPtr( new DiaSymbol(child, m_machineType) ) ); - child = NULL; + child.Release(); } return childList; @@ -167,7 +168,6 @@ SymbolPtr DiaSymbol::getChildByIndex(ULONG symTag, ULONG _index ) SymbolPtr DiaSymbol::getChildByName(const std::string &name ) { - // ищем прямое совпадение DiaEnumSymbolsPtr symbols; HRESULT hres = m_symbol->findChildren( @@ -181,8 +181,11 @@ SymbolPtr DiaSymbol::getChildByName(const std::string &name ) if (S_OK != hres) throw DiaException("Call IDiaEnumSymbols::get_Count", hres); - if (count >0 ) + if (count > 0) { + if (count > 1) + throw SymbolException(name + "is ambiguous"); + DiaSymbolPtr child; hres = symbols->Item(0, &child); if (S_OK != hres) @@ -191,6 +194,14 @@ SymbolPtr DiaSymbol::getChildByName(const std::string &name ) return SymbolPtr( new DiaSymbol(child, m_machineType) ); } + if (m_publicSymbols) + { + DiaSymbolPtr publicSymbol = m_publicSymbols->lookup(name); + if (publicSymbol) + return SymbolPtr( new DiaSymbol(publicSymbol, m_machineType) ); + } + +/* c++ c++ decoration is not supported // _имя std::string underscoreName; underscoreName += '_'; @@ -217,7 +228,7 @@ SymbolPtr DiaSymbol::getChildByName(const std::string &name ) return SymbolPtr( new DiaSymbol(child, m_machineType) ); } - + // _имя@парам std::string pattern = "_"; pattern += name; @@ -250,7 +261,7 @@ SymbolPtr DiaSymbol::getChildByName(const std::string &name ) return SymbolPtr( new DiaSymbol(child, m_machineType) ); } - +*/ throw DiaException(name + " is not found"); } @@ -319,20 +330,30 @@ ULONG DiaSymbol::getLocType() ////////////////////////////////////////////////////////////////////////////// -static const boost::regex stdcallMatch("^_(\\w+)(@\\d+)?$"); -static const boost::regex fastcallMatch("^@(\\w+)(@\\d+)?$"); - std::string DiaSymbol::getName() { HRESULT hres; BSTR bstrName = NULL; + hres = m_symbol->get_undecoratedNameEx( UNDNAME_NAME_ONLY, &bstrName); + if (S_OK == hres) + { + std::string name = autoBstr( bstrName ).asStr(); + if (!name.empty()) + return name; + } + +/* c++ decoration is not supported + + static const boost::regex stdcallMatch("^_(\\w+)(@\\d+)?$"); + static const boost::regex fastcallMatch("^@(\\w+)(@\\d+)?$"); + ULONG symTag; hres = m_symbol->get_symTag( &symTag ); if ( FAILED( hres ) ) throw DiaException("Call IDiaSymbol::get_symTag", hres); - + if( symTag == SymTagData || symTag == SymTagFunction || symTag == SymTagPublicSymbol ) { hres = m_symbol->get_undecoratedNameEx( UNDNAME_NAME_ONLY, &bstrName); @@ -354,7 +375,7 @@ std::string DiaSymbol::getName() return retStr; } } - +*/ bstrName = callSymbol(get_name); return autoBstr( bstrName ).asStr(); @@ -498,6 +519,20 @@ ULONG DiaSymbol::getVirtualBaseDispSize() return (ULONG)baseTableType->getType()->getSize(); } +std::string DiaSymbol::getBuildDescription() const +{ + std::stringstream sstr; + + if (m_publicSymbols) + { + sstr << "Public symbols cache build time: "; + sstr << std::dec << m_publicSymbols->getBuildTimeInSeconds(); + sstr << " sec"; + } + + return sstr.str(); +} + ////////////////////////////////////////////////////////////////////////////// bool DiaSymbol::isBasicType() diff --git a/pykd/dia/diasymbol.h b/pykd/dia/diasymbol.h index b1708fc..6de4268 100644 --- a/pykd/dia/diasymbol.h +++ b/pykd/dia/diasymbol.h @@ -2,6 +2,7 @@ #pragma once #include "dia\diadecls.h" +#include "dia\diapubsymcache.h" namespace pykd { @@ -23,8 +24,7 @@ public: SymbolPtrList findChildren( ULONG symTag, - const std::string &name = "", - bool caseSensitive = FALSE + const std::string &name = "" ); ULONGLONG getSize(); @@ -63,15 +63,12 @@ public: ULONG getDataKind(); - //ULONG getRegisterId(); virtual ULONG getRegRealativeId() override; ULONG getMachineType() { return m_machineType; } - //SymbolPtr getChildByName(const std::string &_name); - ULONG getChildCount( ULONG symTag ); ULONG getChildCount() { @@ -86,19 +83,13 @@ public: bool isConstant(); - //std::string print(); - - //bool eq(Symbol &rhs); - int getVirtualBasePointerOffset(); ULONG getVirtualBaseDispIndex(); ULONG getVirtualBaseDispSize(); - //ULONG getSection(); - - void setLoadAddress( ULONGLONG baseAddress ); + virtual std::string getBuildDescription() const; public: typedef std::pair ValueNameEntry; @@ -128,8 +119,8 @@ protected: } DiaSymbolPtr m_symbol; - DWORD m_machineType; + DiaPublicSymbolCachePtr m_publicSymbols; }; diff --git a/pykd/dia/symexport.cpp b/pykd/dia/symexport.cpp index 6cdc652..a1cf22d 100644 --- a/pykd/dia/symexport.cpp +++ b/pykd/dia/symexport.cpp @@ -18,7 +18,7 @@ namespace pykd { class ExportSymbolBase : public Symbol { - virtual SymbolPtrList findChildren( ULONG symTag, const std::string &name = "", bool caseSensitive = FALSE ) + virtual SymbolPtrList findChildren( ULONG symTag, const std::string &name = "" ) { throw ImplementException( __FILE__, __LINE__, "TODO" ); } @@ -162,6 +162,10 @@ class ExportSymbolBase : public Symbol { throw ImplementException( __FILE__, __LINE__, "TODO" ); } + + virtual std::string getBuildDescription() const { + return std::string(); + } }; /////////////////////////////////////////////////////////////////////////////// @@ -437,6 +441,10 @@ public: return std::string("export symbols"); } + virtual std::string getBuildDescription() const { + return std::string(); + } + private: ULONGLONG m_moduleBase; diff --git a/pykd/module.cpp b/pykd/module.cpp index 656f4af..69fe906 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -186,9 +186,16 @@ std::string Module::print() sstr << (m_unloaded ? ", UNLOADED!" : "") << std::endl; sstr << "Image: " << m_imageName << std::endl; if ( m_symSession ) + { sstr << "Symbols: " << m_symSession->getSymbolFileName() << std::endl; + std::string buildDesc = m_symSession->getBuildDescription(); + if (!buildDesc.empty()) + sstr << "\t" << buildDesc << std::endl; + } else + { sstr << "Symbols: not found" << std::endl; + } sstr << "Timestamp: " << m_timeDataStamp << std::endl; @@ -197,6 +204,32 @@ std::string Module::print() return sstr.str(); } +/////////////////////////////////////////////////////////////////////////////////// + +python::list Module::getUdts() +{ + SymbolPtrList symlst = getSymScope()->findChildren( SymTagUDT ); + + python::list lst; + for ( SymbolPtrList::iterator it = symlst.begin(); it != symlst.end(); ++it ) + lst.append( (*it)->getName() ); + + return lst; +} + +/////////////////////////////////////////////////////////////////////////////////// + +python::list Module::getEnums() +{ + SymbolPtrList symlst = getSymScope()->findChildren( SymTagEnum ); + + python::list lst; + for ( SymbolPtrList::iterator it = symlst.begin(); it != symlst.end(); ++it ) + lst.append( (*it)->getName() ); + + return lst; +} + /////////////////////////////////////////////////////////////////////////////// TypedVarPtr @@ -348,7 +381,7 @@ python::list Module::enumSymbols( const std::string &mask) { python::list lst; - SymbolPtrList symlst = getSymScope()->findChildren( SymTagData, mask, true ); + SymbolPtrList symlst = getSymScope()->findChildren( SymTagData, mask ); for ( SymbolPtrList::iterator it = symlst.begin(); it != symlst.end(); ++it ) { @@ -362,7 +395,7 @@ python::list Module::enumSymbols( const std::string &mask) } } - symlst = getSymScope()->findChildren( SymTagFunction, mask, true ); + symlst = getSymScope()->findChildren( SymTagFunction, mask ); for ( SymbolPtrList::iterator it = symlst.begin(); it != symlst.end(); ++it ) { @@ -374,26 +407,6 @@ python::list Module::enumSymbols( const std::string &mask) /////////////////////////////////////////////////////////////////////////////////// -python::list Module::enumTypes( const std::string &mask ) -{ - python::list lst; - int tags[] = { SymTagUDT, SymTagEnum }; - - for ( size_t i = 0; i < sizeof(tags)/sizeof(tags[0]); ++i ) - { - SymbolPtrList symlst = getSymScope()->findChildren( tags[i], mask, true ); - - for ( SymbolPtrList::iterator it = symlst.begin(); it != symlst.end(); ++it ) - { - lst.append( (*it)->getName() ); - } - } - - return lst; -} - -/////////////////////////////////////////////////////////////////////////////////// - std::string Module::queryVersion( const std::string &value) { return getModuleVersionInfo( m_base, value ); } diff --git a/pykd/module.h b/pykd/module.h index 3140b09..f0e4eac 100644 --- a/pykd/module.h +++ b/pykd/module.h @@ -92,6 +92,10 @@ public: return TypeInfo::getTypeInfo( boost::static_pointer_cast( getSymScope() ), typeName); } + python::list getUdts(); + + python::list getEnums(); + TypedVarPtr getTypedVarByAddr( ULONG64 addr ); TypedVarPtr getTypedVarByName( const std::string &symName ); @@ -118,8 +122,6 @@ public: python::list enumSymbols( const std::string &mask = "*" ); - python::list enumTypes( const std::string &mask = std::string() ); - std::string print(); std::string queryVersion( const std::string &value); diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index db50989..54f9432 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -641,6 +641,14 @@ RelativePath=".\dia\diaload.cpp" > + + + + diff --git a/pykd/python/pymod.cpp b/pykd/python/pymod.cpp index e913fc8..2cc037a 100644 --- a/pykd/python/pymod.cpp +++ b/pykd/python/pymod.cpp @@ -68,7 +68,6 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( findSymbol_, TypeInfo::findSymbol, 1, 2 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( TypeBuilder_createStruct, TypeBuilder::createStruct, 1, 2 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( Module_enumSymbols, Module::enumSymbols, 0, 1 ); -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( Module_enumTypes, Module::enumTypes, 0, 1 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( Module_findSymbol, Module::getSymbolNameByVa, 1, 2 ); @@ -386,6 +385,10 @@ BOOST_PYTHON_MODULE( pykd ) "Return a size of the type or variable" ) .def("type", &Module::getTypeByName, "Return typeInfo class by type name" ) + .def("getUdts", &Module::getUdts, + "Return a list of all user-defined type names" ) + .def("getEnums", &Module::getEnums, + "Return a list of all enumeration names" ) .def("typedVar", &Module::getTypedVarByAddr, "Return a typedVar class instance" ) .def("typedVar",&Module::getTypedVarByName, @@ -401,8 +404,6 @@ BOOST_PYTHON_MODULE( pykd ) "The start address is calculated by the same method as the standard macro CONTAINING_RECORD does" ) .def("enumSymbols", &Module::enumSymbols, Module_enumSymbols( python::args("mask"), "Return list of tuple ( symbolname, offset )" ) ) - .def("enumTypes", &Module::enumTypes, Module_enumTypes( python::args("mask"), - "Return list of type's names" )) .def("checksum", &Module::getCheckSum, "Return a image file checksum: IMAGE_OPTIONAL_HEADER.CheckSum" ) .def("timestamp", &Module::getTimeDataStamp, diff --git a/pykd/symengine.h b/pykd/symengine.h index 042864e..47db22b 100644 --- a/pykd/symengine.h +++ b/pykd/symengine.h @@ -123,8 +123,9 @@ enum RegRealativeId class Symbol { public: - - virtual SymbolPtrList findChildren( ULONG symTag, const std::string &name = "", bool caseSensitive = FALSE ) = 0; + // > Applies a case-sensitive name match using asterisks (*) and + // > question marks (?) as wildcards + virtual SymbolPtrList findChildren( ULONG symTag, const std::string &name = "") = 0; virtual ULONG getBaseType() = 0; virtual ULONG getBitPosition() = 0; virtual SymbolPtr getChildByIndex(ULONG _index ) = 0; @@ -153,6 +154,8 @@ public: virtual bool isIndirectVirtualBaseClass() = 0; virtual bool isVirtualBaseClass() = 0; virtual ULONG getRegRealativeId() = 0; // <- RegRealativeId + + virtual std::string getBuildDescription() const = 0; }; /////////////////////////////////////////////////////////////////////////////// @@ -168,6 +171,8 @@ public: virtual void getSourceLine( ULONG64 offset, std::string &fileName, ULONG &lineNo, LONG &displacement ) = 0; virtual std::string getSymbolFileName() = 0; + + virtual std::string getBuildDescription() const = 0; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index da2ad2b..222a4ee 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -894,7 +894,7 @@ python::dict EnumTypeInfo::asMap() { python::dict dct; - SymbolPtrList symbolsList = m_dia->findChildren(SymTagData, "", TRUE ); + SymbolPtrList symbolsList = m_dia->findChildren(SymTagData); for ( SymbolPtrList::iterator it = symbolsList.begin(); it != symbolsList.end(); it++ ) { @@ -916,7 +916,7 @@ std::string EnumTypeInfo::print() sstr << "enum: " << getName() << std::endl; - SymbolPtrList symbolsList = m_dia->findChildren(SymTagData, "", true ); + SymbolPtrList symbolsList = m_dia->findChildren(SymTagData); for ( SymbolPtrList::iterator it = symbolsList.begin(); it != symbolsList.end(); it++ ) { diff --git a/test/scripts/moduletest.py b/test/scripts/moduletest.py index 9f41849..16ff565 100644 --- a/test/scripts/moduletest.py +++ b/test/scripts/moduletest.py @@ -78,11 +78,11 @@ class ModuleTest( unittest.TestCase ): fileName = pykd.getSourceFile(target.module.FuncWithName0 ) self.assertTrue( re.search('targetapp\\.cpp', fileName ) ) fileName, lineNo, displacement = pykd.getSourceLine( target.module.FuncWithName0 + 2) - self.assertEqual( 404, lineNo ) + self.assertEqual( 413, lineNo ) self.assertTrue( re.search('targetapp\\.cpp', fileName ) ) self.assertEqual( 2, displacement ) fileName, lineNo, displacement = pykd.getSourceLine() - self.assertEqual( 677, lineNo ) + self.assertEqual( 689, lineNo ) def testEnumSymbols( self ): lst = target.module.enumSymbols() @@ -98,20 +98,13 @@ class ModuleTest( unittest.TestCase ): lst = target.module.enumSymbols( "classChild" ) self.assertEqual( 0, len(lst) ) - def testEnumTypes( self ): - lst1 = target.module.enumTypes() + def testGetTypes( self ): + lst1 = target.module.getUdts() self.assertNotEqual( 0, len(lst1) ) - self.assertTrue( "classChild" in lst1 ) self.assertTrue( "classBase" in lst1 ) self.assertTrue( "structTest" in lst1 ) - lst2 = target.module.enumTypes("*class*") - self.assertTrue( len(lst2) >= 2 ) - self.assertTrue( len(lst1) > len(lst2) ) - - self.assertTrue( "classChild" in lst2 ) - self.assertTrue( "classBase" in lst2 ) - - lst3 = target.module.enumTypes("hello*Str") - self.assertEqual( 0, len(lst3) ) + lst2 = target.module.getEnums() + self.assertNotEqual( 0, len(lst2) ) + self.assertTrue( "enumType" in lst2 ) diff --git a/test/scripts/mspdbtest.py b/test/scripts/mspdbtest.py index c2f9e0f..4706d24 100644 --- a/test/scripts/mspdbtest.py +++ b/test/scripts/mspdbtest.py @@ -25,4 +25,5 @@ class MsPdbTest(unittest.TestCase): def testFindMethodOffset(self): """Lookup method offset by name""" with PeFileAsDumpLoader( os.environ["WINDIR"] + r"\System32\ole32.dll" ) as loadedDump: + print "\n" + str( pykd.module("ole32") ) self.assertNotEqual( 0, pykd.getOffset("ole32!CPackagerMoniker::AddRef") ) diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index bf6ae9a..c73a950 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -11,16 +11,16 @@ class TypedVarTest( unittest.TestCase ): def testCtor( self ): tv = target.module.typedVar( "structTest", target.module.g_structTest ) tv = target.module.typedVar( "g_structTest" ) - + tv = pykd.typedVar( "structTest", target.module.g_structTest ) tv = pykd.typedVar( target.moduleName + "!structTest", target.module.g_structTest ) - + structTest = target.module.type( "structTest" ) tv = pykd.typedVar( structTest, target.module.g_structTest ) - + tv = pykd.typedVar( "g_structTest" ) tv = pykd.typedVar( target.moduleName + "!g_structTest" ) - + def testBaseTypes(self): self.assertEqual( 1, target.module.typedVar( "g_ucharValue" ) ) self.assertEqual( 2, target.module.typedVar( "g_ushortValue" ) ) @@ -46,7 +46,7 @@ class TypedVarTest( unittest.TestCase ): customStructTest.append("m_field1", pykd.typeInfo("UInt8B")) tvCustomStruct = pykd.typedVar( customStructTest.ptrTo(), target.module.offset("g_structTestPtr") ) self.assertEqual( 500, tvCustomStruct.deref().m_field1 ) - + def testArrayOf(self): arrayType = pykd.typeInfo("UInt8B").arrayOf(5) arrayVar = pykd.typedVar( arrayType, target.module.offset("ulonglongArray") ) @@ -74,7 +74,7 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( 16 + pykd.ptrSize(), tv1.sizeof() ) tv2 = target.module.typedVar( "structTest[2]", target.module.g_testArray ) self.assertEqual( tv1.sizeof()*2, tv2.sizeof() ) - + self.assertEqual( pykd.sizeof("g_structTest"), tv1.sizeof() ) self.assertEqual( pykd.sizeof("g_testArray"), tv2.sizeof() ) self.assertEqual( pykd.sizeof("g_ucharValue"), 1 ) @@ -116,12 +116,12 @@ class TypedVarTest( unittest.TestCase ): self.assertTrue(False) except IndexError: self.assertTrue(True) - + def testArrayFieldSlice(self): tv = target.module.typedVar( "g_struct3" ) self.assertEqual( 2, tv.m_arrayField[-1] ) self.assertEqual( [ 0, 2 ], tv.m_arrayField[0:2] ) - + def testGlobalVar(self): self.assertEqual( 4, target.module.typedVar( "g_ulongValue" ) ) self.assertEqual( 0x80000000, target.module.typedVar( "ulongArray" )[3] ) @@ -135,7 +135,7 @@ class TypedVarTest( unittest.TestCase ): off2 = target.module.offset( "g_structTest" ) tv = target.module.containingRecord( off2 + off1, "structTest", "m_field2" ) self.assertEqual( True, tv.m_field2 ) - + def testBitField(self): tv = target.module.typedVar("g_structWithBits") self.assertEqual( 4, tv.m_bit0_4 ) @@ -150,7 +150,7 @@ class TypedVarTest( unittest.TestCase ): tvl = pykd.typedVarList( target.module.g_listHead, target.module.type("listStruct"), "listEntry" ) self.assertEqual( 3, len( tvl ) ) self.assertEqual( [1,2,3], [ tv.num for tv in tvl ] ) - + tvl = pykd.typedVarList( target.module.g_listHead, target.module.type("listStruct"), "listEntry.Flink" ) self.assertEqual( 3, len( tvl ) ) self.assertEqual( [1,2,3], [ tv.num for tv in tvl ] ) @@ -186,17 +186,17 @@ class TypedVarTest( unittest.TestCase ): tvl1 = target.module.typedVarArray( target.module.g_testArray, "structTest", 2 ) tvl2 = pykd.typedVarArray( target.module.g_testArray, target.moduleName + "!structTest", 2 ) self.assertEqual( tvl1, tvl2 ) - + def testEqual(self): tv1 = target.module.typedVar("g_structTest") tv2 = target.module.typedVar("intMatrix") self.assertEqual( tv1.m_field3, tv2[0][1] ) - + def testEnum(self): tv = target.module.typedVar("g_classChild") self.assertEqual( 3, tv.m_enumField ) self.assertEqual( target.module.type("enumType").THREE, tv.m_enumField ) - + def testIndex(self): ind = target.module.typedVar( "g_ucharValue" ) self.assertEqual( 5, [0,5,10][ind] ) @@ -245,8 +245,7 @@ class TypedVarTest( unittest.TestCase ): self.assertRaises( pykd.TypeException, tv1.deref ) self.assertRaises( pykd.TypeException, tv2.deref ) - - + def testTypeVarArg(self): tv1 = target.module.typedVar( "structTest", target.module.g_structTest ) tv2 = target.module.typedVar( "structTest", tv1 ) @@ -278,7 +277,7 @@ class TypedVarTest( unittest.TestCase ): types = ("structTest", "ULong[100]", "ULong*" ) for ti in types: self.assertTrue( str(pykd.typedVar( target.module.type(ti), 0 ) ) ) - + def testStaticField(self): tv = pykd.typedVar( "g_classChild" ) self.assertEqual( 200, tv.m_staticField ) @@ -287,17 +286,15 @@ class TypedVarTest( unittest.TestCase ): def testAmbiguousFieldAccess(self): derivedFiledVal = pykd.loadCStr( pykd.typedVar( "g_fieldSameNameStruct" ).m_field ) self.assertEqual( derivedFiledVal, "toaster" ) - print target.module.type("fieldSameNameStruct") - + def testDiamondVirtualInherit(self): tv = pykd.typedVar( "g_virtChild" ) self.assertEqual( -100, tv.m_baseField ) - + def testDinkumwareMap(self): g_map = target.module.typedVar( "g_map" ) self.assertEqual( 1, g_map._Mysize ) - - + def testUdtSubscribe(self): tv = pykd.typedVar( "g_virtChild" ) self.assertEqual( 5, len(tv) ) @@ -306,9 +303,8 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( fieldVal, tv.m_baseField ) for field in tv: str( field ) - + def testDeadlockList(self): - lst = [] entry = pykd.typedVar("entry1").Flink for i in range( 0, 100000 ): diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index d802b2c..9cea268 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -171,6 +171,15 @@ public: {} }; +struct YetAnotherChild_class : classBase +{ + int m_i; + YetAnotherChild_class() : m_i(0) {} + virtual void virtFunc() {} + virtual void virtFunc2() {} +}; + + int classChild::m_staticField = 200; classChild g_classChild; @@ -405,6 +414,9 @@ void FuncWithName0() classChild _classChild; _classChild.baseMethod(); + static volatile YetAnotherChild_class yetAnotherChild; + std::cout << yetAnotherChild.m_i; + reinterpret_cast(&_classChild)->virtFunc2(); std::cout << _classChild.m_childField2; std::cout << g_constNumValue;