~ 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
This commit is contained in:
SND\EreTIk_cp 2013-04-25 17:39:09 +00:00 committed by Mikhail I. Izmestev
parent 0aec1a092c
commit 3d7f299028
19 changed files with 329 additions and 120 deletions

View File

@ -1,12 +1,12 @@
#pragma once
#include <dia2.h>
#include <atltime.h>
#include "symengine.h"
#include "dia\diaexcept.h"
namespace pykd {
//////////////////////////////////////////////////////////////////////////////

View File

@ -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() )
);
}
//////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,84 @@
#include "stdafx.h"
#include <set>
#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, &currentSym, &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

31
pykd/dia/diapubsymcache.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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;
};
////////////////////////////////////////////////////////////////////////////

View File

@ -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<enum ::SymTagEnum>(symTag),
NULL,
(caseSensitive ? nsCaseSensitive : nsCaseInsensitive) | nsfUndecoratedName | nsfRegularExpression,
&symbols);
const bool bFindAllNames = ( name.empty() || name == "*" );
if ( bFindAllNames )
{
hres =
m_symbol->findChildren(
static_cast<enum ::SymTagEnum>(symTag),
NULL,
nsNone,
&symbols);
}
else
{
hres = m_symbol->findChildren(
static_cast<enum ::SymTagEnum>(symTag),
hres =
m_symbol->findChildren(
static_cast<enum ::SymTagEnum>(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()

View File

@ -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<ULONG, const char *> ValueNameEntry;
@ -128,8 +119,8 @@ protected:
}
DiaSymbolPtr m_symbol;
DWORD m_machineType;
DiaPublicSymbolCachePtr m_publicSymbols;
};

View File

@ -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;

View File

@ -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 );
}

View File

@ -92,6 +92,10 @@ public:
return TypeInfo::getTypeInfo( boost::static_pointer_cast<Symbol>( 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);

View File

@ -641,6 +641,14 @@
RelativePath=".\dia\diaload.cpp"
>
</File>
<File
RelativePath=".\dia\diapubsymcache.cpp"
>
</File>
<File
RelativePath=".\dia\diapubsymcache.h"
>
</File>
<File
RelativePath=".\dia\diasession.cpp"
>

View File

@ -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,

View File

@ -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;
};
///////////////////////////////////////////////////////////////////////////////

View File

@ -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++ )
{

View File

@ -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 )

View File

@ -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") )

View File

@ -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 ):

View File

@ -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 *>(&_classChild)->virtFunc2();
std::cout << _classChild.m_childField2;
std::cout << g_constNumValue;