mirror of
https://github.com/rizinorg/rz-lang.git
synced 2026-11-08 17:47:38 -10:00
317 lines
7.2 KiB
C
317 lines
7.2 KiB
C
// SPDX-FileCopyrightText: 2009-2019 pancake <[email protected]>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include "python/common.h"
|
|
#include "python/core.h"
|
|
#include "python/io.h"
|
|
#include "python/asm.h"
|
|
#include "python/analysis.h"
|
|
#include "python/bin.h"
|
|
|
|
#define PLUGIN_NAME rz_lang_plugin_python
|
|
|
|
RzCore *core;
|
|
|
|
typedef struct {
|
|
const char *type;
|
|
PyObject *(*handler)(Rizin *, PyObject *);
|
|
} RzPlugins;
|
|
|
|
RzPlugins plugins[] = {
|
|
{ "asm", &Rizin_plugin_asm },
|
|
{ "analysis", &Rizin_plugin_analysis },
|
|
{ "bin", &Rizin_plugin_bin },
|
|
{ "io", &Rizin_plugin_io },
|
|
{ NULL }
|
|
};
|
|
|
|
static int run(RzLang *lang, const char *code, int len) {
|
|
core = (RzCore *)lang->user;
|
|
PyRun_SimpleString(code);
|
|
return true;
|
|
}
|
|
|
|
static int slurp_python(const char *file) {
|
|
FILE *fd = rz_sys_fopen(file, "r");
|
|
if (fd) {
|
|
PyRun_SimpleFile(fd, file);
|
|
fclose(fd);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static int run_file(struct rz_lang_t *lang, const char *file) {
|
|
return slurp_python(file);
|
|
}
|
|
|
|
static char *py_nullstr = "";
|
|
|
|
static void Rizin_dealloc(Rizin *self) {
|
|
Py_XDECREF(self->first);
|
|
Py_XDECREF(self->last);
|
|
// self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
static PyObject *Rizin_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
|
Rizin *self = (Rizin *)type->tp_alloc(type, 0);
|
|
if (self) {
|
|
self->first = PyUnicode_FromString("");
|
|
if (!self->first) {
|
|
Py_DECREF(self);
|
|
return NULL;
|
|
}
|
|
self->last = PyUnicode_FromString("");
|
|
if (!self->last) {
|
|
Py_DECREF(self);
|
|
return NULL;
|
|
}
|
|
self->number = 0;
|
|
}
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
static PyObject *Rizin_plugin(Rizin *self, PyObject *args) {
|
|
char *type = NULL;
|
|
void *cb = NULL;
|
|
int i;
|
|
|
|
if (!PyArg_ParseTuple(args, "sO", &type, &cb)) {
|
|
return Py_False;
|
|
}
|
|
if (!PyCallable_Check(cb)) {
|
|
PyErr_SetString(PyExc_TypeError, "second parameter must be callable");
|
|
return Py_False;
|
|
}
|
|
for (i = 0; plugins[i].type; i++) {
|
|
if (!strcmp(type, plugins[i].type)) {
|
|
return plugins[i].handler(self, cb);
|
|
}
|
|
}
|
|
eprintf("TODO: rzlang.plugin does not supports '%s' plugins yet\n", type);
|
|
return Py_False;
|
|
}
|
|
|
|
static PyObject *Rizin_cmd(Rizin *self, PyObject *args) {
|
|
char *str, *cmd = NULL;
|
|
if (!PyArg_ParseTuple(args, "s", &cmd)) {
|
|
return NULL;
|
|
}
|
|
str = rz_core_cmd_str(core, cmd);
|
|
return PyUnicode_FromString(str ? str : py_nullstr);
|
|
}
|
|
|
|
static int Rizin_init(Rizin *self, PyObject *args, PyObject *kwds) {
|
|
static char *kwlist[] = { "first", "last", "number", NULL };
|
|
PyObject *first = NULL, *last = NULL, *tmp;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi",
|
|
(char **)kwlist, &first, &last, &self->number)) {
|
|
return -1;
|
|
}
|
|
if (first) {
|
|
tmp = self->first;
|
|
Py_INCREF(first);
|
|
self->first = first;
|
|
Py_XDECREF(tmp);
|
|
}
|
|
if (last) {
|
|
tmp = self->last;
|
|
Py_INCREF(last);
|
|
self->last = last;
|
|
Py_XDECREF(tmp);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static PyMemberDef Rizin_members[] = {
|
|
{ "first", T_OBJECT_EX, offsetof(Rizin, first), 0, "first name" },
|
|
{ "last", T_OBJECT_EX, offsetof(Rizin, last), 0, "last name" },
|
|
{ "number", T_INT, offsetof(Rizin, number), 0, "noddy number" },
|
|
{ NULL } /* Sentinel */
|
|
};
|
|
|
|
static PyMethodDef Rizin_methods[] = {
|
|
{ "cmd", (PyCFunction)Rizin_cmd, METH_VARARGS,
|
|
"Executes a rizin command and returns a string" },
|
|
{ "plugin", (PyCFunction)Rizin_plugin, METH_VARARGS,
|
|
"Register plugins in rizin" },
|
|
{ NULL } /* Sentinel */
|
|
};
|
|
|
|
static PyTypeObject RizinType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0) "rizin.RizinInternal", /*tp_name*/
|
|
sizeof(Rizin), /*tp_basicsize*/
|
|
0, /*tp_itemsize*/
|
|
(destructor)Rizin_dealloc, /*tp_dealloc*/
|
|
0, /*tp_print*/
|
|
0, /*tp_getattr*/
|
|
0, /*tp_setattr*/
|
|
0, /*tp_compare*/
|
|
0, /*tp_repr*/
|
|
0, /*tp_as_number*/
|
|
0, /*tp_as_sequence*/
|
|
0, /*tp_as_mapping*/
|
|
0, /*tp_hash */
|
|
0, /*tp_call*/
|
|
0, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
0, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
|
"Rizin objects", /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
Rizin_methods, /* tp_methods */
|
|
Rizin_members, /* tp_members */
|
|
0, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)Rizin_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
Rizin_new, /* tp_new */
|
|
};
|
|
|
|
/*
|
|
SEE
|
|
static PyMethodDef EmbMethods[] = {
|
|
{"numargs", emb_numargs, METH_VARARGS,
|
|
"Return the number of arguments received by the process."},
|
|
{NULL, NULL, 0, NULL}
|
|
};
|
|
*/
|
|
|
|
static PyModuleDef EmbModule = {
|
|
PyModuleDef_HEAD_INIT,
|
|
"rzlang",
|
|
NULL, -1, Rizin_methods,
|
|
NULL, NULL, NULL, NULL
|
|
};
|
|
|
|
static PyObject *init_rizin_module(void) {
|
|
if (PyType_Ready(&RizinType) < 0) {
|
|
return NULL;
|
|
}
|
|
RizinType.tp_dict = PyDict_New();
|
|
py_export_analysis_enum(RizinType.tp_dict);
|
|
py_export_asm_enum(RizinType.tp_dict);
|
|
PyObject *m = PyModule_Create(&EmbModule);
|
|
if (!m) {
|
|
eprintf("Cannot create python3 rz module\n");
|
|
return NULL;
|
|
}
|
|
Py_INCREF(&RizinType);
|
|
PyModule_AddObject(m, "RZ", (PyObject *)&RizinType);
|
|
return m;
|
|
}
|
|
|
|
/* -init- */
|
|
|
|
static int init(RzLang *user);
|
|
static bool setup(RzLang *user);
|
|
|
|
static int prompt(void *user) {
|
|
return !PyRun_SimpleString(
|
|
"rz = None\n"
|
|
"try:\n"
|
|
" import rzlang\n"
|
|
" import rzpipe\n"
|
|
" rz = rzpipe.open()\n"
|
|
" import IPython\n"
|
|
" IPython.embed()\n"
|
|
"except:\n"
|
|
" raise Exception(\"Cannot find IPython\")\n");
|
|
}
|
|
|
|
static bool setup(RzLang *lang) {
|
|
RzListIter *iter;
|
|
RzLangDef *def;
|
|
char cmd[128];
|
|
// Segfault if already initialized ?
|
|
PyRun_SimpleString(
|
|
"try:\n"
|
|
" from rz.rz_core import RzCore\n"
|
|
"except:\n"
|
|
" pass\n");
|
|
PyRun_SimpleString("import rzpipe");
|
|
core = lang->user;
|
|
rz_list_foreach (lang->defs, iter, def) {
|
|
if (!def->type || !def->name) {
|
|
continue;
|
|
}
|
|
if (!strcmp(def->type, "int"))
|
|
snprintf(cmd, sizeof(cmd), "%s=%d", def->name, (int)(size_t)def->value);
|
|
else if (!strcmp(def->type, "string"))
|
|
snprintf(cmd, sizeof(cmd), "%s=\"%s\"", def->name, (char *)def->value);
|
|
else
|
|
snprintf(cmd, sizeof(cmd),
|
|
"try:\n"
|
|
" %s=%s.ncast(%p)\n"
|
|
"except:\n"
|
|
" pass",
|
|
def->name, def->type, def->value);
|
|
PyRun_SimpleString(cmd);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int init(RzLang *lang) {
|
|
if (lang) {
|
|
core = lang->user;
|
|
}
|
|
// DO NOT INITIALIZE MODULE IF ALREADY INITIALIZED
|
|
if (Py_IsInitialized()) {
|
|
return 0;
|
|
}
|
|
PyImport_AppendInittab("rzlang", init_rizin_module);
|
|
PyImport_AppendInittab("binfile", init_pybinfile_module);
|
|
Py_Initialize();
|
|
// Add a current directory to the PYTHONPATH
|
|
PyObject *sys = PyImport_ImportModule("sys");
|
|
PyObject *path = PyObject_GetAttrString(sys, "path");
|
|
PyList_Append(path, PyUnicode_FromString("."));
|
|
return true;
|
|
}
|
|
|
|
static int fini(void *user) {
|
|
#if (PY_MAJOR_VERSION >= 3) && (PY_MINOR_VERSION >= 6)
|
|
return Py_FinalizeEx() ? false : true;
|
|
#else
|
|
Py_Finalize();
|
|
return true;
|
|
#endif
|
|
}
|
|
|
|
static const char *help =
|
|
" print rz.cmd(\"p8 10\");\n";
|
|
|
|
RzLangPlugin PLUGIN_NAME = {
|
|
.name = "python",
|
|
.alias = "python",
|
|
.ext = "py",
|
|
.desc = "Python language extension",
|
|
.license = "LGPL",
|
|
.init = &init,
|
|
.setup = &setup,
|
|
.fini = (void *)&fini,
|
|
.help = &help,
|
|
.prompt = (void *)&prompt,
|
|
.run = &run,
|
|
.run_file = &run_file,
|
|
};
|
|
|
|
#if !CORELIB
|
|
RzLibStruct rizin_plugin = {
|
|
.type = RZ_LIB_TYPE_LANG,
|
|
.data = &PLUGIN_NAME,
|
|
.version = RZ_VERSION
|
|
};
|
|
#endif
|