summaryrefslogtreecommitdiff
path: root/plugins/pychrysa/arch/processor.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pychrysa/arch/processor.c')
-rw-r--r--plugins/pychrysa/arch/processor.c342
1 files changed, 233 insertions, 109 deletions
diff --git a/plugins/pychrysa/arch/processor.c b/plugins/pychrysa/arch/processor.c
index 6a275d4..0a9ae3a 100644
--- a/plugins/pychrysa/arch/processor.c
+++ b/plugins/pychrysa/arch/processor.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * processor.h - prototypes pour l'équivalent Python du fichier "arch/processor.h"
+ * processor.c - équivalent Python du fichier "arch/processor.c"
*
- * Copyright (C) 2010-2013 Cyrille Bagard
+ * Copyright (C) 2015 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,22 +25,21 @@
#include "processor.h"
-#include "../../../src/arch/processor.h"
+#include <pygobject.h>
+#include <i18n.h>
-/* ------------------------- TYPAGE DES ENUMERATIONS PYTHON ------------------------- */
+#include <arch/processor.h>
-/* Définit les constantes pour les types de processeur. */
-bool py_arch_processor_type_define_constants(PyObject *);
-/* Ajoute l'objet 'arch.processor.ArchProcessorType' au module. */
-bool add_arch_processor_type_to_python_module(PyObject *);
+#include "instruction.h"
+#include "vmpa.h"
+#include "../helpers.h"
-/* ------------------------- PARTIE STATIQUE DE PROCESSEURS ------------------------- */
@@ -48,12 +47,7 @@ bool add_arch_processor_type_to_python_module(PyObject *);
-/* Classe 'analysis.roptions' pour Python */
-typedef struct _py_processor
-{
- PyObject_HEAD
-} py_processor;
@@ -63,120 +57,246 @@ typedef struct _py_processor
+/* ------------------ MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES ------------------ */
+
+
+
+/* Fournit les instructions désassemblées pour une architecture. */
+static PyObject *py_arch_processor_get_disass_instrs(PyObject *, void *);
+
+/* Recherche une instruction d'après son adresse. */
+static PyObject *py_arch_processor_find_instr_by_addr(PyObject *, PyObject *);
+
+/* Fournit l'instruction qui en précède une autre. */
+static PyObject *py_arch_processor_get_prev_instr(PyObject *, PyObject *);
+
+/* Fournit l'instruction qui en suit une autre. */
+static PyObject *py_arch_processor_get_next_instr(PyObject *, PyObject *);
+
+
+
+
/* ---------------------------------------------------------------------------------- */
-/* TYPAGE DES ENUMERATIONS PYTHON */
+/* MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : dict = dictionnaire à compléter. *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
* *
-* Description : Définit les constantes pour les types de processeur. *
+* Description : Fournit les instructions désassemblées pour une architecture.*
* *
-* Retour : - *
+* Retour : Liste des instructions désassemblées ou None si aucune. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool py_arch_processor_type_define_constants(PyObject *dict)
+static PyObject *py_arch_processor_get_disass_instrs(PyObject *self, void *closure)
{
- int ret; /* Bilan d'un ajout */
+ PyObject *result; /* Instance Python à retourner */
+ GArchProcessor *proc; /* Architecture visée */
+ GArchInstruction *instrs; /* Série d'instructions liées */
- ret = PyDict_SetItemString(dict, "APT_JVM", PyInt_FromLong(APT_JVM));
- if (ret == -1) return false;
+ proc = G_ARCH_PROCESSOR(pygobject_get(self));
+ instrs = g_arch_processor_get_disassembled_instructions(proc);
- ret = PyDict_SetItemString(dict, "APT_MIPS", PyInt_FromLong(APT_MIPS));
- if (ret == -1) return false;
+ if (instrs != NULL)
+ result = pygobject_new(G_OBJECT(instrs));
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
- ret = PyDict_SetItemString(dict, "APT_386", PyInt_FromLong(APT_386));
- if (ret == -1) return false;
-
- ret = PyDict_SetItemString(dict, "APT_COUNT", PyInt_FromLong(APT_COUNT));
- if (ret == -1) return false;
-
- return true;
+ return result;
}
-PyObject *__test;
+
/******************************************************************************
* *
-* Paramètres : module = module dont la définition est à compléter. *
+* Paramètres : self = objet Python concerné par l'appel. *
+* value = valeur fournie à intégrer ou prendre en compte. *
+* closure = non utilisé ici. *
* *
-* Description : Ajoute l'objet 'arch.processor.ArchProcessorType' au module. *
+* Description : Note les instructions désassemblées avec une architecture. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération pour Python. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool add_arch_processor_type_to_python_module(PyObject *module)
+static int py_arch_processor_set_disass_instrs(PyObject *self, PyObject *value, void *closure)
{
- int ret; /* Bilan d'un appel */
+ GArchProcessor *proc; /* Architecture visée */
+ GArchInstruction *instrs; /* Série d'instructions liées */
- static PyTypeObject py_arch_processor_type_type = {
+ if (!PyObject_TypeCheck(value, get_python_arch_instruction_type()))
+ {
+ PyErr_SetString(PyExc_TypeError, _("The attribute value must be an instruction."));
+ return -1;
+ }
- PyObject_HEAD_INIT(NULL)
+ proc = G_ARCH_PROCESSOR(pygobject_get(self));
+ instrs = G_ARCH_INSTRUCTION(pygobject_get(value));
- .tp_name = "pyoida.arch.processor.ArchProcessorType",
+ g_arch_processor_set_disassembled_instructions(proc, instrs);
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ return 0;
- .tp_doc = "PyOIDA version of the ArchProcessorType enumeration",
+}
- };
- if (PyType_Ready(&py_arch_processor_type_type) < 0)
- return false;
+/******************************************************************************
+* *
+* Paramètres : self = processeur d'architecture à manipuler. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Recherche une instruction d'après son adresse. *
+* *
+* Retour : Instruction trouvée à l'adresse donnée, None si aucune. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_arch_processor_find_instr_by_addr(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ PyObject *addr_obj; /* Objet pour une localisation */
+ int ret; /* Bilan de lecture des args. */
+ GArchProcessor *proc; /* Processeur manipulé */
+ vmpa2t *addr; /* Localisation à retrouver */
+ GArchInstruction *found; /* Instruction liée trouvée */
+
+ ret = PyArg_ParseTuple(args, "O", &addr_obj);
+ if (!ret) return NULL;
+
+ ret = PyObject_IsInstance(addr_obj, (PyObject *)get_python_vmpa_type());
+ if (!ret) return NULL;
+
+ proc = G_ARCH_PROCESSOR(pygobject_get(self));
+ addr = get_internal_vmpa(addr_obj);
- py_arch_processor_type_define_constants(py_arch_processor_type_type.tp_dict);
+ found = g_arch_processor_find_instr_by_address(proc, addr);
- Py_INCREF(&py_arch_processor_type_type);
- ret = PyModule_AddObject(module, "ArchProcessorType", (PyObject *)&py_arch_processor_type_type);
+ if (found != NULL)
+ result = pygobject_new(G_OBJECT(found));
- __test = (PyObject *)&py_arch_processor_type_type;
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
- return (ret == 0);
+ return result;
}
+/******************************************************************************
+* *
+* Paramètres : self = processeur d'architecture à manipuler. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Fournit l'instruction qui en précède une autre. *
+* *
+* Retour : Instruction précédente trouvée, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
-/* ---------------------------------------------------------------------------------- */
-/* PARTIE STATIQUE DE PROCESSEURS */
-/* ---------------------------------------------------------------------------------- */
+static PyObject *py_arch_processor_get_prev_instr(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ PyObject *instr_obj; /* Objet pour une instruction */
+ int ret; /* Bilan de lecture des args. */
+ GArchProcessor *proc; /* Processeur manipulé */
+ GArchInstruction *instr; /* Instruction de référence */
+ GArchInstruction *found; /* Instruction liée trouvée */
+ ret = PyArg_ParseTuple(args, "O", &instr_obj);
+ if (!ret) return NULL;
+ ret = PyObject_IsInstance(instr_obj, (PyObject *)get_python_arch_instruction_type());
+ if (!ret) return NULL;
+ proc = G_ARCH_PROCESSOR(pygobject_get(self));
+ instr = G_ARCH_INSTRUCTION(pygobject_get(instr_obj));
+ found = g_arch_processor_get_prev_instr(proc, instr);
+ if (found != NULL)
+ result = pygobject_new(G_OBJECT(found));
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ return result;
+}
+/******************************************************************************
+* *
+* Paramètres : self = processeur d'architecture à manipuler. *
+* args = instruction représentant le point de départ. *
+* *
+* Description : Fournit l'instruction qui en suit une autre. *
+* *
+* Retour : Instruction suivante trouvée, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+static PyObject *py_arch_processor_get_next_instr(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ PyObject *instr_obj; /* Objet pour une instruction */
+ int ret; /* Bilan de lecture des args. */
+ GArchProcessor *proc; /* Processeur manipulé */
+ GArchInstruction *instr; /* Instruction de référence */
+ GArchInstruction *found; /* Instruction liée trouvée */
+ ret = PyArg_ParseTuple(args, "O", &instr_obj);
+ if (!ret) return NULL;
+ ret = PyObject_IsInstance(instr_obj, (PyObject *)get_python_arch_instruction_type());
+ if (!ret) return NULL;
+ proc = G_ARCH_PROCESSOR(pygobject_get(self));
+ instr = G_ARCH_INSTRUCTION(pygobject_get(instr_obj));
+ found = g_arch_processor_get_next_instr(proc, instr);
+ if (found != NULL)
+ result = pygobject_new(G_OBJECT(found));
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+ return result;
+}
-/* ---------------------------------------------------------------------------------- */
-/* PARTIE GRAPHIQUE DES [DE]CHARGEMENTS */
-/* ---------------------------------------------------------------------------------- */
@@ -186,103 +306,107 @@ bool add_arch_processor_type_to_python_module(PyObject *module)
-/* Crée un nouvel objet Python de type 'py_processor'. */
-static PyObject *py_processor_new(PyTypeObject *, PyObject *, PyObject *);
/******************************************************************************
* *
-* Paramètres : type = type de l'objet à instancier. *
-* args = arguments fournis à l'appel. *
-* kwds = arguments de type key=val fournis. *
+* Paramètres : - *
* *
-* Description : Crée un nouvel objet Python de type 'py_processor'. *
+* Description : Fournit un accès à une définition de type à diffuser. *
* *
-* Retour : - *
+* Retour : Définition d'objet pour Python. *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_processor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+PyTypeObject *get_python_arch_processor_type(void)
{
- py_processor *result; /* Instance à retourner */
-
- result = (py_processor *)type->tp_alloc(type, 0);
-
- return (PyObject *)result;
-
-}
-
-
+ static PyMethodDef py_arch_processor_methods[] = {
+ {
+ "find_instr_by_addr", py_arch_processor_find_instr_by_addr,
+ METH_VARARGS,
+ "find_instr_by_addr($self, addr, /)\n--\n\nLook for an instruction located at a given address."
+ },
+ {
+ "get_prev_instr", py_arch_processor_get_prev_instr,
+ METH_VARARGS,
+ "get_prev_instr($self, instr, /)\n--\n\nProvide the instruction preceding a given instruction."
+ },
+ {
+ "get_next_instr", py_arch_processor_get_next_instr,
+ METH_VARARGS,
+ "get_next_instr($self, instr, /)\n--\n\nProvide the instruction following a given instruction."
+ },
+ { NULL }
+ };
+ static PyGetSetDef py_arch_processor_getseters[] = {
+ {
+ "disass_instrs", py_arch_processor_get_disass_instrs, py_arch_processor_set_disass_instrs,
+ "Give access to the disassembled instructions run by the current processor.", NULL
+ },
+ { NULL }
+ };
+ static PyTypeObject py_arch_processor_type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "pychrysalide.arch.ArchProcessor",
+ .tp_basicsize = sizeof(PyGObject),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_BASETYPE,
+ .tp_doc = "PyChrysalide processor for a given architecture.",
+ .tp_methods = py_arch_processor_methods,
+ .tp_getset = py_arch_processor_getseters,
+ };
+ return &py_arch_processor_type;
+}
/******************************************************************************
* *
* Paramètres : module = module dont la définition est à compléter. *
* *
-* Description : Ajoute l'objet 'analysis.roptions' au module Python. *
+* Description : Prend en charge l'objet 'pychrysalide.arch.ArchProcessor'. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool add_arch_processor_to_python_module(PyObject *module)
+bool register_python_arch_processor(PyObject *module)
{
- bool result; /* Bilan à retourner */
+ PyTypeObject *py_arch_processor_type; /* Type Python 'BinContent' */
int ret; /* Bilan d'un appel */
+ PyObject *dict; /* Dictionnaire du module */
- static PyMethodDef py_processor_methods[] = {
- { NULL }
- };
-
- static PyGetSetDef py_processor_getset[] = {
- { NULL }
- };
-
- static PyTypeObject py_processor_type = {
+ py_arch_processor_type = get_python_arch_processor_type();
- PyObject_HEAD_INIT(NULL)
+ py_arch_processor_type->tp_base = &PyGObject_Type;
+ py_arch_processor_type->tp_basicsize = py_arch_processor_type->tp_base->tp_basicsize;
- .tp_name = "pyoida.arch.Processor",
- .tp_basicsize = sizeof(py_processor),
+ APPLY_ABSTRACT_FLAG(py_arch_processor_type);
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-
- .tp_doc = "PyOIDA processor for a given architecture",
-
- .tp_methods = py_processor_methods,
- .tp_getset = py_processor_getset,
- .tp_new = (newfunc)py_processor_new
-
- };
-
- if (PyType_Ready(&py_processor_type) < 0)
+ if (PyType_Ready(py_arch_processor_type) != 0)
return false;
- //printf("ret import = %p\n", PyImport_ImportModule("pyoida.arch.processor.ArchProcessorType"));
+ Py_INCREF(py_arch_processor_type);
+ ret = PyModule_AddObject(module, "ArchProcessor", (PyObject *)py_arch_processor_type);
+ if (ret != 0) return false;
+ dict = PyModule_GetDict(module);
+ pygobject_register_class(dict, "ArchProcessor", G_TYPE_ARCH_PROCESSOR, py_arch_processor_type,
+ Py_BuildValue("(O)", py_arch_processor_type->tp_base));
-
- Py_INCREF(&py_processor_type);
- ret = PyModule_AddObject(module, "Processor", (PyObject *)&py_processor_type);
-
- result = add_arch_processor_type_to_python_module(module);
-
-
- return (ret == 0 && result);
+ return true;
}