diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 61258ba..2bd9381 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -388,46 +388,49 @@ BOOST_PYTHON_MODULE( pykd ) .def("__len__", &TypedVar::getElementCount ) .def("__getitem__", &TypedVar::getElementByIndex ); - python::class_("module", "Class representing executable module", python::no_init ) - .def("begin", &pykd::Module::getBase, + python::class_("module", "Class representing executable module", python::no_init ) + .def("begin", &Module::getBase, "Return start address of the module" ) - .def("end", &pykd::Module::getEnd, + .def("end", &Module::getEnd, "Return end address of the module" ) - .def("size", &pykd::Module::getSize, + .def("size", &Module::getSize, "Return size of the module" ) - .def("name", &pykd::Module::getName, + .def("name", &Module::getName, "Return name of the module" ) - .def("image", &pykd::Module::getImageName, + .def("image", &Module::getImageName, "Return name of the image of the module" ) - .def("pdb", &pykd::Module::getPdbName, + .def("pdb", &Module::getPdbName, "Return the full path to the module's pdb file ( symbol information )" ) - .def("reload", &pykd::Module::reloadSymbols, + .def("reload", &Module::reloadSymbols, "(Re)load symbols for the module" ) - .def("offset", &pykd::Module::getSymbol, + .def("offset", &Module::getSymbol, "Return offset of the symbol" ) - .def("rva", &pykd::Module::getSymbolRva, + .def("rva", &Module::getSymbolRva, "Return rva of the symbol" ) - .def("type", &pykd::Module::getTypeByName, + .def("type", &Module::getTypeByName, "Return typeInfo class by type name" ) - .def("typedVar", &pykd::Module::getTypedVarByAddr, + .def("typedVar", &Module::getTypedVarByAddr, "Return a typedVar class instance" ) - .def("typedVar",&pykd::Module::getTypedVarByName, + .def("typedVar",&Module::getTypedVarByName, "Return a typedVar class instance" ) - .def("typedVar",&pykd::Module::getTypedVarByType, + .def("typedVar",&Module::getTypedVarByType, "Return a typedVar class instance" ) - .def("typedVar",&pykd::Module::getTypedVarByTypeName, + .def("typedVar",&Module::getTypedVarByTypeName, "Return a typedVar class instance" ) - .def("__getattr__", &pykd::Module::getSymbol, + .def("containingRecord", &Module::contaningRecord, + "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("__getattr__", &Module::getSymbol, "Return address of the symbol" ); python::class_( "dout", "dout", python::no_init ) - .def( "write", &pykd::DbgOut::write ); + .def( "write", &DbgOut::write ); python::class_( "din", "din", python::no_init ) - .def( "readline", &pykd::DbgIn::readline ); + .def( "readline", &DbgIn::readline ); - python::class_("ext", python::no_init ) - .def( "call", &pykd::DbgExtension::call, + python::class_("ext", python::no_init ) + .def( "call", &DbgExtension::call, "Call debug extension command end return it's result as a string" ); python::class_( diff --git a/pykd/module.cpp b/pykd/module.cpp index 3d7e0af..ea6afbb 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -219,5 +219,41 @@ ULONG Module::getRvaByName(const std::string &symName) /////////////////////////////////////////////////////////////////////////////////// +TypedVarPtr Module::contaningRecord( ULONG64 address, const std::string &typeName, const std::string &fieldName ) +{ + address = addr64(address); + + TypeInfoPtr typeInfo = getTypeByName( typeName ); + + TypeInfoPtr fieldTypeInfo = typeInfo->getField( fieldName ); + + return TypedVar::getTypedVar( m_client, typeInfo, address - fieldTypeInfo->getOffset() ); + + + //HRESULT hres; + //ULONG64 moduleBase; + + //hres = dbgExt->symbols->GetModuleByModuleName( moduleName.c_str(), 0, NULL, &moduleBase ); + //if ( FAILED( hres ) ) + // throw TypeException(); + + //ULONG typeId; + //hres = dbgExt->symbols->GetTypeId( moduleBase, typeName.c_str(), &typeId ); + //if ( FAILED( hres ) ) + // throw TypeException(); + + //ULONG fieldTypeId; + //ULONG fieldOffset; + //hres = dbgExt->symbols3->GetFieldTypeAndOffset( moduleBase, typeId, fieldName.c_str(), &fieldTypeId, &fieldOffset ); + //if ( FAILED( hres ) ) + // throw TypeException(); + // + //TypedVar var( moduleName, typeName, address - fieldOffset ); + // + //return boost::python::object( var ); +} + +/////////////////////////////////////////////////////////////////////////////////// + }; // end of namespace pykd diff --git a/pykd/module.h b/pykd/module.h index f6737f3..4b7c784 100644 --- a/pykd/module.h +++ b/pykd/module.h @@ -68,6 +68,8 @@ public: TypedVarPtr getTypedVarByName( const std::string &symName ); + TypedVarPtr contaningRecord( ULONG64 addr, const std::string &typeName, const std::string &fieldName ); + private: ULONG getRvaByName(const std::string &symName); diff --git a/test/scripts/basetest.py b/test/scripts/basetest.py index a287fe3..5d5a234 100644 --- a/test/scripts/basetest.py +++ b/test/scripts/basetest.py @@ -17,7 +17,6 @@ class BaseTest( unittest.TestCase ): self.assertTrue( hasattr(pykd, 'addr64') ) self.assertTrue( hasattr(pykd, 'breakin') ) self.assertTrue( hasattr(pykd, 'compareMemory') ) - self.assertTrue( hasattr(pykd, 'containingRecord') ) self.assertTrue( hasattr(pykd, 'dbgCommand') ) self.assertTrue( hasattr(pykd, 'dprint') ) self.assertTrue( hasattr(pykd, 'dprintln') ) @@ -104,6 +103,7 @@ class BaseTest( unittest.TestCase ): def testOldRemovedApi( self ): """ Branch test: old API 0.0.x what should be removed """ + self.assertFalse( hasattr(pykd, 'containingRecord') ) self.assertFalse( hasattr(pykd, 'cpuReg') ) self.assertFalse( hasattr(pykd, 'dbgModuleClass') ) self.assertFalse( hasattr(pykd, 'debugEvent') ) diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py index 9d58449..1c962cc 100644 --- a/test/scripts/pykdtest.py +++ b/test/scripts/pykdtest.py @@ -59,9 +59,7 @@ if __name__ == "__main__": suite = getTestSuite() #suite = getTestSuite( "typeinfo.TypeInfoTest.testCreateBySymbol" ) - #suite = getTestSuite( "intbase.IntBaseTest.testLongConvert" ) - #suite = getTestSuite( "typedvar.TypedVarTest.testStruct" ) unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( suite ) - a = raw_input("\npress return\n") + #a = raw_input("\npress return\n") diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index ab8f151..d907615 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -62,4 +62,9 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( -100000, target.module.typedVar( "longArray" )[3]) self.assertEqual( -10000000000, target.module.typedVar( "longlongArray" )[4]) self.assertEqual( target.module.g_structTest, target.module.typedVar( "g_structTestPtr" ) ) - \ No newline at end of file + + def testContainingRecord(self): + off1 = target.module.type( "structTest" ).m_field2.offset() + off2 = target.module.offset( "g_structTest" ) + tv = target.module.containingRecord( off2 + off1, "structTest", "m_field2" ) + self.assertEqual( True, tv.m_field2 ) diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index c7eb665..641fd21 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -19,6 +19,7 @@ class TypeInfoTest( unittest.TestCase ): self.assertEqual( "structTest**", target.module.type( "structTest**" ).name() ) self.assertEqual( "Int4B[2][3]", target.module.type("Int4B[2][3]").name() ) self.assertEqual( "Int4B(*[4])[2][3]", target.module.type("Int4B(*[4])[2][3]").name() ) + self.assertEqual( "Int4B(*)[2][3]", target.module.type("Int4B((*))[2][3]").name() ) def testCreateBySymbol(self): """ creating typeInfo by the symbol name """ @@ -29,6 +30,8 @@ class TypeInfoTest( unittest.TestCase ): self.assertEqual( "Char*[2]", target.module.type("strArray").name() ) self.assertEqual( "Char*(*)[2]", target.module.type("ptrStrArray").name() ) self.assertEqual( "Int4B(*[4])[2][3]", target.module.type("arrIntMatrixPtrs").name() ) + self.assertEqual( "Int4B(*)[2][3]", target.module.type("ptrIntMatrix1").name() ) + def testGetField( self ): """ get field of the complex type """ diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index 7231543..9a30f20 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -79,6 +79,8 @@ int (* arrIntMatrixPtrs[4])[2][3] = { &intMatrix, &intMatrix2, &intMatrix3, &intMatrix4 }; +int ((*ptrIntMatrix1))[2][3] = &intMatrix; + char *(*ptrStrArray)[2] = &strArray; class classChild : public classBase {