mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-21 12:53:23 +08:00
[0.1.x] ~field offset moved to parent TypeInfo (method fieldOffset)
git-svn-id: https://pykd.svn.codeplex.com/svn@78192 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
8cf2e95695
commit
ed9c2be858
@ -591,9 +591,7 @@ TypedVarPtr DebugClient::containingRecordByType( ULONG64 addr, const TypeInfoPtr
|
|||||||
{
|
{
|
||||||
addr = addr64(addr);
|
addr = addr64(addr);
|
||||||
|
|
||||||
TypeInfoPtr fieldTypeInfo = typeInfo->getField( fieldName );
|
VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, addr - typeInfo->getFieldOffsetByNameRecirsive(fieldName) );
|
||||||
|
|
||||||
VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, addr - fieldTypeInfo->getOffset() );
|
|
||||||
|
|
||||||
return TypedVar::getTypedVar( m_client, typeInfo, varData );
|
return TypedVar::getTypedVar( m_client, typeInfo, varData );
|
||||||
}
|
}
|
||||||
@ -617,7 +615,7 @@ python::list DebugClient::getTypedVarListByType( ULONG64 listHeadAddress, const
|
|||||||
|
|
||||||
if ( fieldTypeInfo->getName() == ( typeInfo->getName() + "*" ) )
|
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 ) );
|
lst.append( getTypedVarByTypeInfo( typeInfo, entryAddress ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -322,9 +322,11 @@ TypedVarPtr Module::containingRecordByName( ULONG64 address, const std::string &
|
|||||||
|
|
||||||
TypeInfoPtr typeInfo = getTypeByName( typeName );
|
TypeInfoPtr typeInfo = getTypeByName( typeName );
|
||||||
|
|
||||||
TypeInfoPtr fieldTypeInfo = typeInfo->getField( fieldName );
|
VarDataPtr varData =
|
||||||
|
VarDataMemory::factory(
|
||||||
VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, address - fieldTypeInfo->getOffset() );
|
m_dataSpaces,
|
||||||
|
address - typeInfo->getFieldOffsetByNameRecirsive( fieldName )
|
||||||
|
);
|
||||||
|
|
||||||
return TypedVar::getTypedVar( m_client, typeInfo, varData );
|
return TypedVar::getTypedVar( m_client, typeInfo, varData );
|
||||||
}
|
}
|
||||||
@ -335,9 +337,11 @@ TypedVarPtr Module::containingRecordByType( ULONG64 address, const TypeInfoPtr &
|
|||||||
{
|
{
|
||||||
address = addr64(address);
|
address = addr64(address);
|
||||||
|
|
||||||
TypeInfoPtr fieldTypeInfo = typeInfo->getField( fieldName );
|
VarDataPtr varData =
|
||||||
|
VarDataMemory::factory(
|
||||||
VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, address - fieldTypeInfo->getOffset() );
|
m_dataSpaces,
|
||||||
|
address - typeInfo->getFieldOffsetByNameRecirsive( fieldName )
|
||||||
|
);
|
||||||
|
|
||||||
return TypedVar::getTypedVar( m_client, typeInfo, varData );
|
return TypedVar::getTypedVar( m_client, typeInfo, varData );
|
||||||
}
|
}
|
||||||
@ -364,7 +368,7 @@ python::list Module::getTypedVarListByType( ULONG64 listHeadAddress, const TypeI
|
|||||||
|
|
||||||
if ( fieldTypeInfo->getName() == ( typeInfo->getName() + "*" ) )
|
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 ) );
|
lst.append( getTypedVarByType( typeInfo, entryAddress ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -493,6 +493,10 @@
|
|||||||
RelativePath=".\typeinfo.cpp"
|
RelativePath=".\typeinfo.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\udtutils.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\vardata.cpp"
|
RelativePath=".\vardata.cpp"
|
||||||
>
|
>
|
||||||
@ -615,6 +619,10 @@
|
|||||||
RelativePath=".\typeinfo.h"
|
RelativePath=".\typeinfo.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\udtutils.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\utils.h"
|
RelativePath=".\utils.h"
|
||||||
>
|
>
|
||||||
|
@ -546,7 +546,8 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
.def("__init__", python::make_constructor(TypeInfo::getTypeInfoByName ) )
|
.def("__init__", python::make_constructor(TypeInfo::getTypeInfoByName ) )
|
||||||
.def( "name", &TypeInfo::getName )
|
.def( "name", &TypeInfo::getName )
|
||||||
.def( "size", &TypeInfo::getSize )
|
.def( "size", &TypeInfo::getSize )
|
||||||
.def( "offset", &TypeInfo::getTypeOffset )
|
.def( "staticOffset", &TypeInfo::getStaticOffset )
|
||||||
|
.def( "fieldOffset", &TypeInfo::getFieldOffsetByNameRecirsive )
|
||||||
.def( "bitOffset", &TypeInfo::getBitOffset )
|
.def( "bitOffset", &TypeInfo::getBitOffset )
|
||||||
.def( "bitWidth", &TypeInfo::getBitWidth )
|
.def( "bitWidth", &TypeInfo::getBitWidth )
|
||||||
.def( "field", &TypeInfo::getField )
|
.def( "field", &TypeInfo::getField )
|
||||||
@ -566,8 +567,8 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
"Return virtual address" )
|
"Return virtual address" )
|
||||||
.def("sizeof", &TypedVar::getSize,
|
.def("sizeof", &TypedVar::getSize,
|
||||||
"Return size of a variable in the target memory" )
|
"Return size of a variable in the target memory" )
|
||||||
.def("offset", &TypedVar::getOffset,
|
.def("fieldOffset", &TypedVar::getFieldOffsetByNameRecirsive,
|
||||||
"Return offset to parent" )
|
"Return target field offset" )
|
||||||
.def("field", &TypedVar::getField,
|
.def("field", &TypedVar::getField,
|
||||||
"Return field of structure as an object attribute" )
|
"Return field of structure as an object attribute" )
|
||||||
.def( "dataKind", &TypedVar::getDataKind,
|
.def( "dataKind", &TypedVar::getDataKind,
|
||||||
|
@ -240,7 +240,7 @@ UdtTypedVar::getField( const std::string &fieldName )
|
|||||||
|
|
||||||
ULONG fieldOffset = 0;
|
ULONG fieldOffset = 0;
|
||||||
|
|
||||||
fieldOffset = fieldType->getOffset();
|
fieldOffset = m_typeInfo->getFieldOffsetByNameRecirsive(fieldName);
|
||||||
|
|
||||||
if ( fieldType->isVirtualMember() )
|
if ( fieldType->isVirtualMember() )
|
||||||
{
|
{
|
||||||
@ -267,7 +267,7 @@ UdtTypedVar::getElementByIndex( ULONG index )
|
|||||||
TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) ) );
|
TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG fieldOffset = fieldType->getOffset();
|
ULONG fieldOffset = m_typeInfo->getFieldOffsetByIndex(index);
|
||||||
|
|
||||||
if ( fieldType->isVirtualMember() )
|
if ( fieldType->isVirtualMember() )
|
||||||
{
|
{
|
||||||
@ -320,7 +320,7 @@ std::string UdtTypedVar::print()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ULONG fieldOffset = fieldType->getOffset();
|
ULONG fieldOffset = m_typeInfo->getFieldOffsetByIndex(i);
|
||||||
|
|
||||||
if ( fieldType->isVirtualMember() )
|
if ( fieldType->isVirtualMember() )
|
||||||
{
|
{
|
||||||
|
@ -35,8 +35,8 @@ public:
|
|||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG64 getOffset() {
|
ULONG getFieldOffsetByNameRecirsive(const std::string &fieldName) {
|
||||||
return m_typeInfo->getOffset();
|
return m_typeInfo->getFieldOffsetByNameRecirsive(fieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeInfoPtr
|
TypeInfoPtr
|
||||||
|
@ -483,7 +483,8 @@ TypeInfoPtr TypeInfo::getRecurciveComplexType( TypeInfoPtr &lowestType, std::str
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ULONG64 TypeInfo::getStaticOffset() {
|
ULONG64 TypeInfo::getStaticOffset()
|
||||||
|
{
|
||||||
if ( !m_staticMember )
|
if ( !m_staticMember )
|
||||||
throw TypeException( getName(), "This is not a static member" );
|
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()
|
ULONG UdtTypeInfo::getFieldCount()
|
||||||
{
|
{
|
||||||
if ( m_fields.empty() )
|
refreshFields();
|
||||||
{
|
|
||||||
getFields( m_dia, pyDia::SymbolPtr() );
|
|
||||||
getVirtualFields();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ULONG)m_fields.size();
|
return (ULONG)m_fields.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,6 +529,7 @@ void UdtTypeInfo::getFields(
|
|||||||
{
|
{
|
||||||
TypeInfoPtr ti = TypeInfo::getTypeInfo( rootSym, childSym );
|
TypeInfoPtr ti = TypeInfo::getTypeInfo( rootSym, childSym );
|
||||||
|
|
||||||
|
ULONG fieldOffset = 0;
|
||||||
switch ( childSym->getDataKind() )
|
switch ( childSym->getDataKind() )
|
||||||
{
|
{
|
||||||
case DataIsMember:
|
case DataIsMember:
|
||||||
@ -615,8 +543,7 @@ void UdtTypeInfo::getFields(
|
|||||||
virtualDispSize );
|
virtualDispSize );
|
||||||
}
|
}
|
||||||
|
|
||||||
ti->setOffset( startOffset + childSym->getOffset() );
|
fieldOffset = startOffset + childSym->getOffset();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DataIsStaticMember:
|
case DataIsStaticMember:
|
||||||
@ -624,7 +551,7 @@ void UdtTypeInfo::getFields(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_fields.push_back( std::make_pair( childSym->getName(), ti ) );
|
m_fields.push_back( UdtUtils::Field( fieldOffset, childSym->getName(), ti ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if ( symTag == SymTagVTable )
|
if ( symTag == SymTagVTable )
|
||||||
@ -641,9 +568,7 @@ void UdtTypeInfo::getFields(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ti->setOffset( startOffset + childSym->getOffset() );
|
m_fields.push_back( UdtUtils::Field( childSym->getOffset(), "__VFN_table", ti ) );
|
||||||
|
|
||||||
m_fields.push_back( std::make_pair( "__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::string UdtTypeInfo::print()
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
@ -683,12 +619,13 @@ std::string UdtTypeInfo::print()
|
|||||||
|
|
||||||
for ( ULONG i = 0; i < fieldCount; ++i )
|
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() )
|
if ( fieldType->isStaticMember() )
|
||||||
{
|
{
|
||||||
sstr << " =" << std::right << std::setw(10) << std::setfill('0') << std::hex << fieldType->getStaticOffset();
|
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
|
else
|
||||||
if ( fieldType->isVirtualMember() )
|
if ( fieldType->isVirtualMember() )
|
||||||
@ -697,13 +634,13 @@ std::string UdtTypeInfo::print()
|
|||||||
fieldType->getVirtualDisplacement( virtualBasePtr, virtualDispIndex, virtualDispSize );
|
fieldType->getVirtualDisplacement( virtualBasePtr, virtualDispIndex, virtualDispSize );
|
||||||
|
|
||||||
sstr << " virtual base " << fieldType->getVirtualBase()->getName();
|
sstr << " virtual base " << fieldType->getVirtualBase()->getName();
|
||||||
sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldType->getOffset();
|
sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << udtField.m_offset;
|
||||||
sstr << " " << getFieldNameByIndex(i) << ':';
|
sstr << " " << udtField.m_name << ':';
|
||||||
}
|
}
|
||||||
else
|
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 << udtField.m_offset;
|
||||||
sstr << " " << std::left << std::setw(24) << std::setfill(' ') << getFieldNameByIndex(i) << ':';
|
sstr << " " << std::left << std::setw(24) << std::setfill(' ') << udtField.m_name << ':';
|
||||||
}
|
}
|
||||||
|
|
||||||
sstr << " " << std::left << fieldType->getName();
|
sstr << " " << std::left << fieldType->getName();
|
||||||
@ -715,11 +652,9 @@ std::string UdtTypeInfo::print()
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TypeInfoPtr EnumTypeInfo::getField( const std::string &fieldName ) {
|
TypeInfoPtr EnumTypeInfo::getField( const std::string &fieldName )
|
||||||
pyDia::SymbolPtr field = m_dia->getChildByName( fieldName );
|
{
|
||||||
TypeInfoPtr ti = TypeInfo::getTypeInfo( m_dia, fieldName );
|
return TypeInfo::getTypeInfo( m_dia, fieldName );
|
||||||
ti->setOffset( 0 );
|
|
||||||
return ti;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -734,9 +669,7 @@ TypeInfoPtr EnumTypeInfo::getFieldByIndex( ULONG index )
|
|||||||
if ( !field )
|
if ( !field )
|
||||||
throw TypeException( m_dia->getName(), ": field not found" );
|
throw TypeException( m_dia->getName(), ": field not found" );
|
||||||
|
|
||||||
TypeInfoPtr ti = TypeInfo::getTypeInfo( m_dia, field->getName() );
|
return TypeInfo::getTypeInfo( m_dia, field->getName() );
|
||||||
ti->setOffset( 0 );
|
|
||||||
return ti;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost\enable_shared_from_this.hpp>
|
||||||
|
|
||||||
|
#include "udtutils.h"
|
||||||
#include "diawrapper.h"
|
#include "diawrapper.h"
|
||||||
#include "intbase.h"
|
#include "intbase.h"
|
||||||
|
|
||||||
@ -14,7 +17,7 @@ typedef boost::shared_ptr<TypeInfo> TypeInfoPtr;
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class TypeInfo : boost::noncopyable, public intBase {
|
class TypeInfo : boost::noncopyable, public intBase, public boost::enable_shared_from_this<TypeInfo> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -42,7 +45,6 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
TypeInfo() :
|
TypeInfo() :
|
||||||
m_offset( 0 ),
|
|
||||||
m_staticOffset( 0 ),
|
m_staticOffset( 0 ),
|
||||||
m_constant( false ),
|
m_constant( false ),
|
||||||
m_staticMember( false ),
|
m_staticMember( false ),
|
||||||
@ -77,6 +79,17 @@ public:
|
|||||||
throw TypeException( getName(), "type is not a struct" );
|
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() {
|
virtual ULONG getFieldCount() {
|
||||||
throw TypeException( getName(), "type is not a struct" );
|
throw TypeException( getName(), "type is not a struct" );
|
||||||
}
|
}
|
||||||
@ -139,10 +152,6 @@ public:
|
|||||||
throw PyException( PyExc_TypeError, "object is unsubscriptable");
|
throw PyException( PyExc_TypeError, "object is unsubscriptable");
|
||||||
}
|
}
|
||||||
|
|
||||||
void setOffset( ULONG offset ) {
|
|
||||||
m_offset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setConstant( const VARIANT& var )
|
void setConstant( const VARIANT& var )
|
||||||
{
|
{
|
||||||
m_constant = true;
|
m_constant = true;
|
||||||
@ -177,10 +186,6 @@ public:
|
|||||||
m_virtualDispSize = virtualDispSize;
|
m_virtualDispSize = virtualDispSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG64 getTypeOffset();
|
|
||||||
|
|
||||||
ULONG getOffset();
|
|
||||||
|
|
||||||
ULONG64 getStaticOffset();
|
ULONG64 getStaticOffset();
|
||||||
|
|
||||||
void getVirtualDisplacement( ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) {
|
void getVirtualDisplacement( ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) {
|
||||||
@ -203,8 +208,6 @@ protected:
|
|||||||
static
|
static
|
||||||
TypeInfoPtr getRecurciveComplexType( TypeInfoPtr &lowestType, std::string &suffix, ULONG ptrSize );
|
TypeInfoPtr getRecurciveComplexType( TypeInfoPtr &lowestType, std::string &suffix, ULONG ptrSize );
|
||||||
|
|
||||||
ULONG m_offset;
|
|
||||||
|
|
||||||
ULONG64 m_staticOffset;
|
ULONG64 m_staticOffset;
|
||||||
|
|
||||||
bool m_constant;
|
bool m_constant;
|
||||||
@ -295,8 +298,10 @@ class UdtTypeInfo : public TypeInfo
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
UdtTypeInfo ( pyDia::SymbolPtr &symbol ) :
|
UdtTypeInfo ( pyDia::SymbolPtr &symbol ) :
|
||||||
m_dia( symbol )
|
m_dia( symbol ),
|
||||||
{}
|
m_fields( symbol->getName() )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -308,11 +313,28 @@ protected:
|
|||||||
return (ULONG)m_dia->getSize();
|
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();
|
virtual ULONG getFieldCount();
|
||||||
|
|
||||||
@ -332,11 +354,7 @@ protected:
|
|||||||
|
|
||||||
pyDia::SymbolPtr m_dia;
|
pyDia::SymbolPtr m_dia;
|
||||||
|
|
||||||
typedef std::pair< std::string, TypeInfoPtr > FieldType;
|
UdtUtils::FieldCollection m_fields;
|
||||||
|
|
||||||
typedef std::vector< FieldType > FieldList;
|
|
||||||
|
|
||||||
FieldList m_fields;
|
|
||||||
|
|
||||||
void getFields(
|
void getFields(
|
||||||
pyDia::SymbolPtr &rootSym,
|
pyDia::SymbolPtr &rootSym,
|
||||||
@ -348,6 +366,15 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
void getVirtualFields();
|
void getVirtualFields();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void refreshFields();
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const UdtUtils::Field &lookupField( T index) {
|
||||||
|
refreshFields();
|
||||||
|
return m_fields.lookup(index);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
68
pykd/udtutils.cpp
Normal file
68
pykd/udtutils.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include <boost\tokenizer.hpp>
|
||||||
|
|
||||||
|
#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<char> 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
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
65
pykd/udtutils.h
Normal file
65
pykd/udtutils.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class TypeInfo;
|
||||||
|
typedef boost::shared_ptr<TypeInfo> 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
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
@ -72,9 +72,9 @@ class TypedVarTest( unittest.TestCase ):
|
|||||||
|
|
||||||
def testFieldOffset(self):
|
def testFieldOffset(self):
|
||||||
tv = target.module.typedVar( "g_structTest" )
|
tv = target.module.typedVar( "g_structTest" )
|
||||||
self.assertEqual( 0, tv.m_field0.offset() )
|
self.assertEqual( 0, tv.fieldOffset("m_field0") )
|
||||||
self.assertEqual( 4, tv.m_field1.offset() )
|
self.assertEqual( 4, tv.fieldOffset("m_field1") )
|
||||||
self.assertEqual( 16, tv.m_field4.offset() )
|
self.assertEqual( 16, tv.fieldOffset("m_field4") )
|
||||||
|
|
||||||
def testArrayField(self):
|
def testArrayField(self):
|
||||||
tv = target.module.typedVar( "g_struct3" )
|
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" ) )
|
self.assertEqual( target.module.g_structTest, target.module.typedVar( "g_structTestPtr" ) )
|
||||||
|
|
||||||
def testContainingRecord(self):
|
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" )
|
off2 = target.module.offset( "g_structTest" )
|
||||||
tv = target.module.containingRecord( off2 + off1, "structTest", "m_field2" )
|
tv = target.module.containingRecord( off2 + off1, "structTest", "m_field2" )
|
||||||
self.assertEqual( True, tv.m_field2 )
|
self.assertEqual( True, tv.m_field2 )
|
||||||
@ -141,7 +141,6 @@ class TypedVarTest( unittest.TestCase ):
|
|||||||
tvl2 = pykd.typedVarList( target.module.g_listHead, target.moduleName + "!listStruct", "listEntry" )
|
tvl2 = pykd.typedVarList( target.module.g_listHead, target.moduleName + "!listStruct", "listEntry" )
|
||||||
self.assertEqual( tvl1, tvl2 )
|
self.assertEqual( tvl1, tvl2 )
|
||||||
|
|
||||||
|
|
||||||
def testTypedVarArray(self):
|
def testTypedVarArray(self):
|
||||||
tvl = target.module.typedVarArray( target.module.g_testArray, "structTest", 2 )
|
tvl = target.module.typedVarArray( target.module.g_testArray, "structTest", 2 )
|
||||||
self.assertEqual( 2, len( tvl ) )
|
self.assertEqual( 2, len( tvl ) )
|
||||||
|
@ -93,10 +93,15 @@ class TypeInfoTest( unittest.TestCase ):
|
|||||||
|
|
||||||
def testOffset( self ):
|
def testOffset( self ):
|
||||||
ti1 = target.module.type( "structTest" )
|
ti1 = target.module.type( "structTest" )
|
||||||
self.assertEqual( 0, ti1.m_field0.offset() )
|
self.assertEqual( 0, ti1.fieldOffset("m_field0") )
|
||||||
self.assertEqual( 4, ti1.m_field1.offset() )
|
self.assertEqual( 4, ti1.fieldOffset("m_field1") )
|
||||||
self.assertEqual( 12, ti1.m_field2.offset() )
|
self.assertEqual( 12, ti1.fieldOffset("m_field2") )
|
||||||
self.assertEqual( 14, ti1.m_field3.offset() )
|
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 ):
|
def testSize( self ):
|
||||||
ti1 = target.module.type( "structTest" )
|
ti1 = target.module.type( "structTest" )
|
||||||
@ -106,10 +111,9 @@ class TypeInfoTest( unittest.TestCase ):
|
|||||||
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 ):
|
def testBitField( self ):
|
||||||
ti = target.module.type( "g_structWithBits" )
|
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( 4, ti.m_bit6_7.size() )
|
||||||
self.assertEqual( "ULong:2", ti.m_bit6_7.name() )
|
self.assertEqual( "ULong:2", ti.m_bit6_7.name() )
|
||||||
self.assertEqual( 2, ti.m_bit6_7.bitWidth() )
|
self.assertEqual( 2, ti.m_bit6_7.bitWidth() )
|
||||||
@ -133,8 +137,8 @@ class TypeInfoTest( unittest.TestCase ):
|
|||||||
|
|
||||||
def testUnion(self):
|
def testUnion(self):
|
||||||
ti = target.module.type("unionTest")
|
ti = target.module.type("unionTest")
|
||||||
self.assertEqual( 0, ti.m_doubleValue.offset() )
|
self.assertEqual( 0, ti.fieldOffset("m_doubleValue") )
|
||||||
self.assertEqual( 0, ti.m_bits.offset() )
|
self.assertEqual( 0, ti.fieldOffset("m_bits") )
|
||||||
self.assertEqual( ti.size(), ti.m_doubleValue.size() )
|
self.assertEqual( ti.size(), ti.m_doubleValue.size() )
|
||||||
|
|
||||||
def testAsMap(self):
|
def testAsMap(self):
|
||||||
@ -186,9 +190,10 @@ class TypeInfoTest( unittest.TestCase ):
|
|||||||
|
|
||||||
def testStaticField(self):
|
def testStaticField(self):
|
||||||
ti = pykd.typeInfo( "g_classChild" )
|
ti = pykd.typeInfo( "g_classChild" )
|
||||||
self.assertNotEqual( 0, ti.m_staticField.offset() )
|
self.assertNotEqual( 0, ti.m_staticField.staticOffset() )
|
||||||
self.assertNotEqual( 0, ti.m_staticConst.offset() )
|
if not ti.m_staticConst.staticOffset():
|
||||||
self.assertNotEqual( 0, ti.m_stdstr.offset() )
|
self.assertFalse( "MS DIA bug: https://connect.microsoft.com/VisualStudio/feedback/details/737430" )
|
||||||
|
self.assertNotEqual( 0, ti.m_stdstr.staticOffset() )
|
||||||
|
|
||||||
def testUdtSubscribe(self):
|
def testUdtSubscribe(self):
|
||||||
tv = pykd.typeInfo( "g_virtChild" )
|
tv = pykd.typeInfo( "g_virtChild" )
|
||||||
|
Loading…
Reference in New Issue
Block a user