From 1f350f90b7886308100d812bb1eac930eda8e4d6 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 16 Nov 2011 06:42:00 +0000 Subject: [PATCH] [0.1.x] added : typeInfo construction by type name git-svn-id: https://pykd.svn.codeplex.com/svn@71384 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgclient.cpp | 19 +++ pykd/dbgclient.h | 24 +++ pykd/dbgext.cpp | 8 +- pykd/module.cpp | 16 +- pykd/module.h | 8 +- pykd/stdafx.h | 17 +-- pykd/typedvar.cpp | 22 +-- pykd/typedvar.h | 14 +- pykd/typeinfo.cpp | 224 +++++++++++++++++++++------- pykd/typeinfo.h | 281 ++++++++++++++++++++++++++++++----- test/scripts/pykdtest.py | 4 +- test/scripts/typeinfo.py | 34 ++++- test/targetapp/targetapp.cpp | 9 ++ 13 files changed, 531 insertions(+), 149 deletions(-) diff --git a/pykd/dbgclient.cpp b/pykd/dbgclient.cpp index 899860a..5c8c3bc 100644 --- a/pykd/dbgclient.cpp +++ b/pykd/dbgclient.cpp @@ -251,4 +251,23 @@ void waitForEvent() /////////////////////////////////////////////////////////////////////////////////// +ULONG DebugClient::ptrSize() +{ + HRESULT hres; + + hres = m_control->IsPointer64Bit(); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::IsPointer64Bit failed" ); + + return S_OK == hres ? 8 : 4; +} + +ULONG ptrSize() +{ + return g_dbgClient->ptrSize(); +} + +/////////////////////////////////////////////////////////////////////////////////// + }; // end of namespace pykd \ No newline at end of file diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index be399cb..4282d41 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -119,6 +119,28 @@ public: std::wstring loadWChars( ULONG64 offset, ULONG count, bool phyAddr = FALSE ); + ULONG ptrSize(); + + LONG64 ptrByte(); + + LONG64 ptrWord(); + + LONG64 ptrDWord(); + + LONG64 ptrQWord(); + + LONG64 ptrMWord(); + + ULONG64 ptrSignByte(); + + ULONG64 ptrSignWord(); + + ULONG64 ptrSignDWord(); + + ULONG64 ptrSignQWord(); + + ULONG64 ptrSignMWord(); + void readMemory( ULONG64 address, PVOID buffer, ULONG length, bool phyAddr = FALSE ); void setExecutionStatus( ULONG status ); @@ -184,6 +206,8 @@ bool isKernelDebugging(); bool isDumpAnalyzing(); +ULONG ptrSize(); + void setExecutionStatus( ULONG status ); void waitForEvent(); diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index c8880e7..0a2600f 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -218,6 +218,8 @@ BOOST_PYTHON_MODULE( pykd ) "Print out string. If dml = True string is printed with dml highlighting ( only for windbg )" ) .def( "dprintln", &pykd::DebugClient::dprintln, "Print out string and insert end of line symbol. If dml = True string is printed with dml highlighting ( only for windbg )" ) + .def( "ptrSize", &DebugClient::ptrSize, + "Return effective pointer size" ) .def( "setExecutionStatus", &pykd::DebugClient::setExecutionStatus, "Requests that the debugger engine enter an executable state" ) .def( "step", &pykd::DebugClient::changeDebuggerStatus, @@ -281,6 +283,8 @@ BOOST_PYTHON_MODULE( pykd ) "Print out string. If dml = True string is printed with dml highlighting ( only for windbg )" ) ); python::def( "dprintln", &pykd::dprintln, dprintln_( boost::python::args( "str", "dml" ), "Print out string and insert end of line symbol. If dml = True string is printed with dml highlighting ( only for windbg )" ) ); + python::def( "ptrSize", &ptrSize, + "Return effective pointer size" ); python::def( "setExecutionStatus", &pykd::setExecutionStatus, "Requests that the debugger engine enter an executable state" ); python::def( "step", &pykd::changeDebuggerStatus, @@ -290,7 +294,7 @@ BOOST_PYTHON_MODULE( pykd ) python::def( "waitForEvent", &pykd::waitForEvent, "Wait for events that breaks into the debugger" ); - python::class_("typeInfo", "Class representing typeInfo", python::no_init ) + python::class_("typeInfo", "Class representing typeInfo", python::no_init ) .def( "name", &pykd::TypeInfo::getName ) .def( "size", &pykd::TypeInfo::getSize ) .def( "offset", &pykd::TypeInfo::getOffset ) @@ -300,7 +304,7 @@ BOOST_PYTHON_MODULE( pykd ) python::class_ >("typedVar", "Class of non-primitive type object, child class of typeClass. Data from target is copied into object instance", python::no_init ) - .def( python::init() ) + .def( python::init() ) .def("getAddress", &TypedVar::getAddress, "Return virtual address" ) .def("sizeof", &TypedVar::getSize, diff --git a/pykd/module.cpp b/pykd/module.cpp index 77fe40b..5052306 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -153,24 +153,16 @@ Module::reloadSymbols() /////////////////////////////////////////////////////////////////////////////////// -TypeInfo -Module::getTypeByName( const std::string &typeName ) -{ - return TypeInfo( getDia(), typeName ); -} - -/////////////////////////////////////////////////////////////////////////////////// - TypedVar Module::getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ) { - return TypedVar( TypeInfo( getDia(), typeName ), addr ); + return TypedVar( getTypeByName(typeName), addr ); } /////////////////////////////////////////////////////////////////////////////////// TypedVar -Module::getTypedVarByType( const TypeInfo &typeInfo, ULONG64 addr ) +Module::getTypedVarByType( const TypeInfoPtr &typeInfo, ULONG64 addr ) { return TypedVar( typeInfo, addr ); } @@ -182,7 +174,7 @@ Module::getTypedVarByName( const std::string &symName ) { pyDia::SymbolPtr typeSym = getDia()->getChildByName( symName ); - return TypedVar( TypeInfo( typeSym->getType() ), typeSym->getRva() + m_base ); + return TypedVar( TypeInfo::getTypeInfo( typeSym->getType() ), typeSym->getRva() + m_base ); } /////////////////////////////////////////////////////////////////////////////////// @@ -201,7 +193,7 @@ Module::getTypedVarByAddr( ULONG64 addr ) if (displacement) throw DbgException( "not exactly match by RVA" ); - return TypedVar( TypeInfo( diaSym->getType() ), addr ); + return TypedVar( TypeInfo::getTypeInfo( diaSym->getType() ), addr ); } /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/module.h b/pykd/module.h index bee7e00..a18b418 100644 --- a/pykd/module.h +++ b/pykd/module.h @@ -59,11 +59,13 @@ public: return sym->getRva(); } - TypeInfo getTypeByName( const std::string &typeName ); + TypeInfoPtr getTypeByName( const std::string &typeName ) { + return TypeInfo::getTypeInfo( boost::static_pointer_cast( getDia() ), typeName); + } TypedVar getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ); - TypedVar getTypedVarByType( const TypeInfo &typeInfo, ULONG64 addr ); + TypedVar getTypedVarByType( const TypeInfoPtr &typeInfo, ULONG64 addr ); TypedVar getTypedVarByAddr( ULONG64 addr ); @@ -71,7 +73,7 @@ public: private: - pyDia::GlobalScopePtr getDia() { + pyDia::GlobalScopePtr& getDia() { if (!m_dia) m_dia = pyDia::GlobalScope::loadPdb( getPdbName() ); return m_dia; diff --git a/pykd/stdafx.h b/pykd/stdafx.h index b1273e3..d1655a4 100644 --- a/pykd/stdafx.h +++ b/pykd/stdafx.h @@ -48,18 +48,5 @@ #include #pragma warning(pop) namespace python = boost::python; -// -//#include -// -//template -//TElem *getVectorBuffer(std::vector &vec) -//{ -// return vec.size() ? &vec[0] : NULL; -//} -//template -//const TElem *getVectorBuffer(const std::vector &vec) -//{ -// return vec.size() ? &vec[0] : NULL; -//} -// -//// TODO: reference additional headers your program requires here + +#include diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index fcc065b..c14fe1b 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -7,22 +7,22 @@ namespace pykd { /////////////////////////////////////////////////////////////////////////////////// -TypedVar::TypedVar ( IDebugClient4 *client, const TypeInfo& typeInfo, ULONG64 offset ) : +TypedVar::TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : DbgObject( client ), m_typeInfo( typeInfo ), m_offset( offset ) { - m_size = m_typeInfo.getSize(); + m_size = m_typeInfo->getSize(); } /////////////////////////////////////////////////////////////////////////////////// -TypedVar::TypedVar( const TypeInfo& typeInfo, ULONG64 offset ) : +TypedVar::TypedVar( const TypeInfoPtr& typeInfo, ULONG64 offset ) : DbgObject( g_dbgClient->client() ), m_typeInfo( typeInfo ), m_offset( offset ) { - m_size = m_typeInfo.getSize(); + m_size = m_typeInfo->getSize(); } /////////////////////////////////////////////////////////////////////////////////// @@ -30,25 +30,25 @@ TypedVar::TypedVar( const TypeInfo& typeInfo, ULONG64 offset ) : TypedVarPtr TypedVar::getField( const std::string &fieldName ) { - TypeInfo fieldType = m_typeInfo.getField( fieldName ); + TypeInfoPtr fieldType = m_typeInfo->getField( fieldName ); TypedVarPtr tv; - if ( fieldType.isBasicType() ) + if ( fieldType->isBasicType() ) { - tv.reset( new BasicTypedVar( m_client, fieldType, m_offset + fieldType.getOffset() ) ); + tv.reset( new BasicTypedVar( m_client, fieldType, m_offset + fieldType->getOffset() ) ); return tv; } - if ( fieldType.isPointer() ) + if ( fieldType->isPointer() ) { - tv.reset( new PtrTypedVar( m_client, fieldType, m_offset + fieldType.getOffset() ) ); + tv.reset( new PtrTypedVar( m_client, fieldType, m_offset + fieldType->getOffset() ) ); return tv; } - if ( fieldType.isUserDefined() ) + if ( fieldType->isUserDefined() ) { - tv.reset( new TypedVar( m_client, fieldType, m_offset + fieldType.getOffset() ) ); + tv.reset( new TypedVar( m_client, fieldType, m_offset + fieldType->getOffset() ) ); return tv; } diff --git a/pykd/typedvar.h b/pykd/typedvar.h index cdd59c7..03d4abe 100644 --- a/pykd/typedvar.h +++ b/pykd/typedvar.h @@ -17,10 +17,10 @@ class TypedVar : public intBase, protected DbgObject { public: - TypedVar ( const TypeInfo& typeInfo, ULONG64 offset ); + TypedVar ( const TypeInfoPtr& typeInfo, ULONG64 offset ); - TypedVar ( IDebugClient4 *client, const TypeInfo& typeInfo, ULONG64 offset ); + TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ); ULONG64 getAddress() const { return m_offset; @@ -31,10 +31,10 @@ public: } ULONG getOffset() { - return m_typeInfo.getOffset(); + return m_typeInfo->getOffset(); } - TypeInfo + TypeInfoPtr getType() const { return m_typeInfo; } @@ -55,7 +55,7 @@ protected: throw DbgException("can not change"); } - TypeInfo m_typeInfo; + TypeInfoPtr m_typeInfo; ULONG64 m_offset; @@ -68,7 +68,7 @@ class BasicTypedVar : public TypedVar { public: - BasicTypedVar ( IDebugClient4 *client, const TypeInfo& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){} + BasicTypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){} TypedVarPtr virtual getField( const std::string &fieldName ) { @@ -89,7 +89,7 @@ class PtrTypedVar : public TypedVar { public: - PtrTypedVar ( IDebugClient4 *client, const TypeInfo& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){} + PtrTypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){} TypedVarPtr virtual getField( const std::string &fieldName ) { diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index 9724b9f..25e9c4c 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -4,90 +4,206 @@ namespace pykd { -/////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// -TypeInfo::TypeInfo( pyDia::GlobalScopePtr &diaScope, const std::string &symName ) : - m_offset( 0 ) +TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &typeSym ) { - pyDia::SymbolPtr typeSym = diaScope->getChildByName( symName ); + ULONG tag = typeSym->getSymTag(); - if ( typeSym->getSymTag() == SymTagData ) + switch( typeSym->getSymTag() ) { - m_dia = typeSym->getType(); - } - else - { - m_dia = typeSym; + case SymTagBaseType: + return getBaseTypeInfo( typeSym ); + + case SymTagUDT: + return TypeInfoPtr( new UdtTypeInfo( typeSym ) ); + + case SymTagArrayType: + return TypeInfoPtr( new ArrayTypeInfo( typeSym ) ); + + case SymTagPointerType: + return TypeInfoPtr( new PointerTypeInfo( typeSym ) ); } + + throw DbgException( "type name invalid" ); } -/////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// -std::string -TypeInfo::getName() +static const boost::regex arrayMatch("^(.*)\\[(\\d+)\\]$"); + +TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName ) { - std::stringstream sstr; + size_t pos = symName.find_first_of( "*[" ); - pyDia::SymbolPtr diaptr = m_dia; + if ( pos == std::string::npos ) + { + TypeInfoPtr basePtr = getBaseTypeInfo( symName ); + if ( basePtr != 0 ) + return basePtr; + + pyDia::SymbolPtr typeSym = symScope->getChildByName( symName ); + + if ( typeSym->getSymTag() == SymTagData ) + typeSym = typeSym->getType(); + + return getTypeInfo( typeSym ); + } - int symtag = diaptr->getSymTag(); + if ( symName[ symName.size() - 1 ] == '*' ) + return TypeInfoPtr( new PointerTypeInfo( symScope,symName.substr( 0, symName.size() - 1 ) ) ); - while( symtag == SymTagArrayType || symtag == SymTagPointerType ) + boost::cmatch matchResult; + + if ( boost::regex_match( symName.c_str(), matchResult, arrayMatch ) ) { - if ( symtag == SymTagArrayType ) - { - sstr << '[' << diaptr->getCount() << ']'; - } - else - { - sstr << '*'; - } + std::string sym = std::string( matchResult[1].first, matchResult[1].second ); - diaptr = diaptr->getType(); - symtag = diaptr->getSymTag(); + return TypeInfoPtr( new ArrayTypeInfo( symScope, sym, std::atoi( matchResult[2].first ) ) ); } - std::string typeName = symtag == SymTagBaseType ? - diaptr->getBasicTypeName( diaptr->getBaseType() ) : - diaptr->getName(); - typeName += sstr.str(); - - return typeName; -}; - -/////////////////////////////////////////////////////////////////////////////////// - -bool -TypeInfo::isBasicType() -{ - return m_dia->getSymTag() == SymTagBaseType; + throw DbgException( "type name invalid" ); } -/////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// -bool -TypeInfo::isArrayType() +static const boost::regex baseMatch("^(Char)|(WChar)|(Int2B)|(UInt2B)|(Int4B)|(UInt4B)|(Int8B)|(UInt8B)|(Long)|(ULong)|(Float)|(Bool)$" ); + +TypeInfoPtr +TypeInfo::getBaseTypeInfo( const std::string &symName ) { - return m_dia->getSymTag() == SymTagArrayType; + boost::cmatch baseMatchResult; + + if ( boost::regex_match( symName.c_str(), baseMatchResult, baseMatch ) ) + { + if ( baseMatchResult[1].matched ) + return TypeInfoPtr( new TypeInfoWrapper("Char") ); + + if ( baseMatchResult[2].matched ) + return TypeInfoPtr( new TypeInfoWrapper("WChar") ); + + if ( baseMatchResult[3].matched ) + return TypeInfoPtr( new TypeInfoWrapper("Int2B") ); + + if ( baseMatchResult[4].matched ) + return TypeInfoPtr( new TypeInfoWrapper("UInt2B") ); + + if ( baseMatchResult[5].matched ) + return TypeInfoPtr( new TypeInfoWrapper("Int4B") ); + + if ( baseMatchResult[6].matched ) + return TypeInfoPtr( new TypeInfoWrapper("UInt4B") ); + + if ( baseMatchResult[7].matched ) + return TypeInfoPtr( new TypeInfoWrapper<__int64>("Int8B") ); + + if ( baseMatchResult[8].matched ) + return TypeInfoPtr( new TypeInfoWrapper("UInt8B") ); + + if ( baseMatchResult[9].matched ) + return TypeInfoPtr( new TypeInfoWrapper("Long") ); + + if ( baseMatchResult[10].matched ) + return TypeInfoPtr( new TypeInfoWrapper("ULong") ); + + if ( baseMatchResult[11].matched ) + return TypeInfoPtr( new TypeInfoWrapper("Float") ); + + if ( baseMatchResult[12].matched ) + return TypeInfoPtr( new TypeInfoWrapper("Bool") ); + } + + return TypeInfoPtr(); } -/////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// -bool -TypeInfo::isPointer() +TypeInfoPtr +TypeInfo::getBaseTypeInfo( pyDia::SymbolPtr &symbol ) { - return m_dia->getSymTag() == SymTagPointerType; + std::string symName = symbol->getBasicTypeName( symbol->getBaseType() ); + + if ( symName == "Int" || symName == "UInt" ) + { + std::stringstream sstr; + sstr << symName << symbol->getSize() << "B"; + + return getBaseTypeInfo( sstr.str() ); + } + + TypeInfoPtr ptr = getBaseTypeInfo( symName ); + + if ( ptr == 0 ) + ptr = TypeInfoPtr( new BaseTypeInfo( symbol ) ); + + return ptr; } -/////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// -bool -TypeInfo::isUserDefined() +PointerTypeInfo::PointerTypeInfo( pyDia::SymbolPtr &symbol ) { - return m_dia->getSymTag() == SymTagUDT; + m_derefType = TypeInfo::getTypeInfo( symbol->getType() ); + m_size = (ULONG)symbol->getSize(); } -/////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +PointerTypeInfo::PointerTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName ) +{ + m_derefType = TypeInfo::getTypeInfo( symScope, symName ); + m_size = symScope->getMachineType() == CV_CFL_X64 ? 8 : 4; +} + +///////////////////////////////////////////////////////////////////////////////////// + +std::string PointerTypeInfo::getName() +{ + return m_derefType->getName() + '*'; +} + +///////////////////////////////////////////////////////////////////////////////////// + +ULONG PointerTypeInfo::getSize() +{ + return m_size; +} + +///////////////////////////////////////////////////////////////////////////////////// + +ArrayTypeInfo::ArrayTypeInfo( pyDia::SymbolPtr &symbol ) +{ + m_derefType = TypeInfo::getTypeInfo( symbol->getType() ); + m_count = symbol->getCount(); +} + +///////////////////////////////////////////////////////////////////////////////////// + +ArrayTypeInfo::ArrayTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName, ULONG count ) +{ + m_derefType = TypeInfo::getTypeInfo( symScope, symName ); + m_count = count; +} + +///////////////////////////////////////////////////////////////////////////////////// + +std::string ArrayTypeInfo::getName() +{ + std::stringstream sstr; + + sstr << m_derefType->getName() << '[' << m_count << ']'; + + return sstr.str(); +} + +///////////////////////////////////////////////////////////////////////////////////// + +ULONG ArrayTypeInfo::getSize() +{ + return m_derefType->getSize() * m_count; +} + +///////////////////////////////////////////////////////////////////////////////////// }; // end namespace pykd \ No newline at end of file diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index 5814ff4..95e7a93 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -8,57 +8,266 @@ namespace pykd { /////////////////////////////////////////////////////////////////////////////////// -class TypeInfo { +class TypeInfo; +typedef boost::shared_ptr TypeInfoPtr; + +/////////////////////////////////////////////////////////////////////////////////// + +class TypeInfo : boost::noncopyable { public: - TypeInfo( pyDia::GlobalScopePtr &diaScope, const std::string &symName ); + static + TypeInfoPtr getTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName ); - TypeInfo( pyDia::SymbolPtr &diaType ) : - m_offset( 0 ), - m_dia( diaType ) - {} + static + TypeInfoPtr getTypeInfo( pyDia::SymbolPtr &symbol ); - TypeInfo - getField( const std::string &fieldName ) { - pyDia::SymbolPtr field = m_dia->getChildByName( fieldName ); - TypeInfo ti( field->getType() ); - ti.m_offset = field->getOffset(); - return ti; + static + TypeInfoPtr getBaseTypeInfo( const std::string &name ); + + static + TypeInfoPtr getBaseTypeInfo( pyDia::SymbolPtr &symbol ); + +public: + + virtual std::string getName() = 0; + + virtual ULONG getSize() = 0; + + virtual TypeInfoPtr getField( const std::string &fieldName ) = 0; + + virtual bool isBasicType() { + return false; } - std::string - getName(); + virtual bool isPointer() { + return false; + } - ULONG - getOffset() { + virtual bool isUserDefined() { + return false; + } + + ULONG getOffset() { return m_offset; } - ULONG - getSize() { - return (ULONG)m_dia->getSize(); - } + void setOffset( ULONG offset ) { + m_offset = offset; + } - bool - isBasicType(); +protected: - bool - isArrayType(); - - bool - isPointer(); - - bool - isUserDefined(); - -private: - - pyDia::SymbolPtr m_dia; - - ULONG m_offset; + ULONG m_offset; }; /////////////////////////////////////////////////////////////////////////////////// +class BaseTypeInfo : public TypeInfo +{ +public: + + BaseTypeInfo( pyDia::SymbolPtr &symbol ) : + m_dia( symbol ) + {} + +protected: + + virtual std::string getName() { + return m_dia->getBasicTypeName( m_dia->getBaseType() ); + } + + virtual ULONG getSize() { + return (ULONG)m_dia->getSize(); + } + + virtual TypeInfoPtr getField( const std::string &fieldName ) { + throw DbgException( "there is no such field" ); + } + + virtual bool isBasicType() { + return true; + } + + pyDia::SymbolPtr m_dia; + +}; + +/////////////////////////////////////////////////////////////////////////////////// + +template +class TypeInfoWrapper : public TypeInfo +{ +public: + TypeInfoWrapper( const std::string &name ) : + m_name(name) + {} + +private: + + virtual std::string getName() { + return m_name; + } + + virtual ULONG getSize() { + return sizeof(T); + } + + virtual TypeInfoPtr getField( const std::string &fieldName ) { + throw DbgException( "there is no such field" ); + } + + virtual bool isBasicType() { + return true; + } + + std::string m_name; + +}; + +/////////////////////////////////////////////////////////////////////////////////// + +class UdtTypeInfo : public BaseTypeInfo +{ +public: + + UdtTypeInfo ( pyDia::SymbolPtr &symbol ) : + BaseTypeInfo( symbol ) + {} + + virtual std::string getName() { + return m_dia->getName(); + } + + virtual TypeInfoPtr getField( const std::string &fieldName ) { + pyDia::SymbolPtr field = m_dia->getChildByName( fieldName ); + TypeInfoPtr ti = TypeInfo::getTypeInfo( m_dia, fieldName ); + ti->setOffset( field->getOffset() ); + return ti; + } + + virtual bool isUserDefined() { + return true; + } +}; + +/////////////////////////////////////////////////////////////////////////////////// + +class PointerTypeInfo : public TypeInfo { + +public: + + PointerTypeInfo( pyDia::SymbolPtr &symbol ); + + PointerTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName ); + + virtual std::string getName(); + + virtual ULONG getSize(); + + virtual TypeInfoPtr getField( const std::string &fieldName ) { + throw DbgException( "there is no such field" ); + } + + virtual bool isPointer() { + return true; + } + +private: + + TypeInfoPtr m_derefType; + + ULONG m_size; +}; + +/////////////////////////////////////////////////////////////////////////////////// + +class ArrayTypeInfo : public TypeInfo { + +public: + + ArrayTypeInfo( pyDia::SymbolPtr &symbol ); + + ArrayTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName, ULONG count ); + + virtual std::string getName(); + + virtual ULONG getSize(); + + virtual TypeInfoPtr getField( const std::string &fieldName ) { + throw DbgException( "there is no such field" ); + } + +private: + + TypeInfoPtr m_derefType; + + ULONG m_count; +}; + +/////////////////////////////////////////////////////////////////////////////////// + + + + + + + + +// +//class TypeInfo { +// +//public: +// +// TypeInfo( pyDia::GlobalScopePtr &diaScope, const std::string &symName ); +// +// TypeInfo( pyDia::SymbolPtr &diaType ) : +// m_offset( 0 ), +// m_dia( diaType ) +// {} +// +// TypeInfo +// getField( const std::string &fieldName ) { +// pyDia::SymbolPtr field = m_dia->getChildByName( fieldName ); +// TypeInfo ti( field->getType() ); +// ti.m_offset = field->getOffset(); +// return ti; +// } +// +// std::string +// getName(); +// +// ULONG +// getOffset() { +// return m_offset; +// } +// +// ULONG +// getSize() { +// return (ULONG)m_dia->getSize(); +// } +// +// bool +// isBasicType(); +// +// bool +// isArrayType(); +// +// bool +// isPointer(); +// +// bool +// isUserDefined(); +// +//private: +// +// pyDia::SymbolPtr m_dia; +// +// ULONG m_offset; +// +//}; + +/////////////////////////////////////////////////////////////////////////////////// + }; // namespace pykd diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py index ef0f5f2..5a480d2 100644 --- a/test/scripts/pykdtest.py +++ b/test/scripts/pykdtest.py @@ -52,6 +52,8 @@ if __name__ == "__main__": target.module.reload(); suite = getTestSuite() - #suite = getTestSuite( "typedvar.TypedVarTest.testCtor" ) + #suite = getTestSuite( "typeinfo.TypeInfoTest" ) unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( suite ) + + a = raw_input("\npress return\n") \ No newline at end of file diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index ff14cf2..a300bc3 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -15,29 +15,46 @@ class TypeInfoTest( unittest.TestCase ): def testCreateByName( self ): """ creating typeInfo by the type name """ - ti1 = target.module.type( "structTest" ) - ti2 = target.module.type( "classChild" ) + #self.assertEqual( "structTest", target.module.type( "structTest" ).name() ) + #self.assertEqual( "structTest**", target.module.type( "structTest**" ).name() ) + self.assertEqual( "Int4B[2][3]", target.module.type("Int4B[2][3]").name() ) def testGetField( self ): """ get field of the complex type """ ti1 = target.module.type( "structTest" ) self.assertTrue( hasattr( ti1, "m_field0" ) ) try: hasattr(ti1, "m_field4" ) # non-exsisting field - except pykd.DiaException: pass + except pykd.BaseException: pass + + def testBaseTypes( self ): + self.assertEqual( 1, target.module.type("Char").size() ) + self.assertEqual( 2, target.module.type("WChar").size() ) + self.assertEqual( 2, target.module.type("Int2B").size() ) + self.assertEqual( 2, target.module.type("UInt2B").size() ) + self.assertEqual( 4, target.module.type("Int4B").size() ) + self.assertEqual( 4, target.module.type("UInt4B").size() ) + self.assertEqual( 8, target.module.type("Int8B").size() ) + self.assertEqual( 8, target.module.type("UInt8B").size() ) def testName( self ): ti1 = target.module.type( "classChild" ) self.assertEqual( "classChild", ti1.name() ) - self.assertEqual( "Int", ti1.m_childField.name() ) + self.assertEqual( "Int4B", ti1.m_childField.name() ) self.assertEqual( "structTest", ti1.m_childField3.name() ) self.assertEqual( "structTest", target.module.type("g_structTest").name() ) - def testArrayName( self ): - self.assertEqual( "structTest[2]", target.module.type("g_testArray").name() ) - def testPtrName( self ): self.assertEqual( "structTest*", target.module.type("g_structTestPtr").name() ) - self.assertEqual( "structTest**", target.module.type("g_structTestPtrPtr").name() ) + self.assertEqual( "structTest**", target.module.type("g_structTestPtrPtr").name() ) + self.assertEqual( "structTest**", target.module.type("structTest**").name() ) + + def testArrayName( self ): + self.assertEqual( "structTest[2]", target.module.type("g_testArray").name() ) + self.assertEqual( "Int4B[2][3]", target.module.type("intMatrix").name() ) + self.assertEqual( "Char*[2]", target.module.type("strArray").name() ) + self.assertEqual( "Int4B[2][3]*",target.module.type("ptrIntMatrix").name() ) + self.assertEqual( "Char*[2]*", target.module.type("ptrStrArray").name() ) + self.assertEqual( "Int4B[2][3]", target.module.type("Int[2][3]").name() ) def testOffset( self ): ti1 = target.module.type( "structTest" ) @@ -49,4 +66,5 @@ class TypeInfoTest( unittest.TestCase ): def testSize( self ): ti1 = target.module.type( "structTest" ) self.assertEqual( 20, ti1.size() ) + self.assertEqual( pykd.ptrSize(), target.module.type("structTest**").size() ) diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index 1003ae0..940ec22 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -64,6 +64,11 @@ unsigned short ushortArray[] = {0, 10, 0xFF, 0x8000, 0xFFFF }; unsigned long ulongArray[] = {0, 0xFF, 0x8000, 0x80000000, 0xFFFFFFFF }; unsigned __int64 ulonglongArray[] = {0, 0xFF, 0xFFFFFFFF, 0x8000000000000000, 0xFFFFFFFFFFFFFFFF }; +int intMatrix[2][3] = { { 0, 1, 2}, { 3, 4, 5 } }; +char* strArray[] = { "hello", "bye" }; +int (*ptrIntMatrix)[2][3] = &intMatrix; +char *(*ptrStrArray)[2] = &strArray; + class classChild : public classBase { public: int m_childField; @@ -105,6 +110,10 @@ void FuncWithName0() std::cout << ushortArray[2]; std::cout << ulongArray[2]; std::cout << ulonglongArray[2]; + + std::cout << intMatrix[1][1]; + std::cout << strArray[0]; + std::cout << (*ptrIntMatrix)[0][1]; } void FuncWithName1(int a)