From 4398021988df8c7d51ded76d36e34117626f6a7b Mon Sep 17 00:00:00 2001
From: "SND\\kernelnet_cp"
 <SND\kernelnet_cp@9b283d60-5439-405e-af05-b73fd8c4d996>
Date: Tue, 10 Jan 2012 06:54:25 +0000
Subject: [PATCH] [0.1.x] added : method deref for typeInfo class [0.1.x] added
 : method deref for typedVar class

git-svn-id: https://pykd.svn.codeplex.com/svn@73050 9b283d60-5439-405e-af05-b73fd8c4d996
---
 pykd/dbgext.cpp          |  7 +++++--
 pykd/module.cpp          | 15 ++++++++++++++-
 pykd/pykd.rc             |  8 ++++----
 pykd/typedvar.cpp        | 14 ++++++++++++++
 pykd/typedvar.h          | 10 ++++++++--
 pykd/typeinfo.h          |  8 ++++++++
 test/scripts/typedvar.py | 15 ++++++++++++---
 test/scripts/typeinfo.py | 17 +++++++++++++++++
 8 files changed, 82 insertions(+), 12 deletions(-)

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_<TypedVar, TypedVarPtr, python::bases<intBase>, 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