[0.1.x] fixed : issue #10767 ( typeInfo raises symbolException for classes with diamond virtual inheritance )

git-svn-id: https://pykd.svn.codeplex.com/svn@76514 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\kernelnet_cp 2012-05-22 08:50:21 +00:00 committed by Mikhail I. Izmestev
parent 2527901eed
commit d1a30dc6b0
8 changed files with 218 additions and 31 deletions

View File

@ -174,10 +174,27 @@ ULONG Symbol::getCount()
int Symbol::getVirtualBasePointerOffset() 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) void Symbol::getValueImpl(IDiaSymbol *_symbol, VARIANT &vtValue)
{ {
HRESULT hres = _symbol->get_value(&vtValue); HRESULT hres = _symbol->get_value(&vtValue);

View File

@ -162,6 +162,10 @@ public:
int getVirtualBasePointerOffset(); int getVirtualBasePointerOffset();
ULONG getVirtualBaseDispIndex();
ULONG getVirtualBaseDispSize();
public: public:
typedef std::pair<ULONG, const char *> ValueNameEntry; typedef std::pair<ULONG, const char *> ValueNameEntry;

View File

@ -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, 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 else
{ {
fieldVar = TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldType->getOffset()) ); ULONG fieldOffset = fieldType->getOffset();
sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << 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) << ':'; sstr << " " << std::left << std::setw(24) << std::setfill(' ') << m_typeInfo->getFieldNameByIndex(i) << ':';
} }

View File

@ -177,6 +177,8 @@ public:
virtual std::string printValue(); virtual std::string printValue();
virtual TypedVarPtr getField( const std::string &fieldName ); virtual TypedVarPtr getField( const std::string &fieldName );
LONG getVirtualBaseDisplacement( TypeInfoPtr& typeInfo );
}; };
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////

View File

