From fd6ed0769eda48af919a10ed641384fd30c6244d Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Tue, 27 Dec 2011 08:32:50 +0000 Subject: [PATCH] =?UTF-8?q?[0.1.x]=20added=20:=20typeInfo=20=D0=B8=20typed?= =?UTF-8?q?Var=20classes=20support=20enum=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: https://pykd.svn.codeplex.com/svn@72711 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 4 +-- pykd/diawrapper.cpp | 21 ++++++++++++ pykd/diawrapper.h | 7 ++++ pykd/pykd.rc | 8 ++--- pykd/typedvar.cpp | 20 ++++++++++++ pykd/typedvar.h | 13 +++++++- pykd/typeinfo.cpp | 62 ++++++++++++++++++++++++++++++++++-- pykd/typeinfo.h | 57 +++++++++++++++++++++++++++++++-- test/scripts/intbase.py | 25 ++++++++++++--- test/scripts/typedvar.py | 12 +++++++ test/scripts/typeinfo.py | 16 ++++++++-- test/targetapp/targetapp.cpp | 16 ++++++++++ 12 files changed, 242 insertions(+), 19 deletions(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 6cd870a..e575140 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -447,7 +447,7 @@ BOOST_PYTHON_MODULE( pykd ) python::def( "waitForEvent", &waitForEvent, "Wait for events that breaks into the debugger" ); - python::class_("typeInfo", "Class representing typeInfo", python::no_init ) + python::class_, 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") diff --git a/pykd/diawrapper.cpp b/pykd/diawrapper.cpp index bdad74c..976edff 100644 --- a/pykd/diawrapper.cpp +++ b/pykd/diawrapper.cpp @@ -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; diff --git a/pykd/diawrapper.h b/pykd/diawrapper.h index 93b0e85..f315c97 100644 --- a/pykd/diawrapper.h +++ b/pykd/diawrapper.h @@ -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 ValueNameEntry; diff --git a/pykd/pykd.rc b/pykd/pykd.rc index 2683666..2bdbef6 100644 --- a/pykd/pykd.rc +++ b/pykd/pykd.rc @@ -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" diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index e9cc7f8..ec5db53 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -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 \ No newline at end of file diff --git a/pykd/typedvar.h b/pykd/typedvar.h index 0a7a606..14a0977 100644 --- a/pykd/typedvar.h +++ b/pykd/typedvar.h @@ -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 diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index bc1f27f..a6357be 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -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") ); + + if ( baseMatchResult[13].matched ) + return TypeInfoPtr( new TypeInfoWrapper("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 ); } diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index f9f6b35..03ad8c7 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -3,6 +3,7 @@ #include #include "diawrapper.h" +#include "intbase.h" namespace pykd { @@ -13,7 +14,7 @@ typedef boost::shared_ptr TypeInfoPtr; /////////////////////////////////////////////////////////////////////////////////// -class TypeInfo : boost::noncopyable { +class TypeInfo : boost::noncopyable, public intBase { public: @@ -36,9 +37,11 @@ public: virtual ULONG getSize() = 0; virtual TypeInfoPtr getField( const std::string &fieldName ) { - throw DbgException( "there is no fields" ); + 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; }; /////////////////////////////////////////////////////////////////////////////////// @@ -198,7 +215,41 @@ protected: pyDia::SymbolPtr m_dia; }; - + +/////////////////////////////////////////////////////////////////////////////////// + +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 { diff --git a/test/scripts/intbase.py b/test/scripts/intbase.py index b451760..5689a1a 100644 --- a/test/scripts/intbase.py +++ b/test/scripts/intbase.py @@ -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) ) @@ -43,7 +44,8 @@ class IntBaseTest( unittest.TestCase ): self.assertTrue( -20 + 1 != intBase(-20) ) self.assertTrue( -2000 + 1 != intBase(-2000) ) self.assertTrue( -20000000000 + 1 != intBase(-20000000000) ) - self.assertTrue( -0x8000000000000000 - 1 != intBase(-0x8000000000000000) ) + 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( 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 ) diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index bb047a7..033b24a 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -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 ) + + diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index 1294f5a..c1fc821 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -76,5 +76,17 @@ class TypeInfoTest( unittest.TestCase ): self.assertEqual( "ULong:2", ti.m_bit6_7.name() ) 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() ) diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index f2d1b40..766a07e 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -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)