[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

@ -178,6 +178,23 @@ int Symbol::getVirtualBasePointerOffset()
}
////////////////////////////////////////////////////////////////////////////////
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);

View File

@ -162,6 +162,10 @@ public:
int getVirtualBasePointerOffset();
ULONG getVirtualBaseDispIndex();
ULONG getVirtualBaseDispSize();
public:
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, 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) << ':';
}

View File

@ -177,6 +177,8 @@ public:
virtual std::string printValue();
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 )
{
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,12 +615,38 @@ 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 ) );
}
}
}
}
/////////////////////////////////////////////////////////////////////////////////////
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() );
}
}
/////////////////////////////////////////////////////////////////////////////////////
@ -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) << ':';

View File

@ -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_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();
};
///////////////////////////////////////////////////////////////////////////////////

View File

@ -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):

View File

@ -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;
}
////////////////////////////////////////////////////////////////////////////////