From 733ee783cae25dae9787df116330df6a38ca6c52 Mon Sep 17 00:00:00 2001
From: "SND\\kernelnet_cp"
 <SND\kernelnet_cp@9b283d60-5439-405e-af05-b73fd8c4d996>
Date: Tue, 31 Jul 2012 16:47:26 +0000
Subject: [PATCH] [0.2.x] refactored : module class

git-svn-id: https://pykd.svn.codeplex.com/svn@78412 9b283d60-5439-405e-af05-b73fd8c4d996
---
 pykd/dbgengine.h           |  3 +++
 pykd/module.cpp            | 37 ++++++++++++++++++++++---
 pykd/module.h              | 26 +++++++++++++++---
 pykd/pymod.cpp             | 35 +++++++++++-------------
 pykd/win/dbgeng.cpp        | 55 ++++++++++++++++++++++++++++++++++++++
 test/scripts/moduletest.py | 46 +++++++++++--------------------
 test/scripts/pykdtest.py   |  3 +++
 7 files changed, 149 insertions(+), 56 deletions(-)

diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h
index 82b5ecf..3010872 100644
--- a/pykd/dbgengine.h
+++ b/pykd/dbgengine.h
@@ -16,7 +16,10 @@ ULONG ptrSize();
 ULONG64 findModuleBase( const std::string &moduleName );
 ULONG64 findModuleBase( ULONG64 offset );
 std::string getModuleName( ULONG64 baseOffset );
+std::string getModuleImageName( ULONG64 baseOffset ); 
 std::string getModuleSymbolFileName( ULONG64 baseOffset );
+ULONG getModuleTimeStamp( ULONG64 baseOffset );
+ULONG getModuleCheckSum( ULONG64 baseOffset );
 
 //manage access to target memory
 ULONG64 addr64( ULONG64 offset );
