diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 674bf58..2ee7b85 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -408,7 +408,8 @@ BOOST_PYTHON_MODULE( pykd ) "Create custom union" ) ); python::def( "defineFunction", &pykd::defineFunction, defineFunction_( python::args("returnType", "callconv"), "Define custom function prototype" ) ); - python::def( "callFunction", python::raw_function(pykd::callFunctionByVar, 1) ); + python::def( "callFunctionByPtr", python::raw_function(pykd::callFunctionByVar, 1) ); + python::def( "callFunctionByAddr", python::raw_function(pykd::callFunctionByOffset, 2) ); // CPU registers python::def( "reg", pykd::getRegisterByName, diff --git a/pykd/pytypeinfo.cpp b/pykd/pytypeinfo.cpp index 3b9eb75..45398f3 100644 --- a/pykd/pytypeinfo.cpp +++ b/pykd/pytypeinfo.cpp @@ -132,26 +132,25 @@ python::list TypeInfoAdapter::getElementDir(kdlib::TypeInfo &typeInfo) return pylst; } + /////////////////////////////////////////////////////////////////////////////// -python::object callFunctionByVar( python::tuple& args, python::dict& kwargs ) +python::object callTypedVar(kdlib::TypedVarPtr& funcobj, python::tuple& args) { kdlib::NumVariant retVal; + + size_t argCount = python::len(args); - kdlib::TypedVarPtr funcvar = python::extract<kdlib::TypedVarPtr>(args[0]); - - size_t argCount = python::len(args) - 1; - - if ( argCount != funcvar->getType()->getElementCount() ) + if ( argCount != funcobj->getType()->getElementCount() ) throw kdlib::TypeException(L"wrong argument count"); kdlib::CallArgList argLst; for ( size_t i = 0; i < argCount; ++i ) { - kdlib::TypeInfoPtr argType = funcvar->getType()->getElement(i); + kdlib::TypeInfoPtr argType = funcobj->getType()->getElement(i); - python::object arg = args[i+1]; + python::object arg = args[i]; if ( argType->isBase() ) { @@ -272,7 +271,7 @@ python::object callFunctionByVar( python::tuple& args, python::dict& kwargs ) { AutoRestorePyState pystate; - retVal = funcvar->call(argLst); + retVal = funcobj->call(argLst); } return NumVariantAdaptor::convertToPython(retVal); @@ -280,4 +279,28 @@ python::object callFunctionByVar( python::tuple& args, python::dict& kwargs ) /////////////////////////////////////////////////////////////////////////////// +python::object callFunctionByVar( python::tuple& args, python::dict& kwargs ) +{ + kdlib::TypedVarPtr funcobj = python::extract<kdlib::TypedVarPtr>(args[0]); + + python::tuple newArgs = python::tuple(args.slice(1, python::_)); + + return callTypedVar(funcobj, newArgs ); +} + +/////////////////////////////////////////////////////////////////////////////// + +python::object callFunctionByOffset( python::tuple& args, python::dict& kwargs) +{ + kdlib::TypeInfoPtr functype = python::extract<kdlib::TypeInfoPtr>(args[0]); + kdlib::MEMOFFSET_64 funcaddr = python::extract<kdlib::MEMOFFSET_64>(args[1]); + + kdlib::TypedVarPtr funcobj = kdlib::loadTypedVar(functype, funcaddr); + python::tuple newArgs = python::tuple(args.slice(2, python::_)); + + return callTypedVar( funcobj, newArgs ); +} + +/////////////////////////////////////////////////////////////////////////////// + } // pykd namespace diff --git a/pykd/pytypeinfo.h b/pykd/pytypeinfo.h index 9e2ef4c..0a96c3f 100644 --- a/pykd/pytypeinfo.h +++ b/pykd/pytypeinfo.h @@ -46,6 +46,8 @@ inline kdlib::TypeInfoPtr defineFunction( const kdlib::TypeInfoPtr& returnType, python::object callFunctionByVar( python::tuple& args, python::dict& kwargs ); +python::object callFunctionByOffset( python::tuple& args, python::dict& kwargs); + inline kdlib::TypeInfoPtr getTypeInfoByName( const std::wstring &name ) { diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index c46ed1e..0406454 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -375,8 +375,13 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual(0, target.module.typedVar( "g_structTest" ).castTo("UInt4B")) def testCallFunction(self): - #funcptr = target.module.typedVar("StdcallFuncRet"); - #self.assertEqual( 200000/10, pykd.callFunction( funcptr, 10, 200000 ) ) + funcptr = target.module.typedVar("StdcallFuncRet"); + self.assertEqual( 200000/10, pykd.callFunctionByPtr( funcptr, 10, 200000 ) ) funcptr = target.module.typedVar("CdeclFuncLong"); - self.assertEqual( 0xffffff000000 + 5, pykd.callFunction( funcptr, target.module.typedVar("ulonglongConst") ) ) + self.assertEqual( 0xffffff000000 + 5, pykd.callFunctionByPtr( funcptr, target.module.typedVar("ulonglongConst") ) ) + + functype = pykd.defineFunction( pykd.baseTypes.Int4B, pykd.callingConvention.NearStd) + functype.append("arg1", pykd.baseTypes.Int1B) + functype.append("arg2", pykd.baseTypes.Long) + self.assertEqual( 500 / 25, pykd.callFunctionByAddr(functype, target.module.offset("StdcallFuncRet"), 25, 500 ) )