From 2c6f6c889a4722532663ae299a1f1b4791a5c4bc Mon Sep 17 00:00:00 2001 From: "SND\\ussrhero_cp" Date: Tue, 13 Sep 2016 18:17:41 +0000 Subject: [PATCH] [0.3.x] added : callFunction routine ( call function in the target process ) git-svn-id: https://pykd.svn.codeplex.com/svn@91040 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/pymod.cpp | 1 + pykd/pytypeinfo.cpp | 147 +++++++++++++++++++++++++++++++++++++++ pykd/pytypeinfo.h | 3 + pykd/stdafx.h | 1 + pykd/variant.h | 11 ++- test/scripts/typedvar.py | 7 ++ 6 files changed, 168 insertions(+), 2 deletions(-) diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index f6a442e..674bf58 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -408,6 +408,7 @@ 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) ); // CPU registers python::def( "reg", pykd::getRegisterByName, diff --git a/pykd/pytypeinfo.cpp b/pykd/pytypeinfo.cpp index 84001e2..3b9eb75 100644 --- a/pykd/pytypeinfo.cpp +++ b/pykd/pytypeinfo.cpp @@ -4,6 +4,7 @@ #include "kdlib/exceptions.h" #include "pytypeinfo.h" +#include "variant.h" namespace pykd { @@ -133,4 +134,150 @@ python::list TypeInfoAdapter::getElementDir(kdlib::TypeInfo &typeInfo) /////////////////////////////////////////////////////////////////////////////// +python::object callFunctionByVar( python::tuple& args, python::dict& kwargs ) +{ + kdlib::NumVariant retVal; + + kdlib::TypedVarPtr funcvar = python::extract(args[0]); + + size_t argCount = python::len(args) - 1; + + if ( argCount != funcvar->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); + + python::object arg = args[i+1]; + + if ( argType->isBase() ) + { + 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() ); + } + } + else if ( argType->isPointer() ) + { + 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"); + } + } + + { + AutoRestorePyState pystate; + retVal = funcvar->call(argLst); + } + + return NumVariantAdaptor::convertToPython(retVal); +} + +/////////////////////////////////////////////////////////////////////////////// + } // pykd namespace diff --git a/pykd/pytypeinfo.h b/pykd/pytypeinfo.h index c388399..9e2ef4c 100644 --- a/pykd/pytypeinfo.h +++ b/pykd/pytypeinfo.h @@ -44,6 +44,9 @@ inline kdlib::TypeInfoPtr defineFunction( const kdlib::TypeInfoPtr& returnType, return kdlib::defineFunction(returnType, callconv); } +python::object callFunctionByVar( python::tuple& args, python::dict& kwargs ); + + inline kdlib::TypeInfoPtr getTypeInfoByName( const std::wstring &name ) { AutoRestorePyState pystate; diff --git a/pykd/stdafx.h b/pykd/stdafx.h index f9920fd..fc917a6 100644 --- a/pykd/stdafx.h +++ b/pykd/stdafx.h @@ -20,6 +20,7 @@ #include #include #include +#include #pragma warning(pop) namespace python = boost::python; diff --git a/pykd/variant.h b/pykd/variant.h index 81f3d27..f158220 100644 --- a/pykd/variant.h +++ b/pykd/variant.h @@ -17,6 +17,13 @@ public: { kdlib::NumVariant var; + python::extract getNumVar(obj); + if ( getNumVar.check() ) + { + var = getNumVar(); + return var; + } + if (PyBool_Check(obj.ptr())) { if (obj.ptr() == Py_True) @@ -43,8 +50,8 @@ public: if (_PyLong_Sign(obj.ptr()) >= 0) { - if (_PyLong_NumBits(obj.ptr()) > 64) - 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())); } diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index 5635648..c46ed1e 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -373,3 +373,10 @@ class TypedVarTest( unittest.TestCase ): def testCastTo(self): self.assertEqual(0xD2, target.module.typedVar( "ulonglongVar" ).castTo("UInt1B")) 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("CdeclFuncLong"); + self.assertEqual( 0xffffff000000 + 5, pykd.callFunction( funcptr, target.module.typedVar("ulonglongConst") ) )