diff --git a/pykd/module.cpp b/pykd/module.cpp
index c5daa5b..e97d78f 100644
--- a/pykd/module.cpp
+++ b/pykd/module.cpp
@@ -21,6 +21,10 @@ Module::Module(const std::string &moduleName )
 {
     m_base = findModuleBase( moduleName );
     m_name = moduleName;
+    m_symfile = getModuleSymbolFileName( m_base );
+    m_imageName = getModuleImageName( m_base );
+    m_timeDataStamp = getModuleTimeStamp( m_base );
+    m_checkSum = getModuleCheckSum( m_base );
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
@@ -29,6 +33,10 @@ Module::Module(ULONG64 offset )
 {
     m_base = findModuleBase( addr64(offset) );
     m_name = getModuleName( m_base );
+    m_symfile = getModuleSymbolFileName( m_base );
+    m_imageName = getModuleImageName( m_base );
+    m_timeDataStamp = getModuleTimeStamp( m_base );
+    m_checkSum = getModuleCheckSum( m_base );
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
@@ -40,11 +48,10 @@ SymbolPtr& Module::getSymScope()
         if ( m_symScope )
             break;
 
-        std::string  symbolName = getModuleSymbolFileName( m_base );
-        if ( symbolName.empty() )
+        if ( m_symfile.empty() )
             break;
 
-        m_symScope = loadSymbolFile( symbolName );
+        m_symScope = loadSymbolFile( m_symfile );
 
     } while( false );
 
@@ -56,6 +63,14 @@ SymbolPtr& Module::getSymScope()
 
 /////////////////////////////////////////////////////////////////////////////////////
 
+void Module::reloadSymbols()
+{
+    m_symfile = getModuleSymbolFileName( m_base );
+    m_symScope.reset();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+
 ULONG Module::getRvaByName(const std::string &symName)
 {
     SymbolPtr  &symScope = getSymScope();
@@ -65,6 +80,22 @@ ULONG Module::getRvaByName(const std::string &symName)
 
 /////////////////////////////////////////////////////////////////////////////////////
 
+std::string Module::print()
+{
+    std::stringstream   sstr;
+
+    sstr << "Module: " << m_name <<  std::endl;
+    sstr << "Start: " << std::hex << m_base << " End: " << getEnd() << " Size: " << m_size << std::endl;
+    sstr << "Image: " << m_imageName << std::endl;
+    sstr << "Symnol: " << m_symfile << std::endl;
+    //sstr << "Timestamp: " << m_timeDataStamp << std::endl;
+    //sstr << "Check Sum: " << m_checkSum << std::endl;
+
+    return sstr.str();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+
 }; // end of namespace pykd
 
 
diff --git a/pykd/module.h b/pykd/module.h
index 2a19164..9b65632 100644
--- a/pykd/module.h
+++ b/pykd/module.h
@@ -44,11 +44,17 @@ public:
         return m_size;
     }
 
-    void
-    reloadSymbols()
-    {
+    std::string getSymFile() const {
+        return m_symfile;
     }
 
+    std::string getImageName() const {
+        return m_imageName;
+    }
+
+    void
+    reloadSymbols();
+
     ULONG64
     getSymbol( const std::string &symbolname ) {
         return m_base + getRvaByName(symbolname);
@@ -59,6 +65,16 @@ public:
         return getRvaByName(symbolname);
     }
 
+    ULONG getCheckSum() const {
+        return m_checkSum;
+    }
+
+    ULONG getTimeDataStamp() const {
+        return m_timeDataStamp;
+    }
+
+    std::string print();
+
 private:
 
     SymbolPtr& getSymScope();
@@ -70,8 +86,12 @@ private:
     ULONG getRvaByName(const std::string &symName);
 
     std::string             m_name;
+    std::string             m_imageName;
+    std::string             m_symfile;
     ULONG64                 m_base;
     ULONG                   m_size;
+    ULONG                   m_timeDataStamp;
+    ULONG                   m_checkSum;
 
     SymbolPtr               m_symScope;
 };
diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp
index 4fc11f4..e02df50 100644
--- a/pykd/pymod.cpp
+++ b/pykd/pymod.cpp
@@ -176,19 +176,14 @@ BOOST_PYTHON_MODULE( pykd )
              "Return name of the module" )
         .def("reload", &Module::reloadSymbols,
             "(Re)load symbols for the module" )
-        .def("__getattr__", &Module::getSymbol,
-            "Return address of the symbol" );
-
-        //.def("image", &Module::getImageName,
-        //     "Return name of the image of the module" )
-        //.def("pdb", &Module::getPdbName,
-        //     "Return the full path to the module's pdb file ( symbol information )" )
-        //.def("reload", &Module::reloadSymbols,
-        //    "(Re)load symbols for the module" )
-        //.def("offset", &Module::getSymbol,
-        //    "Return offset of the symbol" )
-        //.def("rva", &Module::getSymbolRva,
-        //    "Return rva of the symbol" )
+        .def("image", &Module::getImageName,
+            "Return name of the image of the module" )
+        .def("symfile", &Module::getSymFile,
+             "Return the full path to the module's symbol information" )
+        .def("offset", &Module::getSymbol,
+            "Return offset of the symbol" )
+        .def("rva", &Module::getSymbolRva,
+            "Return rva of the symbol" )
         //.def( "sizeof", &Module::getSymbolSize,
         //    "Return a size of the type or variable" )
         //.def("type", &Module::getTypeByName,
@@ -215,13 +210,13 @@ BOOST_PYTHON_MODULE( pykd )
         //.def("containingRecord", &Module::containingRecordByType,
         //    "Return instance of the typedVar class. It's value are loaded from the target memory."
         //    "The start address is calculated by the same method as the standard macro CONTAINING_RECORD does" )
-        //.def("checksum",&Module::getCheckSum,
-        //    "Return a image file checksum: IMAGE_OPTIONAL_HEADER.CheckSum" )
-        //.def("timestamp",&Module::getTimeDataStamp,
-        //    "Return a low 32 bits of the time stamp of the image: IMAGE_FILE_HEADER.TimeDateStamp" )
-        //.def("__getattr__", &Module::getSymbol,
-        //    "Return address of the symbol" )
-        //.def( "__str__", &Module::print );
+        .def("checksum",&Module::getCheckSum,
+            "Return a image file checksum: IMAGE_OPTIONAL_HEADER.CheckSum" )
+        .def("timestamp",&Module::getTimeDataStamp,
+            "Return a low 32 bits of the time stamp of the image: IMAGE_FILE_HEADER.TimeDateStamp" )
+        .def("__getattr__", &Module::getSymbol,
+            "Return address of the symbol" )
+        .def( "__str__", &Module::print );
 
     pykd::exception<DbgException>( "BaseException", "Pykd base exception class" );
     pykd::exception<MemoryException,DbgException>( "MemoryException", "Target memory access exception class" );
diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp
index 9f5d963..ae71c49 100644
--- a/pykd/win/dbgeng.cpp
+++ b/pykd/win/dbgeng.cpp
@@ -174,6 +174,29 @@ std::string getModuleName( ULONG64 baseOffset )
 
 ///////////////////////////////////////////////////////////////////////////////////
 
+std::string getModuleImageName( ULONG64 baseOffset )
+{
+    PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
+
+    HRESULT  hres;
+    char  imageName[0x100];
+
+    hres = g_dbgEng->symbols->GetModuleNameString( 
+        DEBUG_MODNAME_IMAGE,
+        DEBUG_ANY_ID,
+        baseOffset,
+        imageName,
+        sizeof( imageName ),
+        NULL );
+
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugSymbol::GetModuleNameString failed" );
+
+    return std::string( imageName );
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
 std::string getModuleSymbolFileName( ULONG64 baseOffset )
 {
     PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
@@ -227,6 +250,38 @@ std::string getModuleSymbolFileName( ULONG64 baseOffset )
 
 ///////////////////////////////////////////////////////////////////////////////////
 
+ULONG getModuleTimeStamp( ULONG64 baseOffset )
+{
+    PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
+
+    HRESULT  hres;
+    DEBUG_MODULE_PARAMETERS     moduleParam = { 0 };
+
+    hres = g_dbgEng->symbols->GetModuleParameters( 1, &baseOffset, 0, &moduleParam );
+    if ( FAILED( hres ) )
+         throw DbgException( "IDebugSymbol::GetModuleParameters  failed" );    
+
+    return moduleParam.TimeDateStamp;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
+ULONG getModuleCheckSum( ULONG64 baseOffset )
+{
+    PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
+
+    HRESULT  hres;
+    DEBUG_MODULE_PARAMETERS     moduleParam = { 0 };
+
+    hres = g_dbgEng->symbols->GetModuleParameters( 1, &baseOffset, 0, &moduleParam );
+    if ( FAILED( hres ) )
+         throw DbgException( "IDebugSymbol::GetModuleParameters  failed" );    
+
+    return moduleParam.Checksum;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
 ULONG ptrSize()
 {
     PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
diff --git a/test/scripts/moduletest.py b/test/scripts/moduletest.py
index 20830e4..90b974b 100644
--- a/test/scripts/moduletest.py
+++ b/test/scripts/moduletest.py
@@ -26,40 +26,26 @@ class ModuleTest( unittest.TestCase ):
     def testEnd( self ):
         self.assertEqual( target.module.size(), target.module.end() - target.module.begin() )
          
-#    def testPdb( self ):
-#        self.assertNotEqual( "", target.module.pdb() )
+    def testPdb( self ):
+       self.assertNotEqual( "", target.module.symfile() )
          
-#    def testImage( self ):
-#        self.assertEqual( target.module.name() + ".exe", target.module.image() )
+    def testImage( self ):
+       self.assertEqual( target.module.name() + ".exe", target.module.image() )
 
-#    def testFindModule( self ):
-    
-#        try: 
-#            pykd.loadModule( target.module.begin() - 0x10 )
-#            self.assertTrue( False )
-#        except pykd.BaseException: 
-#            self.assertTrue( True )
+    def testFindModule( self ):
+        self.assertRaises( pykd.BaseException, pykd.module, target.module.begin() - 0x10 )            
 
-#        self.assertNotEqual( None, pykd.loadModule( target.module.begin() ) )
-#        self.assertNotEqual( None, pykd.loadModule( target.module.begin() + 0x10) )
+        self.assertNotEqual( None, pykd.module( target.module.begin() ) )
+        self.assertNotEqual( None, pykd.module( target.module.begin() + 0x10) )
 
-#        try: 
-#            pykd.loadModule( target.module.end() )
-#            self.assertTrue( False )
-#        except pykd.BaseException: 
-#            self.assertTrue( True )
- 
-#        try: 
-#            pykd.loadModule( target.module.end() + 0x10 )
-#            self.assertTrue( False )
-#        except pykd.BaseException: 
-#            self.assertTrue( True )
+        self.assertRaises( pykd.BaseException, pykd.module, target.module.end() )
+        self.assertRaises( pykd.BaseException, pykd.module, target.module.end() + 0x10 )
 
-#    def testSymbol( self ):
-#        self.assertEqual( target.module.rva("FuncWithName0"), target.module.offset("FuncWithName0") - target.module.begin() )
-#        self.assertEqual( target.module.rva("FuncWithName0"), target.module.FuncWithName0 - target.module.begin() )
+    def testSymbol( self ):
+        self.assertEqual( target.module.rva("FuncWithName0"), target.module.offset("FuncWithName0") - target.module.begin() )
+        self.assertEqual( target.module.rva("FuncWithName0"), target.module.FuncWithName0 - target.module.begin() )
         
-#    def testType( self ):
-#        self.assertEqual( "structTest", target.module.type("structTest").name() );
-#        self.assertEqual( "structTest", target.module.type("g_structTest").name() );
+    def testType( self ):
+        self.assertEqual( "structTest", target.module.type("structTest").name() );
+        self.assertEqual( "structTest", target.module.type("g_structTest").name() );
 
diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py
index 7393a2f..367b3f1 100644
--- a/test/scripts/pykdtest.py
+++ b/test/scripts/pykdtest.py
@@ -55,6 +55,9 @@ if __name__ == "__main__":
 
 
 
+
+
+
 #import target
 #import moduletest