[0.1.x] added : typeInfo и typedVar classes support enum types

git-svn-id: https://pykd.svn.codeplex.com/svn@72711 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\kernelnet_cp 2011-12-27 08:32:50 +00:00 committed by Mikhail I. Izmestev
parent 8fd90cf647
commit fd6ed0769e
12 changed files with 242 additions and 19 deletions

View File

@ -447,7 +447,7 @@ BOOST_PYTHON_MODULE( pykd )
python::def( "waitForEvent", &waitForEvent,
"Wait for events that breaks into the debugger" );
python::class_<TypeInfo, TypeInfoPtr, boost::noncopyable >("typeInfo", "Class representing typeInfo", python::no_init )
python::class_<TypeInfo, TypeInfoPtr, python::bases<intBase>, boost::noncopyable >("typeInfo", "Class representing typeInfo", python::no_init )
.def( "name", &TypeInfo::getName )
.def( "size", &TypeInfo::getSize )
.def( "offset", &TypeInfo::getOffset )
@ -605,7 +605,7 @@ BOOST_PYTHON_MODULE( pykd )
"Retrieves the offset of the symbol location" )
.def( "count", &pyDia::Symbol::getCount,
"Retrieves the number of items in a list or array" )
.def( "value", &pyDia::Symbol::getValue,
.def( "value", (python::object(pyDia::Symbol::*)())&pyDia::Symbol::getValue,
"Retrieves the value of a constant")
.def( "isBasic", &pyDia::Symbol::isBasicType,
"Retrieves a flag of basic type for symbol")

View File

@ -160,6 +160,13 @@ void Symbol::getValueImpl(IDiaSymbol *_symbol, VARIANT &vtValue)
throw Exception("Call IDiaSymbol::get_value", hres);
}
void Symbol::getValue( VARIANT &vtValue)
{
HRESULT hres = m_symbol->get_value(&vtValue);
if (S_OK != hres)
throw Exception("Call IDiaSymbol::get_value", hres);
}
////////////////////////////////////////////////////////////////////////////////
python::object Symbol::getValue()
@ -244,6 +251,13 @@ ULONG Symbol::getUdtKind()
////////////////////////////////////////////////////////////////////////////////
ULONG Symbol::getDataKind()
{
return callSymbol(get_dataKind);
}
////////////////////////////////////////////////////////////////////////////////
ULONG Symbol::getRegisterId()
{
return callSymbol(get_registerId);
@ -251,6 +265,13 @@ ULONG Symbol::getRegisterId()
////////////////////////////////////////////////////////////////////////////////
bool Symbol::isConstant()
{
return !!callSymbol(get_constType);
}
////////////////////////////////////////////////////////////////////////////////
SymbolPtr Symbol::getChildByName(const std::string &_name)
{
DiaEnumSymbolsPtr symbols;

View File

@ -119,6 +119,7 @@ public:
static void getValueImpl(IDiaSymbol *_symbol, VARIANT &vtValue);
python::object getValue();
void getValue( VARIANT &vtValue);
bool isBasicType();
@ -130,6 +131,8 @@ public:
ULONG getUdtKind();
ULONG getDataKind();
ULONG getRegisterId();
ULONG getMachineType() const {
@ -140,7 +143,11 @@ public:
ULONG getChildCount();
SymbolPtr getChildByIndex(ULONG _index);
bool isConstant();
std::string print();
public:
typedef std::pair<ULONG, const char *> ValueNameEntry;

View File

@ -53,8 +53,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,1,0,1
PRODUCTVERSION 0,1,0,1
FILEVERSION 0,1,0,2
PRODUCTVERSION 0,1,0,2
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -70,11 +70,11 @@ BEGIN
BLOCK "041904b0"
BEGIN
VALUE "FileDescription", "pykd - python extension for windbg"
VALUE "FileVersion", "0, 1, 0, 1"
VALUE "FileVersion", "0, 1, 0, 2"
VALUE "InternalName", "pykd"
VALUE "OriginalFilename", "pykd.dll"
VALUE "ProductName", "pykd - python extension for windbg"
VALUE "ProductVersion", "0, 1, 0, 1"
VALUE "ProductVersion", "0, 1, 0, 2"
END
END
BLOCK "VarFileInfo"

View File

@ -41,6 +41,12 @@ TypedVarPtr TypedVar::getTypedVar( IDebugClient4 *client, const TypeInfoPtr& t
return tv;
}
if ( typeInfo->isEnum() )
{
tv.reset( new EnumTypedVar( client, typeInfo, offset ) );
return tv;
}
throw DbgException( "can not create typedVar for this type" );
return tv;
@ -161,4 +167,18 @@ BaseTypeVariant BitFieldVar::getValue()
///////////////////////////////////////////////////////////////////////////////////
BaseTypeVariant EnumTypedVar::getValue()
{
ULONG val = 0;
HRESULT hres;
hres = m_dataSpaces->ReadVirtual( m_offset, &val, m_typeInfo->getSize(), NULL );
if ( FAILED( hres ) )
throw MemoryException( m_offset, false );
return val;
};
///////////////////////////////////////////////////////////////////////////////////
} // end pykd namespace

View File

@ -42,7 +42,7 @@ public:
}
virtual std::string print() {
return "TypeVar";
return "TypedVar";
}
virtual ULONG getElementCount() {
@ -159,4 +159,15 @@ public:
///////////////////////////////////////////////////////////////////////////////////
class EnumTypedVar : public TypedVar {
public:
EnumTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){}
virtual BaseTypeVariant getValue();
};
///////////////////////////////////////////////////////////////////////////////////
} // namespace pykd

