diff options
Diffstat (limited to 'plugins/pychrysalide/arch')
-rw-r--r-- | plugins/pychrysalide/arch/processor.c | 10 | ||||
-rw-r--r-- | plugins/pychrysalide/arch/register.c | 407 |
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, |