From 5060f746a2ea51e14282b02bd374f9550c925827 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Fri, 29 May 2020 01:29:24 +0200 Subject: Updated the Python bindings for targetable operands. --- plugins/pychrysalide/arch/operands/rename.c | 6 +- plugins/pychrysalide/arch/operands/targetable.c | 197 +++++++++++++++++++++++- plugins/pychrysalide/arch/operands/targetable.h | 3 + 3 files changed, 199 insertions(+), 7 deletions(-) diff --git a/plugins/pychrysalide/arch/operands/rename.c b/plugins/pychrysalide/arch/operands/rename.c index 7a5be98..60985db 100644 --- a/plugins/pychrysalide/arch/operands/rename.c +++ b/plugins/pychrysalide/arch/operands/rename.c @@ -441,12 +441,14 @@ static GRenamedOperand *py_renameable_operand_build_wrapper(const GRenameableOpe if (ret == 1) g_object_ref(G_OBJECT(result)); - Py_DECREF(pyret); + PyErr_Clear(); - Py_DECREF(args); + Py_DECREF(pyret); } + Py_DECREF(args); + } Py_DECREF(pyobj); diff --git a/plugins/pychrysalide/arch/operands/targetable.c b/plugins/pychrysalide/arch/operands/targetable.c index d686bcf..78a4617 100644 --- a/plugins/pychrysalide/arch/operands/targetable.c +++ b/plugins/pychrysalide/arch/operands/targetable.c @@ -28,7 +28,7 @@ #include -#include +#include #include "../processor.h" @@ -39,18 +39,151 @@ +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Procède à l'initialisation de l'interface pour ciblage. */ +static void py_targetable_operand_init(GTargetableOperandIface *, gpointer *); + +/* Obtient l'adresse de la cible visée par un opérande. */ +static bool py_targetable_operand_get_addr_wrapper(const GTargetableOperand *, const vmpa2t *, GBinFormat *, GArchProcessor *, vmpa2t *); + + + +/* ------------------------ INTERFACE POUR OPERANDE CIBLABLE ------------------------ */ + + +/* Obtient l'adresse de la cible visée par un opérande. */ +static PyObject *py_targetable_operand_get_addr(PyObject *, PyObject *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* unused = adresse non utilisée ici. * +* * +* Description : Procède à l'initialisation de l'interface pour ciblage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_targetable_operand_init(GTargetableOperandIface *iface, gpointer *unused) +{ + #define TARGETABLE_OPERAND_DOC \ "The TargetableOperand interface depicts operands which can drive to" \ " another location.\n" \ "\n" \ "By instance, an immediate value can target a given address into" \ - " some function code." + " some function code." \ + "\n" \ + "A typical class declaration for a new implementation looks like:\n" \ + "\n" \ + " class NewImplem(GObject.Object, RenamedOperand):\n" \ + " ...\n" \ + "\n" \ + "The following method has to be defined for new implementations:\n" \ + "* pychrysalide.arch.operands.RenamedOperand._get_addr();\n" \ + iface->get_addr = py_targetable_operand_get_addr_wrapper; +} -/* Obtient l'adresse de la cible visée par un opérande. */ -static PyObject *py_targetable_operand_get_addr(PyObject *, PyObject *); +/****************************************************************************** +* * +* Paramètres : operand = operande à consulter. * +* src = localisation de l'instruction mère. * +* format = format reconnu pour le binaire chargé. * +* proc = architecture associée à ce même binaire. * +* addr = localisation de la cible. [OUT] * +* * +* Description : Obtient l'adresse de la cible visée par un opérande. * +* * +* Retour : true si la cible est valide, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_targetable_operand_get_addr_wrapper(const GTargetableOperand *operand, const vmpa2t *src, GBinFormat *format, GArchProcessor *proc, vmpa2t *addr) +{ + bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyret; /* Bilan de consultation */ + int ret; /* Bilan d'une conversion */ + +#define TARGETABLE_OPERAND_GET_ADDR_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _get_addr, "$self, src, format, proc", \ + METH_VARARGS, \ + "Abstract method used to compute a target address from an operand." \ + "\n" \ + "The *src* argument is the location of the instruction owning the" \ + " operand, as a pychrysalide.arch.vmpa instance. The format is a" \ + " pychrysalide.format.BinFormat instance, providing all needed" \ + " information and the processor is a" \ + " pychrysalide.arch.ArchProcessor instance, providing all needed" \ + " information too.\n" \ + "\n" \ + "The result has to be a pychrysalide.arch.vmpa address or None." \ +) + + result = false; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(operand)); + + if (has_python_method(pyobj, "_get_addr")) + { + args = PyTuple_New(3); + PyTuple_SetItem(args, 0, build_from_internal_vmpa(src)); + PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(format))); + PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(proc))); + + pyret = run_python_method(pyobj, "_get_addr", NULL); + + if (pyret != NULL) + { + ret = convert_any_to_vmpa(pyret, addr); + + result = (ret == 1); + + PyErr_Clear(); + + Py_DECREF(pyret); + + } + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* INTERFACE POUR OPERANDE CIBLABLE */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** @@ -134,6 +267,7 @@ static PyObject *py_targetable_operand_get_addr(PyObject *self, PyObject *args) PyTypeObject *get_python_targetable_operand_type(void) { static PyMethodDef py_targetable_operand_methods[] = { + TARGETABLE_OPERAND_GET_ADDR_WRAPPER, TARGETABLE_OPERAND_GET_ADDR_METHOD, { NULL } }; @@ -181,6 +315,14 @@ bool ensure_python_targetable_operand_is_registered(void) PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ + static GInterfaceInfo info = { /* Paramètres d'inscription */ + + .interface_init = (GInterfaceInitFunc)py_targetable_operand_init, + .interface_finalize = NULL, + .interface_data = NULL, + + }; + type = get_python_targetable_operand_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) @@ -189,7 +331,7 @@ bool ensure_python_targetable_operand_is_registered(void) dict = PyModule_GetDict(module); - if (!register_interface_for_pygobject(dict, G_TYPE_TARGETABLE_OPERAND, type)) + if (!register_interface_for_pygobject_2(dict, G_TYPE_TARGETABLE_OPERAND, type, &info)) return false; } @@ -197,3 +339,48 @@ bool ensure_python_targetable_operand_is_registered(void) return true; } + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en opérande ciblable. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_targetable_operand(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_targetable_operand_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to targetable operand"); + break; + + case 1: + *((GTargetableOperand **)dst) = G_TARGETABLE_OPERAND(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/arch/operands/targetable.h b/plugins/pychrysalide/arch/operands/targetable.h index eaa05d2..26d13b9 100644 --- a/plugins/pychrysalide/arch/operands/targetable.h +++ b/plugins/pychrysalide/arch/operands/targetable.h @@ -37,6 +37,9 @@ PyTypeObject *get_python_targetable_operand_type(void); /* Prend en charge l'objet 'pychrysalide.arch.TargetableOperand'. */ bool ensure_python_targetable_operand_is_registered(void); +/* Tente de convertir en opérande ciblable. */ +int convert_to_targetable_operand(PyObject *, void *); + #endif /* _PLUGINS_PYCHRYSALIDE_ARCH_OPERANDS_TARGETABLE_H */ -- cgit v0.11.2-87-g4458