diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2015-07-17 16:36:21 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2015-07-17 16:36:21 (GMT) |
commit | 24d3836fcf8d443eb654b981f65478cd9923b8f1 (patch) | |
tree | 7672a28b864127e8958c3c6cce751dcf646d2fbe /plugins/pychrysa/arch/processor.c | |
parent | a61f089babe336b012da31a494b0f7470b6e1a9a (diff) |
Updated the Python bindings.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@552 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'plugins/pychrysa/arch/processor.c')
-rw-r--r-- | plugins/pychrysa/arch/processor.c | 342 |
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; } |