@ -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 ) TypeInfoPtr UdtTypeInfo::getField( const std::string &fieldName )
{ {
if ( m_fields.empty() ) if ( m_fields.empty() )
getFields( m_dia ); {
getFields( m_dia, pyDia::SymbolPtr() );
getVirtualFields();
}
FieldList::reverse_iterator it; FieldList::reverse_iterator it;
@ -495,7 +524,10 @@ TypeInfoPtr UdtTypeInfo::getField( const std::string &fieldName )
TypeInfoPtr UdtTypeInfo::getFieldByIndex( ULONG index ) TypeInfoPtr UdtTypeInfo::getFieldByIndex( ULONG index )
{ {
if ( m_fields.empty() ) if ( m_fields.empty() )
getFields( m_dia ); {
getFields( m_dia, pyDia::SymbolPtr() );
getVirtualFields();
}
return m_fields[ index ].second; return m_fields[ index ].second;
} }
@ -505,7 +537,10 @@ TypeInfoPtr UdtTypeInfo::getFieldByIndex( ULONG index )
std::string UdtTypeInfo::getFieldNameByIndex( ULONG index ) std::string UdtTypeInfo::getFieldNameByIndex( ULONG index )
{ {
if ( m_fields.empty() ) if ( m_fields.empty() )
getFields( m_dia); {
getFields( m_dia, pyDia::SymbolPtr() );
getVirtualFields();
}
return m_fields[ index ].first; return m_fields[ index ].first;
} }
@ -515,14 +550,23 @@ std::string UdtTypeInfo::getFieldNameByIndex( ULONG index )
ULONG UdtTypeInfo::getFieldCount() ULONG UdtTypeInfo::getFieldCount()
{ {
if ( m_fields.empty() ) if ( m_fields.empty() )
getFields( m_dia ); {
getFields( m_dia, pyDia::SymbolPtr() );
getVirtualFields();
}
return (ULONG)m_fields.size(); 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(); ULONG childCount = rootSym->getChildCount();
@ -536,18 +580,29 @@ void UdtTypeInfo::getFields( pyDia::SymbolPtr &rootSym, ULONG startOffset )
{ {
if ( !childSym->isVirtualBaseClass() ) if ( !childSym->isVirtualBaseClass() )
{ {
getFields( childSym, startOffset + childSym->getOffset() ); getFields( childSym, pyDia::SymbolPtr(), startOffset + childSym->getOffset() );
} }
} }
else else
if ( symTag == SymTagData ) if ( symTag == SymTagData )
{ {
TypeInfoPtr ti = TypeInfo::getTypeInfo( m_dia, childSym ); TypeInfoPtr ti = TypeInfo::getTypeInfo( rootSym, childSym );
switch ( childSym->getDataKind() ) switch ( childSym->getDataKind() )
{ {
case DataIsMember: case DataIsMember:
if ( baseVirtualSym )
{
ti->setVirtualBase(
TypeInfo::getTypeInfo(baseVirtualSym),
virtualBasePtr,
virtualDispIndex,
virtualDispSize );
}
ti->setOffset( startOffset + childSym->getOffset() ); ti->setOffset( startOffset + childSym->getOffset() );
break; break;
case DataIsStaticMember: case DataIsStaticMember:
@ -560,15 +615,41 @@ void UdtTypeInfo::getFields( pyDia::SymbolPtr &rootSym, ULONG startOffset )
else else
if ( symTag == SymTagVTable ) 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<SymTagBaseClass>();
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::string UdtTypeInfo::print()
{ {
std::stringstream sstr; std::stringstream sstr;
@ -587,6 +668,16 @@ std::string UdtTypeInfo::print()
sstr << " " << std::left << std::setw(18) << std::setfill(' ') << getFieldNameByIndex(i) << ':'; sstr << " " << std::left << std::setw(18) << std::setfill(' ') << getFieldNameByIndex(i) << ':';
} }
else 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::right << std::setw(4) << std::setfill('0') << std::hex << fieldType->getOffset();
sstr << " " << std::left << std::setw(24) << std::setfill(' ') << getFieldNameByIndex(i) << ':'; sstr << " " << std::left << std::setw(24) << std::setfill(' ') << getFieldNameByIndex(i) << ':';

View File

@ -42,12 +42,15 @@ public:
m_offset( 0 ), m_offset( 0 ),
m_staticOffset( 0 ), m_staticOffset( 0 ),
m_constant( false ), 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; m_constantValue.vt = VT_EMPTY;
} }
virtual std::string print() { virtual std::string print() {
std::stringstream sstr; std::stringstream sstr;
sstr << "Type name: " << getName(); sstr << "Type name: " << getName();
@ -125,10 +128,6 @@ public:
throw TypeException( getName(), "type is not a pointer" ); throw TypeException( getName(), "type is not a pointer" );
} }
ULONG getOffset() const {
return (ULONG)m_offset;
}
void setOffset( ULONG offset ) { void setOffset( ULONG offset ) {
m_offset = offset; m_offset = offset;
} }
@ -138,7 +137,6 @@ public:
m_constant = true; m_constant = true;
m_constantValue = var; m_constantValue = var;
} }
bool isConstant() const bool isConstant() const
{ {
return m_constant == true; return m_constant == true;
@ -149,19 +147,40 @@ public:
return m_staticMember == true; return m_staticMember == true;
} }
bool isVirtualMember() const
{
return m_virtualMember == true;
}
void setStaticOffset( ULONG64 offset ) { void setStaticOffset( ULONG64 offset ) {
m_staticOffset = offset; m_staticOffset = offset;
m_staticMember = true; m_staticMember = true;
} }
ULONG64 getStaticOffset() const { void setVirtualBase( TypeInfoPtr virtualBase, LONG virtualBasePtr, ULONG virtualDispIndex, ULONG virtualDispSize )
return m_staticOffset; {
m_virtualMember = true;
m_virtualBaseType = virtualBase;
m_virtualBasePtr = virtualBasePtr;
m_virtualDispIndex = virtualDispIndex;
m_virtualDispSize = virtualDispSize;
} }
ULONG64 getTypeOffset() const { ULONG64 getTypeOffset();
return m_staticMember ? m_staticOffset : m_offset;
}
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: protected:
@ -181,7 +200,17 @@ protected:
bool m_staticMember; bool m_staticMember;
bool m_virtualMember;
VARIANT m_constantValue; VARIANT m_constantValue;
LONG m_virtualBasePtr;
ULONG m_virtualDispIndex;
ULONG m_virtualDispSize;
TypeInfoPtr m_virtualBaseType;
}; };
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -290,7 +319,16 @@ protected:
FieldList m_fields; 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();
}; };
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////

View File

@ -248,7 +248,6 @@ class TypedVarTest( unittest.TestCase ):
def testDiamondVirtualInherit(self): def testDiamondVirtualInherit(self):
tv = pykd.typedVar( "g_virtChild" ) tv = pykd.typedVar( "g_virtChild" )
print tv
self.assertEqual( -100, tv.m_baseField ) self.assertEqual( -100, tv.m_baseField )
def testDinkumwareMap(self): def testDinkumwareMap(self):

View File

@ -335,10 +335,12 @@ public:
virtual void virtFunc2() {} virtual void virtFunc2() {}
}; };
class VirtualChildClass : public VirtualBaseClass1, public VirtualBaseClass2, public virtual classBase class VirtualChildClass : public VirtualBaseClass1, public VirtualBaseClass2
{ {
void virtFunc() {} void virtFunc() {}
void virtFunc2() {} void virtFunc2() {}
void virtual virtFunc3() {}
}; };
VirtualChildClass g_virtChild; VirtualChildClass g_virtChild;
@ -426,7 +428,7 @@ void FuncWithName0()
std::cout << g_structTypeDef.m_field0; std::cout << g_structTypeDef.m_field0;
std::cout << g_virtChild.VirtualBaseClass1::m_baseField; //std::cout << g_virtChild.VirtualBaseClass1::m_baseField;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////