diff --git a/pykd/customtypes.cpp b/pykd/customtypes.cpp index 7a61ca1..3a9a959 100644 --- a/pykd/customtypes.cpp +++ b/pykd/customtypes.cpp @@ -1,22 +1,30 @@ #include "stdafx.h" #include "customtypes.h" +#include "dbgexcept.h" //////////////////////////////////////////////////////////////////////////////// namespace pykd { + //////////////////////////////////////////////////////////////////////////////// -CustomTypeBase::CustomTypeBase(const std::string &name, ULONG pointerSize) - : UdtFieldColl(name) +TypeInfoPtr TypeBuilder::createStruct( const std::string &name, ULONG align ) { - m_ptrSize = pointerSize ? pointerSize : ptrSize(); + return TypeInfoPtr( new CustomStruct( name, m_ptrSize, align ? align : m_ptrSize ) ); } //////////////////////////////////////////////////////////////////////////////// -void CustomTypeBase::throwIfFiledExist(const std::string &fieldName) +TypeInfoPtr TypeBuilder::createUnion( const std::string &name, ULONG align ) +{ + return TypeInfoPtr( new CustomUnion( name, m_ptrSize, align ? align : m_ptrSize ) ); +} + +//////////////////////////////////////////////////////////////////////////////// + +void CustomBase::throwIfFiledExist(const std::string &fieldName) { bool fieldExist = false; try @@ -24,29 +32,22 @@ void CustomTypeBase::throwIfFiledExist(const std::string &fieldName) lookupField(fieldName); fieldExist = true; } - catch (const TypeException &except) + catch (const TypeException&) { - DBG_UNREFERENCED_PARAMETER(except); } + if (fieldExist) throw TypeException(getName(), "duplicate field name: " + fieldName); } //////////////////////////////////////////////////////////////////////////////// -void CustomTypeBase::throwIfTypeRecursive(TypeInfoPtr type) +void CustomBase::throwIfTypeRecursive(TypeInfoPtr type) { if (type->is(this)) - throw TypeException(getName(), "wrong type of field"); + throw TypeException(getName(), "recursive type definition"); - return throwIfTypeRecursiveImpl(type); -} - -//////////////////////////////////////////////////////////////////////////////// - -void CustomTypeBase::throwIfTypeRecursiveImpl(TypeInfoPtr type) -{ - if (type->isEnum()) + if ( !type->isUserDefined() ) return; try @@ -58,7 +59,7 @@ void CustomTypeBase::throwIfTypeRecursiveImpl(TypeInfoPtr type) if (fileldType->is(this)) throw TypeException(getName(), "wrong type of field"); - throwIfTypeRecursiveImpl(fileldType); + throwIfTypeRecursive(fileldType); } } catch (const TypeException &except) @@ -69,78 +70,188 @@ void CustomTypeBase::throwIfTypeRecursiveImpl(TypeInfoPtr type) //////////////////////////////////////////////////////////////////////////////// -TypeInfoPtr CustomStruct::create( - const std::string &name, - ULONG alignReq /*= 0*/, - ULONG pointerSize /*= 0*/) +void CustomStruct::appendField(const std::string &fieldName, TypeInfoPtr &fieldType ) { - return TypeInfoPtr( new CustomStruct(name, alignReq, pointerSize) ); + throwIfFiledExist(fieldName); + throwIfTypeRecursive(fieldType); + + CustomUdtField *field = new CustomUdtField( fieldType, fieldName ); + + ULONG fieldSize = fieldType->getSize(); + ULONG offset = m_size; + ULONG align = fieldSize < m_align ? fieldSize : m_align; + + offset += offset % align > 0 ? align - offset % align : 0; + + field->setOffset( offset ); + + m_size = offset + fieldSize; + + m_fields.push_back( UdtFieldPtr( field ) ); } //////////////////////////////////////////////////////////////////////////////// -ULONG CustomStruct::getSize() +void CustomUnion::appendField(const std::string &fieldName, TypeInfoPtr &fieldType ) { - if (Base::empty()) - return 0; + throwIfFiledExist(fieldName); + throwIfTypeRecursive(fieldType); - UdtUtils::Field &field = Base::last(); - return field.m_offset + field.m_type->getSize(); + CustomUdtField *field = new CustomUdtField( fieldType, fieldName ); + + ULONG fieldSize = fieldType->getSize(); + + m_size = fieldSize > m_size ? fieldSize : m_size; + + m_fields.push_back( UdtFieldPtr( field ) ); } //////////////////////////////////////////////////////////////////////////////// -void CustomStruct::appendField(const std::string &fieldName, TypeInfoPtr fieldType) -{ - Base::throwIfFiledExist(fieldName); - Base::throwIfTypeRecursive(fieldType); - ULONG offset = getSize(); - offset += offset % (m_align ? m_align : fieldType->getAlignReq()); - Base::push_back( - UdtUtils::Field(offset, fieldName, fieldType) - ); -} -//////////////////////////////////////////////////////////////////////////////// -TypeInfoPtr CustomUnion::create(const std::string &name, ULONG pointerSize /*= 0*/) -{ - return TypeInfoPtr( new CustomUnion(name, pointerSize) ); -} -//////////////////////////////////////////////////////////////////////////////// -ULONG CustomUnion::getSize() -{ - ULONG size = 0; - for (ULONG i = 0; i < getFieldCount(); ++i) - { - ULONG fieldSize = lookupField(i).m_type->getSize(); - if (fieldSize > size) - size = fieldSize; - } - return size; -} -//////////////////////////////////////////////////////////////////////////////// -void CustomUnion::appendField(const std::string &fieldName, TypeInfoPtr fieldType) -{ - Base::throwIfFiledExist(fieldName); - Base::throwIfTypeRecursive(fieldType); - Base::push_back( - UdtUtils::Field(0, fieldName, fieldType) - ); -} -//////////////////////////////////////////////////////////////////////////////// - -TypeInfoPtr PtrToVoid() -{ - return TypeInfoPtr( new PointerTypeInfo(ptrSize()) ); -} +////////////////////////////////////////////////////////////////////////////////// +// +//CustomTypeBase::CustomTypeBase(const std::string &name, ULONG pointerSize) +// : UdtFieldColl(name) +//{ +// m_ptrSize = pointerSize ? pointerSize : ptrSize(); +//} +// +////////////////////////////////////////////////////////////////////////////////// +// +//void CustomTypeBase::throwIfFiledExist(const std::string &fieldName) +//{ +// bool fieldExist = false; +// try +// { +// lookupField(fieldName); +// fieldExist = true; +// } +// catch (const TypeException &except) +// { +// DBG_UNREFERENCED_PARAMETER(except); +// } +// if (fieldExist) +// throw TypeException(getName(), "duplicate field name: " + fieldName); +//} +// +////////////////////////////////////////////////////////////////////////////////// +// +//void CustomTypeBase::throwIfTypeRecursive(TypeInfoPtr type) +//{ +// if (type->is(this)) +// throw TypeException(getName(), "wrong type of field"); +// +// return throwIfTypeRecursiveImpl(type); +//} +// +////////////////////////////////////////////////////////////////////////////////// +// +//void CustomTypeBase::throwIfTypeRecursiveImpl(TypeInfoPtr type) +//{ +// if (type->isEnum()) +// return; +// +// try +// { +// const ULONG fields = type->getFieldCount(); +// for (ULONG i = 0; i < fields; ++i) +// { +// TypeInfoPtr fileldType = type->getFieldByIndex(i); +// if (fileldType->is(this)) +// throw TypeException(getName(), "wrong type of field"); +// +// throwIfTypeRecursiveImpl(fileldType); +// } +// } +// catch (const TypeException &except) +// { +// DBG_UNREFERENCED_PARAMETER(except); +// } +//} +// +////////////////////////////////////////////////////////////////////////////////// +// +//TypeInfoPtr CustomStruct::create( +// const std::string &name, +// ULONG alignReq /*= 0*/, +// ULONG pointerSize /*= 0*/) +//{ +// return TypeInfoPtr( new CustomStruct(name, alignReq, pointerSize) ); +//} +// +////////////////////////////////////////////////////////////////////////////////// +// +//ULONG CustomStruct::getSize() +//{ +// if (Base::empty()) +// return 0; +// +// UdtUtils::Field &field = Base::last(); +// return field.m_offset + field.m_type->getSize(); +//} +// +////////////////////////////////////////////////////////////////////////////////// +// +//void CustomStruct::appendField(const std::string &fieldName, TypeInfoPtr fieldType) +//{ +// Base::throwIfFiledExist(fieldName); +// Base::throwIfTypeRecursive(fieldType); +// +// ULONG offset = getSize(); +// offset += offset % (m_align ? m_align : fieldType->getAlignReq()); +// Base::push_back( +// UdtUtils::Field(offset, fieldName, fieldType) +// ); +//} +// +////////////////////////////////////////////////////////////////////////////////// +// +//TypeInfoPtr CustomUnion::create(const std::string &name, ULONG pointerSize /*= 0*/) +//{ +// return TypeInfoPtr( new CustomUnion(name, pointerSize) ); +//} +// +////////////////////////////////////////////////////////////////////////////////// +// +//ULONG CustomUnion::getSize() +//{ +// ULONG size = 0; +// for (ULONG i = 0; i < getFieldCount(); ++i) +// { +// ULONG fieldSize = lookupField(i).m_type->getSize(); +// if (fieldSize > size) +// size = fieldSize; +// } +// return size; +//} +// +////////////////////////////////////////////////////////////////////////////////// +// +//void CustomUnion::appendField(const std::string &fieldName, TypeInfoPtr fieldType) +//{ +// Base::throwIfFiledExist(fieldName); +// Base::throwIfTypeRecursive(fieldType); +// +// Base::push_back( +// UdtUtils::Field(0, fieldName, fieldType) +// ); +//} +// +////////////////////////////////////////////////////////////////////////////////// +// +//TypeInfoPtr PtrToVoid() +//{ +// return TypeInfoPtr( new PointerTypeInfo(ptrSize()) ); +//} //////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/customtypes.h b/pykd/customtypes.h index 2b1e8eb..d63ab31 100644 --- a/pykd/customtypes.h +++ b/pykd/customtypes.h @@ -4,90 +4,217 @@ //////////////////////////////////////////////////////////////////////////////// #include "typeinfo.h" -#include "win\dbgeng.h" +#include "dbgengine.h" +#include //////////////////////////////////////////////////////////////////////////////// namespace pykd { + +class TypeBuilder { + +public: + + TypeBuilder( ULONG pointerSize = 0 ) + { + m_ptrSize = pointerSize ? pointerSize : ptrSize(); + } + + TypeInfoPtr getUInt1B() { return TypeInfo::getBaseTypeInfo( "UInt1B" ); } + TypeInfoPtr getUInt2B() { return TypeInfo::getBaseTypeInfo( "UInt2B" ); } + TypeInfoPtr getUInt4B() { return TypeInfo::getBaseTypeInfo( "UInt4B" ); } + TypeInfoPtr getUInt8B() { return TypeInfo::getBaseTypeInfo( "UInt8B" ); } + TypeInfoPtr getInt1B() { return TypeInfo::getBaseTypeInfo( "Int1B" ); } + TypeInfoPtr getInt2B() { return TypeInfo::getBaseTypeInfo( "Int2B" ); } + TypeInfoPtr getInt4B() { return TypeInfo::getBaseTypeInfo( "Int4B" ); } + TypeInfoPtr getInt8B() { return TypeInfo::getBaseTypeInfo( "Int8B" ); } + TypeInfoPtr getLong() { return TypeInfo::getBaseTypeInfo( "Long" ); } + TypeInfoPtr getULong() { return TypeInfo::getBaseTypeInfo( "Ulong" ); } + TypeInfoPtr getBool() { return TypeInfo::getBaseTypeInfo( "Bool" ); } + TypeInfoPtr getChar() { return TypeInfo::getBaseTypeInfo( "Char" ); } + TypeInfoPtr getWChar() { return TypeInfo::getBaseTypeInfo( "WChar" ); } + + TypeInfoPtr getVoidPtr() { + return TypeInfoPtr( new PointerTypeInfo(m_ptrSize) ); + } + + TypeInfoPtr createStruct( const std::string &name, ULONG align = 0 ); + + TypeInfoPtr createUnion( const std::string &name, ULONG align = 0); + +private: + + ULONG m_ptrSize; +}; + + //////////////////////////////////////////////////////////////////////////////// -class CustomTypeBase : public UdtFieldColl +class CustomBase : public UdtTypeInfoBase { - typedef UdtFieldColl Base; + protected: - CustomTypeBase(const std::string &name, ULONG pointerSize); + + CustomBase( const std::string &name, ULONG pointerSize, ULONG align ) : + UdtTypeInfoBase( name ), + m_size( 0 ), + m_ptrSize( pointerSize ), + m_align( align ) + {} void throwIfFiledExist(const std::string &fieldName); void throwIfTypeRecursive(TypeInfoPtr type); -private: - void throwIfTypeRecursiveImpl(TypeInfoPtr type); -}; +protected: -//////////////////////////////////////////////////////////////////////////////// - -class CustomStruct : public CustomTypeBase -{ - typedef CustomTypeBase Base; -public: - static TypeInfoPtr create(const std::string &name, ULONG align = 0, ULONG pointerSize = 0); + virtual ULONG getSize() { + return m_size; + } protected: - CustomStruct(const std::string &name, ULONG align, ULONG pointerSize) - : Base(name, pointerSize), m_name(name), m_align(align) - { - } - virtual std::string getName() override { - return m_name; - } + ULONG m_ptrSize; - virtual ULONG getSize() override; + ULONG m_align; - virtual void appendField(const std::string &fieldName, TypeInfoPtr fieldType) override; + std::string m_name; - virtual std::string getTypeString() const override { - return "custom struct"; - } - -private: - std::string m_name; - ULONG m_align; + ULONG m_size; }; //////////////////////////////////////////////////////////////////////////////// -class CustomUnion : public CustomTypeBase +class CustomStruct : public CustomBase { - typedef CustomTypeBase Base; public: - static TypeInfoPtr create(const std::string &name, ULONG pointerSize = 0); - -protected: - CustomUnion(const std::string &name, ULONG pointerSize) - : Base(name, pointerSize) - { - } - - virtual ULONG getSize() override; - - virtual void appendField(const std::string &fieldName, TypeInfoPtr fieldType) override; - - virtual std::string getTypeString() const override { - return "custom union"; - } + + CustomStruct( const std::string &name, ULONG ptrSize, ULONG align ) : + CustomBase( name, ptrSize, align ) + {} private: - std::string m_name; + + virtual void appendField(const std::string &fieldName, TypeInfoPtr &fieldType ); + }; //////////////////////////////////////////////////////////////////////////////// -TypeInfoPtr PtrToVoid(); +class CustomUnion : public CustomBase +{ +public: + + CustomUnion( const std::string &name, ULONG ptrSize, ULONG align ) : + CustomBase( name, ptrSize, align ) + {} + +private: + + virtual void appendField(const std::string &fieldName, TypeInfoPtr &fieldType ); + +}; //////////////////////////////////////////////////////////////////////////////// + + + + + + + + + + + + + + + + + + + +// +////////////////////////////////////////////////////////////////////////////////// +// +//class CustomTypeBase : public UdtFieldColl +//{ +// typedef UdtFieldColl Base; +//protected: +// CustomTypeBase(const std::string &name, ULONG pointerSize); +// +// void throwIfFiledExist(const std::string &fieldName); +// void throwIfTypeRecursive(TypeInfoPtr type); +// +//private: +// void throwIfTypeRecursiveImpl(TypeInfoPtr type); +//}; +// +////////////////////////////////////////////////////////////////////////////////// +// +//class CustomStruct : public CustomTypeBase +//{ +// typedef CustomTypeBase Base; +//public: +// static TypeInfoPtr create(const std::string &name, ULONG align = 0, ULONG pointerSize = 0); +// +//protected: +// CustomStruct(const std::string &name, ULONG align, ULONG pointerSize) +// : Base(name, pointerSize), m_name(name), m_align(align) +// { +// } +// +// virtual std::string getName() override { +// return m_name; +// } +// +// virtual ULONG getSize() override; +// +// virtual void appendField(const std::string &fieldName, TypeInfoPtr fieldType) override; +// +// virtual std::string getTypeString() const override { +// return "custom struct"; +// } +// +//private: +// std::string m_name; +// ULONG m_align; +//}; +// +////////////////////////////////////////////////////////////////////////////////// +// +//class CustomUnion : public CustomTypeBase +//{ +// typedef CustomTypeBase Base; +//public: +// static TypeInfoPtr create(const std::string &name, ULONG pointerSize = 0); +// +//protected: +// CustomUnion(const std::string &name, ULONG pointerSize) +// : Base(name, pointerSize) +// { +// } +// +// virtual ULONG getSize() override; +// +// virtual void appendField(const std::string &fieldName, TypeInfoPtr fieldType) override; +// +// virtual std::string getTypeString() const override { +// return "custom union"; +// } +// +//private: +// std::string m_name; +//}; +// +////////////////////////////////////////////////////////////////////////////////// +// +//TypeInfoPtr PtrToVoid(); +// +////////////////////////////////////////////////////////////////////////////////// + } // namespace pykd //////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index d452d2e..f55a0c5 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -20,6 +20,7 @@ #include "disasm.h" #include "stkframe.h" #include "bpoint.h" +#include "eventhandler.h" #include "win/dbgio.h" #include "win/windbg.h" @@ -59,11 +60,11 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( getSourceFile_, getSourceFile, 0, 1 ); BOOST_PYTHON_FUNCTION_OVERLOADS( setSoftwareBp_, setSoftwareBp, 1, 2 ); BOOST_PYTHON_FUNCTION_OVERLOADS( setHardwareBp_, setHardwareBp, 3, 4 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( CustomStruct_create, CustomStruct::create, 1, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( CustomUnion_create, CustomUnion::create, 1, 2 ); - BOOST_PYTHON_FUNCTION_OVERLOADS( findSymbol_, TypeInfo::findSymbol, 1, 2 ); +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( TypeBuilder_createStruct, TypeBuilder::createStruct, 1, 2 ); +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( TypeBuilder_createUnion, TypeBuilder::createUnion, 1, 2 ); + BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( Module_enumSymbols, Module::enumSymbols, 0, 1 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( Module_enumTypes, Module::enumTypes, 0, 1 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( Module_findSymbol, Module::getSymbolNameByVa, 1, 2 ); @@ -286,12 +287,12 @@ BOOST_PYTHON_MODULE( pykd ) python::def( "setSymbolPath", &setSymbolPath, "Set current symbol path"); python::def( "appendSymbolPath", &appendSymbolPath, "Append current symbol path"); - // custom types - python::def( "createStruct", &CustomStruct::create, CustomStruct_create( python::args( "name", "align", "ptrSize" ), - "Create empty structure. Use append() method for building" ) ); - python::def( "createUnion", &CustomUnion::create, CustomUnion_create( python::args( "name", "ptrSize" ), - "Create empty union. Use append() method for building" ) ); - python::def( "pVoid", &PtrToVoid, "Create \"Void*\" type" ); + //// custom types + //python::def( "createStruct", &CustomStruct::create, CustomStruct_create( python::args( "name", "align", "ptrSize" ), + // "Create empty structure. Use append() method for building" ) ); + //python::def( "createUnion", &CustomUnion::create, CustomUnion_create( python::args( "name", "ptrSize" ), + // "Create empty union. Use append() method for building" ) ); + //python::def( "pVoid", &PtrToVoid, "Create \"Void*\" type" ); python::class_( "intBase", "intBase", python::no_init ) .def( python::init() ) @@ -393,8 +394,8 @@ BOOST_PYTHON_MODULE( pykd ) .def("__init__", python::make_constructor(TypeInfo::getTypeInfoByName ) ) .def( "name", &TypeInfo::getName ) .def( "size", &TypeInfo::getSize ) - .def( "staticOffset", &TypeInfo::getStaticOffset ) - .def( "fieldOffset", &TypeInfo::getFieldOffsetByNameRecirsive ) + .def( "staticOffset", &TypeInfo::getStaticOffsetByName ) + .def( "fieldOffset", &TypeInfo::getFieldOffsetByNameRecursive ) .def( "bitOffset", &TypeInfo::getBitOffset ) .def( "bitWidth", &TypeInfo::getBitWidth ) .def( "field", &TypeInfo::getField ) @@ -416,7 +417,7 @@ BOOST_PYTHON_MODULE( pykd ) "Return virtual address" ) .def("sizeof", &TypedVar::getSize, "Return size of a variable in the target memory" ) - .def("fieldOffset", &TypedVar::getFieldOffsetByNameRecirsive, + .def("fieldOffset", &TypedVar::getFieldOffsetByNameRecursive, "Return target field offset" ) .def("field", &TypedVar::getField, "Return field of structure as an object attribute" ) @@ -433,6 +434,29 @@ BOOST_PYTHON_MODULE( pykd ) .def("__getitem__", &TypedVar::getElementByIndex ) .def("__getitem__", &TypedVar::getElementByIndexPtr ); + python::class_("typeBuilder", + "Class for building dynamically defined types", boost::python::no_init ) + .def( python::init() ) + .def( python::init<>() ) + .add_property( "UInt1B", &TypeBuilder::getUInt1B ) + .add_property( "UInt2B", &TypeBuilder::getUInt2B ) + .add_property( "UInt4B", &TypeBuilder::getUInt4B ) + .add_property( "UInt8B", &TypeBuilder::getUInt8B ) + .add_property( "Int1B", &TypeBuilder::getInt1B ) + .add_property( "Int2B", &TypeBuilder::getInt2B ) + .add_property( "Int4B", &TypeBuilder::getInt4B ) + .add_property( "Int8B", &TypeBuilder::getInt8B ) + .add_property( "Long", &TypeBuilder::getLong ) + .add_property( "ULong", &TypeBuilder::getLong ) + .add_property( "Bool", &TypeBuilder::getLong ) + .add_property( "Char", &TypeBuilder::getLong ) + .add_property( "WChar", &TypeBuilder::getLong ) + .add_property( "VoidPtr", &TypeBuilder::getVoidPtr ) + .def( "createStruct", &TypeBuilder::createStruct, TypeBuilder_createStruct( python::args( "name", "align" ), + "create custom struct" ) ) + .def( "createUnion", &TypeBuilder::createUnion, TypeBuilder_createUnion( python::args( "name", "align" ), + "create custom union" ) ); + python::class_ >( "cpuReg", "CPU regsiter class", boost::python::no_init ) .def( "name", &CpuReg::name, "The name of the regsiter" ) diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index 2ce3254..184ebbb 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -265,21 +265,23 @@ UdtTypedVar::getField( const std::string &fieldName ) { TypeInfoPtr fieldType = m_typeInfo->getField( fieldName ); - if ( fieldType->isStaticMember() ) + if ( m_typeInfo->isStaticMember(fieldName) ) { - if ( fieldType->getStaticOffset() == 0 ) + ULONG64 staticOffset = m_typeInfo->getStaticOffsetByName( fieldName ); + + if ( staticOffset == 0 ) throw ImplementException( __FILE__, __LINE__, "Fix ME"); - return TypedVar::getTypedVar( fieldType, VarDataMemory::factory(fieldType->getStaticOffset() ) ); + return TypedVar::getTypedVar( fieldType, VarDataMemory::factory(staticOffset) ); } ULONG fieldOffset = 0; - fieldOffset = m_typeInfo->getFieldOffsetByNameRecirsive(fieldName); + fieldOffset = m_typeInfo->getFieldOffsetByNameRecursive(fieldName); - if ( fieldType->isVirtualMember() ) + if ( m_typeInfo->isVirtualMember( fieldName ) ) { - fieldOffset += getVirtualBaseDisplacement( fieldType ); + fieldOffset += getVirtualBaseDisplacement( fieldName ); } return TypedVar::getTypedVar( fieldType, m_varData->fork(fieldOffset) ); @@ -290,23 +292,27 @@ UdtTypedVar::getField( const std::string &fieldName ) python::object UdtTypedVar::getElementByIndex( ULONG index ) { - TypeInfoPtr fieldType = m_typeInfo->getFieldByIndex(index); + TypeInfoPtr fieldType = m_typeInfo->getFieldByIndex( index ); - if ( fieldType->isStaticMember() ) + if ( m_typeInfo->isStaticMemberByIndex(index) ) { - if ( fieldType->getStaticOffset() == 0 ) + ULONG64 staticOffset = m_typeInfo->getStaticOffsetByIndex( index ); + + if ( staticOffset == 0 ) throw ImplementException( __FILE__, __LINE__, "Fix ME"); - return python::make_tuple( + return python::make_tuple( m_typeInfo->getFieldNameByIndex(index), - TypedVar::getTypedVar(fieldType, VarDataMemory::factory(fieldType->getStaticOffset() ) ) ); + TypedVar::getTypedVar( fieldType, VarDataMemory::factory(staticOffset) ) ); } - ULONG fieldOffset = m_typeInfo->getFieldOffsetByIndex(index); + ULONG fieldOffset = 0; - if ( fieldType->isVirtualMember() ) + fieldOffset = m_typeInfo->getFieldOffsetByIndex(index); + + if ( m_typeInfo->isVirtualMemberByIndex( index ) ) { - fieldOffset += getVirtualBaseDisplacement( fieldType ); + fieldOffset += getVirtualBaseDisplacementByIndex( index ); } return python::make_tuple( @@ -316,12 +322,30 @@ UdtTypedVar::getElementByIndex( ULONG index ) /////////////////////////////////////////////////////////////////////////////////// -LONG UdtTypedVar::getVirtualBaseDisplacement( TypeInfoPtr& typeInfo ) +LONG UdtTypedVar::getVirtualBaseDisplacement( const std::string &fieldName ) { ULONG virtualBasePtr, virtualDispIndex, virtualDispSize; - typeInfo->getVirtualDisplacement( virtualBasePtr, virtualDispIndex, virtualDispSize ); + m_typeInfo->getVirtualDisplacement( fieldName, virtualBasePtr, virtualDispIndex, virtualDispSize ); - ULONG64 vbtableOffset = m_varData->fork( virtualBasePtr )->readPtr( typeInfo->ptrSize() ); + ULONG64 vbtableOffset = m_varData->fork( virtualBasePtr )->readPtr( m_typeInfo->ptrSize() ); + + VarDataPtr vbtable = VarDataMemory::factory(vbtableOffset); + + LONG displacement = 0; + + vbtable->read( &displacement, sizeof(displacement), virtualDispIndex*virtualDispSize ); + + return virtualBasePtr + displacement; +} + +/////////////////////////////////////////////////////////////////////////////// + +LONG UdtTypedVar::getVirtualBaseDisplacementByIndex( ULONG index ) +{ + ULONG virtualBasePtr, virtualDispIndex, virtualDispSize; + m_typeInfo->getVirtualDisplacementByIndex( index, virtualBasePtr, virtualDispIndex, virtualDispSize ); + + ULONG64 vbtableOffset = m_varData->fork( virtualBasePtr )->readPtr( m_typeInfo->ptrSize() ); VarDataPtr vbtable = VarDataMemory::factory(vbtableOffset); @@ -345,21 +369,23 @@ std::string UdtTypedVar::print() TypeInfoPtr fieldType = m_typeInfo->getFieldByIndex(i); TypedVarPtr fieldVar; - if ( fieldType->isStaticMember() ) + if ( m_typeInfo->isStaticMemberByIndex(i) ) { - if ( fieldType->getStaticOffset() != 0 ) - fieldVar = TypedVar::getTypedVar( fieldType, VarDataMemory::factory( fieldType->getStaticOffset() ) ); + ULONG64 staticOffset = m_typeInfo->getStaticOffsetByIndex(i); - sstr << " =" << std::right << std::setw(10) << std::setfill('0') << std::hex << fieldType->getStaticOffset(); + if ( staticOffset != 0 ) + fieldVar = TypedVar::getTypedVar( fieldType, VarDataMemory::factory( staticOffset ) ); + + sstr << " =" << std::right << std::setw(10) << std::setfill('0') << std::hex << staticOffset; sstr << " " << std::left << std::setw(18) << std::setfill(' ') << m_typeInfo->getFieldNameByIndex(i) << ':'; } else { ULONG fieldOffset = m_typeInfo->getFieldOffsetByIndex(i); - if ( fieldType->isVirtualMember() ) + if ( m_typeInfo->isVirtualMemberByIndex( i ) ) { - fieldOffset += getVirtualBaseDisplacement( fieldType ); + fieldOffset += getVirtualBaseDisplacementByIndex( i ); } fieldVar = TypedVar::getTypedVar( fieldType, m_varData->fork(fieldOffset) ); @@ -514,7 +540,7 @@ TypedVarPtr containingRecordByType( ULONG64 addr, const TypeInfoPtr &typeInfo, c { addr = addr64(addr); - VarDataPtr varData = VarDataMemory::factory( addr - typeInfo->getFieldOffsetByNameRecirsive(fieldName) ); + VarDataPtr varData = VarDataMemory::factory( addr - typeInfo->getFieldOffsetByNameRecursive(fieldName) ); return TypedVar::getTypedVar( typeInfo, varData ); } @@ -549,7 +575,7 @@ python::list getTypedVarListByType( ULONG64 listHeadAddress, const TypeInfoPtr & if ( fieldTypeInfo->getName() == ( typeInfo->getName() + "*" ) ) { - for( entryAddress = ptrFunc( listHeadAddress ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrFunc( entryAddress + typeInfo->getFieldOffsetByNameRecirsive(listEntryName) ) ) + for( entryAddress = ptrFunc( listHeadAddress ); addr64(entryAddress) != listHeadAddress && entryAddress != NULL; entryAddress = ptrFunc( entryAddress + typeInfo->getFieldOffsetByNameRecursive(listEntryName) ) ) lst.append( TypedVar::getTypedVarByTypeInfo( typeInfo, entryAddress ) ); } else diff --git a/pykd/typedvar.h b/pykd/typedvar.h index 64230d8..880d93a 100644 --- a/pykd/typedvar.h +++ b/pykd/typedvar.h @@ -34,8 +34,8 @@ public: return m_size; } - ULONG getFieldOffsetByNameRecirsive(const std::string &fieldName) { - return m_typeInfo->getFieldOffsetByNameRecirsive(fieldName); + ULONG getFieldOffsetByNameRecursive(const std::string &fieldName) { + return m_typeInfo->getFieldOffsetByNameRecursive(fieldName); } TypeInfoPtr @@ -87,6 +87,9 @@ protected: TypedVar ( const TypeInfoPtr& typeInfo, VarDataPtr varData ); + virtual ~TypedVar() + {} + TypeInfoPtr m_typeInfo; VarDataPtr m_varData; @@ -171,12 +174,13 @@ protected: virtual TypedVarPtr getField( const std::string &fieldName ); virtual ULONG getElementCount() { - return m_typeInfo->getFieldCount(); + return m_typeInfo->getFieldCount(); } virtual python::object getElementByIndex( ULONG index ); - LONG getVirtualBaseDisplacement( TypeInfoPtr& typeInfo ); + LONG getVirtualBaseDisplacement( const std::string &fieldName ); + LONG getVirtualBaseDisplacementByIndex( ULONG index ); }; /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index b2f287b..1bf736f 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -609,51 +609,39 @@ TypeInfoPtr TypeInfo::ptrTo() ///////////////////////////////////////////////////////////////////////////////////// -ULONG64 TypeInfo::getStaticOffset() -{ - if ( !m_staticMember ) - throw TypeException( getName(), "This is not a static member" ); - - return m_staticOffset; -} - -///////////////////////////////////////////////////////////////////////////////////// - -std::string UdtFieldColl::print() +std::string UdtTypeInfoBase::print() { std::stringstream sstr; - sstr << getTypeString() << ": " << getName() << " Size: 0x" << std::hex << getSize() << " (" << std::dec << getSize() << ")" << std::endl; + sstr << "class/struct " << ": " << getName() << " Size: 0x" << std::hex << getSize() << " (" << std::dec << getSize() << ")" << std::endl; ULONG fieldCount = getFieldCount(); for ( ULONG i = 0; i < fieldCount; ++i ) { - const UdtUtils::Field &udtField = lookupField(i); - TypeInfoPtr fieldType = udtField.m_type; + UdtFieldPtr& udtField = lookupField(i); - if ( fieldType->isStaticMember() ) - { - sstr << " =" << std::right << std::setw(10) << std::setfill('0') << std::hex << fieldType->getStaticOffset(); - sstr << " " << std::left << std::setw(18) << std::setfill(' ') << udtField.m_name << ':'; - } - else - if ( fieldType->isVirtualMember() ) + if ( udtField->isStaticMember() ) { - 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 << udtField.m_offset; - sstr << " " << udtField.m_name << ':'; + sstr << " =" << std::right << std::setw(10) << std::setfill('0') << std::hex << udtField->getStaticOffset(); + sstr << " " << std::left << std::setw(18) << std::setfill(' ') << udtField->getName() << ':'; } else { - 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 << ':'; + if ( udtField->isVirtualMember() ) + { + sstr << " virtual base " << udtField->getVirtualBaseClassName(); + sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << udtField->getOffset(); + sstr << " " << udtField->getName() << ':'; + } + else + { + sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << udtField->getOffset(); + sstr << " " << std::left << std::setw(24) << std::setfill(' ') << udtField->getName() << ':'; + } } - sstr << " " << std::left << fieldType->getName(); + sstr << " " << std::left << udtField->getTypeInfo()->getName(); sstr << std::endl; } @@ -662,14 +650,40 @@ std::string UdtFieldColl::print() ///////////////////////////////////////////////////////////////////////////////////// -ULONG UdtFieldColl::getAlignReq() +ULONG UdtTypeInfoBase::getAlignReq() { - ULONG alignReq = 1; - const ULONG fieldCount = getFieldCount(); - for ( ULONG i = 0; i < fieldCount; ++i ) - alignReq = max(alignReq, lookupField(i).m_type->getAlignReq()); + //ULONG alignReq = 1; + //const ULONG fieldCount = getFieldCount(); + //for ( ULONG i = 0; i < fieldCount; ++i ) + // alignReq = max(alignReq, lookupField(i).m_type->getAlignReq()); - return alignReq; + //return alignReq; + + throw ImplementException( __FILE__, __LINE__, "TODO" ); +} + +///////////////////////////////////////////////////////////////////////////////////// + +void UdtTypeInfoBase::getVirtualDisplacement( const std::string& fieldName, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) +{ + const UdtFieldPtr &field = lookupField(fieldName); + + if ( !field->isVirtualMember() ) + throw TypeException( getName(), "field is not a virtual member" ); + + field->getVirtualDisplacement( virtualBasePtr, virtualDispIndex, virtualDispSize ); +} + +///////////////////////////////////////////////////////////////////////////////////// + +void UdtTypeInfoBase::getVirtualDisplacementByIndex( ULONG index, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) +{ + const UdtFieldPtr &field = lookupField(index); + + if ( !field->isVirtualMember() ) + throw TypeException( getName(), "field is not a virtual member" ); + + field->getVirtualDisplacement( virtualBasePtr, virtualDispIndex, virtualDispSize ); } ///////////////////////////////////////////////////////////////////////////////////// @@ -700,52 +714,34 @@ void UdtTypeInfo::getFields( else if ( symTag == SymTagData ) { - TypeInfoPtr ti = TypeInfo::getTypeInfo( childSym ); + SymbolUdtField *fieldPtr = new SymbolUdtField( childSym, childSym->getName() ); - ULONG fieldOffset = 0; switch ( childSym->getDataKind() ) { case DataIsMember: - - if ( baseVirtualSym ) - { - ti->setVirtualBase( - TypeInfo::getTypeInfo(baseVirtualSym), - virtualBasePtr, - virtualDispIndex, - virtualDispSize ); - } - - fieldOffset = startOffset + childSym->getOffset(); + fieldPtr->setOffset( startOffset + childSym->getOffset() ); break; - case DataIsStaticMember: - ti->setStaticOffset( childSym->getVa() ); + fieldPtr->setStaticOffset( childSym->getVa() ); break; } - UdtFieldColl::push_back( - UdtUtils::Field( fieldOffset, childSym->getName(), ti ) - ); + if ( baseVirtualSym ) + fieldPtr->setVirtualDisplacement( virtualBasePtr, virtualDispIndex, virtualDispSize ); + + m_fields.push_back( UdtFieldPtr( fieldPtr ) ); } else if ( symTag == SymTagVTable ) { - TypeInfoPtr ti = TypeInfo::getTypeInfo( childSym ); + SymbolUdtField *fieldPtr = new SymbolUdtField( childSym, "__VFN_table" ); + + fieldPtr->setOffset( startOffset + childSym->getOffset() ); if ( baseVirtualSym ) - { - ti->setVirtualBase( - TypeInfo::getTypeInfo(baseVirtualSym), - virtualBasePtr, - virtualDispIndex, - virtualDispSize ); - - } + fieldPtr->setVirtualDisplacement( virtualBasePtr, virtualDispIndex, virtualDispSize ); - UdtFieldColl::push_back( - UdtUtils::Field( startOffset + childSym->getOffset(), "__VFN_table", ti ) - ); + m_fields.push_back( UdtFieldPtr( fieldPtr ) ); } } } @@ -777,11 +773,8 @@ void UdtTypeInfo::getVirtualFields() void UdtTypeInfo::refreshFields() { - if ( UdtFieldColl::empty() ) - { - getFields( m_dia, SymbolPtr() ); - getVirtualFields(); - } + getFields( m_dia, SymbolPtr() ); + getVirtualFields(); } ///////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index 34fb5f3..3678ab5 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -52,16 +52,13 @@ public: public: TypeInfo() : - m_staticOffset( 0 ), m_constant( false ), - m_staticMember( false ), - m_virtualMember( false ), - m_virtualBasePtr( 0 ), - m_virtualDispIndex( 0 ), - m_virtualDispSize( 0 ), m_ptrSize( 0 ) {} + virtual ~TypeInfo() + {} + virtual std::string print() { std::stringstream sstr; sstr << "Type name: " << getName(); @@ -85,7 +82,7 @@ public: throw TypeException( getName(), "type is not a struct" ); } - virtual ULONG getFieldOffsetByNameRecirsive( const std::string &fieldName ) { + virtual ULONG getFieldOffsetByNameRecursive( const std::string &fieldName ) { throw TypeException( getName(), "type is not a struct" ); } virtual ULONG getFieldOffsetByNameNotRecursively( const std::string &fieldName ) { @@ -100,6 +97,46 @@ public: throw TypeException( getName(), "type is not a struct" ); } + virtual bool isStaticMember( const std::string& fieldName ) + { + throw TypeException( getName(), "type is not a struct" ); + } + + virtual bool isStaticMemberByIndex( ULONG index ) + { + throw TypeException( getName(), "type is not a struct" ); + } + + virtual ULONG64 getStaticOffsetByName( const std::string& fieldName ) + { + throw TypeException( getName(), "type is not a struct" ); + } + + virtual ULONG64 getStaticOffsetByIndex( ULONG index ) + { + throw TypeException( getName(), "type is not a struct" ); + } + + virtual bool isVirtualMember( const std::string& fieldName ) + { + throw TypeException( getName(), "type is not a struct" ); + } + + virtual bool isVirtualMemberByIndex( ULONG index ) + { + throw TypeException( getName(), "type is not a struct" ); + } + + virtual void getVirtualDisplacement( const std::string& fieldName, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) + { + throw TypeException( getName(), "type is not a struct" ); + } + + virtual void getVirtualDisplacementByIndex( ULONG index, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) + { + throw TypeException( getName(), "type is not a struct" ); + } + virtual BaseTypeVariant getValue(); virtual bool isBasicType() { @@ -158,8 +195,8 @@ public: throw PyException( PyExc_TypeError, "object is unsubscriptable"); } - virtual void appendField(const std::string &fieldName, TypeInfoPtr fieldType) { - throw TypeException( getName(), "type is not is not extensible" ); + virtual void appendField(const std::string &fieldName, TypeInfoPtr &fieldType) { + throw TypeException( getName(), "type is not is not editable" ); } TypeInfoPtr ptrTo(); @@ -178,42 +215,6 @@ public: return m_constant == true; } - bool isStaticMember() const - { - return m_staticMember == true; - } - - bool isVirtualMember() const - { - return m_virtualMember == true; - } - - void setStaticOffset( ULONG64 offset ) { - m_staticOffset = offset; - m_staticMember = true; - } - - 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 getStaticOffset(); - - void getVirtualDisplacement( ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) { - virtualBasePtr = m_virtualBasePtr; - virtualDispIndex = m_virtualDispIndex; - virtualDispSize = m_virtualDispSize; - }; - - TypeInfoPtr getVirtualBase() { - return m_virtualBaseType; - } - bool is(TypeInfo *rhs) const { return this == rhs; } @@ -232,24 +233,10 @@ protected: static TypeInfoPtr getRecurciveComplexType( TypeInfoPtr &lowestType, std::string &suffix, ULONG ptrSize ); - ULONG64 m_staticOffset; - bool m_constant; - bool m_staticMember; - - bool m_virtualMember; - BaseTypeVariant m_constantValue; - LONG m_virtualBasePtr; - - ULONG m_virtualDispIndex; - - ULONG m_virtualDispSize; - - TypeInfoPtr m_virtualBaseType; - ULONG m_ptrSize; }; @@ -323,40 +310,60 @@ private: /////////////////////////////////////////////////////////////////////////////////// -class UdtFieldColl : public TypeInfo +class UdtTypeInfoBase : public TypeInfo { protected: virtual std::string getName() { - return m_fields.getName(); + return m_name; } virtual TypeInfoPtr getField( const std::string &fieldName ) { - return lookupField(fieldName).m_type; + return lookupField(fieldName)->getTypeInfo(); } virtual TypeInfoPtr getFieldByIndex( ULONG index ) { - return lookupField(index).m_type; + return lookupField(index)->getTypeInfo(); } virtual std::string getFieldNameByIndex( ULONG index ) { - return lookupField(index).m_name; + return lookupField(index)->getName(); } - virtual ULONG getFieldOffsetByNameRecirsive( const std::string &fieldName ) { - return UdtUtils::getFieldOffsetRecirsive( shared_from_this(), fieldName ); + virtual ULONG getFieldOffsetByNameRecursive( const std::string &fieldName ) { + return getFieldOffsetRecursive( shared_from_this(), fieldName ); } virtual ULONG getFieldOffsetByNameNotRecursively( const std::string &fieldName ) { - return lookupField(fieldName).m_offset; + return lookupField(fieldName)->getOffset(); } virtual ULONG getFieldOffsetByIndex( ULONG index ) { - return lookupField(index).m_offset; + return lookupField(index)->getOffset(); + } + + virtual bool isStaticMember( const std::string& fieldName ) { + return lookupField(fieldName)->isStaticMember(); + } + + virtual bool isStaticMemberByIndex( ULONG index ) { + return lookupField(index)->isStaticMember(); + } + + virtual ULONG64 getStaticOffsetByName( const std::string& fieldName ) { + return lookupField(fieldName)->getStaticOffset(); + } + + virtual ULONG64 getStaticOffsetByIndex( ULONG index ) { + return lookupField(index)->getStaticOffset(); } virtual ULONG getFieldCount() { - refreshFields(); - return (ULONG)m_fields.size(); + if ( !m_fieldsGot ) + { + refreshFields(); + m_fieldsGot = true; + } + return m_fields.count(); } virtual ULONG getElementCount() { @@ -375,42 +382,70 @@ protected: virtual ULONG getAlignReq() override; -protected: - UdtFieldColl(const std::string &typeName) : m_fields(typeName) {} - - virtual void refreshFields() {} - virtual std::string getTypeString() const = 0; - - bool empty() const { - return m_fields.empty(); + virtual bool isVirtualMember( const std::string& fieldName ) + { + return lookupField(fieldName)->isVirtualMember(); } - void push_back(const UdtUtils::Field &field) { + virtual bool isVirtualMemberByIndex( ULONG index ) + { + return lookupField(index)->isVirtualMember(); + } + + virtual void getVirtualDisplacement( const std::string& fieldName, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ); + virtual void getVirtualDisplacementByIndex( ULONG index, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ); + +protected: + + UdtTypeInfoBase(const std::string &typeName) : + m_name(typeName), + m_fieldsGot( false ) + {} + + virtual void refreshFields() {} + + void push_back(const UdtFieldPtr &field) { m_fields.push_back(field); } template - const UdtUtils::Field &lookupField( T index) { - refreshFields(); + const UdtFieldPtr &lookupField( T index)const { + if ( !m_fieldsGot ) + { + refreshFields(); + m_fieldsGot = true; + } return m_fields.lookup(index); } - UdtUtils::Field &last(){ - return *m_fields.rbegin(); + template + UdtFieldPtr &lookupField( T index) { + if ( !m_fieldsGot ) + { + refreshFields(); + m_fieldsGot = true; + } + return m_fields.lookup(index); } -private: - UdtUtils::FieldCollection m_fields; +protected: + + bool m_fieldsGot; + + FieldCollection m_fields; + + std::string m_name; + }; /////////////////////////////////////////////////////////////////////////////////// -class UdtTypeInfo : public UdtFieldColl +class UdtTypeInfo : public UdtTypeInfoBase { public: UdtTypeInfo (SymbolPtr &symbol ) : - UdtFieldColl( symbol->getName() ), + UdtTypeInfoBase( symbol->getName() ), m_dia( symbol ) { } @@ -423,10 +458,6 @@ protected: virtual void refreshFields() override; - virtual std::string getTypeString() const override { - return "struct/class"; - } - void getFields( SymbolPtr &rootSym, SymbolPtr &baseVirtualSym, diff --git a/pykd/udtutils.cpp b/pykd/udtutils.cpp index 5b8fc01..95e1725 100644 --- a/pykd/udtutils.cpp +++ b/pykd/udtutils.cpp @@ -10,33 +10,58 @@ /////////////////////////////////////////////////////////////////////////////////// namespace pykd { -namespace UdtUtils { ///////////////////////////////////////////////////////////////////////////////////// -const Field &FieldCollection::lookup(ULONG index) const +const UdtFieldPtr& FieldCollection::lookup(ULONG index) const { - if (index >= Base::size()) - throw PyException( PyExc_IndexError, m_baseTypeName + " index out of range" ); - return at(index); + if (index >= m_fields.size() ) + throw PyException( PyExc_IndexError, "index out of range" ); + + return m_fields[index]; } ///////////////////////////////////////////////////////////////////////////////////// -const Field &FieldCollection::lookup(const std::string &name) const +const UdtFieldPtr& FieldCollection::lookup(const std::string &name) const { - Base::const_reverse_iterator it = - std::find(Base::rbegin(), Base::rend(), name); + FieldList::const_reverse_iterator it; + for ( it = m_fields.rbegin(); it != m_fields.rend(); ++it ) + { + if ( (*it)->getName() == name ) + return *it; + } - if ( it == Base::rend() ) - throw TypeException( m_baseTypeName, name + ": field not found" ); + throw TypeException( "", "field not found" ); +} - return *it; +///////////////////////////////////////////////////////////////////////////////////// + +UdtFieldPtr &FieldCollection::lookup(ULONG index) +{ + if (index >= m_fields.size() ) + throw PyException( PyExc_IndexError, "index out of range" ); + + return m_fields[index]; +} + +///////////////////////////////////////////////////////////////////////////////////// + +UdtFieldPtr &FieldCollection::lookup(const std::string &name) +{ + FieldList::reverse_iterator it; + for ( it = m_fields.rbegin(); it != m_fields.rend(); ++it ) + { + if ( (*it)->getName() == name ) + return *it; + } + + throw TypeException( "", "field not found" ); } /////////////////////////////////////////////////////////////////////////////////// -ULONG getFieldOffsetRecirsive(TypeInfoPtr typeInfo, const std::string &fieldName) +ULONG getFieldOffsetRecursive(TypeInfoPtr typeInfo, const std::string &fieldName) { // "m_field1.m_field2" -> ["m_field1", "m_field2"] typedef boost::char_separator CharSep; @@ -59,7 +84,10 @@ ULONG getFieldOffsetRecirsive(TypeInfoPtr typeInfo, const std::string &fieldName /////////////////////////////////////////////////////////////////////////////////// -} // namespace UdtUtils +TypeInfoPtr SymbolUdtField::getTypeInfo() +{ + return TypeInfo::getTypeInfo(m_symbol); +} /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/udtutils.h b/pykd/udtutils.h index 29aec43..024beb9 100644 --- a/pykd/udtutils.h +++ b/pykd/udtutils.h @@ -6,64 +6,266 @@ #include #include +#include "symengine.h" + /////////////////////////////////////////////////////////////////////////////////// namespace pykd { -/////////////////////////////////////////////////////////////////////////////////// +class UdtField; +typedef boost::shared_ptr UdtFieldPtr; class TypeInfo; typedef boost::shared_ptr TypeInfoPtr; /////////////////////////////////////////////////////////////////////////////////// -namespace UdtUtils { +class UdtField +{ -/////////////////////////////////////////////////////////////////////////////////// +public: -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; + const std::string& getName() const + { + return m_name; } - ULONG m_offset; - std::string m_name; - TypeInfoPtr m_type; + const std::string& getVirtualBaseClassName() const + { + return m_virtualBaseName; + } + + ULONG getOffset() const + { + return m_offset; + } + + void setOffset( ULONG offset ) + { + m_offset = offset; + } + + bool isVirtualMember() const + { + return m_virtualMember; + } + + bool isStaticMember() const + { + return m_staticMember; + } + + ULONG64 getStaticOffset() const + { + return m_staticOffset; + } + + void setStaticOffset( ULONG64 staticOffset) + { + m_staticMember = true; + m_staticOffset = staticOffset; + } + + void getVirtualDisplacement( ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) + { + virtualBasePtr = m_virtualBasePtr; + virtualDispIndex = m_virtualDispIndex; + virtualDispSize = m_virtualDispSize; + } + + void setVirtualDisplacement( ULONG virtualBasePtr, ULONG virtualDispIndex, ULONG virtualDispSize ) + { + m_virtualMember = true; + m_virtualBasePtr = virtualBasePtr; + m_virtualDispIndex = virtualDispIndex; + m_virtualDispSize = virtualDispSize; + } + + virtual TypeInfoPtr getTypeInfo() = 0; + +protected: + + UdtField( const std::string &name ) : + m_name( name ), + m_offset( 0 ), + m_virtualMember( false ), + m_staticMember( false ), + m_virtualBasePtr( 0 ), + m_virtualDispIndex( 0 ), + m_virtualDispSize( 0 ) + {} + + std::string m_name; + + std::string m_virtualBaseName; + + ULONG m_offset; + + ULONG64 m_staticOffset; + + bool m_staticMember; + + bool m_virtualMember; + + ULONG m_virtualBasePtr; + ULONG m_virtualDispIndex; + ULONG m_virtualDispSize; + }; /////////////////////////////////////////////////////////////////////////////////// -class FieldCollection : public std::vector< Field > { - typedef std::vector< Field > Base; +class SymbolUdtField : public UdtField +{ public: - FieldCollection(const std::string &baseTypeName) : m_baseTypeName(baseTypeName) - {} - const Field &lookup(ULONG index) const; - const Field &lookup(const std::string &name) const; + SymbolUdtField( const SymbolPtr &sym, const std::string& name ) : + UdtField( name ), + m_symbol( sym ) + {} - const std::string &getName() const { - return m_baseTypeName; + SymbolPtr& getSymbol() { + return m_symbol; } private: - std::string m_baseTypeName; + + virtual TypeInfoPtr getTypeInfo(); + + SymbolPtr m_symbol; }; /////////////////////////////////////////////////////////////////////////////////// -ULONG getFieldOffsetRecirsive(TypeInfoPtr typeInfo, const std::string &fieldName); +class CustomUdtField : public UdtField +{ +public: + + CustomUdtField( const TypeInfoPtr &typeInfo, const std::string& name ) : + UdtField( name ), + m_type( typeInfo ) + {} + +private: + + virtual TypeInfoPtr getTypeInfo() { + return m_type; + } + + TypeInfoPtr m_type; +}; /////////////////////////////////////////////////////////////////////////////////// -} // namespace UdtUtils +class FieldCollection +{ +public: + + const UdtFieldPtr &lookup(ULONG index) const; + const UdtFieldPtr &lookup(const std::string &name) const; + + UdtFieldPtr &lookup(ULONG index); + UdtFieldPtr &lookup(const std::string &name); + + void push_back( const UdtFieldPtr& field ) { + m_fields.push_back( field ); + } + + ULONG count() const { + return static_cast( m_fields.size() ); + } + +private: + + typedef std::vector FieldList; + FieldList m_fields; +}; /////////////////////////////////////////////////////////////////////////////////// +ULONG getFieldOffsetRecursive(TypeInfoPtr typeInfo, const std::string &fieldName); + +/////////////////////////////////////////////////////////////////////////////////// + + + + + + + + + + + +///////////////////////////////////////////////////////////////////////////////////// +// +//namespace UdtUtils { +// +///////////////////////////////////////////////////////////////////////////////////// +// +// +// +// +// +// +// +// +//struct Field { +// +// Field( ULONG offset, const std::string &name, SymbolPtr &symbol, SymbolPtr &baseVirtClass = SymbolPtr(), +// ULONG virtualBasePtr = 0, ULONG virtualDispIndex = 0, ULONG virtualDispSize = 0 ) : +// m_offset(offset), +// m_name(name), +// m_symbol(symbol), +// m_baseVirtClass( baseVirtClass ), +// m_virtualBasePtr( virtualBasePtr ), +// m_virtualDispIndex( virtualDispIndex ), +// m_virtualDispSize( virtualDispSize ) +// {} +// +// bool operator ==(const std::string &name) const { +// return m_name == name; +// } +// +// ULONG m_offset; +// std::string m_name; +// SymbolPtr m_symbol; +// SymbolPtr m_baseVirtClass; +// ULONG m_virtualBasePtr; +// ULONG m_virtualDispIndex; +// ULONG m_virtualDispSize; +//}; +// +///////////////////////////////////////////////////////////////////////////////////// +// +//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; +// +// Field &lookup(ULONG index); +// Field &lookup(const std::string &name); +// +// const std::string &getName() const { +// return m_baseTypeName; +// } +// +//private: +// std::string m_baseTypeName; +//}; +// +///////////////////////////////////////////////////////////////////////////////////// +// +//ULONG getFieldOffsetRecursive(TypeInfoPtr typeInfo, const std::string &fieldName); +// +///////////////////////////////////////////////////////////////////////////////////// +// +//} // namespace UdtUtils +// +///////////////////////////////////////////////////////////////////////////////////// + } // namespace pykd - -/////////////////////////////////////////////////////////////////////////////////// diff --git a/test/scripts/customtypestest.py b/test/scripts/customtypestest.py index 750d824..dff9815 100644 --- a/test/scripts/customtypestest.py +++ b/test/scripts/customtypestest.py @@ -6,21 +6,24 @@ import pykd class CustomTypesTest(unittest.TestCase): def testCommonStruct(self): - mySubStruct = pykd.createStruct("MySubCustomStruct") - mySubStruct.append( "m_uint1", pykd.typeInfo("UInt1B") ) - mySubStruct.append( "m_uint2", pykd.typeInfo("UInt2B") ) - mySubUnion = pykd.createUnion("MySubCustomUnion") - mySubUnion.append( "m_uint1", pykd.typeInfo("UInt1B") ) - mySubUnion.append( "m_uint2", pykd.typeInfo("UInt2B") ) + tb = pykd.typeBuilder() + + mySubStruct =tb.createStruct("MySubCustomStruct") + mySubStruct.append( "m_uint1", tb.UInt1B ) + mySubStruct.append( "m_uint2", tb.UInt2B ) - myType = pykd.createStruct("MyCustomStruct") - myType.append( "m_uint1", pykd.typeInfo("UInt1B") ) - myType.append( "m_uint4", pykd.typeInfo("UInt4B") ) - myType.append( "m_uint2", pykd.typeInfo("UInt2B") ) + mySubUnion = tb.createUnion("MySubCustomUnion") + mySubUnion.append( "m_uint1", tb.UInt1B ) + mySubUnion.append( "m_uint2", tb.UInt2B ) + + myType = tb.createStruct("MyCustomStruct") + myType.append( "m_uint1", tb.UInt1B ) + myType.append( "m_uint4", tb.UInt4B ) + myType.append( "m_uint2", tb.UInt2B ) myType.append( "m_struct", mySubStruct ) myType.append( "m_union", mySubUnion ) - myType.append( "m_uint8", pykd.typeInfo("UInt8B") ) + myType.append( "m_uint8", tb.UInt8B ) self.assertTrue( myType.size() != 0 ) self.assertTrue( myType.size() >= myType.fieldOffset("m_uint8") + myType.m_uint8.size() ) @@ -42,10 +45,13 @@ class CustomTypesTest(unittest.TestCase): # print myType def testCommonUnion(self): - myType = pykd.createUnion("MyCustomStruct") - myType.append( "m_uint1", pykd.typeInfo("UInt1B") ) - myType.append( "m_uint4", pykd.typeInfo("UInt4B") ) - myType.append( "m_uint2", pykd.typeInfo("UInt2B") ) + + tb = pykd.typeBuilder() + + myType = tb.createUnion("MyCustomStruct") + myType.append( "m_uint1", tb.UInt1B ) + myType.append( "m_uint4", tb.UInt4B ) + myType.append( "m_uint2", tb.UInt2B ) self.assertFalse( myType.size() == 0 ) self.assertTrue( myType.fieldOffset("m_uint1") == 0 ) @@ -53,20 +59,23 @@ class CustomTypesTest(unittest.TestCase): self.assertTrue( myType.fieldOffset("m_uint2") == 0 ) def testDupFieldName(self): - myType = pykd.createStruct("MyCustomStruct") + + tb = pykd.typeBuilder() + + myType = tb.createStruct("MyCustomStruct") exceptionRised = False - myType.append( "m_uint1", pykd.typeInfo("UInt1B") ) + myType.append( "m_uint1", tb.UInt1B ) try: - myType.append( "m_uint1", pykd.typeInfo("UInt1B") ) + myType.append( "m_uint1", tb.UInt1B ) except pykd.TypeException: exceptionRised = True self.assertTrue(exceptionRised) - myType = pykd.createUnion("MyCustomStruct") + myType = tb.createUnion("MyCustomStruct") exceptionRised = False - myType.append( "m_uint1", pykd.typeInfo("UInt1B") ) + myType.append( "m_uint1", tb.UInt1B ) try: - myType.append( "m_uint1", pykd.typeInfo("UInt1B") ) + myType.append( "m_uint1", tb.UInt1B ) except pykd.TypeException: exceptionRised = True self.assertTrue(exceptionRised) diff --git a/test/scripts/moduletest.py b/test/scripts/moduletest.py index 83c2f05..ead0a23 100644 --- a/test/scripts/moduletest.py +++ b/test/scripts/moduletest.py @@ -69,7 +69,7 @@ class ModuleTest( unittest.TestCase ): self.assertTrue( re.search('targetapp\\.cpp', fileName ) ) self.assertEqual( 2, displacement ) fileName, lineNo, displacement = pykd.getSourceLine() - self.assertEqual( 644, lineNo ) + self.assertEqual( 653, lineNo ) def testEnumSymbols( self ): lst = target.module.enumSymbols() diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index e9d7fc1..408d7dd 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -41,11 +41,10 @@ class TypedVarTest( unittest.TestCase ): target.module.offset("g_structTestPtr") ) self.assertEqual( 500, tvDiaStruct.deref().m_field1 ) - customStructTest = pykd.createStruct("customStructTest") + customStructTest = pykd.typeBuilder().createStruct("customStructTest", 4) customStructTest.append("m_field0", pykd.typeInfo("UInt4B")) customStructTest.append("m_field1", pykd.typeInfo("UInt8B")) - tvCustomStruct = pykd.typedVar( customStructTest.ptrTo(), - target.module.offset("g_structTestPtr") ) + tvCustomStruct = pykd.typedVar( customStructTest.ptrTo(), target.module.offset("g_structTestPtr") ) self.assertEqual( 500, tvCustomStruct.deref().m_field1 ) def testConst(self): diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index da08c61..b3da326 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -109,7 +109,6 @@ class TypeInfoTest( unittest.TestCase ): 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 ): @@ -199,10 +198,14 @@ class TypeInfoTest( unittest.TestCase ): def testStaticField(self): ti = pykd.typeInfo( "g_classChild" ) - self.assertNotEqual( 0, ti.m_staticField.staticOffset() ) - if not ti.m_staticConst.staticOffset(): + self.assertNotEqual( 0, ti.staticOffset( "m_staticField" ) ) + self.assertNotEqual( 0, ti.staticOffset("m_stdstr") ) + if not ti.staticOffset("m_staticConst"): self.assertFalse( "MS DIA bug: https://connect.microsoft.com/VisualStudio/feedback/details/737430" ) - self.assertNotEqual( 0, ti.m_stdstr.staticOffset() ) + + def testVfnTable(self): + ti = pykd.typeInfo( "g_classChild" ) + self.assertTrue( hasattr( ti, "__VFN_table" ) ) def testUdtSubscribe(self): ti = pykd.typeInfo( "g_virtChild" ) @@ -214,3 +217,8 @@ class TypeInfoTest( unittest.TestCase ): ti = target.module.type("structNullSize") self.assertEqual( 0, len(ti) ) + def testDerefName(self): + entry = pykd.typedVar("entry1").Flink + self.assertEqual( "_LIST_ENTRY*", entry.type().name() ) + +