View File

@ -23,6 +23,9 @@ TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &typeSym )
case SymTagPointerType:
return TypeInfoPtr( new PointerTypeInfo( typeSym ) );
case SymTagEnum:
return TypeInfoPtr( new EnumTypeInfo( typeSym ) );
}
throw DbgException( "type name invalid" );
@ -30,9 +33,47 @@ TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &typeSym )
/////////////////////////////////////////////////////////////////////////////////////
BaseTypeVariant TypeInfo::getValue()
{
if ( !m_constant )
throw DbgException( "The type is not a constant and has not a value" );
switch( m_constantValue.vt )
{
case VT_UI1:
return (ULONG)m_constantValue.bVal;;
case VT_I1:
return (LONG)m_constantValue.cVal;
case VT_UI2:
return (ULONG)m_constantValue.uiVal;
case VT_I2:
return (LONG)m_constantValue.iVal;
case VT_UI4:
return (ULONG)m_constantValue.lVal;
case VT_I4:
return (LONG)m_constantValue.ulVal;
case VT_UI8:
return (ULONG64)m_constantValue.ullVal;
case VT_I8:
return (LONG64)m_constantValue.llVal;
}
throw DbgException( "Failed to convert constatnt type" );
}
/////////////////////////////////////////////////////////////////////////////////////
TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName )
{
size_t pos = symName.find_first_of( "*[" );
CComVariant constVal;
if ( pos == std::string::npos )
{
@ -49,10 +90,19 @@ TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &symScope, const std::strin
return TypeInfoPtr( new BitFieldTypeInfo(typeSym) );
}
if ( typeSym->getDataKind() == DataIsConstant )
{
typeSym->getValue( constVal );
}
typeSym = typeSym->getType();
}
return getTypeInfo( typeSym );
TypeInfoPtr ptr = getTypeInfo( typeSym );
ptr->setConstant( constVal );
return ptr;
}
return getComplexType( symScope, symName );
@ -60,7 +110,7 @@ TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &symScope, const std::strin
/////////////////////////////////////////////////////////////////////////////////////
static const boost::regex baseMatch("^(Char)|(WChar)|(Int2B)|(UInt2B)|(Int4B)|(UInt4B)|(Int8B)|(UInt8B)|(Long)|(ULong)|(Float)|(Bool)$" );
static const boost::regex baseMatch("^(Char)|(WChar)|(Int2B)|(UInt2B)|(Int4B)|(UInt4B)|(Int8B)|(UInt8B)|(Long)|(ULong)|(Float)|(Bool)|(Double)$" );
TypeInfoPtr
TypeInfo::getBaseTypeInfo( const std::string &symName )
@ -104,6 +154,9 @@ TypeInfo::getBaseTypeInfo( const std::string &symName )
if ( baseMatchResult[12].matched )
return TypeInfoPtr( new TypeInfoWrapper<bool>("Bool") );
if ( baseMatchResult[13].matched )
return TypeInfoPtr( new TypeInfoWrapper<double>("Double") );
}
return TypeInfoPtr();
@ -124,6 +177,11 @@ TypeInfo::getBaseTypeInfo( pyDia::SymbolPtr &symbol )
return getBaseTypeInfo( sstr.str() );
}
if ( symName == "Float" && symbol->getSize() == 8 )
{
symName = "Double";
}
return getBaseTypeInfo( symName );
}

View File

