mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-21 04:13:22 +08:00
[0.2.x] + custom types
git-svn-id: https://pykd.svn.codeplex.com/svn@79382 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
77b1eee2f4
commit
70747aac37
98
pykd/customtypes.cpp
Normal file
98
pykd/customtypes.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "customtypes.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TypeInfoPtr CustomStruct::create(const std::string &name, ULONG alignReq /*= 0*/)
|
||||||
|
{
|
||||||
|
return TypeInfoPtr( new CustomStruct(name, alignReq) );
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG CustomStruct::getSize()
|
||||||
|
{
|
||||||
|
if (UdtFieldColl::empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
UdtUtils::Field &field = UdtFieldColl::last();
|
||||||
|
return field.m_offset + field.m_type->getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void CustomStruct::appendField(const std::string &fieldName, TypeInfoPtr fieldType)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
ULONG offset = getSize();
|
||||||
|
offset += (offset % m_alignReq);
|
||||||
|
UdtFieldColl::push_back(
|
||||||
|
UdtUtils::Field(offset, fieldName, fieldType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TypeInfoPtr CustomUnion::create(const std::string &name)
|
||||||
|
{
|
||||||
|
return TypeInfoPtr( new CustomUnion(name) );
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
UdtFieldColl::push_back(
|
||||||
|
UdtUtils::Field(0, fieldName, fieldType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
} // namespace pykd
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
69
pykd/customtypes.h
Normal file
69
pykd/customtypes.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "typeinfo.h"
|
||||||
|
#include "win\dbgeng.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace pykd {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class CustomStruct : public UdtFieldColl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static TypeInfoPtr create(const std::string &name, ULONG alignReq = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CustomStruct(const std::string &name, ULONG alignReq)
|
||||||
|
: UdtFieldColl(name), m_name(name), m_alignReq(alignReq ? alignReq : ptrSize())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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_alignReq;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class CustomUnion : public UdtFieldColl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static TypeInfoPtr create(const std::string &name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CustomUnion(const std::string &name) : UdtFieldColl(name) {}
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
} // namespace pykd
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
@ -361,6 +361,10 @@
|
|||||||
RelativePath=".\cpureg.cpp"
|
RelativePath=".\cpureg.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\customtypes.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\dbgexcept.cpp"
|
RelativePath=".\dbgexcept.cpp"
|
||||||
>
|
>
|
||||||
@ -467,6 +471,10 @@
|
|||||||
RelativePath=".\cpureg.h"
|
RelativePath=".\cpureg.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\customtypes.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\dbgengine.h"
|
RelativePath=".\dbgengine.h"
|
||||||
>
|
>
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "dbgexcept.h"
|
#include "dbgexcept.h"
|
||||||
#include "dbgmem.h"
|
#include "dbgmem.h"
|
||||||
#include "typeinfo.h"
|
#include "typeinfo.h"
|
||||||
|
#include "customtypes.h"
|
||||||
#include "typedvar.h"
|
#include "typedvar.h"
|
||||||
#include "cpureg.h"
|
#include "cpureg.h"
|
||||||
#include "disasm.h"
|
#include "disasm.h"
|
||||||
@ -59,6 +60,8 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( getSourceFile_, getSourceFile, 0, 1 );
|
|||||||
BOOST_PYTHON_FUNCTION_OVERLOADS( setSoftwareBp_, setSoftwareBp, 1, 2 );
|
BOOST_PYTHON_FUNCTION_OVERLOADS( setSoftwareBp_, setSoftwareBp, 1, 2 );
|
||||||
BOOST_PYTHON_FUNCTION_OVERLOADS( setHardwareBp_, setHardwareBp, 3, 4 );
|
BOOST_PYTHON_FUNCTION_OVERLOADS( setHardwareBp_, setHardwareBp, 3, 4 );
|
||||||
|
|
||||||
|
BOOST_PYTHON_FUNCTION_OVERLOADS( CustomStruct_create, CustomStruct::create, 1, 2 );
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE( pykd )
|
BOOST_PYTHON_MODULE( pykd )
|
||||||
{
|
{
|
||||||
python::scope().attr("version") = pykdVersion;
|
python::scope().attr("version") = pykdVersion;
|
||||||
@ -231,6 +234,12 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
python::def( "removeAllBp", &breakPointRemoveAll,
|
python::def( "removeAllBp", &breakPointRemoveAll,
|
||||||
"Remove all breapoints" );
|
"Remove all breapoints" );
|
||||||
|
|
||||||
|
// custom types
|
||||||
|
python::def( "createStruct", &CustomStruct::create, CustomStruct_create( python::args( "name", "alignReq" ),
|
||||||
|
"Create empty structure. Use append() method for building" ) );
|
||||||
|
python::def( "createUnion", &CustomUnion::create,
|
||||||
|
"Create empty union. Use append() method for building" );
|
||||||
|
|
||||||
python::class_<intBase>( "intBase", "intBase", python::no_init )
|
python::class_<intBase>( "intBase", "intBase", python::no_init )
|
||||||
.def( python::init<python::object&>() )
|
.def( python::init<python::object&>() )
|
||||||
.def( "__eq__", &intBase::eq )
|
.def( "__eq__", &intBase::eq )
|
||||||
@ -334,6 +343,7 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
.def( "field", &TypeInfo::getField )
|
.def( "field", &TypeInfo::getField )
|
||||||
.def( "asMap", &TypeInfo::asMap )
|
.def( "asMap", &TypeInfo::asMap )
|
||||||
.def( "deref", &TypeInfo::deref )
|
.def( "deref", &TypeInfo::deref )
|
||||||
|
.def( "append", &TypeInfo::appendField )
|
||||||
.def( "__str__", &TypeInfo::print )
|
.def( "__str__", &TypeInfo::print )
|
||||||
.def( "__getattr__", &TypeInfo::getField )
|
.def( "__getattr__", &TypeInfo::getField )
|
||||||
.def("__len__", &TypeInfo::getElementCount )
|
.def("__len__", &TypeInfo::getElementCount )
|
||||||
|
@ -557,10 +557,45 @@ ULONG64 TypeInfo::getStaticOffset()
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ULONG UdtTypeInfo::getFieldCount()
|
std::string UdtFieldColl::print()
|
||||||
{
|
{
|
||||||
refreshFields();
|
std::stringstream sstr;
|
||||||
return (ULONG)m_fields.size();
|
|
||||||
|
sstr << getTypeString() << ": " << 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;
|
||||||
|
|
||||||
|
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() )
|
||||||
|
{
|
||||||
|
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 << ':';
|
||||||
|
}
|
||||||
|
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 << ':';
|
||||||
|
}
|
||||||
|
|
||||||
|
sstr << " " << std::left << fieldType->getName();
|
||||||
|
sstr << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sstr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -615,7 +650,9 @@ void UdtTypeInfo::getFields(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_fields.push_back( UdtUtils::Field( fieldOffset, childSym->getName(), ti ) );
|
UdtFieldColl::push_back(
|
||||||
|
UdtUtils::Field( fieldOffset, childSym->getName(), ti )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if ( symTag == SymTagVTable )
|
if ( symTag == SymTagVTable )
|
||||||
@ -632,7 +669,7 @@ void UdtTypeInfo::getFields(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_fields.push_back(
|
UdtFieldColl::push_back(
|
||||||
UdtUtils::Field( startOffset + childSym->getOffset(), "__VFN_table", ti )
|
UdtUtils::Field( startOffset + childSym->getOffset(), "__VFN_table", ti )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -666,7 +703,7 @@ void UdtTypeInfo::getVirtualFields()
|
|||||||
|
|
||||||
void UdtTypeInfo::refreshFields()
|
void UdtTypeInfo::refreshFields()
|
||||||
{
|
{
|
||||||
if ( m_fields.empty() )
|
if ( UdtFieldColl::empty() )
|
||||||
{
|
{
|
||||||
getFields( m_dia, SymbolPtr() );
|
getFields( m_dia, SymbolPtr() );
|
||||||
getVirtualFields();
|
getVirtualFields();
|
||||||
@ -675,49 +712,6 @@ void UdtTypeInfo::refreshFields()
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::string UdtTypeInfo::print()
|
|
||||||
{
|
|
||||||
std::stringstream sstr;
|
|
||||||
|
|
||||||
sstr << "struct/class: " << 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;
|
|
||||||
|
|
||||||
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() )
|
|
||||||
{
|
|
||||||
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 << ':';
|
|
||||||
}
|
|
||||||
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 << ':';
|
|
||||||
}
|
|
||||||
|
|
||||||
sstr << " " << std::left << fieldType->getName();
|
|
||||||
sstr << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sstr.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
TypeInfoPtr EnumTypeInfo::getField( const std::string &fieldName )
|
TypeInfoPtr EnumTypeInfo::getField( const std::string &fieldName )
|
||||||
{
|
{
|
||||||
return TypeInfo::getTypeInfo( m_dia, fieldName );
|
return TypeInfo::getTypeInfo( m_dia, fieldName );
|
||||||
|
@ -157,6 +157,10 @@ public:
|
|||||||
throw PyException( PyExc_TypeError, "object is unsubscriptable");
|
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" );
|
||||||
|
}
|
||||||
|
|
||||||
void setConstant( const BaseTypeVariant& var )
|
void setConstant( const BaseTypeVariant& var )
|
||||||
{
|
{
|
||||||
m_constant = true;
|
m_constant = true;
|
||||||
@ -298,24 +302,11 @@ private:
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class UdtTypeInfo : public TypeInfo
|
class UdtFieldColl : public TypeInfo
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
|
|
||||||
UdtTypeInfo (SymbolPtr &symbol ) :
|
|
||||||
m_dia( symbol ),
|
|
||||||
m_fields( symbol->getName() )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual std::string getName() {
|
virtual std::string getName() {
|
||||||
return m_dia->getName();
|
return m_fields.getName();
|
||||||
}
|
|
||||||
|
|
||||||
virtual ULONG getSize() {
|
|
||||||
return (ULONG)m_dia->getSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual TypeInfoPtr getField( const std::string &fieldName ) {
|
virtual TypeInfoPtr getField( const std::string &fieldName ) {
|
||||||
@ -331,7 +322,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual ULONG getFieldOffsetByNameRecirsive( const std::string &fieldName ) {
|
virtual ULONG getFieldOffsetByNameRecirsive( const std::string &fieldName ) {
|
||||||
return UdtUtils::getFiledOffsetRecirsive( shared_from_this(), fieldName );
|
return UdtUtils::getFieldOffsetRecirsive( shared_from_this(), fieldName );
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ULONG getFieldOffsetByNameNotRecursively( const std::string &fieldName ) {
|
virtual ULONG getFieldOffsetByNameNotRecursively( const std::string &fieldName ) {
|
||||||
@ -342,10 +333,9 @@ protected:
|
|||||||
return lookupField(index).m_offset;
|
return lookupField(index).m_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ULONG getFieldCount();
|
virtual ULONG getFieldCount() {
|
||||||
|
refreshFields();
|
||||||
virtual bool isUserDefined() {
|
return (ULONG)m_fields.size();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ULONG getElementCount() {
|
virtual ULONG getElementCount() {
|
||||||
@ -358,9 +348,61 @@ protected:
|
|||||||
|
|
||||||
virtual std::string print();
|
virtual std::string print();
|
||||||
|
|
||||||
SymbolPtr m_dia;
|
virtual bool isUserDefined() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const UdtUtils::Field &field) {
|
||||||
|
m_fields.push_back(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const UdtUtils::Field &lookupField( T index) {
|
||||||
|
refreshFields();
|
||||||
|
return m_fields.lookup(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
UdtUtils::Field &last(){
|
||||||
|
return *m_fields.rbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
UdtUtils::FieldCollection m_fields;
|
UdtUtils::FieldCollection m_fields;
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class UdtTypeInfo : public UdtFieldColl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
UdtTypeInfo (SymbolPtr &symbol ) :
|
||||||
|
UdtFieldColl( symbol->getName() ),
|
||||||
|
m_dia( symbol )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ULONG getSize() {
|
||||||
|
return (ULONG)m_dia->getSize();
|
||||||
|
}
|
||||||
|
void getVirtualFields();
|
||||||
|
|
||||||
|
virtual void refreshFields() override;
|
||||||
|
|
||||||
|
virtual std::string getTypeString() const override {
|
||||||
|
return "struct/class";
|
||||||
|
}
|
||||||
|
|
||||||
void getFields(
|
void getFields(
|
||||||
SymbolPtr &rootSym,
|
SymbolPtr &rootSym,
|
||||||
@ -371,16 +413,8 @@ protected:
|
|||||||
ULONG m_virtualDispSize = 0 );
|
ULONG m_virtualDispSize = 0 );
|
||||||
|
|
||||||
|
|
||||||
void getVirtualFields();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refreshFields();
|
SymbolPtr m_dia;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
const UdtUtils::Field &lookupField( T index) {
|
|
||||||
refreshFields();
|
|
||||||
return m_fields.lookup(index);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -36,7 +36,7 @@ const Field &FieldCollection::lookup(const std::string &name) const
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ULONG getFiledOffsetRecirsive(TypeInfoPtr typeInfo, const std::string &fieldName)
|
ULONG getFieldOffsetRecirsive(TypeInfoPtr typeInfo, const std::string &fieldName)
|
||||||
{
|
{
|
||||||
// "m_field1.m_field2" -> ["m_field1", "m_field2"]
|
// "m_field1.m_field2" -> ["m_field1", "m_field2"]
|
||||||
typedef boost::char_separator<char> CharSep;
|
typedef boost::char_separator<char> CharSep;
|
||||||
|
@ -46,13 +46,17 @@ public:
|
|||||||
const Field &lookup(ULONG index) const;
|
const Field &lookup(ULONG index) const;
|
||||||
const Field &lookup(const std::string &name) const;
|
const Field &lookup(const std::string &name) const;
|
||||||
|
|
||||||
|
const std::string &getName() const {
|
||||||
|
return m_baseTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_baseTypeName;
|
std::string m_baseTypeName;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ULONG getFiledOffsetRecirsive(TypeInfoPtr typeInfo, const std::string &fieldName);
|
ULONG getFieldOffsetRecirsive(TypeInfoPtr typeInfo, const std::string &fieldName);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
72
test/scripts/customtypestest.py
Normal file
72
test/scripts/customtypestest.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
"""Custom types tests"""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import target
|
||||||
|
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") )
|
||||||
|
|
||||||
|
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") )
|
||||||
|
myType.append( "m_struct", mySubStruct )
|
||||||
|
myType.append( "m_union", mySubUnion )
|
||||||
|
myType.append( "m_uint8", pykd.typeInfo("UInt8B") )
|
||||||
|
|
||||||
|
self.assertTrue( myType.size() != 0 )
|
||||||
|
self.assertTrue( myType.size() >= myType.fieldOffset("m_uint8") + myType.m_uint8.size() )
|
||||||
|
|
||||||
|
self.assertTrue( myType.fieldOffset("m_uint1") == 0 )
|
||||||
|
|
||||||
|
self.assertTrue( myType.fieldOffset("m_uint1") < myType.fieldOffset("m_uint4") )
|
||||||
|
self.assertTrue( myType.fieldOffset("m_uint1") + myType.m_uint1.size() <= myType.fieldOffset("m_uint4") )
|
||||||
|
|
||||||
|
self.assertTrue( myType.fieldOffset("m_uint4") < myType.fieldOffset("m_uint2") )
|
||||||
|
self.assertTrue( myType.fieldOffset("m_uint4") + myType.m_uint4.size() <= myType.fieldOffset("m_uint2") )
|
||||||
|
|
||||||
|
self.assertTrue( myType.fieldOffset("m_uint2") < myType.fieldOffset("m_struct") )
|
||||||
|
self.assertTrue( myType.fieldOffset("m_uint2") + myType.m_uint2.size() <= myType.fieldOffset("m_struct") )
|
||||||
|
|
||||||
|
self.assertTrue( myType.fieldOffset("m_struct") < myType.fieldOffset("m_union") )
|
||||||
|
self.assertTrue( myType.fieldOffset("m_struct") + myType.m_struct.size() <= myType.fieldOffset("m_union") )
|
||||||
|
|
||||||
|
# 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") )
|
||||||
|
|
||||||
|
self.assertFalse( myType.size() == 0 )
|
||||||
|
self.assertTrue( myType.fieldOffset("m_uint1") == 0 )
|
||||||
|
self.assertTrue( myType.fieldOffset("m_uint4") == 0 )
|
||||||
|
self.assertTrue( myType.fieldOffset("m_uint2") == 0 )
|
||||||
|
|
||||||
|
def testDupFieldName(self):
|
||||||
|
myType = pykd.createStruct("MyCustomStruct")
|
||||||
|
exceptionRised = False
|
||||||
|
myType.append( "m_uint1", pykd.typeInfo("UInt1B") )
|
||||||
|
try:
|
||||||
|
myType.append( "m_uint1", pykd.typeInfo("UInt1B") )
|
||||||
|
except pykd.TypeException:
|
||||||
|
exceptionRised = True
|
||||||
|
self.assertTrue(exceptionRised)
|
||||||
|
|
||||||
|
myType = pykd.createUnion("MyCustomStruct")
|
||||||
|
exceptionRised = False
|
||||||
|
myType.append( "m_uint1", pykd.typeInfo("UInt1B") )
|
||||||
|
try:
|
||||||
|
myType.append( "m_uint1", pykd.typeInfo("UInt1B") )
|
||||||
|
except pykd.TypeException:
|
||||||
|
exceptionRised = True
|
||||||
|
self.assertTrue(exceptionRised)
|
@ -20,6 +20,7 @@ import typeinfo
|
|||||||
import typedvar
|
import typedvar
|
||||||
import regtest
|
import regtest
|
||||||
import localstest
|
import localstest
|
||||||
|
import customtypestest
|
||||||
|
|
||||||
class StartProcessWithoutParamsTest(unittest.TestCase):
|
class StartProcessWithoutParamsTest(unittest.TestCase):
|
||||||
def testStart(self):
|
def testStart(self):
|
||||||
@ -45,6 +46,7 @@ def getTestSuite( singleName = "" ):
|
|||||||
unittest.TestLoader().loadTestsFromTestCase( typeinfo.TypeInfoTest ),
|
unittest.TestLoader().loadTestsFromTestCase( typeinfo.TypeInfoTest ),
|
||||||
unittest.TestLoader().loadTestsFromTestCase( typedvar.TypedVarTest ),
|
unittest.TestLoader().loadTestsFromTestCase( typedvar.TypedVarTest ),
|
||||||
unittest.TestLoader().loadTestsFromTestCase( regtest.CpuRegTest ),
|
unittest.TestLoader().loadTestsFromTestCase( regtest.CpuRegTest ),
|
||||||
|
unittest.TestLoader().loadTestsFromTestCase( customtypestest.CustomTypesTest ),
|
||||||
# ^^^
|
# ^^^
|
||||||
unittest.TestLoader().loadTestsFromTestCase( TerminateProcessTest ),
|
unittest.TestLoader().loadTestsFromTestCase( TerminateProcessTest ),
|
||||||
|
|
||||||
|
@ -408,6 +408,10 @@
|
|||||||
RelativePath="..\scripts\clienttest.py"
|
RelativePath="..\scripts\clienttest.py"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\scripts\customtypestest.py"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\scripts\dbgcmd.py"
|
RelativePath="..\scripts\dbgcmd.py"
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user