diff --git a/pykd/localvar.cpp b/pykd/localvar.cpp deleted file mode 100644 index 1658eb6..0000000 --- a/pykd/localvar.cpp +++ /dev/null @@ -1,209 +0,0 @@ - -#include <stdafx.h> - -#include "localvar.h" -#include "module.h" -#include "symengine.h" -#include "dbgengine.h" -#include "typedvar.h" - -namespace pykd { - -/////////////////////////////////////////////////////////////////////////////// - -python::dict getLocals() -{ - return getLocalsByFrame( getCurrentStackFrame() ); -} - -/////////////////////////////////////////////////////////////////////////////// - -class BuildLocals -{ -public: - BuildLocals( ModulePtr mod, const StackFrame &frame ) - : m_mod(mod), m_frame(frame), m_formalGen(0) - { - m_ipRva = static_cast<ULONG>(m_frame.m_instructionOffset - m_mod->getBase()); - } - - void process( SymbolPtr symParent ); - - python::dict &getResult() { - return m_dct; - } - -protected: - void addVar(SymbolPtr symVar); - -private: - ModulePtr m_mod; - const StackFrame &m_frame; - python::dict m_dct; - size_t m_formalGen; - ULONG m_ipRva; -}; - -/////////////////////////////////////////////////////////////////////////////// - -void BuildLocals::process( - SymbolPtr symParent -) -{ - // add vars from current scope - SymbolPtrList symList = symParent->findChildren(SymTagData); - SymbolPtrList::iterator itVar = symList.begin(); - for (; itVar != symList.end(); ++itVar) - addVar(*itVar); - - // find inners scopes - symList = symParent->findChildren(SymTagBlock); - SymbolPtrList::iterator itScope = symList.begin(); - for (; itScope != symList.end(); ++itScope) - { - SymbolPtr scope = *itScope; - ULONG scopeRva = scope->getRva(); - if (scopeRva <= m_ipRva && (scopeRva + scope->getSize()) > m_ipRva) - process(scope); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -void BuildLocals::addVar(SymbolPtr symVar) -{ - std::string name; - try - { - name = symVar->getName(); - if (name.empty()) - return; - } - catch (const SymbolException &except) - { - DBG_UNREFERENCED_PARAMETER(except); - return; - } - - if (m_dct.has_key(name)) - { - std::stringstream sstream; - sstream << name << "#" << std::dec << ++m_formalGen; - name = sstream.str(); - } - - BOOST_ASSERT(!m_dct.has_key(name)); - if (m_dct.has_key(name)) - return; - - ULONG64 varAddr; - const LocationType locType = static_cast<LocationType>(symVar->getLocType()); - switch (locType) - { - case LocIsStatic: - varAddr = m_mod->getBase() + symVar->getRva(); - break; - - case LocIsRegRel: - { - RegRealativeId rri; - try - { - rri = static_cast<RegRealativeId>(symVar->getRegRealativeId()); - } - catch (const DbgException &except) - { - DBG_UNREFERENCED_PARAMETER(except); - return; - } - varAddr = m_frame.getValue(rri, symVar->getOffset()); - } - break; - - default: - BOOST_ASSERT(LocIsEnregistered == locType); - return; - } - - TypeInfoPtr typeInfo = TypeInfo::getTypeInfo(symVar); - TypedVarPtr typedVar = TypedVar::getTypedVarByTypeInfo(typeInfo, varAddr); - typedVar->setDataKind( symVar->getDataKind() ); - m_dct[name] = typedVar; -} - -/////////////////////////////////////////////////////////////////////////////// - -static bool IsInDebugRange( - SymbolPtr func, - ULONG ipRva -) -{ - SymbolPtrList lstFuncDebugStart; - SymbolPtrList lstFuncDebugEnd; - - try - { - lstFuncDebugStart = func->findChildren(SymTagFuncDebugStart); - if (1 != lstFuncDebugStart.size()) - { - BOOST_ASSERT(lstFuncDebugStart.empty()); - return true; - } - - lstFuncDebugEnd = func->findChildren(SymTagFuncDebugEnd); - if (1 != lstFuncDebugEnd.size()) - { - BOOST_ASSERT(lstFuncDebugEnd.empty()); - return true; - } - } - catch (const SymbolException &except) - { - DBG_UNREFERENCED_PARAMETER(except); - return true; - } - - return - ((*lstFuncDebugStart.begin())->getRva() <= ipRva) && - ((*lstFuncDebugEnd.begin())->getRva() >= ipRva); -} - -/////////////////////////////////////////////////////////////////////////////// - -python::dict getLocalsByFrame( const StackFrame &frame ) -{ - // query target fuction by $ip register - ModulePtr mod; - SymbolPtr func; - try - { - mod = Module::loadModuleByOffset(frame.m_instructionOffset); - LONG displacemnt; - func = mod->getSymbolByVa(frame.m_instructionOffset, SymTagFunction, &displacemnt ); - } - catch (const DbgException &except) - { - DBG_UNREFERENCED_PARAMETER(except); - return python::dict(); - } - -#ifdef _DEBUG - std::string funcName; - funcName = func->getName(); -#endif // _DEBUG - - if (!IsInDebugRange(func, static_cast<ULONG>(frame.m_instructionOffset - mod->getBase()))) - { - // not in debug range - return python::dict(); - } - - BuildLocals buildLocals(mod, frame); - buildLocals.process(func); - return buildLocals.getResult(); -} - -/////////////////////////////////////////////////////////////////////////////// - -} //end pykd namespace - diff --git a/pykd/localvar.h b/pykd/localvar.h deleted file mode 100644 index f4ae3c2..0000000 --- a/pykd/localvar.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "stkframe.h" - -namespace pykd { - -/////////////////////////////////////////////////////////////////////////////// - -python::dict getLocals(); - -python::dict getLocalsByFrame( const StackFrame &frame ); - -/////////////////////////////////////////////////////////////////////////////// - -} // end pykd namespace - - diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index f454a88..acb922b 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="windows-1251"?> <VisualStudioProject ProjectType="Visual C++" - Version="9.00" + Version="9,00" Name="pykd" ProjectGUID="{FE961905-666F-4908-A212-961465F46F13}" RootNamespace="pykd" @@ -389,10 +389,6 @@ RelativePath=".\eventhandler.cpp" > </File> - <File - RelativePath=".\localvar.cpp" - > - </File> <File RelativePath=".\module.cpp" > @@ -507,10 +503,6 @@ RelativePath=".\eventhandler.h" > </File> - <File - RelativePath=".\localvar.h" - > - </File> <File RelativePath=".\module.h" > diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index fbadff0..36b1c9a 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -19,7 +19,6 @@ #include "cpureg.h" #include "disasm.h" #include "stkframe.h" -#include "localvar.h" #include "bpoint.h" #include "win/dbgio.h" @@ -245,9 +244,14 @@ BOOST_PYTHON_MODULE( pykd ) "Set current processor mode by string (X86, ARM, IA64 or X64)" ); // stack and local variables - python::def( "getCurrentStack", &getCurrentStack, + python::def( "getStack", &getCurrentStack, "Return a current stack as a list of stackFrame objects" ); - python::def( "getLocals", &getLocals, "Get list of local variables" ); + python::def( "getFrame", &getCurrentStackFrame, + "Return a current stack frame" ); + python::def( "getLocals", &getLocals, + "Get list of local variables" ); + python::def( "getParams", &getParams, + "Get list of function arguments" ); // breakpoints python::def( "setBp", &setSoftwareBp, setSoftwareBp_( python::args( "offset", "callback" ), @@ -426,7 +430,13 @@ BOOST_PYTHON_MODULE( pykd ) .def( "name", &CpuReg::name, "The name of the regsiter" ) .def( "index", &CpuReg::index, "The index of thr register" ); - python::class_<StackFrame>( "stackFrame", + python::class_<ScopeVars,ScopeVarsPtr,boost::noncopyable>( "locals", + "Class for access to local vars", python::no_init ) + .def("__len__", &ScopeVars::getVarCount ) + .def("__getitem__", &ScopeVars::getVarByIndex ) + .def("__getitem__", &ScopeVars::getVarByName ); + + python::class_<StackFrame, StackFramePtr,boost::noncopyable>( "stackFrame", "Class representing a frame of the call stack", python::no_init ) .def_readonly( "instructionOffset", &StackFrame::m_instructionOffset, "Return a frame's instruction offset" ) @@ -438,8 +448,10 @@ BOOST_PYTHON_MODULE( pykd ) "Return a frame's stack offset" ) .def_readonly( "frameNumber", &StackFrame::m_frameNumber, "Return a frame's number" ) - .def( "getLocals", &StackFrame::getLocals, - "Get list of local variables for this stack frame" ) + .add_property( "locals", &StackFrame::getLocals, + "Get list of local variables for this stack frame" ) + .add_property( "params", &StackFrame::getParams, + "Get list of function params" ) .def( "__str__", &StackFrame::print, "Return stacks frame as a string"); diff --git a/pykd/stkframe.cpp b/pykd/stkframe.cpp index 7e4b19f..2080af9 100644 --- a/pykd/stkframe.cpp +++ b/pykd/stkframe.cpp @@ -5,7 +5,7 @@ #include "stdafx.h" #include "stkframe.h" #include "dbgengine.h" -#include "localvar.h" +#include "module.h" //////////////////////////////////////////////////////////////////////////////// @@ -36,14 +36,21 @@ std::string StackFrame::print() const sstream << ", stack= 0x" << std::hex << m_stackOffset; return sstream.str(); - } + //////////////////////////////////////////////////////////////////////////////// -python::dict StackFrame::getLocals() const +ScopeVarsPtr StackFrame::getLocals() { - return getLocalsByFrame( *this ); + return ScopeVarsPtr( new LocalVars( shared_from_this() ) ); +} + +/////////////////////////////////////////////////////////////////////////////// + +ScopeVarsPtr StackFrame::getParams() +{ + return ScopeVarsPtr( new FunctionParams( shared_from_this() ) ); } /////////////////////////////////////////////////////////////////////////////// @@ -63,6 +70,283 @@ ULONG64 StackFrame::getValue(RegRealativeId rri, LONG64 offset /*= 0*/) const //////////////////////////////////////////////////////////////////////////////// +static bool IsInDebugRange( + SymbolPtr func, + ULONG ipRva +) +{ + SymbolPtrList lstFuncDebugStart; + SymbolPtrList lstFuncDebugEnd; + + try + { + lstFuncDebugStart = func->findChildren(SymTagFuncDebugStart); + if (1 != lstFuncDebugStart.size()) + { + BOOST_ASSERT(lstFuncDebugStart.empty()); + return true; + } + + lstFuncDebugEnd = func->findChildren(SymTagFuncDebugEnd); + if (1 != lstFuncDebugEnd.size()) + { + BOOST_ASSERT(lstFuncDebugEnd.empty()); + return true; + } + } + catch (const SymbolException &except) + { + DBG_UNREFERENCED_PARAMETER(except); + return true; + } + + return + ((*lstFuncDebugStart.begin())->getRva() <= ipRva) && + ((*lstFuncDebugEnd.begin())->getRva() >= ipRva); +} + +python::object StackFrame::getLocalByName( const std::string& name ) +{ + ModulePtr mod = Module::loadModuleByOffset( m_instructionOffset); + + LONG displacemnt; + SymbolPtr func = mod->getSymbolByVa( m_instructionOffset, SymTagFunction, &displacemnt ); + +#ifdef _DEBUG + std::string funcName; + funcName = func->getName(); +#endif // _DEBUG + + if (!IsInDebugRange(func, static_cast<ULONG>( m_instructionOffset - mod->getBase()))) + { + throw DbgException("is not debug range"); + } + + // find var in current scope + SymbolPtrList symList = func->findChildren(SymTagData); + SymbolPtrList::iterator itVar = symList.begin(); + SymbolPtr symVar; + for (; itVar != symList.end(); ++itVar) + { + if ( (*itVar)->getName() == name ) + { + symVar = *itVar; + break; + } + } + + if ( itVar == symList.end() ) + { + // find inners scopes + SymbolPtrList scopeList = func->findChildren(SymTagBlock); + SymbolPtrList::iterator itScope = scopeList.begin(); + + ULONG ipRva = static_cast<ULONG>( m_instructionOffset - mod->getBase()); + + for (; itScope != scopeList.end() && !symVar; ++itScope) + { + SymbolPtr scope = *itScope; + ULONG scopeRva = scope->getRva(); + if (scopeRva <= ipRva && (scopeRva + scope->getSize()) > ipRva) + { + SymbolPtrList symList = scope->findChildren(SymTagData); + SymbolPtrList::iterator itVar = symList.begin(); + + for (; itVar != symList.end(); ++itVar) + { + if ( (*itVar)->getName() == name ) + { + symVar = *itVar; + break; + } + } + } + } + } + + if ( !symVar ) + throw DbgException("local var not found"); + + ULONG64 varAddr; + const LocationType locType = static_cast<LocationType>(symVar->getLocType()); + switch (locType) + { + case LocIsStatic: + varAddr = mod->getBase() + symVar->getRva(); + break; + + case LocIsRegRel: + { + RegRealativeId rri; + rri = static_cast<RegRealativeId>(symVar->getRegRealativeId()); + varAddr = getValue(rri, symVar->getOffset()); + } + break; + + default: + BOOST_ASSERT(LocIsEnregistered == locType); + throw DbgException(""); + } + + TypeInfoPtr typeInfo = TypeInfo::getTypeInfo(symVar); + TypedVarPtr typedVar = TypedVar::getTypedVarByTypeInfo(typeInfo, varAddr); + typedVar->setDataKind( symVar->getDataKind() ); + + return python::object( typedVar ); +} + +//////////////////////////////////////////////////////////////////////////////// + +python::object StackFrame::getParamByName( const std::string& name ) +{ + ModulePtr mod = Module::loadModuleByOffset( m_instructionOffset); + + LONG displacemnt; + SymbolPtr func = mod->getSymbolByVa( m_instructionOffset, SymTagFunction, &displacemnt ); + +#ifdef _DEBUG + std::string funcName; + funcName = func->getName(); +#endif // _DEBUG + + if (!IsInDebugRange(func, static_cast<ULONG>( m_instructionOffset - mod->getBase()))) + { + throw DbgException("is not debug range"); + } + + // find var in current scope + SymbolPtrList symList = func->findChildren(SymTagData); + SymbolPtrList::iterator itVar = symList.begin(); + SymbolPtr symVar; + for (; itVar != symList.end(); ++itVar) + { + if ( (*itVar)->getDataKind() == DataIsParam && (*itVar)->getName() == name ) + { + symVar = *itVar; + break; + } + } + + if ( !symVar ) + throw DbgException("local var not found"); + + ULONG64 varAddr; + const LocationType locType = static_cast<LocationType>(symVar->getLocType()); + switch (locType) + { + case LocIsStatic: + varAddr = mod->getBase() + symVar->getRva(); + break; + + case LocIsRegRel: + { + RegRealativeId rri; + rri = static_cast<RegRealativeId>(symVar->getRegRealativeId()); + varAddr = getValue(rri, symVar->getOffset()); + } + break; + + default: + BOOST_ASSERT(LocIsEnregistered == locType); + throw DbgException(""); + } + + TypeInfoPtr typeInfo = TypeInfo::getTypeInfo(symVar); + TypedVarPtr typedVar = TypedVar::getTypedVarByTypeInfo(typeInfo, varAddr); + typedVar->setDataKind( symVar->getDataKind() ); + + return python::object( typedVar ); +} + +//////////////////////////////////////////////////////////////////////////////// + +ULONG StackFrame::getLocalCount() +{ + ULONG count = 0; + + ModulePtr mod; + mod = Module::loadModuleByOffset( m_instructionOffset); + + LONG displacemnt; + SymbolPtr func = mod->getSymbolByVa( m_instructionOffset, SymTagFunction, &displacemnt ); + +#ifdef _DEBUG + std::string funcName; + funcName = func->getName(); +#endif // _DEBUG + + if (!IsInDebugRange(func, static_cast<ULONG>( m_instructionOffset - mod->getBase()))) + { + throw DbgException("is not debug range"); + } + + // find var in current scope + SymbolPtrList symList = func->findChildren(SymTagData); + + SymbolPtrList::iterator it; + for ( it = symList.begin(); it != symList.end(); it++ ) + { + if ( (*it)->getName() != "" ) + count++; + } + + // find inners scopes + SymbolPtrList scopeList = func->findChildren(SymTagBlock); + SymbolPtrList::iterator itScope = scopeList.begin(); + + ULONG ipRva = static_cast<ULONG>( m_instructionOffset - mod->getBase()); + + for (; itScope != scopeList.end(); ++itScope) + { + SymbolPtr scope = *itScope; + ULONG scopeRva = scope->getRva(); + if (scopeRva <= ipRva && (scopeRva + scope->getSize()) > ipRva) + { + SymbolPtrList symList = scope->findChildren(SymTagData); + count += (ULONG)symList.size(); + } + } + + return count; +} + +//////////////////////////////////////////////////////////////////////////////// + +ULONG StackFrame::getParamCount() +{ + ULONG count = 0; + + ModulePtr mod; + mod = Module::loadModuleByOffset( m_instructionOffset); + + LONG displacemnt; + SymbolPtr func = mod->getSymbolByVa( m_instructionOffset, SymTagFunction, &displacemnt ); + +#ifdef _DEBUG + std::string funcName; + funcName = func->getName(); +#endif // _DEBUG + + if (!IsInDebugRange(func, static_cast<ULONG>( m_instructionOffset - mod->getBase()))) + { + throw DbgException("is not debug range"); + } + + // find var in current scope + SymbolPtrList symList = func->findChildren(SymTagData); + + SymbolPtrList::iterator it; + for ( it = symList.begin(); it != symList.end(); it++ ) + { + if ( (*it)->getDataKind() == DataIsParam ) + count++; + } + + return count; +} + +//////////////////////////////////////////////////////////////////////////////// + python::list getCurrentStack() { std::vector<STACK_FRAME_DESC> frames; @@ -72,7 +356,7 @@ python::list getCurrentStack() for ( ULONG i = 0; i < frames.size(); ++i ) { - python::object frameObj( StackFrame( frames.at(i) ) ); + python::object frameObj( StackFramePtr( new StackFrame( frames.at(i) ) ) ); frameList.append( frameObj ); } @@ -81,11 +365,25 @@ python::list getCurrentStack() //////////////////////////////////////////////////////////////////////////////// -StackFrame getCurrentStackFrame() +StackFramePtr getCurrentStackFrame() { std::vector<STACK_FRAME_DESC> frames; getStackTrace( frames ); - return frames[0]; + return StackFramePtr( new StackFrame( frames[0] ) ); +} + +/////////////////////////////////////////////////////////////////////////////// + +ScopeVarsPtr getLocals() +{ + return getCurrentStackFrame()->getLocals(); +} + +/////////////////////////////////////////////////////////////////////////////// + +ScopeVarsPtr getParams() +{ + return getCurrentStackFrame()->getParams(); } /////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/stkframe.h b/pykd/stkframe.h index d9af538..d0e6468 100644 --- a/pykd/stkframe.h +++ b/pykd/stkframe.h @@ -8,23 +8,52 @@ #include "context.h" #include "symengine.h" +#include <boost/enable_shared_from_this.hpp> + //////////////////////////////////////////////////////////////////////////////// namespace pykd { //////////////////////////////////////////////////////////////////////////////// -class StackFrame +class StackFrame; +typedef boost::shared_ptr<StackFrame> StackFramePtr; + +class ScopeVars; +typedef boost::shared_ptr<ScopeVars> ScopeVarsPtr; + +//////////////////////////////////////////////////////////////////////////////// + +class StackFrame : public boost::enable_shared_from_this<StackFrame> { public: + StackFrame( const STACK_FRAME_DESC& desc ); - python::dict getLocals() const; + ScopeVarsPtr getLocals(); + + ScopeVarsPtr getParams(); std::string print() const; ULONG64 getValue(RegRealativeId rri, LONG64 offset = 0) const; + ULONG getLocalCount(); + + ULONG getParamCount(); + + python::object getLocalByName( const std::string& name ); + + python::object getParamByName( const std::string& name ); + + python::object getLocalByIndex( ULONG index ){ + return python::long_(0); + } + + python::object getParamByIndex( ULONG index ){ + return python::long_(0); + } + public: ULONG m_frameNumber; @@ -35,12 +64,82 @@ public: }; +class ScopeVars { + +public: + + ScopeVars( StackFramePtr &frame ) : + m_frame( frame ) + {} + + virtual ULONG getVarCount() const = 0; + virtual python::object getVarByName( const std::string &name ) = 0; + virtual python::object getVarByIndex(ULONG index) const = 0 ; + +protected: + + StackFramePtr m_frame; + +}; + + +class LocalVars : public ScopeVars { + +public: + + LocalVars( StackFramePtr &frame ) : + ScopeVars( frame ) + {} + +private: + + ULONG getVarCount() const { + return m_frame->getLocalCount(); + } + + python::object getVarByName( const std::string &name ) { + return m_frame->getLocalByName( name ); + } + + python::object getVarByIndex(ULONG index) const { + return m_frame->getLocalByIndex( index ); + } +}; + + +class FunctionParams : public ScopeVars { + +public: + + FunctionParams( StackFramePtr &frame ) : + ScopeVars( frame ) + {} + +private: + + ULONG getVarCount() const { + return m_frame->getParamCount(); + } + + python::object getVarByName( const std::string &name ) { + return m_frame->getParamByName( name ); + } + + python::object getVarByIndex(ULONG index) const { + return python::long_(0L); + } +}; + /////////////////////////////////////////////////////////////////////////////// -StackFrame getCurrentStackFrame(); +StackFramePtr getCurrentStackFrame(); python::list getCurrentStack(); +ScopeVarsPtr getLocals(); + +ScopeVarsPtr getParams(); + /////////////////////////////////////////////////////////////////////////////// } // namespace pykd diff --git a/test/scripts/localstest.py b/test/scripts/localstest.py index d955af2..726e992 100644 --- a/test/scripts/localstest.py +++ b/test/scripts/localstest.py @@ -35,10 +35,9 @@ class LocalVarsTest(unittest.TestCase): testEnumWindowsProc1Locals(self, pykd.getLocals()) pykd.go() # targetapp!EnumWindowsProc1 -> targetapp!functionCalledFromEnumWindowsProc1 - testEnumWindowsProc1Locals(self, pykd.getCurrentStack()[1].getLocals()) + testEnumWindowsProc1Locals(self, pykd.getStack()[1].locals ) pykd.go() # targetapp!EnumWindowsProc1 -> targetapp!EnumWindowsProc2 locals = pykd.getLocals() self.assertEqual( len(locals), 2 ) - locValues = locals.values() - self.assertTrue( locValues[0] == 7 or locValues[1] == 7 ) + self.assertTrue( locals[0] == 7 or locals[1] == 7 ) diff --git a/test/scripts/moduletest.py b/test/scripts/moduletest.py index 05dafc0..506d2ac 100644 --- a/test/scripts/moduletest.py +++ b/test/scripts/moduletest.py @@ -63,11 +63,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( 382, lineNo ) + self.assertEqual( 393, lineNo ) self.assertTrue( re.search('targetapp\\.cpp', fileName ) ) self.assertEqual( 2, displacement ) fileName, lineNo, displacement = pykd.getSourceLine() - self.assertEqual( 624, lineNo ) + self.assertEqual( 639, lineNo ) def testEnumSymbols( self ): lst = target.module.enumSymbols() diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index db8ffc3..da08c61 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -80,6 +80,13 @@ class TypeInfoTest( unittest.TestCase ): self.assertEqual("Int9B", target.module.type( "Int9B" ).name() ) except pykd.SymbolException: pass + + def testBaseTypePtr(self): + self.assertEqual("Int1B*", target.module.type( "Int1B*" ).name() ) + self.assertEqual("Int1B", target.module.type( "Int1B*" ).deref().name() ) + + def testBaseTypeArray(self): + self.assertEqual("Int4B[20]", target.module.type( "Int4B[20]" ).name() ) def testName( self ): ti1 = target.module.type( "classChild" ) @@ -198,7 +205,12 @@ class TypeInfoTest( unittest.TestCase ): self.assertNotEqual( 0, ti.m_stdstr.staticOffset() ) def testUdtSubscribe(self): - tv = pykd.typeInfo( "g_virtChild" ) - self.assertEqual( 5, len(tv) ) - for field in tv: + ti = pykd.typeInfo( "g_virtChild" ) + self.assertEqual( 5, len(ti) ) + for field in ti: str( field ) + + def testStructNullSize(self): + ti = target.module.type("structNullSize") + self.assertEqual( 0, len(ti) ) + diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index 9af0bcc..640360f 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -84,6 +84,16 @@ struct structTest { structTest* m_field4; }; +struct structNullSize { +}; + +structNullSize* g_nullSizeArray = 0; + +struct structAbstract; +typedef struct structAbstract *pstructAbstract; + +pstructAbstract g_structAbstract = 0; + structWithBits g_structWithBits = { 4, 1, 3}; structTest g_structTest = { 0, 500, true, 1, NULL }; @@ -435,6 +445,9 @@ void FuncWithName0() std::cout << g_structTypeDef.m_field0; + std::cout << g_nullSizeArray; + std::cout << g_structAbstract; + //std::cout << g_virtChild.VirtualBaseClass1::m_baseField; }