summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/arch
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-05-28 23:29:24 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-05-28 23:29:32 (GMT)
commit5060f746a2ea51e14282b02bd374f9550c925827 (patch)
tree5cfd195d09568f13f919cbe060f8cf253eda4ed2 /plugins/pychrysalide/arch
parentce174b991223c85afba55a24e7adc9c8156f7d48 (diff)
Updated the Python bindings for targetable operands.
Diffstat (limited to 'plugins/pychrysalide/arch')
-rw-r--r--plugins/pychrysalide/arch/operands/rename.c6
-rw-r--r--plugins/pychrysalide/arch/operands/targetable.c197
-rw-r--r--plugins/pychrysalide/arch/operands/targetable.h3
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 <pygobject.h>
-#include <arch/operands/targetable.h>
+#include <arch/operands/targetable-int.h>
#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 */