From eac07d8add05d8a3cf664e9263aa2478ff1b4c4a Mon Sep 17 00:00:00 2001 From: "SND\\ussrhero_cp" Date: Sat, 3 Dec 2016 20:47:47 +0000 Subject: [PATCH] [0.3.x] added : typedVar.method ( return function object ) git-svn-id: https://pykd.svn.codeplex.com/svn@91075 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/pymod.cpp | 2 + pykd/pytypedvar.cpp | 29 +++++++++ pykd/pytypedvar.h | 20 ++---- pykd/pytypeinfo.cpp | 134 +++++---------------------------------- test/scripts/typedvar.py | 15 +++++ 5 files changed, 68 insertions(+), 132 deletions(-) diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 7bb78b5..04a7d4f 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -932,6 +932,8 @@ BOOST_PYTHON_MODULE( pykd ) "Return list of tuple ( filedName, fieldOffset, fieldValue )" ) .def( "fieldName", TypedVarAdapter::getElementName, "Return name of struct field by index" ) + .def("method", TypedVarAdapter::getMethodByName, + "Return method of class as an object attribute" ) .def("deref",TypedVarAdapter::deref, "Return value by pointer" ) .def("type", TypedVarAdapter::getType, diff --git a/pykd/pytypedvar.cpp b/pykd/pytypedvar.cpp index 7e50771..9ff63fe 100644 --- a/pykd/pytypedvar.cpp +++ b/pykd/pytypedvar.cpp @@ -126,5 +126,34 @@ python::list TypedVarAdapter::getElementsDir(kdlib::TypedVar& typedVar) /////////////////////////////////////////////////////////////////////////////// +kdlib::TypedVarPtr TypedVarAdapter::getFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name) +{ + { + + AutoRestorePyState pystate; + + try + { + return typedVar.getElement( name ); + } + catch (kdlib::TypeException&) + {} + + try + { + return typedVar.getMethod( name ); + } + catch (kdlib::TypeException&) + {} + } + + std::wstringstream sstr; + sstr << L"typed var has no field " << L'\'' << name << L'\''; + throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str()); +} + +/////////////////////////////////////////////////////////////////////////////// + + } // namesapce pykd diff --git a/pykd/pytypedvar.h b/pykd/pytypedvar.h index f020010..e0a1268 100644 --- a/pykd/pytypedvar.h +++ b/pykd/pytypedvar.h @@ -109,19 +109,7 @@ struct TypedVarAdapter { return typedVar.getElement( name ); } - static kdlib::TypedVarPtr getFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name) - { - try - { - return getField(typedVar, name); - } - catch (kdlib::DbgException&) - { - std::wstringstream sstr; - sstr << L"typed var has no field " << L'\'' << name << L'\''; - throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str()); - } - } + static kdlib::TypedVarPtr getFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name); static size_t getElementCount( kdlib::TypedVar& typedVar ) { @@ -141,6 +129,12 @@ struct TypedVarAdapter { return typedVar.getElement( index ); } + static kdlib::TypedVarPtr getMethodByName(kdlib::TypedVar& typedVar, const std::wstring &name) + { + AutoRestorePyState pystate; + return typedVar.getMethod(name); + } + static std::wstring print( kdlib::TypedVar& typedVar ) { AutoRestorePyState pystate; diff --git a/pykd/pytypeinfo.cpp b/pykd/pytypeinfo.cpp index 44a9b8c..df91e58 100644 --- a/pykd/pytypeinfo.cpp +++ b/pykd/pytypeinfo.cpp @@ -162,135 +162,31 @@ python::list TypeInfoAdapter::getElementDir(kdlib::TypeInfo &typeInfo) python::object callTypedVar(kdlib::TypedVarPtr& funcobj, python::tuple& args) { kdlib::NumVariant retVal; - - size_t argCount = python::len(args); - if ( argCount != funcobj->getType()->getElementCount() ) - throw kdlib::TypeException(L"wrong argument count"); + size_t argCount = python::len(args); kdlib::TypedValueList argLst; for ( size_t i = 0; i < argCount; ++i ) { - kdlib::TypeInfoPtr argType = funcobj->getType()->getElement(i); - - python::object arg = args[i]; - - if ( argType->isBase() ) + python::extract getTypedVar(args[i]); + if ( getTypedVar.check() ) { - kdlib::NumVariant var= NumVariantAdaptor::convertToVariant(arg); - - if ( argType->getName() == L"Char" ) - { - argLst.push_back( var.asChar() ); - } - else if ( argType->getName() == L"WChar" ) - { - argLst.push_back( var.asShort() ); - } - else if ( argType->getName() == L"Int1B" ) - { - argLst.push_back( var.asChar() ); - } - else if ( argType->getName() == L"UInt1B" ) - { - argLst.push_back( var.asUChar() ); - } - else if ( argType->getName() == L"Int2B" ) - { - argLst.push_back( var.asShort() ); - } - else if ( argType->getName() == L"UInt2B" ) - { - argLst.push_back( var.asUShort() ); - } - else if ( argType->getName() == L"Int4B" ) - { - argLst.push_back( var.asLong() ); - } - else if ( argType->getName() == L"UInt4B" ) - { - argLst.push_back( var.asULong() ); - } - else if ( argType->getName() == L"Int8B" ) - { - argLst.push_back( var.asLongLong() ); - } - else if ( argType->getName() == L"UInt8B" ) - { - argLst.push_back(var.asULongLong()); - } - else if ( argType->getName() == L"Long" ) - { - argLst.push_back( var.asLong() ); - } - else if ( argType->getName() == L"ULong" ) - { - argLst.push_back( var.asULong() ); - } - else if ( argType->getName() == L"Bool" ) - { - argLst.push_back( var.asChar() ); - } - else if ( argType->getName() == L"Float" ) - { - argLst.push_back( var.asFloat() ); - } - else if ( argType->getName() == L"Double") - { - argLst.push_back( var.asDouble() ); - } - else - { - throw kdlib::TypeException( std::wstring(L"unsupported argument type ") + argType->getName() ); - } + argLst.push_back( getTypedVar() ); + continue; } - else if ( argType->isPointer() ) + + python::extract getNumVar(args[i]); + if ( getNumVar.check() ) { - kdlib::MEMOFFSET_64 addr; - - python::extract getNumVar(arg); - python::extract getLongLong(arg); - python::extract getLong(arg); - - if ( getNumVar.check() ) - { - kdlib::NumVariant var = getNumVar(); - addr = var.asULongLong(); - } - if ( getLongLong.check() ) - { - addr = getLongLong(); - } - else if ( getLong.check() ) - { - addr = getLong(); - } - else - { - std::wstringstream sstr; - sstr << "failed to convert " << i << " argument to pointer"; - throw kdlib::TypeException(sstr.str() ); - } - - switch ( argType->getPtrSize() ) - { - case 4: - argLst.push_back( static_cast(addr) ); - break; - - case 8: - argLst.push_back( static_cast(addr) ); - break; - - default: - throw kdlib::TypeException(L"unsupported call argument"); - } - } - else - { - throw kdlib::TypeException(L"unsupported argument type"); + kdlib::NumVariant var = getNumVar(); + argLst.push_back( var ); + continue; } + + kdlib::NumVariant var= NumVariantAdaptor::convertToVariant(args[i]); + argLst.push_back( var ); + } { diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index e0ccc8d..7e48be7 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -388,4 +388,19 @@ class TypedVarTest( unittest.TestCase ): functype.append("arg2", pykd.baseTypes.Long) self.assertEqual( 500 / 25, pykd.callFunctionByAddr(functype, target.module.offset("StdcallFuncRet"), 25, 500 ) ) + def testCallFunctionWithTypedVar(self): + funcptr = target.module.typedVar("StdcallFuncRet"); + ucharVar = target.module.typedVar( "ucharVar" ); + self.assertEqual( 10, ucharVar ) + self.assertEqual( 200000/10, funcptr( ucharVar, pykd.numVariant(200000) ) ) + + def testCallWithWrongArgs(self): + self.assertRaises( pykd.TypeException, target.module.typedVar("StdcallFuncRet"), *(1,) ) + self.assertRaises( pykd.TypeException, target.module.typedVar("StdcallFuncRet"), *(1,2,3) ) + self.assertRaises( pykd.TypeException, target.module.typedVar("StdcallFuncRet"), *(10, target.module.typedVar("g_classChild") )) + + def testCallMethod(self): + g_classChild = target.module.typedVar("g_classChild") + self.assertEqual( 1000*5, g_classChild.childMethod(10) ) +