diff --git a/pykd/diawrapper.cpp b/pykd/diawrapper.cpp index c70110f..b8cbbbd 100644 --- a/pykd/diawrapper.cpp +++ b/pykd/diawrapper.cpp @@ -174,10 +174,27 @@ ULONG Symbol::getCount() int Symbol::getVirtualBasePointerOffset() { - return callSymbol( get_virtualBasePointerOffset); + return callSymbol(get_virtualBasePointerOffset); } //////////////////////////////////////////////////////////////////////////////// + +ULONG Symbol::getVirtualBaseDispIndex() +{ + return callSymbol(get_virtualBaseDispIndex); +} + +//////////////////////////////////////////////////////////////////////////////// + +ULONG Symbol::getVirtualBaseDispSize() +{ + SymbolPtr baseTableType = SymbolPtr( new Symbol( callSymbol(get_virtualBaseTableType), m_machineType ) ); + + return (ULONG)baseTableType->getType()->getSize(); +} + +//////////////////////////////////////////////////////////////////////////////// + void Symbol::getValueImpl(IDiaSymbol *_symbol, VARIANT &vtValue) { HRESULT hres = _symbol->get_value(&vtValue); diff --git a/pykd/diawrapper.h b/pykd/diawrapper.h index f40e6a7..4b8c090 100644 --- a/pykd/diawrapper.h +++ b/pykd/diawrapper.h @@ -162,6 +162,10 @@ public: int getVirtualBasePointerOffset(); + ULONG getVirtualBaseDispIndex(); + + ULONG getVirtualBaseDispSize(); + public: typedef std::pair ValueNameEntry; diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index c0343d9..3ea6395 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -238,7 +238,34 @@ UdtTypedVar::getField( const std::string &fieldName ) return TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) ); } - return TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldType->getOffset()) ); + ULONG fieldOffset = 0; + + fieldOffset = fieldType->getOffset(); + + if ( fieldType->isVirtualMember() ) + { + fieldOffset += getVirtualBaseDisplacement( fieldType ); + } + + return TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldOffset) ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +LONG UdtTypedVar::getVirtualBaseDisplacement( TypeInfoPtr& typeInfo ) +{ + ULONG virtualBasePtr, virtualDispIndex, virtualDispSize; + typeInfo->getVirtualDisplacement( virtualBasePtr, virtualDispIndex, virtualDispSize ); + + ULONG64 vbtableOffset = m_varData->fork( virtualBasePtr )->readPtr(); + + VarDataPtr vbtable = VarDataMemory::factory(m_dataSpaces, vbtableOffset); + + LONG displacement = 0; + + vbtable->read( &displacement, sizeof(displacement), virtualDispIndex*virtualDispSize ); + + return virtualBasePtr + displacement; } /////////////////////////////////////////////////////////////////////////////////// @@ -264,8 +291,15 @@ std::string UdtTypedVar::print() } else { - fieldVar = TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldType->getOffset()) ); - sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldType->getOffset(); + ULONG fieldOffset = fieldType->getOffset(); + + if ( fieldType->isVirtualMember() ) + { + fieldOffset += getVirtualBaseDisplacement( fieldType ); + } + + fieldVar = TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldOffset) ); + sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldOffset; sstr << " " << std::left << std::setw(24) << std::setfill(' ') << m_typeInfo->getFieldNameByIndex(i) << ':'; } diff --git a/pykd/typedvar.h b/pykd/typedvar.h index 01313cf..acb32ff 100644 --- a/pykd/typedvar.h +++ b/pykd/typedvar.h @@ -177,6 +177,8 @@ public: virtual std::string printValue(); virtual TypedVarPtr getField( const std::string &fieldName ); + + LONG getVirtualBaseDisplacement( TypeInfoPtr& typeInfo ); }; /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index 1ae8024..1f50114 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -475,10 +475,39 @@ TypeInfoPtr TypeInfo::getRecurciveComplexType( TypeInfoPtr &lowestType, std::str ///////////////////////////////////////////////////////////////////////////////////// +ULONG64 TypeInfo::getStaticOffset() { + if ( !m_staticMember ) + throw TypeException( getName(), "This is not a static member" ); + + return m_staticOffset; +} + +///////////////////////////////////////////////////////////////////////////////////// + +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 ); + { + getFields( m_dia, pyDia::SymbolPtr() ); + getVirtualFields(); + } FieldList::reverse_iterator it; @@ -495,7 +524,10 @@ TypeInfoPtr UdtTypeInfo::getField( const std::string &fieldName ) TypeInfoPtr UdtTypeInfo::getFieldByIndex( ULONG index ) { if ( m_fields.empty() ) - getFields( m_dia ); + { + getFields( m_dia, pyDia::SymbolPtr() ); + getVirtualFields(); + } return m_fields[ index ].second; } @@ -505,7 +537,10 @@ TypeInfoPtr UdtTypeInfo::getFieldByIndex( ULONG index ) std::string UdtTypeInfo::getFieldNameByIndex( ULONG index ) { if ( m_fields.empty() ) - getFields( m_dia); + { + getFields( m_dia, pyDia::SymbolPtr() ); + getVirtualFields(); + } return m_fields[ index ].first; } @@ -515,14 +550,23 @@ std::string UdtTypeInfo::getFieldNameByIndex( ULONG index ) ULONG UdtTypeInfo::getFieldCount() { if ( m_fields.empty() ) - getFields( m_dia ); + { + getFields( m_dia, pyDia::SymbolPtr() ); + getVirtualFields(); + } return (ULONG)m_fields.size(); } ///////////////////////////////////////////////////////////////////////////////////// -void UdtTypeInfo::getFields( pyDia::SymbolPtr &rootSym, ULONG startOffset ) +void UdtTypeInfo::getFields( + pyDia::SymbolPtr &rootSym, + pyDia::SymbolPtr &baseVirtualSym, + ULONG startOffset, + LONG virtualBasePtr, + ULONG virtualDispIndex, + ULONG virtualDispSize ) { ULONG childCount = rootSym->getChildCount(); @@ -536,18 +580,29 @@ void UdtTypeInfo::getFields( pyDia::SymbolPtr &rootSym, ULONG startOffset ) { if ( !childSym->isVirtualBaseClass() ) { - getFields( childSym, startOffset + childSym->getOffset() ); + getFields( childSym, pyDia::SymbolPtr(), startOffset + childSym->getOffset() ); } } else if ( symTag == SymTagData ) { - TypeInfoPtr ti = TypeInfo::getTypeInfo( m_dia, childSym ); + TypeInfoPtr ti = TypeInfo::getTypeInfo( rootSym, childSym ); switch ( childSym->getDataKind() ) { case DataIsMember: + + if ( baseVirtualSym ) + { + ti->setVirtualBase( + TypeInfo::getTypeInfo(baseVirtualSym), + virtualBasePtr, + virtualDispIndex, + virtualDispSize ); + } + ti->setOffset( startOffset + childSym->getOffset() ); + break; case DataIsStaticMember: @@ -560,15 +615,41 @@ void UdtTypeInfo::getFields( pyDia::SymbolPtr &rootSym, ULONG startOffset ) else if ( symTag == SymTagVTable ) { - TypeInfoPtr ti = TypeInfo::getTypeInfo( m_dia, childSym ); + if ( !baseVirtualSym ) + { + TypeInfoPtr ti = TypeInfo::getTypeInfo( rootSym, childSym ); - m_fields.push_back( std::make_pair( "__VFN_table", ti ) ); + m_fields.push_back( std::make_pair( "__VFN_table", ti ) ); + } } } } ///////////////////////////////////////////////////////////////////////////////////// +void UdtTypeInfo::getVirtualFields() +{ + ULONG childCount = m_dia->getChildCount(); + + for ( ULONG i = 0; i < childCount; ++i ) + { + pyDia::SymbolPtr childSym = m_dia->getChildByIndex( i ); + + if ( !childSym->isVirtualBaseClass() ) + continue; + + getFields( + childSym, + childSym, + 0, + childSym->getVirtualBasePointerOffset(), + childSym->getVirtualBaseDispIndex(), + childSym->getVirtualBaseDispSize() ); + } +} + +///////////////////////////////////////////////////////////////////////////////////// + std::string UdtTypeInfo::print() { std::stringstream sstr; @@ -587,6 +668,16 @@ std::string UdtTypeInfo::print() sstr << " " << std::left << std::setw(18) << std::setfill(' ') << getFieldNameByIndex(i) << ':'; } 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) << ':'; + } + else { sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldType->getOffset(); sstr << " " << std::left << std::setw(24) << std::setfill(' ') << getFieldNameByIndex(i) << ':'; @@ -644,7 +735,7 @@ std::string EnumTypeInfo::getFieldNameByIndex( ULONG index ) ULONG EnumTypeInfo::getFieldCount() { - return m_dia->getChildCount(); + return m_dia->getChildCount(); } ///////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index 488dcd0..320b545 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -42,12 +42,15 @@ public: m_offset( 0 ), m_staticOffset( 0 ), m_constant( false ), - m_staticMember( false ) + m_staticMember( false ), + m_virtualMember( false ), + m_virtualBasePtr( 0 ), + m_virtualDispIndex( 0 ), + m_virtualDispSize( 0 ) { m_constantValue.vt = VT_EMPTY; } - virtual std::string print() { std::stringstream sstr; sstr << "Type name: " << getName(); @@ -125,10 +128,6 @@ public: throw TypeException( getName(), "type is not a pointer" ); } - ULONG getOffset() const { - return (ULONG)m_offset; - } - void setOffset( ULONG offset ) { m_offset = offset; } @@ -138,7 +137,6 @@ public: m_constant = true; m_constantValue = var; } - bool isConstant() const { return m_constant == true; @@ -149,19 +147,40 @@ public: return m_staticMember == true; } + bool isVirtualMember() const + { + return m_virtualMember == true; + } + void setStaticOffset( ULONG64 offset ) { - m_staticOffset = offset; + m_staticOffset = offset; m_staticMember = true; } - ULONG64 getStaticOffset() const { - return m_staticOffset; + void setVirtualBase( TypeInfoPtr virtualBase, LONG virtualBasePtr, ULONG virtualDispIndex, ULONG virtualDispSize ) + { + m_virtualMember = true; + m_virtualBaseType = virtualBase; + m_virtualBasePtr = virtualBasePtr; + m_virtualDispIndex = virtualDispIndex; + m_virtualDispSize = virtualDispSize; } - ULONG64 getTypeOffset() const { - return m_staticMember ? m_staticOffset : m_offset; - } + ULONG64 getTypeOffset(); + ULONG getOffset(); + + ULONG64 getStaticOffset(); + + void getVirtualDisplacement( ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) { + virtualBasePtr = m_virtualBasePtr; + virtualDispIndex = m_virtualDispIndex; + virtualDispSize = m_virtualDispSize; + }; + + TypeInfoPtr getVirtualBase() { + return m_virtualBaseType; + } protected: @@ -181,7 +200,17 @@ protected: bool m_staticMember; + bool m_virtualMember; + VARIANT m_constantValue; + + LONG m_virtualBasePtr; + + ULONG m_virtualDispIndex; + + ULONG m_virtualDispSize; + + TypeInfoPtr m_virtualBaseType; }; /////////////////////////////////////////////////////////////////////////////////// @@ -290,7 +319,16 @@ protected: FieldList m_fields; - void getFields( pyDia::SymbolPtr &rootSym, ULONG startOffset = 0 ); + void getFields( + pyDia::SymbolPtr &rootSym, + pyDia::SymbolPtr &baseVirtualSym, + ULONG startOffset = 0, + LONG virtualBasePtr = 0, + ULONG virtualDispIndex = 0, + ULONG m_virtualDispSize = 0 ); + + + void getVirtualFields(); }; /////////////////////////////////////////////////////////////////////////////////// diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index 53437a5..7ee527f 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -248,7 +248,6 @@ class TypedVarTest( unittest.TestCase ): def testDiamondVirtualInherit(self): tv = pykd.typedVar( "g_virtChild" ) - print tv self.assertEqual( -100, tv.m_baseField ) def testDinkumwareMap(self): diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index ee92d37..62e5dbb 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -335,10 +335,12 @@ public: virtual void virtFunc2() {} }; -class VirtualChildClass : public VirtualBaseClass1, public VirtualBaseClass2, public virtual classBase +class VirtualChildClass : public VirtualBaseClass1, public VirtualBaseClass2 { void virtFunc() {} void virtFunc2() {} + + void virtual virtFunc3() {} }; VirtualChildClass g_virtChild; @@ -426,7 +428,7 @@ void FuncWithName0() std::cout << g_structTypeDef.m_field0; - std::cout << g_virtChild.VirtualBaseClass1::m_baseField; + //std::cout << g_virtChild.VirtualBaseClass1::m_baseField; } ////////////////////////////////////////////////////////////////////////////////