mirror of
https://github.com/cemu-project/idapython.git
synced 2024-11-30 21:14:20 +01:00
python.cpp: Proper extlang implementation from Ilfak
python.cpp: Cleanups and fixes from Ilfak
This commit is contained in:
parent
1a45b5952a
commit
43af79132f
244
python.cpp
244
python.cpp
@ -36,7 +36,7 @@ extern "C"
|
|||||||
/* Python-style version tuple comes from the makefile */
|
/* Python-style version tuple comes from the makefile */
|
||||||
/* Only the serial and status is set here */
|
/* Only the serial and status is set here */
|
||||||
#define VER_SERIAL 0
|
#define VER_SERIAL 0
|
||||||
#define VER_STATUS "alpha"
|
#define VER_STATUS "final"
|
||||||
|
|
||||||
#define IDAPYTHON_RUNFILE 0
|
#define IDAPYTHON_RUNFILE 0
|
||||||
#define IDAPYTHON_RUNSTATEMENT 1
|
#define IDAPYTHON_RUNSTATEMENT 1
|
||||||
@ -80,7 +80,7 @@ int tracefunc(PyObject *obj, _frame *frame, int what, PyObject *arg)
|
|||||||
|
|
||||||
/* Simple Python statement runner function for IDC */
|
/* Simple Python statement runner function for IDC */
|
||||||
static const char idc_runpythonstatement_args[] = { VT_STR, 0 };
|
static const char idc_runpythonstatement_args[] = { VT_STR, 0 };
|
||||||
static error_t idaapi idc_runpythonstatement(value_t *argv, value_t *res)
|
static error_t idaapi idc_runpythonstatement(idc_value_t *argv, idc_value_t *res)
|
||||||
{
|
{
|
||||||
res->num = PyRun_SimpleString(argv[0].str);
|
res->num = PyRun_SimpleString(argv[0].str);
|
||||||
return eOk;
|
return eOk;
|
||||||
@ -88,9 +88,9 @@ static error_t idaapi idc_runpythonstatement(value_t *argv, value_t *res)
|
|||||||
|
|
||||||
|
|
||||||
/* QuickFix for the FILE* incompatibility problem */
|
/* QuickFix for the FILE* incompatibility problem */
|
||||||
int ExecFile(char *FileName)
|
int ExecFile(const char *FileName)
|
||||||
{
|
{
|
||||||
PyObject* PyFileObject = PyFile_FromString(FileName, "r");
|
PyObject* PyFileObject = PyFile_FromString((char*)FileName, "r");
|
||||||
|
|
||||||
if (!PyFileObject)
|
if (!PyFileObject)
|
||||||
{
|
{
|
||||||
@ -171,7 +171,7 @@ void IDAPython_RunScript(char *script)
|
|||||||
slashpath[i] = '\0';
|
slashpath[i] = '\0';
|
||||||
|
|
||||||
/* Add the script't path to sys.path */
|
/* Add the script't path to sys.path */
|
||||||
snprintf(statement, sizeof(statement), "runscript(\"%s\")", slashpath);
|
qsnprintf(statement, sizeof(statement), "runscript(\"%s\")", slashpath);
|
||||||
PyRun_SimpleString(statement);
|
PyRun_SimpleString(statement);
|
||||||
|
|
||||||
/* Error handling */
|
/* Error handling */
|
||||||
@ -256,74 +256,46 @@ bool idaapi IDAPython_Menu_Callback(void *ud)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compile callback for Python external language evaluator */
|
/* Return a formatted error or just print it to the console */
|
||||||
bool idaapi IDAPython_extlang_compile(const char *name,
|
static void handle_python_error(char *errbuf, size_t errbufsize)
|
||||||
ea_t current_ea,
|
|
||||||
const char *expr,
|
|
||||||
char *errbuf,
|
|
||||||
size_t errbufsize)
|
|
||||||
{
|
|
||||||
qstrncpy(errbuf, "evaluation error", errbufsize);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Run callback for Python external language evaluator */
|
|
||||||
bool idaapi IDAPython_extlang_run(const char *name,
|
|
||||||
int nargs,
|
|
||||||
const idc_value_t args[],
|
|
||||||
idc_value_t *result,
|
|
||||||
char *errbuf,
|
|
||||||
size_t errbufsize)
|
|
||||||
{
|
|
||||||
qstrncpy(errbuf, "evaluation error", errbufsize);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Calculator callback for Python external language evaluator */
|
|
||||||
bool idaapi IDAPython_extlang_calcexpr(ea_t current_ea,
|
|
||||||
const char *expr,
|
|
||||||
idc_value_t *rv,
|
|
||||||
char *errbuf,
|
|
||||||
size_t errbufsize)
|
|
||||||
{
|
{
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
PyObject *ptype, *pvalue, *ptraceback;
|
PyObject *ptype, *pvalue, *ptraceback;
|
||||||
PyObject *module = PyImport_AddModule("__main__");
|
|
||||||
double dresult;
|
|
||||||
|
|
||||||
if (module == NULL)
|
if ( errbufsize > 0 )
|
||||||
return false;
|
errbuf[0] = '\0';
|
||||||
|
|
||||||
PyObject *globals = PyModule_GetDict(module);
|
if (PyErr_Occurred())
|
||||||
|
{
|
||||||
result = PyRun_String(expr, Py_eval_input, globals, globals);
|
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
|
||||||
|
result = PyObject_Repr(pvalue);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
qsnprintf(errbuf, errbufsize, "ERROR: %s", PyString_AsString(result));
|
||||||
|
PyErr_Clear();
|
||||||
|
Py_XDECREF(ptype);
|
||||||
|
Py_XDECREF(pvalue);
|
||||||
|
Py_XDECREF(ptraceback);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_Print();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert return value from Python to IDC or report about an error */
|
||||||
|
static bool return_python_result(idc_value_t *rv,
|
||||||
|
PyObject *result,
|
||||||
|
char *errbuf,
|
||||||
|
size_t errbufsize)
|
||||||
|
{
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
{
|
{
|
||||||
/* Return a formatted error or just print it to the console */
|
handle_python_error(errbuf, errbufsize);
|
||||||
if (PyErr_Occurred())
|
|
||||||
{
|
|
||||||
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
|
|
||||||
result = PyObject_Repr(pvalue);
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
qsnprintf(errbuf, errbufsize, "ERROR: %s", PyString_AsString(result));
|
|
||||||
PyErr_Clear();
|
|
||||||
Py_XDECREF(ptype);
|
|
||||||
Py_XDECREF(pvalue);
|
|
||||||
Py_XDECREF(ptraceback);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PyErr_Print();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
VarFree(rv);
|
|
||||||
|
|
||||||
if (PyInt_Check(result))
|
if (PyInt_Check(result))
|
||||||
{
|
{
|
||||||
rv->num = PyInt_AsLong(result);
|
rv->num = PyInt_AsLong(result);
|
||||||
@ -339,7 +311,7 @@ bool idaapi IDAPython_extlang_calcexpr(ea_t current_ea,
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
strcpy(rv->str, PyString_AsString(result));
|
qstrncpy(rv->str, PyString_AsString(result), MAXSTR);
|
||||||
rv->vtype = VT_STR;
|
rv->vtype = VT_STR;
|
||||||
Py_XDECREF(result);
|
Py_XDECREF(result);
|
||||||
return true;
|
return true;
|
||||||
@ -347,7 +319,7 @@ bool idaapi IDAPython_extlang_calcexpr(ea_t current_ea,
|
|||||||
|
|
||||||
if (PyFloat_Check(result))
|
if (PyFloat_Check(result))
|
||||||
{
|
{
|
||||||
dresult = PyFloat_AsDouble(result);
|
double dresult = PyFloat_AsDouble(result);
|
||||||
ieee_realcvt((void *)&dresult, rv->e, 3);
|
ieee_realcvt((void *)&dresult, rv->e, 3);
|
||||||
rv->vtype = VT_FLOAT;
|
rv->vtype = VT_FLOAT;
|
||||||
Py_XDECREF(result);
|
Py_XDECREF(result);
|
||||||
@ -357,6 +329,142 @@ bool idaapi IDAPython_extlang_calcexpr(ea_t current_ea,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compile callback for Python external language evaluator */
|
||||||
|
bool idaapi IDAPython_extlang_compile(const char *name,
|
||||||
|
ea_t /*current_ea*/,
|
||||||
|
const char *expr,
|
||||||
|
char *errbuf,
|
||||||
|
size_t errbufsize)
|
||||||
|
{
|
||||||
|
PyObject *main = PyImport_AddModule("__main__"); QASSERT(main != NULL);
|
||||||
|
PyObject *globals = PyModule_GetDict(main); QASSERT(globals != NULL);
|
||||||
|
|
||||||
|
PyCodeObject *code = (PyCodeObject *)Py_CompileString(expr, "<string>", Py_eval_input);
|
||||||
|
if (code == NULL)
|
||||||
|
{
|
||||||
|
handle_python_error(errbuf, errbufsize);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the desired function name
|
||||||
|
Py_XDECREF(code->co_name);
|
||||||
|
code->co_name = PyString_FromString(name);
|
||||||
|
|
||||||
|
// create a function out of code
|
||||||
|
PyObject *func = PyFunction_New((PyObject *)code, globals);
|
||||||
|
if (func == NULL)
|
||||||
|
{
|
||||||
|
ERR:
|
||||||
|
handle_python_error(errbuf, errbufsize);
|
||||||
|
Py_XDECREF(code);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = PyDict_SetItemString(globals, name, func);
|
||||||
|
if (err)
|
||||||
|
goto ERR;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run callback for Python external language evaluator */
|
||||||
|
bool idaapi IDAPython_extlang_run(const char *name,
|
||||||
|
int nargs,
|
||||||
|
const idc_value_t args[],
|
||||||
|
idc_value_t *result,
|
||||||
|
char *errbuf,
|
||||||
|
size_t errbufsize)
|
||||||
|
{
|
||||||
|
// convert arguments to python
|
||||||
|
qvector<PyObject *> pargs;
|
||||||
|
|
||||||
|
for (int i=0; i<nargs; i++)
|
||||||
|
{
|
||||||
|
double dresult;
|
||||||
|
PyObject *pa;
|
||||||
|
switch (args[i].vtype)
|
||||||
|
{
|
||||||
|
case VT_LONG:
|
||||||
|
pa = PyInt_FromLong(args[i].num);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VT_STR:
|
||||||
|
pa = PyString_FromString(args[i].str);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VT_FLOAT:
|
||||||
|
ieee_realcvt(&dresult, (ushort *)args[i].e, 013);
|
||||||
|
pa = PyFloat_FromDouble(dresult);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
qsnprintf(errbuf, errbufsize, "arg#%d has wrong type %d", i, args[i].vtype);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pargs.push_back(pa);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *main = PyImport_AddModule("__main__"); QASSERT(main != NULL);
|
||||||
|
PyObject *globals = PyModule_GetDict(main); QASSERT(globals != NULL);
|
||||||
|
PyObject *func = PyDict_GetItemString(globals, name);
|
||||||
|
|
||||||
|
if (func == NULL)
|
||||||
|
{
|
||||||
|
qsnprintf(errbuf, errbufsize, "undefined function %s", name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyCodeObject *code = (PyCodeObject *)PyFunction_GetCode(func);
|
||||||
|
PyObject *pres = PyEval_EvalCodeEx(code, globals, NULL, &pargs[0], nargs,
|
||||||
|
NULL, 0, NULL, 0, NULL);
|
||||||
|
|
||||||
|
// free argument objects
|
||||||
|
for (int i=0; i<nargs; i++)
|
||||||
|
Py_XDECREF(pargs[i]);
|
||||||
|
|
||||||
|
return return_python_result(result, pres, errbuf, errbufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Compile callback for Python external language evaluator */
|
||||||
|
bool idaapi IDAPython_extlang_compile_file(const char *name,
|
||||||
|
char *errbuf,
|
||||||
|
size_t errbufsize)
|
||||||
|
{
|
||||||
|
PyObject *main = PyImport_AddModule("__main__"); QASSERT(main != NULL);
|
||||||
|
PyObject *globals = PyModule_GetDict(main); QASSERT(globals != NULL);
|
||||||
|
|
||||||
|
if (!ExecFile(name))
|
||||||
|
{
|
||||||
|
handle_python_error(errbuf, errbufsize);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculator callback for Python external language evaluator */
|
||||||
|
bool idaapi IDAPython_extlang_calcexpr(ea_t /*current_ea*/,
|
||||||
|
const char *expr,
|
||||||
|
idc_value_t *rv,
|
||||||
|
char *errbuf,
|
||||||
|
size_t errbufsize)
|
||||||
|
{
|
||||||
|
PyObject *result;
|
||||||
|
PyObject *module = PyImport_AddModule("__main__");
|
||||||
|
|
||||||
|
if (module == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
PyObject *globals = PyModule_GetDict(module);
|
||||||
|
|
||||||
|
result = PyRun_String(expr, Py_eval_input, globals, globals);
|
||||||
|
|
||||||
|
VarFree(rv);
|
||||||
|
|
||||||
|
return return_python_result(rv, result, errbuf, errbufsize);
|
||||||
|
}
|
||||||
|
|
||||||
extlang_t extlang_python =
|
extlang_t extlang_python =
|
||||||
{
|
{
|
||||||
sizeof(extlang_t),
|
sizeof(extlang_t),
|
||||||
@ -364,7 +472,9 @@ extlang_t extlang_python =
|
|||||||
"Python",
|
"Python",
|
||||||
IDAPython_extlang_compile,
|
IDAPython_extlang_compile,
|
||||||
IDAPython_extlang_run,
|
IDAPython_extlang_run,
|
||||||
IDAPython_extlang_calcexpr
|
IDAPython_extlang_calcexpr,
|
||||||
|
IDAPython_extlang_compile_file,
|
||||||
|
"py"
|
||||||
};
|
};
|
||||||
|
|
||||||
void enable_extlang_python(bool enable)
|
void enable_extlang_python(bool enable)
|
||||||
@ -452,7 +562,7 @@ bool IDAPython_Init(void)
|
|||||||
/* Init the SWIG wrapper */
|
/* Init the SWIG wrapper */
|
||||||
init_idaapi();
|
init_idaapi();
|
||||||
|
|
||||||
sprintf(tmp, "IDAPYTHON_VERSION=(%d, %d, %d, '%s', %d)", \
|
qsnprintf(tmp, sizeof(tmp), "IDAPYTHON_VERSION=(%d, %d, %d, '%s', %d)", \
|
||||||
VER_MAJOR,
|
VER_MAJOR,
|
||||||
VER_MINOR,
|
VER_MINOR,
|
||||||
VER_PATCH,
|
VER_PATCH,
|
||||||
@ -491,7 +601,7 @@ bool IDAPython_Init(void)
|
|||||||
|
|
||||||
/* Add menu items for all the functions */
|
/* Add menu items for all the functions */
|
||||||
/* Different paths are used for the GUI version */
|
/* Different paths are used for the GUI version */
|
||||||
result = add_menu_item("File/IDC command...", "P~y~thon command...",
|
add_menu_item("File/IDC command...", "P~y~thon command...",
|
||||||
"Alt-8", SETMENU_APP,
|
"Alt-8", SETMENU_APP,
|
||||||
(menu_item_callback_t *)IDAPython_Menu_Callback,
|
(menu_item_callback_t *)IDAPython_Menu_Callback,
|
||||||
(void *)IDAPYTHON_RUNSTATEMENT);
|
(void *)IDAPYTHON_RUNSTATEMENT);
|
||||||
|
Loading…
Reference in New Issue
Block a user