added special method __contains__ for typedVar, typeInfo, module classes - support for 'in' operator

This commit is contained in:
ussrhero 2019-01-04 16:37:14 +03:00
parent d7c18187af
commit 99b48ad0b4
10 changed files with 99 additions and 24 deletions

View File

@ -876,6 +876,7 @@ void pykd_init()
"Return FixedFileInfo" )
.def("__getattr__", ModuleAdapter::getSymbolVaAttr,
"Return address of the symbol" )
.def("__contains__", ModuleAdapter::isContainedSymbol)
.def( "__str__", &ModuleAdapter::print );
python::class_<kdlib::TypeInfo, kdlib::TypeInfoPtr, python::bases<kdlib::NumConvertable>, boost::noncopyable >("typeInfo", "Class representing typeInfo", python::no_init )
@ -971,6 +972,7 @@ void pykd_init()
.def( "__getitem__", TypeInfoAdapter::getElementByIndex )
.def( "__getitem__", TypeInfoAdapter::getElementByKey )
.def( "__dir__", TypeInfoAdapter::getElementDir )
.def("__contains__", TypeInfoAdapter::isContainedField)
#if PY_VERSION_HEX >= 0x03000000
.def("__bool__", TypeInfoAdapter::isZero )
#else
@ -1044,7 +1046,7 @@ void pykd_init()
.def("__dir__", TypedVarAdapter::getElementsDir)
.def("__call__", python::raw_function(pykd::callFunctionByVar, 0) )
.def("__iter__", TypedVarAdapter::getArrayIter, python::return_value_policy<python::manage_new_object>())
//.def("__getitem__", &kdlib::TypedVar::getElementByIndexPtr )
.def("__contains__", TypedVarAdapter::isContainedField)
#if PY_VERSION_HEX >= 0x03000000
.def("__bool__", TypedVarAdapter::isNotZero)
#else

View File

@ -103,6 +103,15 @@ python::list ModuleAdapter::enumTypes(kdlib::Module& module, const std::wstring
///////////////////////////////////////////////////////////////////////////////
bool ModuleAdapter::isContainedSymbol(kdlib::ModulePtr& module, const std::wstring& symbolName)
{
if (!module->enumSymbols(symbolName).empty())
return true;
return !module->enumTypes(symbolName).empty();
}
///////////////////////////////////////////////////////////////////////////////
std::wstring ModuleAdapter::findSymbol( kdlib::Module& module, kdlib::MEMOFFSET_64 offset, bool showDisplacement )
{

View File

@ -198,6 +198,7 @@ struct ModuleAdapter : public kdlib::Module
static python::list getTypedVarArrayByTypeName( kdlib::Module& module, kdlib::MEMOFFSET_64 offset, const std::wstring &typeName, size_t number );
static bool isContainedSymbol(kdlib::ModulePtr& module, const std::wstring& symbolName);
};
} // end namespace pykd

View File

