diff --git a/kdlibcpp b/kdlibcpp index deda36a..58bd656 160000 --- a/kdlibcpp +++ b/kdlibcpp @@ -1 +1 @@ -Subproject commit deda36a086494be526a5d62bf1b104cb780d7a07 +Subproject commit 58bd65641b0a351204b60f0697d4868241eae198 diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 92b1fbb..1dff50b 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -913,6 +913,10 @@ void pykd_init() "Return offset of the nonstatic field") .def("fieldOffset", TypeInfoAdapter::getElementOffsetByIndex, "Return offset of the nonstatic field by index") + .def("isStaticField", TypeInfoAdapter::isStaticField, + "Return True if a field is a static field by field name") + .def("isStaticField", TypeInfoAdapter::isStaticFieldByIndex, + "Return True if a field is a static field by field name") .def("bitOffset", TypeInfoAdapter::getBitOffset, "Return bit field's offset") .def("bitWidth", TypeInfoAdapter::getBitWidth, @@ -929,6 +933,8 @@ void pykd_init() "Return name of struct field by index" ) .def( "fields", TypeInfoAdapter::getFields, "Return list of tuple ( filedName, fieldType )" ) + .def( "members", TypeInfoAdapter::getMembers, + "Return list of tuple ( memberName, fieldType ). Only defined member, not inherited from base class") .def( "getNumberMethods", TypeInfoAdapter::getMethodsCount, "Return number of methods" ) .def( "method", TypeInfoAdapter::getMethodByName, @@ -1049,6 +1055,8 @@ void pykd_init() "Check if a typedVar object has the specified field") .def( "fields", TypedVarAdapter::getFields, "Return list of tuple ( filedName, fieldOffset, fieldValue )" ) + .def ("members", TypedVarAdapter::getMembers, + "Return list of tuple ( filedName, fieldOffset, fieldValue )") .def( "fieldName", TypedVarAdapter::getElementName, "Return name of struct field by index" ) .def("method", TypedVarAdapter::getMethodByName, ( python::arg("name"), python::arg("prototype") = "" ), diff --git a/pykd/pytypeinfo.cpp b/pykd/pytypeinfo.cpp index a3f14fd..6436897 100644 --- a/pykd/pytypeinfo.cpp +++ b/pykd/pytypeinfo.cpp @@ -75,7 +75,7 @@ python::tuple findSymbolAndDisp( ULONG64 offset ) /////////////////////////////////////////////////////////////////////////////// -python::list TypeInfoAdapter::getFields( kdlib::TypeInfo &typeInfo ) +python::list TypeInfoAdapter::getFields( const kdlib::TypeInfoPtr &typeInfo ) { typedef boost::tuple FieldTuple; @@ -85,10 +85,10 @@ python::list TypeInfoAdapter::getFields( kdlib::TypeInfo &typeInfo ) AutoRestorePyState pystate; - for ( size_t i = 0; i < typeInfo.getElementCount(); ++i ) + for ( size_t i = 0; i < typeInfo->getElementCount(); ++i ) { - std::wstring name = typeInfo.getElementName(i); - kdlib::TypeInfoPtr val = typeInfo.getElement(i); + std::wstring name = typeInfo->getElementName(i); + kdlib::TypeInfoPtr val = typeInfo->getElement(i); lst.push_back( FieldTuple( name, val ) ); } @@ -103,6 +103,35 @@ python::list TypeInfoAdapter::getFields( kdlib::TypeInfo &typeInfo ) return pylst; } +python::list TypeInfoAdapter::getMembers(const kdlib::TypeInfoPtr &typeInfo) +{ + typedef boost::tuple FieldTuple; + + std::list lst; + + do { + + AutoRestorePyState pystate; + + for (size_t i = 0; i < typeInfo->getElementCount(); ++i) + { + std::wstring name = typeInfo->getElementName(i); + kdlib::TypeInfoPtr val = typeInfo->getElement(i); + + if (!typeInfo->isInheritedMember(i)) + lst.push_back(FieldTuple(name, val)); + } + + } while (false); + + python::list pylst; + + for (std::list::const_iterator it = lst.begin(); it != lst.end(); ++it) + pylst.append(python::make_tuple(it->get<0>(), it->get<1>())); + + return pylst; +} + bool TypeInfoAdapter::hasFieldOrMethod(kdlib::TypeInfoPtr& typeInfo, const std::wstring& fieldName) { AutoRestorePyState pystate; diff --git a/pykd/pytypeinfo.h b/pykd/pytypeinfo.h index 336a974..f65b6e1 100644 --- a/pykd/pytypeinfo.h +++ b/pykd/pytypeinfo.h @@ -143,6 +143,17 @@ struct TypeInfoAdapter : public kdlib::TypeInfo { return typeInfo.getElementVa( name ); } + static bool isStaticField(const kdlib::TypeInfoPtr &typeInfo, const std::wstring &name) + { + AutoRestorePyState pystate; + return typeInfo->isStaticMember(name); + } + + static bool isStaticFieldByIndex(const kdlib::TypeInfoPtr &typeInfo, size_t index) + { + AutoRestorePyState pystate; + return typeInfo->isStaticMember(index); + } static kdlib::TypeInfoPtr getElementByName( kdlib::TypeInfo &typeInfo, const std::wstring &name ) { @@ -332,7 +343,9 @@ struct TypeInfoAdapter : public kdlib::TypeInfo { return typeInfo.str(); } - static python::list getFields( kdlib::TypeInfo &typeInfo ); + static python::list getFields( const kdlib::TypeInfoPtr &typeInfo ); + + static python::list getMembers(const kdlib::TypeInfoPtr &typeInfo); static python::list getMethods(kdlib::TypeInfo &typeInfo); diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index 5330aa0..817879a 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -371,3 +371,13 @@ class TypeInfoTest( unittest.TestCase ): self.assertTrue(ti.isTemplate) self.assertEqual(['int', 'TestClassTemplate'], ti.getTemplateArgs() ) + def testMembers(self): + self.assertEqual( + ['__VFN_table', '__VFN_table', 'm_staticConst', 'm_staticField', 'm_childField', + 'm_childField2', 'm_childField3', 'm_enumField'], + [ member[0] for member in pykd.typeInfo( "classChild" ).members() ]) + + def testIsStaticField(self): + ti = pykd.typeInfo("classChild") + self.assertTrue(ti.isStaticField("m_staticField")) + self.assertFalse(ti.isStaticField("m_baseField")) \ No newline at end of file