diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-01-16 19:02:56 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-01-16 19:02:56 (GMT) |
commit | 9da8f8b37e3edebc917b4e223dd2447cd7cbc818 (patch) | |
tree | 3f330b13e7ca2a0a163882be3043ca9571f25211 /plugins/pychrysalide/arch/processor.c | |
parent | eb9b7fd76451db5c9f07a800c0394480e4b88c9c (diff) |
Changed the Python bindings source directory and updated code.
Diffstat (limited to 'plugins/pychrysalide/arch/processor.c')
-rw-r--r-- | plugins/pychrysalide/arch/processor.c | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c new file mode 100644 index 0000000..65431af --- /dev/null +++ b/plugins/pychrysalide/arch/processor.c @@ -0,0 +1,459 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * processor.c - équivalent Python du fichier "arch/processor.c" + * + * Copyright (C) 2012-2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "processor.h" + + +#include <malloc.h> +#include <pygobject.h> + + +#include <i18n.h> + + +#include <arch/processor.h> + + +#include "instriter.h" +#include "instruction.h" +#include "vmpa.h" +#include "../helpers.h" + + + + + + + + + + + + + + + + +/* ------------------ CONSERVATION DES SOUCIS DURANT LE CHARGEMENT ------------------ */ + + +/* Etend la liste des soucis détectés avec de nouvelles infos. */ +static PyObject *py_arch_processor_add_error(PyObject *, PyObject *); + +/* Fournit les éléments concernant tous les soucis détectés. */ +static PyObject *py_arch_processor_get_errors(PyObject *, void *); + + + +/* ------------------ MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES ------------------ */ + + +/* Fournit les instructions désassemblées pour une architecture. */ +static PyObject *py_arch_processor_get_instrs(PyObject *, void *); + +/* Note les instructions désassemblées avec une architecture. */ +static int py_arch_processor_set_instrs(PyObject *, PyObject *, void *); + +/* Recherche une instruction d'après son adresse. */ +static PyObject *py_arch_processor_find_instr_by_addr(PyObject *, PyObject *); + + + + + +/* Définit les constantes pour les types d'erreurs. */ +static bool define_python_arch_processor_constants(PyTypeObject *); + + + +/* ---------------------------------------------------------------------------------- */ +/* CONSERVATION DES SOUCIS DURANT LE CHARGEMENT */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = architecture concernée par la procédure. * +* args = instruction représentant le point de départ. * +* * +* Description : Etend la liste des soucis détectés avec de nouvelles infos. * +* * +* Retour : None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_processor_add_error(PyObject *self, PyObject *args) +{ + ArchProcessingError type; /* Type d'erreur détectée */ + vmpa2t addr; /* Position d'une erreur */ + const char *desc; /* Description d'une erreur */ + int ret; /* Bilan de lecture des args. */ + GArchProcessor *proc; /* Processeur manipulé */ + + ret = PyArg_ParseTuple(args, "IO&s", &type, convert_any_to_vmpa, &addr, &desc); + if (!ret) return NULL; + + proc = G_ARCH_PROCESSOR(pygobject_get(self)); + + g_arch_processor_add_error(proc, type, &addr, desc); + + Py_RETURN_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit les éléments concernant tous les soucis détectés. * +* * +* Retour : Liste des erreurs relevées au niveau de l'assembleur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_processor_get_errors(PyObject *self, void *closure) +{ + PyObject *result; /* Instance Python à retourner */ + GArchProcessor *proc; /* Architecture visée */ + size_t count; /* Nombre d'éléments à traiter */ + size_t i; /* Boucle de parcours */ +#ifndef NDEBUG + bool status; /* Bilan d'un appel */ +#endif + ArchProcessingError type; /* Type d'erreur détectée */ + vmpa2t addr; /* Position d'une erreur */ + char *desc; /* Description d'une erreur */ + PyObject *error; /* Nouvelle erreur à rajouter */ + + proc = G_ARCH_PROCESSOR(pygobject_get(self)); + + g_arch_processor_lock_errors(proc); + + count = g_arch_processor_count_errors(proc); + + result = PyTuple_New(count); + + for (i = 0; i < count; i++) + { +#ifndef NDEBUG + status = g_arch_processor_get_error(proc, i, &type, &addr, &desc); + assert(status); +#else + g_arch_processor_get_error(proc, i, &type, &addr, &desc); +#endif + + error = Py_BuildValue("IO&s", type, build_from_internal_vmpa, &addr, desc); + + PyTuple_SetItem(result, i, error); + + } + + g_arch_processor_unlock_errors(proc); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit les instructions désassemblées pour une architecture.* +* * +* Retour : Liste des instructions désassemblées ou None si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_arch_processor_get_instrs(PyObject *self, void *closure) +{ + PyObject *result; /* Instance Python à retourner */ + PyTypeObject *iterator_type; /* Type Python de l'itérateur */ + PyObject *args; /* Liste des arguments d'appel */ + + iterator_type = get_python_instr_iterator_type(); + + args = Py_BuildValue("On", self, 0); + + result = PyObject_CallObject((PyObject *)iterator_type, args); + + Py_DECREF(args); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* value = valeur fournie à intégrer ou prendre en compte. * +* closure = non utilisé ici. * +* * +* Description : Note les instructions désassemblées avec une architecture. * +* * +* Retour : Bilan de l'opération pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_arch_processor_set_instrs(PyObject *self, PyObject *value, void *closure) +{ + size_t count; /* Nombre d'instructions */ + GArchInstruction **list; /* Liste d'instructions */ + size_t i; /* Boucle de parcours */ + PyObject *instr; /* Instruction en Python */ + GArchProcessor *proc; /* Architecture visée */ + + if (!PyTuple_Check(value)) + { + PyErr_SetString(PyExc_TypeError, _("The attribute value must be a tuple of instructions.")); + return -1; + } + + count = PyTuple_Size(value); + + list = (GArchInstruction **)calloc(count, sizeof(GArchInstruction *)); + + for (i = 0; i < count; i++) + { + instr = PyTuple_GetItem(value, i); + + if (!PyObject_TypeCheck(value, get_python_arch_instruction_type())) + { + PyErr_SetString(PyExc_TypeError, _("The attribute value must be a tuple of instructions.")); + count = i; + goto papsi_error; + } + + list[i] = G_ARCH_INSTRUCTION(pygobject_get(instr)); + g_object_ref(G_OBJECT(list[i])); + + } + + proc = G_ARCH_PROCESSOR(pygobject_get(self)); + + g_arch_processor_set_instructions(proc, list, count); + + return 0; + + papsi_error: + + for (i = 0; i < count; i++) + g_object_unref(G_OBJECT(list[i])); + + free(list); + + return -1; + +} + + +/****************************************************************************** +* * +* 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); + + found = g_arch_processor_find_instr_by_address(proc, addr); + + if (found != NULL) + { + result = pygobject_new(G_OBJECT(found)); + g_object_unref(G_OBJECT(found)); + } + + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes pour les types d'erreurs. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool define_python_arch_processor_constants(PyTypeObject *obj_type) +{ + bool result; /* Bilan à retourner */ + + result = true; + + result &= PyDict_AddIntMacro(obj_type, APE_DISASSEMBLY); + result &= PyDict_AddIntMacro(obj_type, APE_LABEL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_arch_processor_type(void) +{ + static PyMethodDef py_arch_processor_methods[] = { + { + "add_error", py_arch_processor_add_error, + METH_VARARGS, + "add_error($self, type, addr, desc, /)\n--\n\nExtend the list of detected disassembling errors." + }, + { + "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." + }, + { NULL } + }; + + static PyGetSetDef py_arch_processor_getseters[] = { + { + "errors", py_arch_processor_get_errors, NULL, + "List of all detected errors which occurred during the disassembling process.", NULL + }, + { + "instrs", py_arch_processor_get_instrs, py_arch_processor_set_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 : Prend en charge l'objet 'pychrysalide.arch.ArchProcessor'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_arch_processor(PyObject *module) +{ + PyTypeObject *py_arch_processor_type; /* Type Python 'BinContent' */ + PyObject *dict; /* Dictionnaire du module */ + + py_arch_processor_type = get_python_arch_processor_type(); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_ARCH_PROCESSOR, py_arch_processor_type, &PyGObject_Type)) + return false; + + if (!define_python_arch_processor_constants(py_arch_processor_type)) + return false; + + return true; + +} |