@ -138,6 +138,22 @@ python::list TypedVarAdapter::getFields( kdlib::TypedVar& typedVar )
///////////////////////////////////////////////////////////////////////////////
bool TypedVarAdapter::isContainedField(kdlib::TypedVarPtr& typedVar, const std::wstring& fieldName)
{
AutoRestorePyState pystate;
for (size_t i = 0; i < typedVar->getElementCount(); ++i)
{
std::wstring name = typedVar->getElementName(i);
if (name == fieldName)
return true;
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
python::list TypedVarAdapter::getElementsDir(kdlib::TypedVar& typedVar)
{
std::list<std::wstring> lst;
@ -306,28 +322,40 @@ void TypedVarAdapter::setFieldByKey(kdlib::TypedVar& typedVar, const std::wstrin
///////////////////////////////////////////////////////////////////////////////
kdlib::TypedVarPtr evalExpr(const std::string expression, python::dict& scope, kdlib::TypeInfoProviderPtr& typeInfoProvider )
class PyScope : public kdlib::Scope
{
std::list < std::pair<std::wstring, kdlib::TypedValue> > scopeList;
public:
for (auto i = 0; i < python::len(scope); ++i)
kdlib::TypedValue get(const std::wstring& varName) const override
{
auto key = scope.keys()[i];
std::wstring varName = python::extract<std::wstring>(key);
try
{
scopeList.push_back(std::make_pair(varName, getTypdedValueFromPyObj(scope[key])));
}
catch (kdlib::DbgException&)
{ }
return getTypdedValueFromPyObj(m_scope[varName]);
}
AutoRestorePyState pystate;
virtual bool find(const std::wstring& varName, kdlib::TypedValue& value) const override
{
if (!m_scope.contains(varName))
return false;
if (!scopeList.empty() )
return kdlib::evalExpr(expression, makeScope(scopeList), typeInfoProvider).get();
value = getTypdedValueFromPyObj(m_scope[varName]);
return true;
}
PyScope(const python::object& scope) :
m_scope(scope)
{}
private:
python::object m_scope;
};
kdlib::TypedVarPtr evalExpr(const std::string expression, python::object& scope, kdlib::TypeInfoProviderPtr& typeInfoProvider )
{
if (scope)
{
return kdlib::evalExpr(expression, kdlib::ScopePtr(new PyScope(scope)), typeInfoProvider).get();
}
return kdlib::evalExpr(expression).get();
}

View File

@ -228,11 +228,13 @@ struct TypedVarAdapter {
{
return new TypedVarIterator(typedVar);
}
static bool isContainedField(kdlib::TypedVarPtr& typedVar, const std::wstring& fieldName);
};
kdlib::TypedValue getTypdedValueFromPyObj(const python::object& value);
kdlib::TypedVarPtr evalExpr(const std::string expression, python::dict& scope = python::dict(), kdlib::TypeInfoProviderPtr& typeInfoProvider = kdlib::getDefaultTypeInfoProvider());
kdlib::TypedVarPtr evalExpr(const std::string expression, python::object& scope = python::object(), kdlib::TypeInfoProviderPtr& typeInfoProvider = kdlib::getDefaultTypeInfoProvider());
} // end namespace pykd

View File

@ -103,6 +103,21 @@ python::list TypeInfoAdapter::getFields( kdlib::TypeInfo &typeInfo )
return pylst;
}
bool TypeInfoAdapter::isContainedField(kdlib::TypeInfoPtr& typeInfo, const std::wstring& fieldName)
{
AutoRestorePyState pystate;
for (size_t i = 0; i < typeInfo->getElementCount(); ++i)
{
std::wstring name = typeInfo->getElementName(i);
if (name == fieldName)
return true;
}
return false;
}
python::list TypeInfoAdapter::getMethods(kdlib::TypeInfo &typeInfo)
{
typedef boost::tuple<std::wstring, kdlib::TypeInfoPtr> FieldTuple;

View File

@ -334,6 +334,8 @@ struct TypeInfoAdapter : public kdlib::TypeInfo {
return false;
}
static bool isContainedField(kdlib::TypeInfoPtr& typedVar, const std::wstring& fieldName);
};

View File

@ -139,4 +139,9 @@ class ModuleTest( unittest.TestCase ):
def testModuleList(self):
self.assertTrue( [] != pykd.getModulesList() )
def testContain(self):
self.assertTrue("voidPtr" in target.module)
self.assertTrue("structTest" in target.module)
self.assertFalse("NotExist" in target.module)
self.assertRaises(Exception, lambda md : 2 in md, target.module)

View File

@ -443,7 +443,6 @@ class TypedVarTest( unittest.TestCase ):
self.assertFalse(hasattr(var, "noexisit"))
self.assertRaises(AttributeError, getattr, *(var, "noexists"))
self.assertRaises(AttributeError, setattr, *(var, "noexists", 0))
def testEvalExpr(self):
self.assertEqual( 2+2, pykd.evalExpr("2+2") )
@ -459,11 +458,21 @@ class TypedVarTest( unittest.TestCase ):
self.assertEqual( v1 + v2.m_field1, pykd.evalExpr("v1 + v2.m_field1", scope) )
def testEvalExprScopeLong(self):
v1 = 100
v2 = -500
scope = { "v1" : v1, "v2" : v2 }
self.assertEqual( v1 + v2, pykd.evalExpr("v1 + v2", scope) )
self.assertEqual( v1 * v2, pykd.evalExpr("v1 * v2", locals()) )
def testEvalExprScopeStruct(self):
var = pykd.typedVar("g_structTest1")
self.assertEqual(var.m_field1, pykd.evalExpr("m_field1", var))
self.assertEqual(var.m_field4.deref().m_field1, pykd.evalExpr("m_field4->m_field1", var))
def testContain(self):
var = pykd.typedVar("g_structTest")
self.assertTrue("m_field1" in var)
self.assertFalse("NotExist" in var)
self.assertRaises(Exception, lambda var : 2 in var, var)

View File

@ -351,7 +351,6 @@ class TypeInfoTest( unittest.TestCase ):
self.assertEqual( classChild.baseClassOffset(0), classChild.baseClassOffset('classBase1'))
self.assertEqual(classChild.baseClassOffset(1), classChild.baseClassOffset('classBase2'))
def testPdbTypeProvider(self):
pdb = target.module.symfile()
typeProvider = pykd.getTypeInfoProviderFromPdb(pdb)
@ -363,5 +362,8 @@ class TypeInfoTest( unittest.TestCase ):
self.assertEqual( target.module.name(), pykd.typeInfo( "structTest" ).scopeName() )
self.assertEqual( target.module.name(), pykd.typeInfo( "structWithNested::Nested" ).scopeName() )
def testContain(self):
ti = target.module.type( "structTest" )
self.assertTrue("m_field1" in ti)
self.assertFalse("NotExist" in ti)
self.assertRaises(Exception, lambda t : 2 in t, ti)