@ -3,6 +3,7 @@
#include <string>
#include "diawrapper.h"
#include "intbase.h"
namespace pykd {
@ -13,7 +14,7 @@ typedef boost::shared_ptr<TypeInfo> TypeInfoPtr;
///////////////////////////////////////////////////////////////////////////////////
class TypeInfo : boost::noncopyable {
class TypeInfo : boost::noncopyable, public intBase {
public:
@ -39,6 +40,8 @@ public:
throw DbgException( "there is no fields" );
}
virtual BaseTypeVariant getValue();
virtual bool isBasicType() {
return false;
}
@ -59,6 +62,10 @@ public:
return false;
}
virtual bool isEnum() {
return false;
}
virtual ULONG getCount() {
throw DbgException( "there is no element" );
}
@ -84,6 +91,12 @@ public:
m_offset = offset;
}
void setConstant( const VARIANT& var )
{
m_constant = true;
m_constantValue = var;
}
protected:
std::string getComplexName();
@ -95,6 +108,10 @@ protected:
TypeInfoPtr getRecurciveComplexType( TypeInfoPtr &lowestType, std::string &suffix, ULONG ptrSize );
ULONG m_offset;
bool m_constant;
VARIANT m_constantValue;
};
///////////////////////////////////////////////////////////////////////////////////
@ -201,6 +218,40 @@ protected:
///////////////////////////////////////////////////////////////////////////////////
class EnumTypeInfo : public TypeInfo
{
public:
EnumTypeInfo ( pyDia::SymbolPtr &symbol ) :
m_dia( symbol )
{}
protected:
virtual std::string getName() {
return m_dia->getName();
}
virtual ULONG getSize() {
return (ULONG)m_dia->getSize();
}
virtual TypeInfoPtr getField( const std::string &fieldName ) {
pyDia::SymbolPtr field = m_dia->getChildByName( fieldName );
TypeInfoPtr ti = TypeInfo::getTypeInfo( m_dia, fieldName );
ti->setOffset( 0 );
return ti;
}
virtual bool isEnum() {
return true;
}
pyDia::SymbolPtr m_dia;
};
///////////////////////////////////////////////////////////////////////////////////
class PointerTypeInfo : public TypeInfo {
public:

View File

@ -33,6 +33,7 @@ class IntBaseTest( unittest.TestCase ):
self.assertTrue( True == intBase(True) )
self.assertTrue( False == intBase(0) )
self.assertTrue( True == intBase(1) )
self.assertTrue( intBase(1) == intBase(1) )
def testNe( self ):
self.assertTrue( 0xFE != intBase(0xFF) )
@ -44,6 +45,7 @@ class IntBaseTest( unittest.TestCase ):
self.assertTrue( -2000 + 1 != intBase(-2000) )
self.assertTrue( -20000000000 + 1 != intBase(-20000000000) )
self.assertTrue( -0x8000000000000000 - 1 != intBase(-0x8000000000000000) )
self.assertTrue( intBase(1) != intBase(2) )
def testLtGt( self ):
self.assertTrue( 0xFE < intBase(0xFF) and intBase(0xFE) < 0xFF )
@ -51,6 +53,7 @@ class IntBaseTest( unittest.TestCase ):
self.assertTrue( 0xFFFFFFFFFFFFFFFE < intBase(0xFFFFFFFFFFFFFFFF) )
self.assertFalse(0xFFFFFFFFFFFFFFFF < intBase(0xFFFFFFFFFFFFFFFE) )
self.assertTrue( intBase(0xFFFFFFFFFFFFFFFE) < 0xFFFFFFFFFFFFFFFF )
self.assertTrue( intBase(1) < intBase(2) )
def testLeGe( self ):
self.assertTrue( 0xFE <= intBase(0xFF) and intBase(0xFE) <= 0xFF )
@ -59,6 +62,7 @@ class IntBaseTest( unittest.TestCase ):
self.assertTrue( 0xFFFFFFFFFFFFFFFE <= intBase(0xFFFFFFFFFFFFFFFF) )
self.assertFalse(0xFFFFFFFFFFFFFFFF <= intBase(0xFFFFFFFFFFFFFFFE) )
self.assertTrue( intBase(0xFFFFFFFFFFFFFFFF) <= 0xFFFFFFFFFFFFFFFF )
self.assertFalse( intBase(1) >= intBase(2) )
def testAdd( self ):
self.assertEqual( 10, intBase(5) + 5 )
@ -71,6 +75,7 @@ class IntBaseTest( unittest.TestCase ):
self.assertEqual( 0x7fffffffffffffff + 1, intBase(0x7fffffffffffffff) + 1)
self.assertEqual( -0x8000000000000000 + 10, intBase(-0x8000000000000000) + 10 )
self.assertEqual( 0, intBase(-0x8000000000000000) + 0x8000000000000000 )
self.assertEqual( 5, intBase(3) + intBase(2) )
def testSub( self ):
self.assertEqual( 0, intBase(5) - 5 )
@ -81,6 +86,7 @@ class IntBaseTest( unittest.TestCase ):
self.assertEqual( -20, intBase(-10) -10 )
self.assertEqual( -10, 10 - intBase(20) )
self.assertEqual( -0xFFFFFFFF - 1, intBase(-0xFFFFFFFF) - 1 )
self.assertEqual( 5, intBase(7) - intBase(2) )
def testMul( self ):
self.assertEqual( 4, intBase(2) * 2 )
@ -90,12 +96,14 @@ class IntBaseTest( unittest.TestCase ):
self.assertEqual( 0x7fffffffffffffff * 2, intBase(0x7fffffffffffffff) * 2)
self.assertEqual( 0x80000000*2, intBase(0x80000000)*2 )
self.assertEqual( -0x80000000*2, 2 * intBase(-0x80000000))
self.assertEqual( 14, intBase(7)*intBase(2) )
def testDiv( self ):
self.assertEqual( 1, intBase(2) / 2 )
self.assertEqual( 2, 5 / intBase(2) )
self.assertEqual( -1, 2 / intBase(-2) )
self.assertEqual( 1, -2 / intBase(-2) )
self.assertEqual( 3, intBase(7)/intBase(2) )
try:
-2 / intBase(0)
@ -109,11 +117,18 @@ class IntBaseTest( unittest.TestCase ):
except ZeroDivisionError:
self.assertTrue( True )
try:
intBase(0)/intBase(0)
self.assertTrue( False )
except ZeroDivisionError:
self.assertTrue( True )
def testMod( self ):
self.assertEqual( 1, intBase(3) % 2 )
self.assertEqual( 0, intBase(3) % 3 )
self.assertEqual( 1, 3 % intBase(2) )
self.assertEqual( 0, 3 % intBase(3) )
self.assertEqual( 2, intBase(5) % intBase(3) )
def testShift( self ):
self.assertEqual( 0xFFFFFFFF >> 8, intBase(0xFFFFFFFF) >> 8 )

View File

@ -100,3 +100,15 @@ class TypedVarTest( unittest.TestCase ):
self.assertEqual( 2, len( tvl ) )
self.assertEqual( 1, tvl[0].m_field3 )
self.assertEqual( 0, tvl[1].m_field4 )
def testEqual(self):
tv1 = target.module.typedVar("g_structTest")
tv2 = target.module.typedVar("intMatrix")
self.assertEqual( tv1.m_field3, tv2[0][1] )
def testEnum(self):
tv = target.module.typedVar("g_classChild")
self.assertEqual( 3, tv.m_enumField )
self.assertEqual( target.module.type("enumType").THREE, tv.m_enumField )

View File

@ -77,4 +77,16 @@ class TypeInfoTest( unittest.TestCase ):
self.assertEqual( 2, ti.m_bit6_7.bitWidth() )
self.assertEqual( 6, ti.m_bit6_7.bitOffset() )
def testEnum(self):
ti = target.module.type("enumType")
self.assertTrue( hasattr( ti, "TWO" ) )
self.assertEqual( 4, ti.TWO.size() )
ti = target.module.type("classChild")
self.assertEqual( "enumType", ti.m_enumField.name() )
def testUnion(self):
ti = target.module.type("unionTest")
self.assertEqual( 0, ti.m_doubleValue.offset() )
self.assertEqual( 0, ti.m_bits.offset() )
self.assertEqual( ti.size(), ti.m_doubleValue.size() )

View File

@ -28,6 +28,7 @@ struct structWithBits {
union unionTest {
ULONG m_value;
double m_doubleValue;
structWithBits m_bits;
};
@ -84,16 +85,30 @@ int ((*ptrIntMatrix1))[2][3] = &intMatrix;
char *(*ptrStrArray)[2] = &strArray;
enum enumType {
ONE = 1,
TWO = 2,
THREE = 3
};
class classChild : public classBase {
public:
int m_childField;
int m_childField2;
structTest m_childField3;
enumType m_enumField;
void childMethod() const {}
virtual void virtFunc() {}
virtual void virtFunc2() {}
classChild() :
m_enumField( THREE )
{}
};
classChild g_classChild;
struct struct2 {
structTest m_struct;
unionTest m_union;
@ -184,6 +199,7 @@ void FuncWithName0()
std::cout << g_structTest1.m_field2;
std::cout << ptrIntMatrix1;
std::cout << g_bigValue;
std::cout << g_classChild.m_enumField;
}
void FuncWithName1(int a)