diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 22b8aaf..128a741 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -469,7 +469,8 @@ BOOST_PYTHON_MODULE( pykd ) .def( "bitWidth", &TypeInfo::getBitWidth ) .def( "field", &TypeInfo::getField ) .def( "__getattr__", &TypeInfo::getField ) - .def( "asMap", &TypeInfo::asMap ); + .def( "asMap", &TypeInfo::asMap ) + .def( "deref", &TypeInfo::deref ); python::class_, boost::noncopyable >("typedVar", "Class of non-primitive type object, child class of typeClass. Data from target is copied into object instance", @@ -480,8 +481,10 @@ BOOST_PYTHON_MODULE( pykd ) "Return size of a variable in the target memory" ) .def("offset", &TypedVar::getOffset, "Return offset to parent" ) - .def("field", &TypedVar::getField, + .def("field", &TypedVar::getField, "Return field of structure as an object attribute" ) + .def("deref", &TypedVar::deref, + "Return value by pointer" ) .def("__getattr__", &TypedVar::getField, "Return field of structure as an object attribute" ) .def( "__str__", &TypedVar::print ) diff --git a/pykd/module.cpp b/pykd/module.cpp index 9fd984f..203e103 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -180,9 +180,22 @@ Module::getTypedVarByType( const TypeInfoPtr &typeInfo, ULONG64 addr ) TypedVarPtr Module::getTypedVarByName( const std::string &symName ) { + HRESULT hres; + pyDia::SymbolPtr typeSym = getDia()->getChildByName( symName ); - return TypedVar::getTypedVar( m_client, TypeInfo::getTypeInfo( typeSym->getType() ), typeSym->getRva() + m_base ); + std::string fullName = m_name; + fullName += '!'; + fullName += symName; + + ULONG64 offset; + + hres = m_symbols->GetOffsetByName( fullName.c_str(), &offset ); + + if ( FAILED( hres ) ) + throw DbgException("IDebugSymbols::GetOffsetByName failed" ); + + return TypedVar::getTypedVar( m_client, TypeInfo::getTypeInfo( typeSym->getType() ), offset ); } /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/pykd.rc b/pykd/pykd.rc index d616026..a4287e7 100644 --- a/pykd/pykd.rc +++ b/pykd/pykd.rc @@ -53,8 +53,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,1,0,4 - PRODUCTVERSION 0,1,0,4 + FILEVERSION 0,1,0,5 + PRODUCTVERSION 0,1,0,5 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, 4" + VALUE "FileVersion", "0, 1, 0, 5" VALUE "InternalName", "pykd" VALUE "OriginalFilename", "pykd.dll" VALUE "ProductName", "pykd - python extension for windbg" - VALUE "ProductVersion", "0, 1, 0, 4" + VALUE "ProductVersion", "0, 1, 0, 5" END END BLOCK "VarFileInfo" diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index 4b9675b..841a9a5 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -131,6 +131,20 @@ BaseTypeVariant PtrTypedVar::getValue() /////////////////////////////////////////////////////////////////////////////////// +TypedVarPtr PtrTypedVar::deref() +{ + HRESULT hres; + ULONG64 val = 0; + + hres = m_dataSpaces->ReadPointersVirtual( 1, m_offset, &val ); + if ( FAILED( hres ) ) + throw MemoryException( m_offset, false ); + + return TypedVar::getTypedVar( m_client, m_typeInfo->deref(), val ); +} + +/////////////////////////////////////////////////////////////////////////////////// + TypedVarPtr UdtTypedVar::getField( const std::string &fieldName ) { diff --git a/pykd/typedvar.h b/pykd/typedvar.h index 1db4892..57b9033 100644 --- a/pykd/typedvar.h +++ b/pykd/typedvar.h @@ -37,7 +37,11 @@ public: return m_typeInfo; } - virtual TypedVarPtr getField( const std::string &fieldName ) { + virtual TypedVarPtr deref() { + throw DbgException("object can not be derefernced" ); + } + + virtual TypedVarPtr getField( const std::string &fieldName ) { throw DbgException("no fields"); } @@ -106,7 +110,9 @@ public: return "PtrTypedVar"; } - virtual BaseTypeVariant getValue(); + virtual TypedVarPtr deref(); + + virtual BaseTypeVariant getValue(); }; diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index 2463e8b..2bb3451 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -86,6 +86,10 @@ public: throw DbgException( "there is no fields" ); } + virtual TypeInfoPtr deref() { + throw DbgException( "type is not a pointer" ); + } + ULONG getOffset() { return m_offset; } @@ -282,6 +286,10 @@ public: return true; } + virtual TypeInfoPtr deref() { + return m_derefType; + } + TypeInfoPtr getDerefType() { return m_derefType; } diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index f27ac02..ba79301 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -128,7 +128,6 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( target.module.type("enumType").THREE, tv.m_enumField ) def testIndex(self): - ind = target.module.typedVar( "g_ucharValue" ) self.assertEqual( 5, [0,5,10][ind] ) @@ -142,5 +141,15 @@ class TypedVarTest( unittest.TestCase ): self.assertTrue( ind in { 1 : "1", 4 : "2" } ) self.assertEqual( "2", { 1 : "1", 4 : "2" }[ind] ) - - + def testDeref(self): + tv = target.module.typedVar( "g_structTest1" ) + self.assertEqual( target.module.g_structTest, tv.m_field4.deref().getAddress() ) + + tv = target.module.typedVar( "g_structTest" ) + self.assertEqual( 0, tv.m_field4.deref().getAddress() ) + + try: + tv.m_field1.deref() + self.assertTrue(False) + except pykd.BaseException: + pass diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index 23b0bca..29bcdc1 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -105,3 +105,20 @@ class TypeInfoTest( unittest.TestCase ): def testAsMap(self): ti = target.module.type("enumType") self.assertEqual( { 1 : "ONE", 2 : "TWO", 3 : "THREE" }, ti.asMap() ) + + def testDeref(self): + ti = target.module.type("listStruct1") + self.assertEqual( "listStruct1", ti.next.deref().name() ) + + ti = target.module.type("listStruct1*") + self.assertEqual( "listStruct1", ti.deref().name() ) + + ti = target.module.type("classChild") + try: + ti.deref() + self.assertTrue(False) + except pykd.BaseException: + pass + + + \ No newline at end of file