summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/arch
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-04-28 21:44:18 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-04-28 21:44:18 (GMT)
commit2e867fcae6e91594ae47528ca097952398ffcca4 (patch)
treec3897d1f27ab3f4f5813a570e7fb0f6988466e7f /plugins/pychrysalide/arch
parent4d370b81498fc93e0199232110e9edeb526fd53b (diff)
Extended the Python bindings for registers.
Diffstat (limited to 'plugins/pychrysalide/arch')
-rw-r--r--plugins/pychrysalide/arch/processor.c10
-rw-r--r--plugins/pychrysalide/arch/register.c407
2 files changed, 393 insertions, 24 deletions
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c
index 37f97a4..557e7a7 100644
--- a/plugins/pychrysalide/arch/processor.c
+++ b/plugins/pychrysalide/arch/processor.c
@@ -677,6 +677,8 @@ static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProces
PyObject *pyins; /* Instruction en objet Python */
int ret; /* Bilan d'une conversion */
+ result = NULL;
+
gstate = PyGILState_Ensure();
pyobj = pygobject_new(G_OBJECT(proc));
@@ -696,10 +698,7 @@ static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProces
Py_DECREF(args);
- if (pyins == NULL)
- result = NULL;
-
- else
+ if (pyins != NULL)
{
ret = convert_to_arch_instruction(pyins, &result);
@@ -721,9 +720,6 @@ static GArchInstruction *py_arch_processor_disassemble_wrapper(const GArchProces
}
- else
- result = NULL;
-
PyGILState_Release(gstate);
return result;
diff --git a/plugins/pychrysalide/arch/register.c b/plugins/pychrysalide/arch/register.c
index 7ecdb0e..84d3180 100644
--- a/plugins/pychrysalide/arch/register.c
+++ b/plugins/pychrysalide/arch/register.c
@@ -48,17 +48,35 @@ static PyObject *py_arch_register_new(PyTypeObject *, PyObject *, PyObject *);
/* Initialise la classe des descriptions de fichier binaire. */
static void py_arch_register_init_gclass(GArchRegisterClass *, gpointer);
+/* Produit une empreinte à partir d'un registre. */
+static guint py_arch_register___hash___wrapper(const GArchRegister *);
+
+/* Compare un registre avec un autre. */
+static int py_arch_register___cmp___wrapper(const GArchRegister *, const GArchRegister *);
+
+/* Traduit un registre en version humainement lisible. */
+static void py_arch_register_print_wrapper(const GArchRegister *, GBufferLine *);
+
/* Indique si le registre correspond à ebp ou similaire. */
-static bool g_arch_register_is_base_pointer_wrapper(const GArchRegister *);
+static bool py_arch_register_is_base_pointer_wrapper(const GArchRegister *);
+
+/* Indique si le registre correspond à esp ou similaire. */
+static bool py_arch_register_is_stack_pointer_wrapper(const GArchRegister *);
/* ---------------------------- PUR REGISTRE DU MATERIEL ---------------------------- */
+/* Effectue une comparaison avec un objet Python 'ArchRegister'. */
+static PyObject *py_arch_register_richcompare(PyObject *, PyObject *, int);
+
/* Indique si le registre correspond à ebp ou similaire. */
static PyObject *py_arch_register_is_base_pointer(PyObject *, void *);
+/* Indique si le registre correspond à esp ou similaire. */
+static PyObject *py_arch_register_is_stack_pointer(PyObject *, void *);
+
/* ---------------------------------------------------------------------------------- */
@@ -88,6 +106,23 @@ static PyObject *py_arch_register_new(PyTypeObject *type, PyObject *args, PyObje
GType gtype; /* Nouveau type de registre */
bool status; /* Bilan d'un enregistrement */
+#define ARCH_REGISTER_DOC \
+ "The ArchRegister object aims to get subclassed to create" \
+ " registers suitable for new architectures.\n" \
+ "\n" \
+ "Calls to the *__init__* constructor of this abstract object expect"\
+ " no particular argument.\n" \
+ "\n" \
+ "The following methods have to be defined for new classes:\n" \
+ "* pychrysalide.arch.ArchRegister.__hash__();\n" \
+ "* pychrysalide.arch.ArchRegister.__cmp__();\n" \
+ "* pychrysalide.arch.ArchRegister._print();\n" \
+ "* pychrysalide.arch.ArchRegister._is_base_pointer();\n" \
+ "* pychrysalide.arch.ArchRegister._is_stack_pointer().\n" \
+ "\n" \
+ "Chrysalide creates an internal glue to provide rich comparisons" \
+ " for registers based on the old-style *__cmp__* function."
+
/* Validations diverses */
base = get_python_arch_register_type();
@@ -144,7 +179,182 @@ static PyObject *py_arch_register_new(PyTypeObject *type, PyObject *args, PyObje
static void py_arch_register_init_gclass(GArchRegisterClass *class, gpointer unused)
{
- class->is_bp = g_arch_register_is_base_pointer_wrapper;
+ class->hash = py_arch_register___hash___wrapper;
+ class->compare = py_arch_register___cmp___wrapper;
+ class->print = py_arch_register_print_wrapper;
+ class->is_bp = py_arch_register_is_base_pointer_wrapper;
+ class->is_sp = py_arch_register_is_stack_pointer_wrapper;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : reg = registre visé par la procédure. *
+* *
+* Description : Produit une empreinte à partir d'un registre. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static guint py_arch_register___hash___wrapper(const GArchRegister *reg)
+{
+ guint result; /* Empreinte à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define ARCH_REGISTER_HASH_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ __hash__, "$self, /", \
+ METH_NOARGS, \
+ "Abstract method used to produce a hash of the object. The" \
+ " result must be an integer value." \
+)
+
+ result = 0;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(reg));
+
+ if (has_python_method(pyobj, "__hash__"))
+ {
+ pyret = run_python_method(pyobj, "__hash__", NULL);
+
+ if (pyret != NULL)
+ {
+ if (PyLong_Check(pyret))
+ result = PyLong_AsUnsignedLong(pyret);
+
+ Py_DECREF(pyret);
+
+ }
+
+ }
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* *
+* Description : Compare un registre avec un autre. *
+* *
+* Retour : Bilan de la comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_arch_register___cmp___wrapper(const GArchRegister *a, const GArchRegister *b)
+{
+ int result; /* Empreinte à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define ARCH_REGISTER_CMP_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ __cmp__, "$self, other, /", \
+ METH_VARARGS, \
+ "Abstract method used to produce a compare the register" \
+ " with another one. This second object is always an" \
+ " pychrysalide.arch.ArchRegister instance.\n" \
+ "\n" \
+ " This is the old-style comparison method, but Chrysalide" \
+ " provides a glue to automatically build a rich version of" \
+ " this function." \
+)
+
+ result = 0;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(a));
+
+ if (has_python_method(pyobj, "__cmp__"))
+ {
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(b)));
+
+ pyret = run_python_method(pyobj, "__cmp__", args);
+
+ if (pyret != NULL)
+ {
+ if (PyLong_Check(pyret))
+ result = PyLong_AsLong(pyret);
+ }
+
+ Py_DECREF(args);
+
+ Py_XDECREF(pyret);
+
+ }
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : reg = registre visé par la procédure. *
+* *
+* Description : Traduit un registre en version humainement lisible. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_arch_register_print_wrapper(const GArchRegister *reg, GBufferLine *line)
+{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define ARCH_REGISTER_PRINT_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _print, "$self, line, /", \
+ METH_VARARGS, \
+ "Abstract method used to print the register into a rendering" \
+ " line, which is a provided pychrysalide.glibext.BufferLine" \
+ " instance." \
+)
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(reg));
+
+ if (has_python_method(pyobj, "_print"))
+ {
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(line)));
+
+ pyret = run_python_method(pyobj, "_print", args);
+
+ Py_DECREF(args);
+
+ Py_XDECREF(pyret);
+
+ }
+
+ PyGILState_Release(gstate);
}
@@ -161,21 +371,96 @@ static void py_arch_register_init_gclass(GArchRegisterClass *class, gpointer unu
* *
******************************************************************************/
-static bool g_arch_register_is_base_pointer_wrapper(const GArchRegister *reg)
+static bool py_arch_register_is_base_pointer_wrapper(const GArchRegister *reg)
+{
+ bool result; /* Bilan à renvoyer */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define ARCH_REGISTER_IS_BASE_POINTER_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _is_base_pointer, "$self, /", \
+ METH_NOARGS, \
+ "Abstract method used to tell if the register is handling a" \
+ " base pointer. The result must be a boolean value." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(reg));
+
+ if (has_python_method(pyobj, "_is_base_pointer"))
+ {
+ pyret = run_python_method(pyobj, "_is_base_pointer", NULL);
+
+ if (pyret != NULL)
+ {
+ result = (pyret == Py_True);
+
+ Py_DECREF(pyret);
+
+ }
+
+ }
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : reg = registre visé par la procédure. *
+* *
+* Description : Indique si le registre correspond à esp ou similaire. *
+* *
+* Retour : true si la correspondance est avérée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_arch_register_is_stack_pointer_wrapper(const GArchRegister *reg)
{
bool result; /* Bilan à renvoyer */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
PyObject *pyret; /* Bilan de consultation */
+#define ARCH_REGISTER_IS_STACK_POINTER_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _is_stack_pointer, "$self, /", \
+ METH_NOARGS, \
+ "Abstract method used to tell if the register is handling a" \
+ " stack pointer. The result must be a boolean value." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
pyobj = pygobject_new(G_OBJECT(reg));
- assert(has_python_method(pyobj, "_is_base_pointer"));
+ if (has_python_method(pyobj, "_is_stack_pointer"))
+ {
+ pyret = run_python_method(pyobj, "_is_stack_pointer", NULL);
+
+ if (pyret != NULL)
+ {
+ result = (pyret == Py_True);
- pyret = run_python_method(pyobj, "_is_base_pointer", NULL);
+ Py_DECREF(pyret);
- result = (pyret == Py_True);
+ }
+
+ }
- Py_XDECREF(pyret);
+ PyGILState_Release(gstate);
return result;
@@ -190,6 +475,51 @@ static bool g_arch_register_is_base_pointer_wrapper(const GArchRegister *reg)
/******************************************************************************
* *
+* Paramètres : a = premier object Python à consulter. *
+* b = second object Python à consulter. *
+* op = type de comparaison menée. *
+* *
+* Description : Effectue une comparaison avec un objet Python 'ArchRegister'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_register_richcompare(PyObject *a, PyObject *b, int op)
+{
+ PyObject *result; /* Bilan à retourner */
+ int ret; /* Bilan de lecture des args. */
+ const GArchRegister *reg_a; /* Premier élément à traiter */
+ const GArchRegister *reg_b; /* Second élément à traiter */
+ int status; /* Résultat d'une comparaison */
+
+ ret = PyObject_IsInstance(b, (PyObject *)get_python_arch_register_type());
+ if (!ret)
+ {
+ result = Py_NotImplemented;
+ goto cmp_done;
+ }
+
+ reg_a = G_ARCH_REGISTER(pygobject_get(a));
+ reg_b = G_ARCH_REGISTER(pygobject_get(b));
+
+ status = py_arch_register___cmp___wrapper(reg_a, reg_b);
+
+ result = status_to_rich_cmp_state(status, op);
+
+ cmp_done:
+
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
@@ -207,6 +537,12 @@ static PyObject *py_arch_register_is_base_pointer(PyObject *self, void *closure)
GArchRegister *reg; /* Registre visé */
bool status; /* Bilan de consultation */
+#define ARCH_REGISTER_IS_BASE_POINTER_ATTRIB PYTHON_IS_DEF_FULL \
+( \
+ base_pointer, py_arch_register, \
+ "Tell if the register is a base pointer or not." \
+)
+
reg = G_ARCH_REGISTER(pygobject_get(self));
status = g_arch_register_is_base_pointer(reg);
@@ -221,6 +557,43 @@ static PyObject *py_arch_register_is_base_pointer(PyObject *self, void *closure)
/******************************************************************************
* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique si le registre correspond à esp ou similaire. *
+* *
+* Retour : True si la correspondance est avérée, False sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_register_is_stack_pointer(PyObject *self, void *closure)
+{
+ PyObject *result; /* Instance Python à retourner */
+ GArchRegister *reg; /* Registre visé */
+ bool status; /* Bilan de consultation */
+
+#define ARCH_REGISTER_IS_STACK_POINTER_ATTRIB PYTHON_IS_DEF_FULL \
+( \
+ stack_pointer, py_arch_register, \
+ "Tell if the register is a stack pointer or not." \
+)
+
+ reg = G_ARCH_REGISTER(pygobject_get(self));
+
+ status = g_arch_register_is_stack_pointer(reg);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : - *
* *
* Description : Fournit un accès à une définition de type à diffuser. *
@@ -234,19 +607,17 @@ static PyObject *py_arch_register_is_base_pointer(PyObject *self, void *closure)
PyTypeObject *get_python_arch_register_type(void)
{
static PyMethodDef py_arch_register_methods[] = {
- {
- "_is_base_pointer", not_yet_implemented_method,
- METH_NOARGS,
- "_is_base_pointer($self, /)\n--\n\nDefine an implementation to provide the relative member value."
- },
+ ARCH_REGISTER_HASH_WRAPPER,
+ ARCH_REGISTER_CMP_WRAPPER,
+ ARCH_REGISTER_PRINT_WRAPPER,
+ ARCH_REGISTER_IS_BASE_POINTER_WRAPPER,
+ ARCH_REGISTER_IS_STACK_POINTER_WRAPPER,
{ NULL }
};
static PyGetSetDef py_arch_register_getseters[] = {
- {
- "is_base_pointer", py_arch_register_is_base_pointer, NULL,
- "Tell if the register is a base pointer or not.", NULL
- },
+ ARCH_REGISTER_IS_BASE_POINTER_ATTRIB,
+ ARCH_REGISTER_IS_STACK_POINTER_ATTRIB,
{ NULL }
};
@@ -259,7 +630,9 @@ PyTypeObject *get_python_arch_register_type(void)
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
- .tp_doc = "PyChrysalide register for a given architecture.",
+ .tp_doc = ARCH_REGISTER_DOC,
+
+ .tp_richcompare = py_arch_register_richcompare,
.tp_methods = py_arch_register_methods,
.tp_getset = py_arch_register_getseters,