diff --git a/pykd/dbgclient.cpp b/pykd/dbgclient.cpp index b4665ff..9aecc37 100644 --- a/pykd/dbgclient.cpp +++ b/pykd/dbgclient.cpp @@ -591,9 +591,7 @@ TypedVarPtr DebugClient::containingRecordByType( ULONG64 addr, const TypeInfoPtr { addr = addr64(addr); - TypeInfoPtr fieldTypeInfo = typeInfo->getField( fieldName ); - - VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, addr - fieldTypeInfo->getOffset() ); + VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, addr - typeInfo->getFieldOffsetByNameRecirsive(fieldName) ); return TypedVar::getTypedVar( m_client, typeInfo, varData ); } @@ -617,7 +615,7 @@ python::list DebugClient::getTypedVarListByType( ULONG64 listHeadAddress, const if ( fieldTypeInfo->getName() == ( typeInfo->getName() + "*" ) ) { - for( entryAddress = ptrPtr( listHeadAddress ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress + fieldTypeInfo->getOffset() ) ) + for( entryAddress = ptrPtr( listHeadAddress ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress + typeInfo->getFieldOffsetByNameRecirsive(listEntryName) ) ) lst.append( getTypedVarByTypeInfo( typeInfo, entryAddress ) ); } else diff --git a/pykd/module.cpp b/pykd/module.cpp index 4eaf0b8..5c74aa9 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -322,9 +322,11 @@ TypedVarPtr Module::containingRecordByName( ULONG64 address, const std::string & TypeInfoPtr typeInfo = getTypeByName( typeName ); - TypeInfoPtr fieldTypeInfo = typeInfo->getField( fieldName ); - - VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, address - fieldTypeInfo->getOffset() ); + VarDataPtr varData = + VarDataMemory::factory( + m_dataSpaces, + address - typeInfo->getFieldOffsetByNameRecirsive( fieldName ) + ); return TypedVar::getTypedVar( m_client, typeInfo, varData ); } @@ -335,9 +337,11 @@ TypedVarPtr Module::containingRecordByType( ULONG64 address, const TypeInfoPtr & { address = addr64(address); - TypeInfoPtr fieldTypeInfo = typeInfo->getField( fieldName ); - - VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, address - fieldTypeInfo->getOffset() ); + VarDataPtr varData = + VarDataMemory::factory( + m_dataSpaces, + address - typeInfo->getFieldOffsetByNameRecirsive( fieldName ) + ); return TypedVar::getTypedVar( m_client, typeInfo, varData ); } @@ -364,7 +368,7 @@ python::list Module::getTypedVarListByType( ULONG64 listHeadAddress, const TypeI if ( fieldTypeInfo->getName() == ( typeInfo->getName() + "*" ) ) { - for( entryAddress = ptrPtr( listHeadAddress, m_dataSpaces ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress + fieldTypeInfo->getOffset() ) ) + for( entryAddress = ptrPtr( listHeadAddress, m_dataSpaces ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrPtr( entryAddress + typeInfo->getFieldOffsetByNameRecirsive(listEntryName) ) ) lst.append( getTypedVarByType( typeInfo, entryAddress ) ); } else diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index 418219c..a4ec4bc 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -493,6 +493,10 @@ RelativePath=".\typeinfo.cpp" > + + @@ -615,6 +619,10 @@ RelativePath=".\typeinfo.h" > + + diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 2af674a..8c609a6 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -546,7 +546,8 @@ BOOST_PYTHON_MODULE( pykd ) .def("__init__", python::make_constructor(TypeInfo::getTypeInfoByName ) ) .def( "name", &TypeInfo::getName ) .def( "size", &TypeInfo::getSize ) - .def( "offset", &TypeInfo::getTypeOffset ) + .def( "staticOffset", &TypeInfo::getStaticOffset ) + .def( "fieldOffset", &TypeInfo::getFieldOffsetByNameRecirsive ) .def( "bitOffset", &TypeInfo::getBitOffset ) .def( "bitWidth", &TypeInfo::getBitWidth ) .def( "field", &TypeInfo::getField ) @@ -566,8 +567,8 @@ BOOST_PYTHON_MODULE( pykd ) "Return virtual address" ) .def("sizeof", &TypedVar::getSize, "Return size of a variable in the target memory" ) - .def("offset", &TypedVar::getOffset, - "Return offset to parent" ) + .def("fieldOffset", &TypedVar::getFieldOffsetByNameRecirsive, + "Return target field offset" ) .def("field", &TypedVar::getField, "Return field of structure as an object attribute" ) .def( "dataKind", &TypedVar::getDataKind, diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index 1faef89..ffea67b 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -240,7 +240,7 @@ UdtTypedVar::getField( const std::string &fieldName ) ULONG fieldOffset = 0; - fieldOffset = fieldType->getOffset(); + fieldOffset = m_typeInfo->getFieldOffsetByNameRecirsive(fieldName); if ( fieldType->isVirtualMember() ) { @@ -267,7 +267,7 @@ UdtTypedVar::getElementByIndex( ULONG index ) TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) ) ); } - ULONG fieldOffset = fieldType->getOffset(); + ULONG fieldOffset = m_typeInfo->getFieldOffsetByIndex(index); if ( fieldType->isVirtualMember() ) { @@ -320,7 +320,7 @@ std::string UdtTypedVar::print() } else { - ULONG fieldOffset = fieldType->getOffset(); + ULONG fieldOffset = m_typeInfo->getFieldOffsetByIndex(i); if ( fieldType->isVirtualMember() ) { diff --git a/pykd/typedvar.h b/pykd/typedvar.h index 11211bb..4350af6 100644 --- a/pykd/typedvar.h +++ b/pykd/typedvar.h @@ -35,8 +35,8 @@ public: return m_size; } - ULONG64 getOffset() { - return m_typeInfo->getOffset(); + ULONG getFieldOffsetByNameRecirsive(const std::string &fieldName) { + return m_typeInfo->getFieldOffsetByNameRecirsive(fieldName); } TypeInfoPtr diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index 6e826f4..0cefe37 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -483,7 +483,8 @@ TypeInfoPtr TypeInfo::getRecurciveComplexType( TypeInfoPtr &lowestType, std::str ///////////////////////////////////////////////////////////////////////////////////// -ULONG64 TypeInfo::getStaticOffset() { +ULONG64 TypeInfo::getStaticOffset() +{ if ( !m_staticMember ) throw TypeException( getName(), "This is not a static member" ); @@ -492,83 +493,9 @@ ULONG64 TypeInfo::getStaticOffset() { ///////////////////////////////////////////////////////////////////////////////////// -ULONG TypeInfo::getOffset() { - - if ( m_staticOffset ) - throw TypeException( getName(), "This is a static member" ); - - return m_offset; -} - -///////////////////////////////////////////////////////////////////////////////////// - -ULONG64 TypeInfo::getTypeOffset() -{ - return m_staticMember ? m_staticOffset : m_offset; -} - -///////////////////////////////////////////////////////////////////////////////////// - -TypeInfoPtr UdtTypeInfo::getField( const std::string &fieldName ) -{ - if ( m_fields.empty() ) - { - getFields( m_dia, pyDia::SymbolPtr() ); - getVirtualFields(); - } - - FieldList::reverse_iterator it; - - it = std::find_if( m_fields.rbegin(), m_fields.rend(), boost::bind( &FieldType::first, _1) == fieldName ); - - if ( it == m_fields.rend() ) - throw TypeException( m_dia->getName(), fieldName + ": unknown field type" ); - - return it->second; -} - -///////////////////////////////////////////////////////////////////////////////////// - -TypeInfoPtr UdtTypeInfo::getFieldByIndex( ULONG index ) -{ - if ( m_fields.empty() ) - { - getFields( m_dia, pyDia::SymbolPtr() ); - getVirtualFields(); - } - - if ( index >= m_fields.size() ) - throw PyException( PyExc_IndexError, "Index out of range"); - - return m_fields[ index ].second; -} - -///////////////////////////////////////////////////////////////////////////////////// - -std::string UdtTypeInfo::getFieldNameByIndex( ULONG index ) -{ - if ( m_fields.empty() ) - { - getFields( m_dia, pyDia::SymbolPtr() ); - getVirtualFields(); - } - - if ( index >= m_fields.size() ) - throw PyException( PyExc_IndexError, "Index out of range"); - - return m_fields[ index ].first; -} - -///////////////////////////////////////////////////////////////////////////////////// - ULONG UdtTypeInfo::getFieldCount() { - if ( m_fields.empty() ) - { - getFields( m_dia, pyDia::SymbolPtr() ); - getVirtualFields(); - } - + refreshFields(); return (ULONG)m_fields.size(); } @@ -577,12 +504,12 @@ ULONG UdtTypeInfo::getFieldCount() void UdtTypeInfo::getFields( pyDia::SymbolPtr &rootSym, pyDia::SymbolPtr &baseVirtualSym, - ULONG startOffset, + ULONG startOffset, LONG virtualBasePtr, ULONG virtualDispIndex, ULONG virtualDispSize ) { - ULONG childCount = rootSym->getChildCount(); + ULONG childCount = rootSym->getChildCount(); for ( ULONG i = 0; i < childCount; ++i ) { @@ -602,6 +529,7 @@ void UdtTypeInfo::getFields( { TypeInfoPtr ti = TypeInfo::getTypeInfo( rootSym, childSym ); + ULONG fieldOffset = 0; switch ( childSym->getDataKind() ) { case DataIsMember: @@ -615,16 +543,15 @@ void UdtTypeInfo::getFields( virtualDispSize ); } - ti->setOffset( startOffset + childSym->getOffset() ); - + fieldOffset = startOffset + childSym->getOffset(); break; case DataIsStaticMember: ti->setStaticOffset( childSym->getVa() ); - break; + break; } - m_fields.push_back( std::make_pair( childSym->getName(), ti ) ); + m_fields.push_back( UdtUtils::Field( fieldOffset, childSym->getName(), ti ) ); } else if ( symTag == SymTagVTable ) @@ -641,9 +568,7 @@ void UdtTypeInfo::getFields( } - ti->setOffset( startOffset + childSym->getOffset() ); - - m_fields.push_back( std::make_pair( "__VFN_table", ti ) ); + m_fields.push_back( UdtUtils::Field( childSym->getOffset(), "__VFN_table", ti ) ); } } } @@ -673,6 +598,17 @@ void UdtTypeInfo::getVirtualFields() ///////////////////////////////////////////////////////////////////////////////////// +void UdtTypeInfo::refreshFields() +{ + if ( m_fields.empty() ) + { + getFields( m_dia, pyDia::SymbolPtr() ); + getVirtualFields(); + } +} + +///////////////////////////////////////////////////////////////////////////////////// + std::string UdtTypeInfo::print() { std::stringstream sstr; @@ -682,28 +618,29 @@ std::string UdtTypeInfo::print() ULONG fieldCount = getFieldCount(); for ( ULONG i = 0; i < fieldCount; ++i ) - { - TypeInfoPtr fieldType = getFieldByIndex(i); + { + const UdtUtils::Field &udtField = lookupField(i); + TypeInfoPtr fieldType = udtField.m_type; if ( fieldType->isStaticMember() ) { sstr << " =" << std::right << std::setw(10) << std::setfill('0') << std::hex << fieldType->getStaticOffset(); - sstr << " " << std::left << std::setw(18) << std::setfill(' ') << getFieldNameByIndex(i) << ':'; + sstr << " " << std::left << std::setw(18) << std::setfill(' ') << udtField.m_name << ':'; } else if ( fieldType->isVirtualMember() ) - { + { ULONG virtualBasePtr, virtualDispIndex, virtualDispSize; fieldType->getVirtualDisplacement( virtualBasePtr, virtualDispIndex, virtualDispSize ); sstr << " virtual base " << fieldType->getVirtualBase()->getName(); - sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldType->getOffset(); - sstr << " " << getFieldNameByIndex(i) << ':'; + sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << udtField.m_offset; + sstr << " " << udtField.m_name << ':'; } else { - sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldType->getOffset(); - sstr << " " << std::left << std::setw(24) << std::setfill(' ') << getFieldNameByIndex(i) << ':'; + sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << udtField.m_offset; + sstr << " " << std::left << std::setw(24) << std::setfill(' ') << udtField.m_name << ':'; } sstr << " " << std::left << fieldType->getName(); @@ -715,11 +652,9 @@ std::string UdtTypeInfo::print() ///////////////////////////////////////////////////////////////////////////////////// -TypeInfoPtr EnumTypeInfo::getField( const std::string &fieldName ) { - pyDia::SymbolPtr field = m_dia->getChildByName( fieldName ); - TypeInfoPtr ti = TypeInfo::getTypeInfo( m_dia, fieldName ); - ti->setOffset( 0 ); - return ti; +TypeInfoPtr EnumTypeInfo::getField( const std::string &fieldName ) +{ + return TypeInfo::getTypeInfo( m_dia, fieldName ); } ///////////////////////////////////////////////////////////////////////////////////// @@ -734,9 +669,7 @@ TypeInfoPtr EnumTypeInfo::getFieldByIndex( ULONG index ) if ( !field ) throw TypeException( m_dia->getName(), ": field not found" ); - TypeInfoPtr ti = TypeInfo::getTypeInfo( m_dia, field->getName() ); - ti->setOffset( 0 ); - return ti; + return TypeInfo::getTypeInfo( m_dia, field->getName() ); } ///////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index f0f4c70..45e06a0 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -2,6 +2,9 @@ #include +#include + +#include "udtutils.h" #include "diawrapper.h" #include "intbase.h" @@ -14,7 +17,7 @@ typedef boost::shared_ptr TypeInfoPtr; /////////////////////////////////////////////////////////////////////////////////// -class TypeInfo : boost::noncopyable, public intBase { +class TypeInfo : boost::noncopyable, public intBase, public boost::enable_shared_from_this { public: @@ -42,7 +45,6 @@ public: public: TypeInfo() : - m_offset( 0 ), m_staticOffset( 0 ), m_constant( false ), m_staticMember( false ), @@ -77,6 +79,17 @@ public: throw TypeException( getName(), "type is not a struct" ); } + virtual ULONG getFieldOffsetByNameRecirsive( const std::string &fieldName ) { + throw TypeException( getName(), "type is not a struct" ); + } + virtual ULONG getFieldOffsetByNameNotRecursively( const std::string &fieldName ) { + throw TypeException( getName(), "type is not a struct" ); + } + + virtual ULONG getFieldOffsetByIndex( ULONG index ) { + throw TypeException( getName(), "type is not a struct" ); + } + virtual ULONG getFieldCount() { throw TypeException( getName(), "type is not a struct" ); } @@ -139,10 +152,6 @@ public: throw PyException( PyExc_TypeError, "object is unsubscriptable"); } - void setOffset( ULONG offset ) { - m_offset = offset; - } - void setConstant( const VARIANT& var ) { m_constant = true; @@ -177,10 +186,6 @@ public: m_virtualDispSize = virtualDispSize; } - ULONG64 getTypeOffset(); - - ULONG getOffset(); - ULONG64 getStaticOffset(); void getVirtualDisplacement( ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) { @@ -203,8 +208,6 @@ protected: static TypeInfoPtr getRecurciveComplexType( TypeInfoPtr &lowestType, std::string &suffix, ULONG ptrSize ); - ULONG m_offset; - ULONG64 m_staticOffset; bool m_constant; @@ -221,7 +224,7 @@ protected: ULONG m_virtualDispSize; - TypeInfoPtr m_virtualBaseType; + TypeInfoPtr m_virtualBaseType; }; /////////////////////////////////////////////////////////////////////////////////// @@ -295,8 +298,10 @@ class UdtTypeInfo : public TypeInfo public: UdtTypeInfo ( pyDia::SymbolPtr &symbol ) : - m_dia( symbol ) - {} + m_dia( symbol ), + m_fields( symbol->getName() ) + { + } protected: @@ -308,11 +313,28 @@ protected: return (ULONG)m_dia->getSize(); } - virtual TypeInfoPtr getField( const std::string &fieldName ); + virtual TypeInfoPtr getField( const std::string &fieldName ) { + return lookupField(fieldName).m_type; + } - virtual TypeInfoPtr getFieldByIndex( ULONG index ); + virtual TypeInfoPtr getFieldByIndex( ULONG index ) { + return lookupField(index).m_type; + } - virtual std::string getFieldNameByIndex( ULONG index ); + virtual std::string getFieldNameByIndex( ULONG index ) { + return lookupField(index).m_name; + } + + virtual ULONG getFieldOffsetByNameRecirsive( const std::string &fieldName ) { + return UdtUtils::getFiledOffsetRecirsive( shared_from_this(), fieldName ); + } + virtual ULONG getFieldOffsetByNameNotRecursively( const std::string &fieldName ) { + return lookupField(fieldName).m_offset; + } + + virtual ULONG getFieldOffsetByIndex( ULONG index ) { + return lookupField(index).m_offset; + } virtual ULONG getFieldCount(); @@ -332,11 +354,7 @@ protected: pyDia::SymbolPtr m_dia; - typedef std::pair< std::string, TypeInfoPtr > FieldType; - - typedef std::vector< FieldType > FieldList; - - FieldList m_fields; + UdtUtils::FieldCollection m_fields; void getFields( pyDia::SymbolPtr &rootSym, @@ -348,6 +366,15 @@ protected: void getVirtualFields(); + +private: + void refreshFields(); + + template + const UdtUtils::Field &lookupField( T index) { + refreshFields(); + return m_fields.lookup(index); + } }; /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/udtutils.cpp b/pykd/udtutils.cpp new file mode 100644 index 0000000..7ff0efe --- /dev/null +++ b/pykd/udtutils.cpp @@ -0,0 +1,68 @@ + +#include "stdafx.h" + +#include + +#include "udtutils.h" +#include "dbgexcept.h" +#include "typeinfo.h" + +/////////////////////////////////////////////////////////////////////////////////// + +namespace pykd { +namespace UdtUtils { + +///////////////////////////////////////////////////////////////////////////////////// + +const Field &FieldCollection::lookup(ULONG index) const +{ + if (index >= Base::size()) + throw PyException( PyExc_IndexError, m_baseTypeName + " index out of range" ); + return at(index); +} + +///////////////////////////////////////////////////////////////////////////////////// + +const Field &FieldCollection::lookup(const std::string &name) const +{ + Base::const_reverse_iterator it = + std::find(Base::rbegin(), Base::rend(), name); + + if ( it == Base::rend() ) + throw TypeException( m_baseTypeName, name + ": field not found" ); + + return *it; +} + +/////////////////////////////////////////////////////////////////////////////////// + +ULONG getFiledOffsetRecirsive(TypeInfoPtr typeInfo, const std::string &fieldName) +{ + // "m_field1.m_field2" -> ["m_field1", "m_field2"] + typedef boost::char_separator CharSep; + boost::tokenizer< CharSep > tokenizer(fieldName, CharSep(".")); + if (tokenizer.begin() == tokenizer.end()) + throw TypeException(typeInfo->getName(), fieldName + ": invalid field name"); + + ULONG fieldOffset = 0; + + boost::tokenizer< CharSep >::iterator it = tokenizer.begin(); + for (; it != tokenizer.end(); ++it) + { + const std::string &name = *it; + fieldOffset += typeInfo->getFieldOffsetByNameNotRecursively(name); + typeInfo = typeInfo->getField(name); + } + + return fieldOffset; +} + +/////////////////////////////////////////////////////////////////////////////////// + +} // namespace UdtUtils + +/////////////////////////////////////////////////////////////////////////////////// + +} // namespace pykd + +/////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/udtutils.h b/pykd/udtutils.h new file mode 100644 index 0000000..b32a818 --- /dev/null +++ b/pykd/udtutils.h @@ -0,0 +1,65 @@ + +#pragma once + +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +/////////////////////////////////////////////////////////////////////////////////// + +namespace pykd { + +/////////////////////////////////////////////////////////////////////////////////// + +class TypeInfo; +typedef boost::shared_ptr TypeInfoPtr; + +/////////////////////////////////////////////////////////////////////////////////// + +namespace UdtUtils { + +/////////////////////////////////////////////////////////////////////////////////// + +struct Field { + Field( ULONG offset, const std::string &name, TypeInfoPtr type ) + : m_offset(offset), m_name(name), m_type(type) + {} + + bool operator ==(const std::string &name) const { + return m_name == name; + } + + ULONG m_offset; + std::string m_name; + TypeInfoPtr m_type; +}; + +/////////////////////////////////////////////////////////////////////////////////// + +class FieldCollection : public std::vector< Field > { + typedef std::vector< Field > Base; +public: + FieldCollection(const std::string &baseTypeName) : m_baseTypeName(baseTypeName) + {} + + const Field &lookup(ULONG index) const; + const Field &lookup(const std::string &name) const; + +private: + std::string m_baseTypeName; +}; + +/////////////////////////////////////////////////////////////////////////////////// + +ULONG getFiledOffsetRecirsive(TypeInfoPtr typeInfo, const std::string &fieldName); + +/////////////////////////////////////////////////////////////////////////////////// + +} // namespace UdtUtils + +/////////////////////////////////////////////////////////////////////////////////// + +} // namespace pykd + +/////////////////////////////////////////////////////////////////////////////////// diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index e361491..2bedc33 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -72,9 +72,9 @@ class TypedVarTest( unittest.TestCase ): def testFieldOffset(self): tv = target.module.typedVar( "g_structTest" ) - self.assertEqual( 0, tv.m_field0.offset() ) - self.assertEqual( 4, tv.m_field1.offset() ) - self.assertEqual( 16, tv.m_field4.offset() ) + self.assertEqual( 0, tv.fieldOffset("m_field0") ) + self.assertEqual( 4, tv.fieldOffset("m_field1") ) + self.assertEqual( 16, tv.fieldOffset("m_field4") ) def testArrayField(self): tv = target.module.typedVar( "g_struct3" ) @@ -104,7 +104,7 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( target.module.g_structTest, target.module.typedVar( "g_structTestPtr" ) ) def testContainingRecord(self): - off1 = target.module.type( "structTest" ).m_field2.offset() + off1 = target.module.type( "structTest" ).fieldOffset("m_field2") off2 = target.module.offset( "g_structTest" ) tv = target.module.containingRecord( off2 + off1, "structTest", "m_field2" ) self.assertEqual( True, tv.m_field2 ) @@ -136,11 +136,10 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( 3, len( tvl ) ) self.assertEqual( [1000,2000,3000], [ tv.m_someBaseFiled2 for tv in tvl ] ) self.assertEqual( [1001,2001,3001], [ tv.m_childFiled1 for tv in tvl ] ) - + tvl1 = target.module.typedVarList( target.module.g_listHead, "listStruct", "listEntry" ) tvl2 = pykd.typedVarList( target.module.g_listHead, target.moduleName + "!listStruct", "listEntry" ) self.assertEqual( tvl1, tvl2 ) - def testTypedVarArray(self): tvl = target.module.typedVarArray( target.module.g_testArray, "structTest", 2 ) diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index 7471f6c..db56f4c 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -93,23 +93,27 @@ class TypeInfoTest( unittest.TestCase ): def testOffset( self ): ti1 = target.module.type( "structTest" ) - self.assertEqual( 0, ti1.m_field0.offset() ) - self.assertEqual( 4, ti1.m_field1.offset() ) - self.assertEqual( 12, ti1.m_field2.offset() ) - self.assertEqual( 14, ti1.m_field3.offset() ) - + self.assertEqual( 0, ti1.fieldOffset("m_field0") ) + self.assertEqual( 4, ti1.fieldOffset("m_field1") ) + self.assertEqual( 12, ti1.fieldOffset("m_field2") ) + self.assertEqual( 14, ti1.fieldOffset("m_field3") ) + + ti2 = target.module.type( "struct2" ) + self.assertTrue( ti2.fieldOffset("m_union") >= ti2.m_struct.size() ) + self.assertEqual( ti2.fieldOffset("m_union"), ti2.fieldOffset("m_union.m_value") ) + self.assertEqual( 0, ti2.m_union.fieldOffset("m_value") ) + def testSize( self ): ti1 = target.module.type( "structTest" ) self.assertEqual( 16 + pykd.ptrSize(), ti1.size() ) - self.assertEqual( pykd.ptrSize(), target.module.type("structTest**").size() ) + self.assertEqual( pykd.ptrSize(), target.module.type("structTest**").size() ) self.assertEqual( pykd.sizeof("structTest"), target.module.type("structTest").size() ) self.assertEqual( pykd.sizeof("structTest**"), target.module.type("structTest**").size() ) - self.assertEqual( pykd.sizeof("Int1B"), target.module.type("Int1B").size() ) - + self.assertEqual( pykd.sizeof("Int1B"), target.module.type("Int1B").size() ) def testBitField( self ): ti = target.module.type( "g_structWithBits" ) - self.assertEqual( 0, ti.m_bit6_7.offset() ) + self.assertEqual( 0, ti.fieldOffset("m_bit6_7") ) self.assertEqual( 4, ti.m_bit6_7.size() ) self.assertEqual( "ULong:2", ti.m_bit6_7.name() ) self.assertEqual( 2, ti.m_bit6_7.bitWidth() ) @@ -119,10 +123,10 @@ class TypeInfoTest( unittest.TestCase ): ti = target.module.type("enumType") self.assertTrue( hasattr( ti, "TWO" ) ) self.assertEqual( 4, ti.TWO.size() ) - + ti = target.module.type("classChild") self.assertEqual( "enumType", ti.m_enumField.name() ) - + def testPtr(self): self.assertEqual( "listStruct1*", target.module.type( "g_listHead1" ).name() ) self.assertEqual( "listStruct1*[2]", target.module.type( "g_arrOfListStruct1" ).name()) @@ -133,8 +137,8 @@ class TypeInfoTest( unittest.TestCase ): def testUnion(self): ti = target.module.type("unionTest") - self.assertEqual( 0, ti.m_doubleValue.offset() ) - self.assertEqual( 0, ti.m_bits.offset() ) + self.assertEqual( 0, ti.fieldOffset("m_doubleValue") ) + self.assertEqual( 0, ti.fieldOffset("m_bits") ) self.assertEqual( ti.size(), ti.m_doubleValue.size() ) def testAsMap(self): @@ -158,7 +162,7 @@ class TypeInfoTest( unittest.TestCase ): ti = target.module.type("StructWithNested::Nested") self.assertTrue( hasattr( ti, "m_nestedFiled" ) ) - + def testPrint(self): self.assertTrue( str(target.module.type( "g_ucharValue" ) ) ) self.assertTrue( str(target.module.type( "g_ushortValue" ) ) ) @@ -183,12 +187,13 @@ class TypeInfoTest( unittest.TestCase ): def testTypedef(self): self.assertEqual( "structTest", pykd.typeInfo( "g_structTypeDef" ).name() ) self.assertEqual( "structTest", pykd.typeInfo( "structTestTypeDef" ).name() ) - + def testStaticField(self): ti = pykd.typeInfo( "g_classChild" ) - self.assertNotEqual( 0, ti.m_staticField.offset() ) - self.assertNotEqual( 0, ti.m_staticConst.offset() ) - self.assertNotEqual( 0, ti.m_stdstr.offset() ) + self.assertNotEqual( 0, ti.m_staticField.staticOffset() ) + if not ti.m_staticConst.staticOffset(): + self.assertFalse( "MS DIA bug: https://connect.microsoft.com/VisualStudio/feedback/details/737430" ) + self.assertNotEqual( 0, ti.m_stdstr.staticOffset() ) def testUdtSubscribe(self): tv = pykd.typeInfo( "g_virtChild" )