mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-19 19:13:22 +08:00
added: evalExpr routine ( Evaluate C++ expression with typed information )
This commit is contained in:
parent
23c1376112
commit
fc90ccc846
2
kdlibcpp
2
kdlibcpp
@ -1 +1 @@
|
|||||||
Subproject commit f27cdbdaef5f68e6704d24beb208921a0a66da4b
|
Subproject commit 809848cf36172dd3fe4c5781b9009d6bd49ca4c1
|
@ -2,7 +2,7 @@
|
|||||||
#define PYKD_VERSION_MAJOR 0
|
#define PYKD_VERSION_MAJOR 0
|
||||||
#define PYKD_VERSION_MINOR 3
|
#define PYKD_VERSION_MINOR 3
|
||||||
#define PYKD_VERSION_SUBVERSION 4
|
#define PYKD_VERSION_SUBVERSION 4
|
||||||
#define PYKD_VERSION_BUILDNO 2
|
#define PYKD_VERSION_BUILDNO 3
|
||||||
|
|
||||||
#define __VER_STR2__(x) #x
|
#define __VER_STR2__(x) #x
|
||||||
#define __VER_STR1__(x) __VER_STR2__(x)
|
#define __VER_STR1__(x) __VER_STR2__(x)
|
||||||
|
@ -104,6 +104,7 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( TypeInfo_ptrTo, TypeInfoAdapter::ptrTo, 1, 2 );
|
|||||||
BOOST_PYTHON_FUNCTION_OVERLOADS( getTypeFromSource_, pykd::getTypeFromSource, 2, 3 );
|
BOOST_PYTHON_FUNCTION_OVERLOADS( getTypeFromSource_, pykd::getTypeFromSource, 2, 3 );
|
||||||
BOOST_PYTHON_FUNCTION_OVERLOADS( getTypeInfoProviderFromPdb_, pykd::getTypeInfoProviderFromPdb, 1, 2 );
|
BOOST_PYTHON_FUNCTION_OVERLOADS( getTypeInfoProviderFromPdb_, pykd::getTypeInfoProviderFromPdb, 1, 2 );
|
||||||
BOOST_PYTHON_FUNCTION_OVERLOADS( getTypeInfoProviderFromSource_, pykd::getTypeInfoProviderFromSource, 1, 2);
|
BOOST_PYTHON_FUNCTION_OVERLOADS( getTypeInfoProviderFromSource_, pykd::getTypeInfoProviderFromSource, 1, 2);
|
||||||
|
BOOST_PYTHON_FUNCTION_OVERLOADS(evalExpr_, pykd::evalExpr, 1, 3);
|
||||||
|
|
||||||
namespace pykd {
|
namespace pykd {
|
||||||
|
|
||||||
@ -432,6 +433,9 @@ void pykd_init()
|
|||||||
"Create typeInfo provider from C/C++ source code") );
|
"Create typeInfo provider from C/C++ source code") );
|
||||||
python::def( "getTypeInfoProviderFromPdb", &pykd::getTypeInfoProviderFromPdb, getTypeInfoProviderFromPdb_( python::args("filePath", "baseOffset"),
|
python::def( "getTypeInfoProviderFromPdb", &pykd::getTypeInfoProviderFromPdb, getTypeInfoProviderFromPdb_( python::args("filePath", "baseOffset"),
|
||||||
"Create typeInfo provider from pdb file") );
|
"Create typeInfo provider from pdb file") );
|
||||||
|
python::def("evalExpr", &pykd::evalExpr, evalExpr_(python::args("expression", "scope", "typeProvider"),
|
||||||
|
"Evaluate C++ expression with typed information"));
|
||||||
|
|
||||||
|
|
||||||
// CPU registers
|
// CPU registers
|
||||||
python::def( "reg", pykd::getRegisterByName,
|
python::def( "reg", pykd::getRegisterByName,
|
||||||
|
@ -306,5 +306,45 @@ void TypedVarAdapter::setFieldByKey(kdlib::TypedVar& typedVar, const std::wstrin
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
kdlib::TypedVarPtr evalExpr(const std::string expression, python::dict& scope, kdlib::TypeInfoProviderPtr& typeInfoProvider )
|
||||||
|
{
|
||||||
|
std::list < std::pair<std::wstring, kdlib::TypedValue> > scopeList;
|
||||||
|
|
||||||
|
for (auto i = 0; i < python::len(scope); ++i)
|
||||||
|
{
|
||||||
|
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&)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoRestorePyState pystate;
|
||||||
|
|
||||||
|
if (!scopeList.empty() )
|
||||||
|
return kdlib::evalExpr(expression, makeScope(scopeList), typeInfoProvider).get();
|
||||||
|
|
||||||
|
return kdlib::evalExpr(expression).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
kdlib::TypedValue getTypdedValueFromPyObj(const python::object& value)
|
||||||
|
{
|
||||||
|
python::extract<kdlib::TypedVarPtr> getTypedVar(value);
|
||||||
|
if (getTypedVar.check())
|
||||||
|
return getTypedVar();
|
||||||
|
|
||||||
|
return NumVariantAdaptor::convertToVariant(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
} // namespace pykd
|
} // namespace pykd
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
namespace python = boost::python;
|
namespace python = boost::python;
|
||||||
|
|
||||||
#include "kdlib/typedvar.h"
|
#include "kdlib/typedvar.h"
|
||||||
|
#include "kdlib/typeinfo.h"
|
||||||
|
|
||||||
#include "stladaptor.h"
|
#include "stladaptor.h"
|
||||||
#include "pythreadstate.h"
|
#include "pythreadstate.h"
|
||||||
@ -229,4 +230,9 @@ struct TypedVarAdapter {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
kdlib::TypedValue getTypdedValueFromPyObj(const python::object& value);
|
||||||
|
|
||||||
|
kdlib::TypedVarPtr evalExpr(const std::string expression, python::dict& scope = python::dict(), kdlib::TypeInfoProviderPtr& typeInfoProvider = kdlib::getDefaultTypeInfoProvider());
|
||||||
|
|
||||||
|
|
||||||
} // end namespace pykd
|
} // end namespace pykd
|
||||||
|
@ -291,7 +291,6 @@ python::object callTypedVar(kdlib::TypedVarPtr& funcobj, python::tuple& args)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( python::extract<int>(args[i]).check() )
|
if ( python::extract<int>(args[i]).check() )
|
||||||
{
|
{
|
||||||
kdlib::NumVariant var= NumVariantAdaptor::convertToVariant(args[i]);
|
kdlib::NumVariant var= NumVariantAdaptor::convertToVariant(args[i]);
|
||||||
|
@ -411,9 +411,4 @@ struct BaseTypesEnum {
|
|||||||
static kdlib::TypeInfoPtr getDouble() { return pykd::getTypeInfoByName(L"Double"); }
|
static kdlib::TypeInfoPtr getDouble() { return pykd::getTypeInfoByName(L"Double"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // end namespace pykd
|
} // end namespace pykd
|
||||||
|
@ -14,12 +14,12 @@ class NumVariantAdaptor : public kdlib::NumConvertable
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static kdlib::NumVariant NumVariantAdaptor::convertToVariant( const python::object &obj)
|
static kdlib::NumVariant convertToVariant(const python::object &obj)
|
||||||
{
|
{
|
||||||
kdlib::NumVariant var;
|
kdlib::NumVariant var;
|
||||||
|
|
||||||
python::extract<kdlib::NumConvertable> getNumVar(obj);
|
python::extract<kdlib::NumConvertable> getNumVar(obj);
|
||||||
if ( getNumVar.check() )
|
if (getNumVar.check())
|
||||||
{
|
{
|
||||||
var = getNumVar();
|
var = getNumVar();
|
||||||
return var;
|
return var;
|
||||||
@ -49,23 +49,27 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (_PyLong_Sign(obj.ptr()) >= 0)
|
if (PyLong_Check(obj.ptr()))
|
||||||
{
|
{
|
||||||
if (_PyLong_NumBits(obj.ptr()) > 64)
|
if (_PyLong_Sign(obj.ptr()) >= 0)
|
||||||
throw pykd::OverflowException("int too big to convert");
|
{
|
||||||
|
if (_PyLong_NumBits(obj.ptr()) > 64)
|
||||||
|
throw pykd::OverflowException("int too big to convert");
|
||||||
|
|
||||||
var.setULongLong(PyLong_AsUnsignedLongLong(obj.ptr()));
|
var.setULongLong(PyLong_AsUnsignedLongLong(obj.ptr()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_PyLong_NumBits(obj.ptr()) > 63)
|
if (_PyLong_NumBits(obj.ptr()) > 63)
|
||||||
throw pykd::OverflowException("int too big to convert");
|
throw pykd::OverflowException("int too big to convert");
|
||||||
|
|
||||||
var.setLongLong(PyLong_AsLongLong(obj.ptr()));
|
var.setLongLong(PyLong_AsLongLong(obj.ptr()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw kdlib::TypeException(L"failed convert argument");
|
||||||
return var;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static python::object NumVariantAdaptor::convertToPython( const kdlib::NumVariant& var )
|
static python::object NumVariantAdaptor::convertToPython( const kdlib::NumVariant& var )
|
||||||
|
@ -8,7 +8,7 @@ import sys
|
|||||||
|
|
||||||
_name = "pykd"
|
_name = "pykd"
|
||||||
_desc = "python windbg extension"
|
_desc = "python windbg extension"
|
||||||
_version = '0.3.4.1'
|
_version = '0.3.4.2'
|
||||||
|
|
||||||
def getReleaseSrc():
|
def getReleaseSrc():
|
||||||
return 'Release_%d.%d' % sys.version_info[0:2]
|
return 'Release_%d.%d' % sys.version_info[0:2]
|
||||||
|
@ -91,7 +91,7 @@ if __name__ == "__main__":
|
|||||||
target.moduleName = os.path.splitext(os.path.basename(target.appPath))[0]
|
target.moduleName = os.path.splitext(os.path.basename(target.appPath))[0]
|
||||||
|
|
||||||
unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( getTestSuite() )
|
unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( getTestSuite() )
|
||||||
#unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( getTestSuite("typedvar.TypedVarTest.testAttr") )
|
#unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( getTestSuite("typedvar.TypedVarTest.testEvalExprScopeLong") )
|
||||||
|
|
||||||
try: input = raw_input
|
try: input = raw_input
|
||||||
except NameError: pass
|
except NameError: pass
|
||||||
|
@ -444,3 +444,26 @@ class TypedVarTest( unittest.TestCase ):
|
|||||||
self.assertFalse(hasattr(var, "noexisit"))
|
self.assertFalse(hasattr(var, "noexisit"))
|
||||||
self.assertRaises(AttributeError, getattr, *(var, "noexists"))
|
self.assertRaises(AttributeError, getattr, *(var, "noexists"))
|
||||||
self.assertRaises(AttributeError, setattr, *(var, "noexists", 0))
|
self.assertRaises(AttributeError, setattr, *(var, "noexists", 0))
|
||||||
|
|
||||||
|
def testEvalExpr(self):
|
||||||
|
self.assertEqual( 2+2, pykd.evalExpr("2+2") )
|
||||||
|
self.assertEqual( target.module.typedVar("g_structTest").m_field1, pykd.evalExpr("g_structTest.m_field1") )
|
||||||
|
self.assertEqual( target.module.typedVar("g_testArray")[1].m_field3, pykd.evalExpr("(g_testArray + 1)->m_field3") )
|
||||||
|
|
||||||
|
def testEvalExprScope(self):
|
||||||
|
|
||||||
|
v1 = target.module.typedVar( "ulongVar" )
|
||||||
|
v2 = target.module.typedVar( "g_structTest" )
|
||||||
|
|
||||||
|
scope = { "v1" : v1, "v2" : v2 }
|
||||||
|
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()) )
|
||||||
|
|
||||||
|
|
||||||
|
@ -164,10 +164,10 @@ class TypeInfoTest( unittest.TestCase ):
|
|||||||
self.assertEqual( "structTest", ti.deref().name() )
|
self.assertEqual( "structTest", ti.deref().name() )
|
||||||
|
|
||||||
ti = pykd.typeInfo("structTest[2]")
|
ti = pykd.typeInfo("structTest[2]")
|
||||||
self.assertRaises( pykd.TypeException, ti.deref );
|
self.assertEqual( "structTest", ti.deref().name() )
|
||||||
|
|
||||||
ti = target.module.type("classChild")
|
ti = target.module.type("classChild")
|
||||||
self.assertRaises( pykd.TypeException, ti.deref );
|
self.assertRaises( pykd.TypeException, ti.deref )
|
||||||
|
|
||||||
def testNestedStruct( self ):
|
def testNestedStruct( self ):
|
||||||
ti = target.module.type("structWithNested")
|
ti = target.module.type("structWithNested")
|
||||||
|
Loading…
Reference in New Issue
Block a user