From 80d779749adf228078b61f268bf952ba91a277f0 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Fri, 15 Nov 2024 17:56:56 +0100 Subject: Rename files relative to binary portions. --- plugins/pychrysalide/glibext/binportion.c | 732 ------------ plugins/pychrysalide/glibext/binportion.h | 45 - plugins/pychrysalide/glibext/portion.c | 732 ++++++++++++ plugins/pychrysalide/glibext/portion.h | 45 + src/Makefile.am | 2 +- src/glibext/Makefile.am | 74 +- src/glibext/gbinportion-int.h | 66 -- src/glibext/gbinportion.c | 1724 ----------------------------- src/glibext/gbinportion.h | 194 ---- src/glibext/portion-int-ui.h | 66 ++ src/glibext/portion-int.h | 66 ++ src/glibext/portion-ui.c | 1724 +++++++++++++++++++++++++++++ src/glibext/portion-ui.h | 194 ++++ src/glibext/portion.c | 1724 +++++++++++++++++++++++++++++ src/glibext/portion.h | 194 ++++ 15 files changed, 4783 insertions(+), 2799 deletions(-) delete mode 100644 plugins/pychrysalide/glibext/binportion.c delete mode 100644 plugins/pychrysalide/glibext/binportion.h create mode 100644 plugins/pychrysalide/glibext/portion.c create mode 100644 plugins/pychrysalide/glibext/portion.h delete mode 100644 src/glibext/gbinportion-int.h delete mode 100644 src/glibext/gbinportion.c delete mode 100644 src/glibext/gbinportion.h create mode 100644 src/glibext/portion-int-ui.h create mode 100644 src/glibext/portion-int.h create mode 100644 src/glibext/portion-ui.c create mode 100644 src/glibext/portion-ui.h create mode 100644 src/glibext/portion.c create mode 100644 src/glibext/portion.h diff --git a/plugins/pychrysalide/glibext/binportion.c b/plugins/pychrysalide/glibext/binportion.c deleted file mode 100644 index 70eb314..0000000 --- a/plugins/pychrysalide/glibext/binportion.c +++ /dev/null @@ -1,732 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * binportion.c - équivalent Python du fichier "glibext/gbinportion.c" - * - * Copyright (C) 2019-2020 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 "binportion.h" - - -#include - - -#include -#include -#include - - -#include "constants.h" -#include "../access.h" -#include "../helpers.h" -#include "../arch/vmpa.h" - - - -/* Accompagne la création d'une instance dérivée en Python. */ -static PyObject *py_bin_portion_new(PyTypeObject *, PyObject *, PyObject *); - -/* Initialise une instance sur la base du dérivé de GObject. */ -static int py_bin_portion_init(PyObject *, PyObject *, PyObject *); - -/* Effectue une comparaison avec un objet Python 'BinPortion'. */ -static PyObject *py_binary_portion_richcompare(PyObject *, PyObject *, int); - -/* Assure qu'une portion ne dépasse pas une position donnée. */ -static PyObject *py_binary_portion_limit_range(PyObject *, PyObject *); - -/* Fournit la description attribuée à une partie de code. */ -static PyObject *py_binary_portion_get_desc(PyObject *, void *); - -/* Attribue une description humaine à une partie de code. */ -static int py_binary_portion_set_desc(PyObject *, PyObject *, void *); - -/* Fournit l'emplacement d'une partie de code binaire. */ -static PyObject *py_binary_portion_get_range(PyObject *, void *); - -/* Indique la nature de la portion en terme d'originalité. */ -static PyObject *py_binary_portion_get_continuation(PyObject *, void *); - -/* Définit la nature de la portion en terme d'originalité. */ -static int py_binary_portion_set_continuation(PyObject *, PyObject *, void *); - -/* Fournit les droits associés à une partie de code. */ -static PyObject *py_binary_portion_get_rights(PyObject *, void *); - -/* Définit les droits associés à une partie de code. */ -static int py_binary_portion_set_rights(PyObject *, PyObject *, void *); - - - -/****************************************************************************** -* * -* Paramètres : type = type du nouvel objet à mettre en place. * -* args = éventuelle liste d'arguments. * -* kwds = éventuel dictionnaire de valeurs mises à disposition. * -* * -* Description : Accompagne la création d'une instance dérivée en Python. * -* * -* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_bin_portion_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *result; /* Objet à retourner */ - PyTypeObject *base; /* Type de base à dériver */ - bool first_time; /* Evite les multiples passages*/ - GType gtype; /* Nouveau type de processeur */ - bool status; /* Bilan d'un enregistrement */ - - /* Validations diverses */ - - base = get_python_binary_portion_type(); - - if (type == base) - goto simple_way; - - /* Mise en place d'un type dédié */ - - first_time = (g_type_from_name(type->tp_name) == 0); - - gtype = build_dynamic_type(G_TYPE_BIN_PORTION, type->tp_name, NULL, NULL, NULL); - - if (first_time) - { - status = register_class_for_dynamic_pygobject(gtype, type); - - if (!status) - { - result = NULL; - goto exit; - } - - } - - /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ - - simple_way: - - result = PyType_GenericNew(type, args, kwds); - - exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = objet à initialiser (théoriquement). * -* args = arguments fournis à l'appel. * -* kwds = arguments de type key=val fournis. * -* * -* Description : Initialise une instance sur la base du dérivé de GObject. * -* * -* Retour : 0. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int py_bin_portion_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - const char *code; /* Identifiant de couleur */ - vmpa2t *addr; /* Emplacement de portion */ - unsigned long long size; /* Taille de la portion */ - int ret; /* Bilan de lecture des args. */ - GBinPortion *portion; /* Portion à manipuler */ - - static char *kwlist[] = { "code", "addr", "size", NULL }; - -#define BINARY_PORTION_DOC \ - "The BinPortion object handles parts of binaries usually formally" \ - " identified in binary formats, like program segments or sections for ELF" \ - " files for example.\n" \ - "\n" \ - "Instances can be created using the following constructor:\n" \ - "\n" \ - " BinPortion(code, addr, size)" \ - "\n" \ - "Where code is the CSS class style for the rendering color to use, addr is" \ - " the starting point of the portion in memory, as a pychrysalide.arch.vmpa" \ - " value, and size is the size of the portion." \ - - /* Récupération des paramètres */ - - ret = PyArg_ParseTupleAndKeywords(args, kwds, "sO&K", kwlist, - &code, convert_any_to_vmpa, &addr, &size); - if (!ret) return -1; - - /* Initialisation d'un objet GLib */ - - ret = forward_pygobjet_init(self); - if (ret == -1) - { - clean_vmpa_arg(addr); - return -1; - } - - /* Eléments de base */ - - portion = G_BIN_PORTION(pygobject_get(self)); - - portion->code = strdup(code); - - init_mrange(&portion->range, addr, size); - - clean_vmpa_arg(addr); - - return 0; - -} - - -/****************************************************************************** -* * -* 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 'BinPortion'. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_binary_portion_richcompare(PyObject *a, PyObject *b, int op) -{ - PyObject *result; /* Bilan à retourner */ - int ret; /* Bilan de lecture des args. */ - const GBinPortion *portion_a; /* Premier élément à traiter */ - const GBinPortion *portion_b; /* Second élément à traiter */ - int status; /* Résultat d'une comparaison */ - - ret = PyObject_IsInstance(b, (PyObject *)get_python_binary_portion_type()); - if (!ret) - { - result = Py_NotImplemented; - goto cmp_done; - } - - portion_a = G_BIN_PORTION(pygobject_get(a)); - portion_b = G_BIN_PORTION(pygobject_get(b)); - - status = g_binary_portion_compare(&portion_a, &portion_b); - - result = status_to_rich_cmp_state(status, op); - - cmp_done: - - Py_INCREF(result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une portion de binaire. * -* args = arguments fournis à l'appel. * -* * -* Description : Assure qu'une portion ne dépasse pas une position donnée. * -* * -* Retour : True si la portion a été modifiée, False sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_binary_portion_limit_range(PyObject *self, PyObject *args) -{ - PyObject *result; /* Trouvailles à retourner */ - unsigned long long max; /* Taille maximale à accorder */ - int ret; /* Bilan de lecture des args. */ - GBinPortion *portion; /* Version GLib du type */ - bool status; /* Bilan de la modification */ - -#define BINARY_SYMBOL_LIMIT_RANGE_METHOD PYTHON_METHOD_DEF \ -( \ - limit_range, "$self, max, /", \ - METH_VARARGS, py_binary_portion, \ - "Ensure the portion range does not cross a boundary size.\n" \ - "\n" \ - "An integer value is expected as the maximum size of the" \ - " portion.\n" \ - "\n" \ - "A boolean value indicating the success of the operation is" \ - " returned." \ -) - - ret = PyArg_ParseTuple(args, "K", &max); - if (!ret) return NULL; - - portion = G_BIN_PORTION(pygobject_get(self)); - - status = g_binary_portion_limit_range(portion, max); - - result = status ? Py_True : Py_False; - Py_INCREF(result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = classe représentant une portion de binaire. * -* args = arguments fournis à l'appel. * -* * -* Description : Procède à l'inclusion d'une portion dans une autre. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_binary_portion_include(PyObject *self, PyObject *args) -{ - GBinPortion *sub; /* Sous-portion à inclure */ - int ret; /* Bilan de lecture des args. */ - GBinPortion *portion; /* Version GLib du type */ - -#define BINARY_SYMBOL_INCLUDE_METHOD PYTHON_METHOD_DEF \ -( \ - include, "$self, sub, /", \ - METH_VARARGS, py_binary_portion, \ - "Include another binary portion as a child item.\n" \ - "\n" \ - "The sub portion has to be a pychrysalide.glibext.BinPortion" \ - " instance." \ -) - - ret = PyArg_ParseTuple(args, "O&", convert_to_binary_portion, &sub); - if (!ret) return NULL; - - portion = G_BIN_PORTION(pygobject_get(self)); - - g_object_ref(G_OBJECT(sub)); - g_binary_portion_include(portion, sub); - - Py_RETURN_NONE; - -} - - -/****************************************************************************** -* * -* Paramètres : self = objet Python concerné par l'appel. * -* closure = non utilisé ici. * -* * -* Description : Fournit la description attribuée à une partie de code. * -* * -* Retour : Nom donné à la partie. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_binary_portion_get_desc(PyObject *self, void *closure) -{ - PyObject *result; /* Résultat à retourner */ - GBinPortion *portion; /* Version GLib du type */ - const char *desc; /* Description récupérée */ - -#define BINARY_PORTION_DESC_ATTRIB PYTHON_GETSET_DEF_FULL \ -( \ - desc, py_binary_portion, \ - "Human description for the binary portion, as a" \ - " simple string." \ -) - - portion = G_BIN_PORTION(pygobject_get(self)); - - desc = g_binary_portion_get_desc(portion); - - result = PyUnicode_FromString(desc); - - 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 : Attribue une description humaine à une partie de code. * -* * -* Retour : 0. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int py_binary_portion_set_desc(PyObject *self, PyObject *value, void *closure) -{ - GBinPortion *portion; /* Version GLib du type */ - const char *desc; /* Description à définir */ - - if (!PyUnicode_Check(value)) - { - PyErr_SetString(PyExc_TypeError, _("The attribute value must be a string.")); - return -1; - } - - portion = G_BIN_PORTION(pygobject_get(self)); - - desc = PyUnicode_DATA(value); - - g_binary_portion_set_desc(portion, desc); - - return 0; - -} - - -/****************************************************************************** -* * -* Paramètres : self = objet Python concerné par l'appel. * -* closure = non utilisé ici. * -* * -* Description : Fournit l'emplacement d'une partie de code binaire. * -* * -* Retour : Espace de couverture associé à la portion. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_binary_portion_get_range(PyObject *self, void *closure) -{ - PyObject *result; /* Résultat à retourner */ - GBinPortion *portion; /* Version GLib du type */ - const mrange_t *range; /* Espace de couverture */ - -#define BINARY_PORTION_RANGE_ATTRIB PYTHON_GET_DEF_FULL \ -( \ - range, py_binary_portion, \ - "Area covered by the binary portion.\n" \ - "\n" \ - "This property is a pychrysalide.arch.mrange instance." \ -) - - portion = G_BIN_PORTION(pygobject_get(self)); - - range = g_binary_portion_get_range(portion); - - result = build_from_internal_mrange(range); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = objet Python concerné par l'appel. * -* closure = non utilisé ici. * -* * -* Description : Indique la nature de la portion en terme d'originalité. * -* * -* Retour : True si la portion est la suite d'une portion découpée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_binary_portion_get_continuation(PyObject *self, void *closure) -{ - PyObject *result; /* Résultat à retourner */ - GBinPortion *portion; /* Version GLib du type */ - bool status; /* Bilan d'une consultation */ - -#define BINARY_PORTION_CONTINUATION_ATTRIB PYTHON_GETSET_DEF_FULL \ -( \ - continuation, py_binary_portion, \ - "Tell if the current portion is a continuation of another" \ - " one.\n" \ - "\n" \ - "If a section belongs to several parents, it is cut into" \ - " several parts when included in the portion tree." \ -) - - portion = G_BIN_PORTION(pygobject_get(self)); - - status = g_binary_portion_is_continuation(portion); - - result = status ? Py_True : Py_False; - Py_INCREF(result); - - 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 : Définit la nature de la portion en terme d'originalité. * -* * -* Retour : 0. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int py_binary_portion_set_continuation(PyObject *self, PyObject *value, void *closure) -{ - GBinPortion *portion; /* Version GLib du type */ - bool status; /* Valeur à manipuler */ - - if (!PyBool_Check(value)) - { - PyErr_SetString(PyExc_TypeError, _("The attribute value must be a boolean.")); - return -1; - } - - portion = G_BIN_PORTION(pygobject_get(self)); - - status = (value == Py_True); - - g_binary_portion_mark_as_continued(portion, status); - - return 0; - -} - - -/****************************************************************************** -* * -* Paramètres : self = objet Python concerné par l'appel. * -* closure = non utilisé ici. * -* * -* Description : Fournit les droits associés à une partie de code. * -* * -* Retour : Droits d'accès de la partie. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_binary_portion_get_rights(PyObject *self, void *closure) -{ - PyObject *result; /* Résultat à retourner */ - GBinPortion *portion; /* Version GLib du type */ - PortionAccessRights rights; /* Bilan d'une consultation */ - -#define BINARY_PORTION_RIGHTS_ATTRIB PYTHON_GETSET_DEF_FULL \ -( \ - rights, py_binary_portion, \ - "Access rights declared for the binary portion, as a" \ - " pychrysalide.glibext.BinPortion.PortionAccessRights value." \ -) - - portion = G_BIN_PORTION(pygobject_get(self)); - - rights = g_binary_portion_get_rights(portion); - - result = cast_with_constants_group_from_type(get_python_binary_portion_type(), "PortionAccessRights", rights); - - 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 : Définit les droits associés à une partie de code. * -* * -* Retour : 0. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int py_binary_portion_set_rights(PyObject *self, PyObject *value, void *closure) -{ - GBinPortion *portion; /* Version GLib du type */ - PortionAccessRights rights; /* Valeur à manipuler */ - - if (convert_to_portion_access_rights(value, &rights) != 1) - return -1; - - portion = G_BIN_PORTION(pygobject_get(self)); - - g_binary_portion_set_rights(portion, rights); - - return 0; - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Fournit un accès à une définition de type à diffuser. * -* * -* Retour : Définition d'objet pour Python. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PyTypeObject *get_python_binary_portion_type(void) -{ - static PyMethodDef py_binary_portion_methods[] = { - BINARY_SYMBOL_LIMIT_RANGE_METHOD, - BINARY_SYMBOL_INCLUDE_METHOD, - { NULL } - }; - - static PyGetSetDef py_binary_portion_getseters[] = { - BINARY_PORTION_DESC_ATTRIB, - BINARY_PORTION_RANGE_ATTRIB, - BINARY_PORTION_CONTINUATION_ATTRIB, - BINARY_PORTION_RIGHTS_ATTRIB, - { NULL } - }; - - static PyTypeObject py_binary_portion_type = { - - PyVarObject_HEAD_INIT(NULL, 0) - - .tp_name = "pychrysalide.glibext.BinPortion", - .tp_basicsize = sizeof(PyGObject), - - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - - .tp_doc = BINARY_PORTION_DOC, - - .tp_richcompare = py_binary_portion_richcompare, - - .tp_methods = py_binary_portion_methods, - .tp_getset = py_binary_portion_getseters, - - .tp_init = py_bin_portion_init, - .tp_new = py_bin_portion_new, - - }; - - return &py_binary_portion_type; - -} - - -/****************************************************************************** -* * -* Paramètres : module = module dont la définition est à compléter. * -* * -* Description : Prend en charge l'objet 'pychrysalide.glibext.BinPortion'. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool ensure_python_binary_portion_is_registered(void) -{ - PyTypeObject *type; /* Type Python 'BinPortion' */ - PyObject *module; /* Module à recompléter */ - PyObject *dict; /* Dictionnaire du module */ - - type = get_python_binary_portion_type(); - - if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) - { - module = get_access_to_python_module("pychrysalide.glibext"); - - dict = PyModule_GetDict(module); - - if (!register_class_for_pygobject(dict, G_TYPE_BIN_PORTION, type)) - return false; - - if (!define_binary_portion_constants(type)) - return false; - - } - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : arg = argument quelconque à tenter de convertir. * -* dst = destination des valeurs récupérées en cas de succès. * -* * -* Description : Tente de convertir en portion de binaire. * -* * -* Retour : Bilan de l'opération, voire indications supplémentaires. * -* * -* Remarques : - * -* * -******************************************************************************/ - -int convert_to_binary_portion(PyObject *arg, void *dst) -{ - int result; /* Bilan à retourner */ - - result = PyObject_IsInstance(arg, (PyObject *)get_python_binary_portion_type()); - - switch (result) - { - case -1: - /* L'exception est déjà fixée par Python */ - result = 0; - break; - - case 0: - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to binary portion"); - break; - - case 1: - *((GBinPortion **)dst) = G_BIN_PORTION(pygobject_get(arg)); - break; - - default: - assert(false); - break; - - } - - return result; - -} diff --git a/plugins/pychrysalide/glibext/binportion.h b/plugins/pychrysalide/glibext/binportion.h deleted file mode 100644 index b27c8ea..0000000 --- a/plugins/pychrysalide/glibext/binportion.h +++ /dev/null @@ -1,45 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * binportion.h - prototypes pour l'équivalent Python du fichier "glibext/gbinportion.h" - * - * Copyright (C) 2019 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 - */ - - -#ifndef _PLUGINS_PYCHRYSALIDE_GLIBEXT_BINPORTION_H -#define _PLUGINS_PYCHRYSALIDE_GLIBEXT_BINPORTION_H - - -#include -#include - - - -/* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_binary_portion_type(void); - -/* Prend en charge l'objet 'pychrysalide.glibext.BinPortion'. */ -bool ensure_python_binary_portion_is_registered(void); - -/* Tente de convertir en portion de binaire. */ -int convert_to_binary_portion(PyObject *, void *); - - - -#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_BINPORTION_H */ diff --git a/plugins/pychrysalide/glibext/portion.c b/plugins/pychrysalide/glibext/portion.c new file mode 100644 index 0000000..70eb314 --- /dev/null +++ b/plugins/pychrysalide/glibext/portion.c @@ -0,0 +1,732 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * binportion.c - équivalent Python du fichier "glibext/gbinportion.c" + * + * Copyright (C) 2019-2020 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 "binportion.h" + + +#include + + +#include +#include +#include + + +#include "constants.h" +#include "../access.h" +#include "../helpers.h" +#include "../arch/vmpa.h" + + + +/* Accompagne la création d'une instance dérivée en Python. */ +static PyObject *py_bin_portion_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_bin_portion_init(PyObject *, PyObject *, PyObject *); + +/* Effectue une comparaison avec un objet Python 'BinPortion'. */ +static PyObject *py_binary_portion_richcompare(PyObject *, PyObject *, int); + +/* Assure qu'une portion ne dépasse pas une position donnée. */ +static PyObject *py_binary_portion_limit_range(PyObject *, PyObject *); + +/* Fournit la description attribuée à une partie de code. */ +static PyObject *py_binary_portion_get_desc(PyObject *, void *); + +/* Attribue une description humaine à une partie de code. */ +static int py_binary_portion_set_desc(PyObject *, PyObject *, void *); + +/* Fournit l'emplacement d'une partie de code binaire. */ +static PyObject *py_binary_portion_get_range(PyObject *, void *); + +/* Indique la nature de la portion en terme d'originalité. */ +static PyObject *py_binary_portion_get_continuation(PyObject *, void *); + +/* Définit la nature de la portion en terme d'originalité. */ +static int py_binary_portion_set_continuation(PyObject *, PyObject *, void *); + +/* Fournit les droits associés à une partie de code. */ +static PyObject *py_binary_portion_get_rights(PyObject *, void *); + +/* Définit les droits associés à une partie de code. */ +static int py_binary_portion_set_rights(PyObject *, PyObject *, void *); + + + +/****************************************************************************** +* * +* Paramètres : type = type du nouvel objet à mettre en place. * +* args = éventuelle liste d'arguments. * +* kwds = éventuel dictionnaire de valeurs mises à disposition. * +* * +* Description : Accompagne la création d'une instance dérivée en Python. * +* * +* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_bin_portion_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Objet à retourner */ + PyTypeObject *base; /* Type de base à dériver */ + bool first_time; /* Evite les multiples passages*/ + GType gtype; /* Nouveau type de processeur */ + bool status; /* Bilan d'un enregistrement */ + + /* Validations diverses */ + + base = get_python_binary_portion_type(); + + if (type == base) + goto simple_way; + + /* Mise en place d'un type dédié */ + + first_time = (g_type_from_name(type->tp_name) == 0); + + gtype = build_dynamic_type(G_TYPE_BIN_PORTION, type->tp_name, NULL, NULL, NULL); + + if (first_time) + { + status = register_class_for_dynamic_pygobject(gtype, type); + + if (!status) + { + result = NULL; + goto exit; + } + + } + + /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + simple_way: + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_bin_portion_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + const char *code; /* Identifiant de couleur */ + vmpa2t *addr; /* Emplacement de portion */ + unsigned long long size; /* Taille de la portion */ + int ret; /* Bilan de lecture des args. */ + GBinPortion *portion; /* Portion à manipuler */ + + static char *kwlist[] = { "code", "addr", "size", NULL }; + +#define BINARY_PORTION_DOC \ + "The BinPortion object handles parts of binaries usually formally" \ + " identified in binary formats, like program segments or sections for ELF" \ + " files for example.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " BinPortion(code, addr, size)" \ + "\n" \ + "Where code is the CSS class style for the rendering color to use, addr is" \ + " the starting point of the portion in memory, as a pychrysalide.arch.vmpa" \ + " value, and size is the size of the portion." \ + + /* Récupération des paramètres */ + + ret = PyArg_ParseTupleAndKeywords(args, kwds, "sO&K", kwlist, + &code, convert_any_to_vmpa, &addr, &size); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) + { + clean_vmpa_arg(addr); + return -1; + } + + /* Eléments de base */ + + portion = G_BIN_PORTION(pygobject_get(self)); + + portion->code = strdup(code); + + init_mrange(&portion->range, addr, size); + + clean_vmpa_arg(addr); + + return 0; + +} + + +/****************************************************************************** +* * +* 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 'BinPortion'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_portion_richcompare(PyObject *a, PyObject *b, int op) +{ + PyObject *result; /* Bilan à retourner */ + int ret; /* Bilan de lecture des args. */ + const GBinPortion *portion_a; /* Premier élément à traiter */ + const GBinPortion *portion_b; /* Second élément à traiter */ + int status; /* Résultat d'une comparaison */ + + ret = PyObject_IsInstance(b, (PyObject *)get_python_binary_portion_type()); + if (!ret) + { + result = Py_NotImplemented; + goto cmp_done; + } + + portion_a = G_BIN_PORTION(pygobject_get(a)); + portion_b = G_BIN_PORTION(pygobject_get(b)); + + status = g_binary_portion_compare(&portion_a, &portion_b); + + result = status_to_rich_cmp_state(status, op); + + cmp_done: + + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une portion de binaire. * +* args = arguments fournis à l'appel. * +* * +* Description : Assure qu'une portion ne dépasse pas une position donnée. * +* * +* Retour : True si la portion a été modifiée, False sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_portion_limit_range(PyObject *self, PyObject *args) +{ + PyObject *result; /* Trouvailles à retourner */ + unsigned long long max; /* Taille maximale à accorder */ + int ret; /* Bilan de lecture des args. */ + GBinPortion *portion; /* Version GLib du type */ + bool status; /* Bilan de la modification */ + +#define BINARY_SYMBOL_LIMIT_RANGE_METHOD PYTHON_METHOD_DEF \ +( \ + limit_range, "$self, max, /", \ + METH_VARARGS, py_binary_portion, \ + "Ensure the portion range does not cross a boundary size.\n" \ + "\n" \ + "An integer value is expected as the maximum size of the" \ + " portion.\n" \ + "\n" \ + "A boolean value indicating the success of the operation is" \ + " returned." \ +) + + ret = PyArg_ParseTuple(args, "K", &max); + if (!ret) return NULL; + + portion = G_BIN_PORTION(pygobject_get(self)); + + status = g_binary_portion_limit_range(portion, max); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une portion de binaire. * +* args = arguments fournis à l'appel. * +* * +* Description : Procède à l'inclusion d'une portion dans une autre. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_portion_include(PyObject *self, PyObject *args) +{ + GBinPortion *sub; /* Sous-portion à inclure */ + int ret; /* Bilan de lecture des args. */ + GBinPortion *portion; /* Version GLib du type */ + +#define BINARY_SYMBOL_INCLUDE_METHOD PYTHON_METHOD_DEF \ +( \ + include, "$self, sub, /", \ + METH_VARARGS, py_binary_portion, \ + "Include another binary portion as a child item.\n" \ + "\n" \ + "The sub portion has to be a pychrysalide.glibext.BinPortion" \ + " instance." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_binary_portion, &sub); + if (!ret) return NULL; + + portion = G_BIN_PORTION(pygobject_get(self)); + + g_object_ref(G_OBJECT(sub)); + g_binary_portion_include(portion, sub); + + Py_RETURN_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la description attribuée à une partie de code. * +* * +* Retour : Nom donné à la partie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_portion_get_desc(PyObject *self, void *closure) +{ + PyObject *result; /* Résultat à retourner */ + GBinPortion *portion; /* Version GLib du type */ + const char *desc; /* Description récupérée */ + +#define BINARY_PORTION_DESC_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + desc, py_binary_portion, \ + "Human description for the binary portion, as a" \ + " simple string." \ +) + + portion = G_BIN_PORTION(pygobject_get(self)); + + desc = g_binary_portion_get_desc(portion); + + result = PyUnicode_FromString(desc); + + 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 : Attribue une description humaine à une partie de code. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_binary_portion_set_desc(PyObject *self, PyObject *value, void *closure) +{ + GBinPortion *portion; /* Version GLib du type */ + const char *desc; /* Description à définir */ + + if (!PyUnicode_Check(value)) + { + PyErr_SetString(PyExc_TypeError, _("The attribute value must be a string.")); + return -1; + } + + portion = G_BIN_PORTION(pygobject_get(self)); + + desc = PyUnicode_DATA(value); + + g_binary_portion_set_desc(portion, desc); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit l'emplacement d'une partie de code binaire. * +* * +* Retour : Espace de couverture associé à la portion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_portion_get_range(PyObject *self, void *closure) +{ + PyObject *result; /* Résultat à retourner */ + GBinPortion *portion; /* Version GLib du type */ + const mrange_t *range; /* Espace de couverture */ + +#define BINARY_PORTION_RANGE_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + range, py_binary_portion, \ + "Area covered by the binary portion.\n" \ + "\n" \ + "This property is a pychrysalide.arch.mrange instance." \ +) + + portion = G_BIN_PORTION(pygobject_get(self)); + + range = g_binary_portion_get_range(portion); + + result = build_from_internal_mrange(range); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique la nature de la portion en terme d'originalité. * +* * +* Retour : True si la portion est la suite d'une portion découpée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_portion_get_continuation(PyObject *self, void *closure) +{ + PyObject *result; /* Résultat à retourner */ + GBinPortion *portion; /* Version GLib du type */ + bool status; /* Bilan d'une consultation */ + +#define BINARY_PORTION_CONTINUATION_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + continuation, py_binary_portion, \ + "Tell if the current portion is a continuation of another" \ + " one.\n" \ + "\n" \ + "If a section belongs to several parents, it is cut into" \ + " several parts when included in the portion tree." \ +) + + portion = G_BIN_PORTION(pygobject_get(self)); + + status = g_binary_portion_is_continuation(portion); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + 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 : Définit la nature de la portion en terme d'originalité. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_binary_portion_set_continuation(PyObject *self, PyObject *value, void *closure) +{ + GBinPortion *portion; /* Version GLib du type */ + bool status; /* Valeur à manipuler */ + + if (!PyBool_Check(value)) + { + PyErr_SetString(PyExc_TypeError, _("The attribute value must be a boolean.")); + return -1; + } + + portion = G_BIN_PORTION(pygobject_get(self)); + + status = (value == Py_True); + + g_binary_portion_mark_as_continued(portion, status); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit les droits associés à une partie de code. * +* * +* Retour : Droits d'accès de la partie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_binary_portion_get_rights(PyObject *self, void *closure) +{ + PyObject *result; /* Résultat à retourner */ + GBinPortion *portion; /* Version GLib du type */ + PortionAccessRights rights; /* Bilan d'une consultation */ + +#define BINARY_PORTION_RIGHTS_ATTRIB PYTHON_GETSET_DEF_FULL \ +( \ + rights, py_binary_portion, \ + "Access rights declared for the binary portion, as a" \ + " pychrysalide.glibext.BinPortion.PortionAccessRights value." \ +) + + portion = G_BIN_PORTION(pygobject_get(self)); + + rights = g_binary_portion_get_rights(portion); + + result = cast_with_constants_group_from_type(get_python_binary_portion_type(), "PortionAccessRights", rights); + + 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 : Définit les droits associés à une partie de code. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_binary_portion_set_rights(PyObject *self, PyObject *value, void *closure) +{ + GBinPortion *portion; /* Version GLib du type */ + PortionAccessRights rights; /* Valeur à manipuler */ + + if (convert_to_portion_access_rights(value, &rights) != 1) + return -1; + + portion = G_BIN_PORTION(pygobject_get(self)); + + g_binary_portion_set_rights(portion, rights); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_binary_portion_type(void) +{ + static PyMethodDef py_binary_portion_methods[] = { + BINARY_SYMBOL_LIMIT_RANGE_METHOD, + BINARY_SYMBOL_INCLUDE_METHOD, + { NULL } + }; + + static PyGetSetDef py_binary_portion_getseters[] = { + BINARY_PORTION_DESC_ATTRIB, + BINARY_PORTION_RANGE_ATTRIB, + BINARY_PORTION_CONTINUATION_ATTRIB, + BINARY_PORTION_RIGHTS_ATTRIB, + { NULL } + }; + + static PyTypeObject py_binary_portion_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.glibext.BinPortion", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = BINARY_PORTION_DOC, + + .tp_richcompare = py_binary_portion_richcompare, + + .tp_methods = py_binary_portion_methods, + .tp_getset = py_binary_portion_getseters, + + .tp_init = py_bin_portion_init, + .tp_new = py_bin_portion_new, + + }; + + return &py_binary_portion_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.glibext.BinPortion'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_binary_portion_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'BinPortion' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_binary_portion_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.glibext"); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_BIN_PORTION, type)) + return false; + + if (!define_binary_portion_constants(type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en portion de binaire. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_binary_portion(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_binary_portion_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to binary portion"); + break; + + case 1: + *((GBinPortion **)dst) = G_BIN_PORTION(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/glibext/portion.h b/plugins/pychrysalide/glibext/portion.h new file mode 100644 index 0000000..b27c8ea --- /dev/null +++ b/plugins/pychrysalide/glibext/portion.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * binportion.h - prototypes pour l'équivalent Python du fichier "glibext/gbinportion.h" + * + * Copyright (C) 2019 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 + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_GLIBEXT_BINPORTION_H +#define _PLUGINS_PYCHRYSALIDE_GLIBEXT_BINPORTION_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_binary_portion_type(void); + +/* Prend en charge l'objet 'pychrysalide.glibext.BinPortion'. */ +bool ensure_python_binary_portion_is_registered(void); + +/* Tente de convertir en portion de binaire. */ +int convert_to_binary_portion(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_BINPORTION_H */ diff --git a/src/Makefile.am b/src/Makefile.am index 933af30..c50af8f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,7 +82,7 @@ libchrysacore4_la_LIBADD = \ common/libcommon4.la \ core/libcore4.la \ format/libformat.la \ - glibext/libglibext4.la \ + glibext/libglibext.la \ plugins/libplugins.la libchrysacore4_la_LDFLAGS = \ diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index 3649d50..2d4abb8 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -1,46 +1,46 @@ BUILT_SOURCES = chrysamarshal.h chrysamarshal.c resources.h resources.c -noinst_LTLIBRARIES = libglibext4.la libglibextui.la # libglibext.la - -libglibext_la_SOURCES = \ - comparison-int.h \ - comparison.h comparison.c \ - configuration-int.h \ - configuration.h configuration.c \ - gbinarycursor.h gbinarycursor.c \ - gbinportion-int.h \ - gbinportion.h gbinportion.c \ - glinecursor-int.h \ - glinecursor.h glinecursor.c \ - gnhash.h gnhash.c \ - notifier.h \ - objhole.h \ - proto.h \ - seq.h seq.c \ - _signal.h signal.c \ - singleton.h singleton.c \ - linetoken.h linetoken.c \ - umemslice-int.h \ - umemslice.h umemslice.c - -if BUILD_GTK_SUPPORT - -libglibext_la_SOURCES += \ - gloadedpanel-int.h \ - gloadedpanel.h gloadedpanel.c \ - named-int.h \ - named.h named.c - -endif - -libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) +noinst_LTLIBRARIES = libglibext.la libglibextui.la + +# libglibext_la_SOURCES = \ +# comparison-int.h \ +# comparison.h comparison.c \ +# configuration-int.h \ +# configuration.h configuration.c \ +# gbinarycursor.h gbinarycursor.c \ +# gbinportion-int.h \ +# gbinportion.h gbinportion.c \ +# glinecursor-int.h \ +# glinecursor.h glinecursor.c \ +# gnhash.h gnhash.c \ +# notifier.h \ +# objhole.h \ +# proto.h \ +# seq.h seq.c \ +# _signal.h signal.c \ +# singleton.h singleton.c \ +# linetoken.h linetoken.c \ +# umemslice-int.h \ +# umemslice.h umemslice.c + +# if BUILD_GTK_SUPPORT + +# libglibext_la_SOURCES += \ +# gloadedpanel-int.h \ +# gloadedpanel.h gloadedpanel.c \ +# named-int.h \ +# named.h named.c + +# endif + +# libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) #libglibext_la_LIBADD = \ # generators/libglibextgenerators.la -libglibext4_la_SOURCES = \ +libglibext_la_SOURCES = \ chrysamarshal.h chrysamarshal.c \ helpers.h \ work-int.h \ @@ -50,7 +50,7 @@ libglibext4_la_SOURCES = \ workqueue-int.h \ workqueue.h workqueue.c -libglibext4_la_CFLAGS = $(TOOLKIT_CFLAGS) +libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) RES_FILES = \ @@ -84,7 +84,7 @@ libglibextui_la_LIBADD = \ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) -dev_HEADERS = $(libglibext_la_SOURCES:%c=) +dev_HEADERS = $(libglibext_la_SOURCES:%c=) $(libglibextui_la_SOURCES:%c=) SUBDIRS = generators options diff --git a/src/glibext/gbinportion-int.h b/src/glibext/gbinportion-int.h deleted file mode 100644 index a29f53c..0000000 --- a/src/glibext/gbinportion-int.h +++ /dev/null @@ -1,66 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * binportion.h - prototypes pour la définition interne des portions de binaire - * - * Copyright (C) 2019 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 Chrysalide. If not, see . - */ - - -#ifndef _GLIBEXT_BINPORTION_INT_H -#define _GLIBEXT_BINPORTION_INT_H - - -#include "gbinportion.h" - - - -/* Portion de données binaires quelconques (instance) */ -struct _GBinPortion -{ - GObject parent; /* A laisser en premier */ - - char *code; /* Code de la couleur de fond */ - -#ifdef INCLUDE_GTK_SUPPORT - cairo_surface_t *icon; /* Image de représentation */ -#endif - - char *desc; /* Désignation humaine */ - char **text; /* Lignes brutes à représenter */ - size_t lcount; /* Quantité de ces lignes */ - - mrange_t range; /* Emplacement dans le code */ - bool continued; /* Suite d'une découpe ? */ - - PortionAccessRights rights; /* Droits d'accès */ - - GBinPortion **subs; /* Portions incluses */ - size_t count; /* Quantité d'inclusions */ - -}; - -/* Portion de données binaires quelconques (classe) */ -struct _GBinPortionClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - - -#endif /* _GLIBEXT_BINPORTION_INT_H */ diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c deleted file mode 100644 index 12e12fb..0000000 --- a/src/glibext/gbinportion.c +++ /dev/null @@ -1,1724 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * binportion.c - représentation graphique de portions de binaire - * - * Copyright (C) 2013-2019 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 Chrysalide. If not, see . - */ - - -#include "gbinportion.h" - - -#include -#include -#include -#include -#include - - -#include - - -#include "gbinportion-int.h" -#include "../analysis/human/asm/lang.h" -#include "../common/extstr.h" -#include "../common/sort.h" -#include "../core/columns.h" -#include "../glibext/gbinarycursor.h" -#include "../glibext/linegen-int.h" - - - -/* ------------------------------- PORTION DE BINAIRE ------------------------------- */ - - -/* Initialise la classe des portions de données binaires. */ -static void g_binary_portion_class_init(GBinPortionClass *); - -/* Initialise une instance de portion de données binaires. */ -static void g_binary_portion_init(GBinPortion *); - -/* Procède à l'initialisation de l'interface de génération. */ -static void g_binary_portion_interface_init(GLineGeneratorInterface *); - -/* Supprime toutes les références externes. */ -static void g_binary_portion_dispose(GBinPortion *); - -/* Procède à la libération totale de la mémoire. */ -static void g_binary_portion_finalize(GBinPortion *); - -#ifdef INCLUDE_GTK_SUPPORT - -/* Détermine l'aire d'une sous-portion. */ -static bool g_binary_portion_compute_sub_area(const GBinPortion *, phys_t, const GdkRectangle *, GdkRectangle *); - -#endif - - - -/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ - - -/* Indique le nombre de ligne prêtes à être générées. */ -static size_t g_binary_portion_count_lines(const GBinPortion *); - -#ifdef INCLUDE_GTK_SUPPORT - -/* Retrouve l'emplacement correspondant à une position donnée. */ -static void g_binary_portion_compute_cursor(const GBinPortion *, gint, size_t, size_t, GLineCursor **); - -/* Détermine si le conteneur s'inscrit dans une plage donnée. */ -static int g_binary_portion_contain_cursor(const GBinPortion *, size_t, size_t, const GLineCursor *); - -#endif - -/* Renseigne sur les propriétés liées à un générateur. */ -static BufferLineFlags g_binary_portion_get_flags(const GBinPortion *, size_t, size_t); - -/* Imprime dans une ligne de rendu le contenu représenté. */ -static void g_binary_portion_print(GBinPortion *, GBufferLine *, size_t, size_t, const GBinContent *); - - - -/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ - - -/* Détermine si une portion contient une adresse donnée. */ -static bool g_binary_portion_contains_vmpa(const GBinPortion *, const vmpa2t *); - -#ifdef INCLUDE_GTK_SUPPORT - -/* Recherche la portion présente à une adresse donnée. */ -static GBinPortion *g_binary_portion_find_with_area_at_addr(GBinPortion *, const vmpa2t *, GdkRectangle *); - -/* Détermine si une portion contient une position donnée. */ -static bool g_binary_portion_contains_physical(const GBinPortion *, phys_t); - -/* Détermine si une portion contient une adresse donnée. */ -static bool g_binary_portion_contains_virtual(const GBinPortion *, virt_t); - -#endif - - - -/* ---------------------------------------------------------------------------------- */ -/* PORTION DE BINAIRE */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type défini par la GLib pour les portions de données binaires. */ -G_DEFINE_TYPE_WITH_CODE(GBinPortion, g_binary_portion, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_binary_portion_interface_init)); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des portions de données binaires. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_portion_class_init(GBinPortionClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_portion_dispose; - object->finalize = (GObjectFinalizeFunc)g_binary_portion_finalize; - - -} - - -/****************************************************************************** -* * -* Paramètres : portion = instance à initialiser. * -* * -* Description : Initialise une instance de portion de données binaires. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_portion_init(GBinPortion *portion) -{ - vmpa2t dummy; /* Coquille presque vide */ - - portion->code = NULL; - -#ifdef INCLUDE_GTK_SUPPORT - portion->icon = NULL; -#endif - - portion->desc = NULL; - portion->text = NULL; - portion->lcount = 0; - - init_vmpa(&dummy, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); - init_mrange(&portion->range, &dummy, VMPA_NO_VIRTUAL); - - portion->continued = false; - -} - - -/****************************************************************************** -* * -* Paramètres : iface = interface GLib à initialiser. * -* * -* Description : Procède à l'initialisation de l'interface de génération. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_portion_interface_init(GLineGeneratorInterface *iface) -{ - iface->count = (linegen_count_lines_fc)g_binary_portion_count_lines; -#ifdef INCLUDE_GTK_SUPPORT - iface->compute = (linegen_compute_fc)g_binary_portion_compute_cursor; - iface->contain = (linegen_contain_fc)g_binary_portion_contain_cursor; -#endif - iface->get_flags = (linegen_get_flags_fc)g_binary_portion_get_flags; - iface->print = (linegen_print_fc)g_binary_portion_print; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_portion_dispose(GBinPortion *portion) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < portion->count; i++) - g_clear_object(&portion->subs[i]); - - G_OBJECT_CLASS(g_binary_portion_parent_class)->dispose(G_OBJECT(portion)); - -} - - -/****************************************************************************** -* * -* Paramètres : portion = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_portion_finalize(GBinPortion *portion) -{ - size_t i; /* Boucle de parcours */ - - if (portion->code != NULL) - free(portion->code); - -#ifdef INCLUDE_GTK_SUPPORT - if (portion->icon != NULL) - cairo_surface_destroy(portion->icon); -#endif - - if (portion->desc != NULL) - free(portion->desc); - - for (i = 0; i < portion->lcount; i++) - free(portion->text[i]); - - if (portion->text != NULL) - free(portion->text); - - if (portion->subs != NULL) - free(portion->subs); - - G_OBJECT_CLASS(g_binary_portion_parent_class)->finalize(G_OBJECT(portion)); - -} - - -/****************************************************************************** -* * -* Paramètres : code = désignation humaine de la couleur de fond. * -* addr = emplacement de la section à conserver. * -* size = taille de la section à conserver. * -* * -* Description : Crée une description de partie de code vierge. * -* * -* Retour : Instance mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBinPortion *g_binary_portion_new(const char *code, const vmpa2t *addr, phys_t size) -{ - GBinPortion *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_BIN_PORTION, NULL); - - result->code = strdup(code); - - init_mrange(&result->range, addr, size); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : a = premières informations à consulter. * -* b = secondes informations à consulter. * -* * -* Description : Etablit la comparaison ascendante entre deux portions. * -* * -* Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). * -* * -* Remarques : - * -* * -******************************************************************************/ - -int g_binary_portion_compare(const GBinPortion **a, const GBinPortion **b) -{ - int result; /* Bilan à retourner */ - const vmpa2t *addr_a; /* Adresse de la portion 'a' */ - const vmpa2t *addr_b; /* Adresse de la portion 'b' */ - - addr_a = get_mrange_addr(&(*a)->range); - addr_b = get_mrange_addr(&(*b)->range); - - result = cmp_vmpa(addr_a, addr_b); - - return result; - -} - - -#ifdef INCLUDE_GTK_SUPPORT - - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à mettre à jour. * -* icon = image miniature de représentation à associer. * -* * -* Description : Attribue à la portion une éventuelle image de représentation.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_portion_set_icon(GBinPortion *portion, cairo_surface_t *icon) -{ - if (icon != NULL) - portion->icon = cairo_surface_reference(icon); - - else - portion->icon = NULL; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à consulter. * -* * -* Description : Fournit une éventuelle image de représentation de portion. * -* * -* Retour : Image miniature de représentation associée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -cairo_surface_t *g_binary_portion_get_icon(const GBinPortion *portion) -{ - cairo_surface_t *result; - - result = portion->icon; - - if (result != NULL) - cairo_surface_reference(result); - - return result; - -} - - -#endif - - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à mettre à jour. * -* desc = nom à donner à la partie. * -* * -* Description : Attribue une description humaine à une partie de code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_portion_set_desc(GBinPortion *portion, const char *desc) -{ - size_t i; /* Boucle de parcours */ - GCodingLanguage *lang; /* Langage de sortie préféré */ - - if (portion->desc != NULL) - { - free(portion->desc); - - for (i = 0; i < portion->lcount; i++) - free(portion->text[i]); - - if (portion->text != NULL) - { - free(portion->text); - portion->text = NULL; - } - - } - - if (desc == NULL) - portion->desc = NULL; - - else - { - portion->desc = strdup(desc); - - if (portion->continued) - portion->desc = stradd(portion->desc, _(" (continued)")); - - /* Constitution du rendu */ - - portion->text = calloc(5, sizeof(char *)); - portion->lcount = 5; - - portion->text[0] = strdup("======================================================"); - portion->text[1] = strdup(""); - - asprintf(&portion->text[2], "%s (%s%s%s%s)", portion->desc, _("rights: "), - portion->rights & PAC_READ ? "r" : "-", - portion->rights & PAC_WRITE ? "w" : "-", - portion->rights & PAC_EXEC ? "x" : "-"); - - portion->text[3] = strdup(""); - portion->text[4] = strdup("======================================================"); - - /* Ajout de la touche "commentaires" */ - - lang = g_asm_language_new(); - - g_coding_language_encapsulate_comments(lang, &portion->text, &portion->lcount); - - g_object_unref(G_OBJECT(lang)); - - /* Ajout de deux bordures vides */ - - portion->lcount += 2; - portion->text = realloc(portion->text, portion->lcount * sizeof(char *)); - - memmove(&portion->text[1], &portion->text[0], (portion->lcount - 2) * sizeof(char *)); - - portion->text[0] = NULL; - portion->text[portion->lcount - 1] = NULL; - - } - -} - - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à consulter. * -* * -* Description : Fournit la description attribuée à une partie de code. * -* * -* Retour : Nom donné à la partie. * -* * -* Remarques : - * -* * -******************************************************************************/ - -const char *g_binary_portion_get_desc(const GBinPortion *portion) -{ - return portion->desc; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à mettre à jour. * -* * -* Description : Fournit l'emplacement d'une partie de code binaire. * -* * -* Retour : Espace de couverture associé à la portion. * -* * -* Remarques : - * -* * -******************************************************************************/ - -const mrange_t *g_binary_portion_get_range(const GBinPortion *portion) -{ - return &portion->range; - -} - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à mettre à jour. * -* max = taille maximale accordée à la portion. * -* * -* Description : Assure qu'une portion ne dépasse pas une position donnée. * -* * -* Retour : true si la portion a été modifiée, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_binary_portion_limit_range(GBinPortion *portion, phys_t max) -{ - bool result; /* Bilan à retourner */ - phys_t current; /* Taille courante */ - - current = get_mrange_length(&portion->range); - - result = (current > max); - - if (result) - set_mrange_length(&portion->range, max); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = portion dont la définition est à metre à jour. * -* * -* Description : Définit la nature de la portion en terme d'originalité. * -* * -* Retour : - * -* * -* Remarques : L'action ne modifie aucunement la description courante. * -* C'est le changement de description qui s'appuie sur la * -* notée ici. * -* * -******************************************************************************/ - -void g_binary_portion_mark_as_continued(GBinPortion *portion, bool continued) -{ - portion->continued = continued; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = portion dont la définition est à consulter. * -* * -* Description : Indique la nature de la portion en terme d'originalité. * -* * -* Retour : true si la portion est la suite d'une portion découpée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_binary_portion_is_continuation(const GBinPortion *portion) -{ - return portion->continued; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à mettre à jour. * -* rights = droits d'accès de la partie. * -* * -* Description : Définit les droits associés à une partie de code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_portion_set_rights(GBinPortion *portion, PortionAccessRights rights) -{ - portion->rights = rights; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à consulter. * -* * -* Description : Fournit les droits associés à une partie de code. * -* * -* Retour : Droits d'accès de la partie. * -* * -* Remarques : - * -* * -******************************************************************************/ - -PortionAccessRights g_binary_portion_get_rights(const GBinPortion *portion) -{ - return portion->rights; - -} - - -#ifdef INCLUDE_GTK_SUPPORT - - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à mettre à jour. * -* tooltip = astuce à compléter. [OUT] * -* * -* Description : Prépare une astuce concernant une portion pour son affichage.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_portion_query_tooltip(GBinPortion *portion, GtkTooltip *tooltip) -{ - char *markup; /* Description à construire */ - VMPA_BUFFER(value); /* Traduction en texte */ - - /* Nom */ - - if (portion->desc != NULL) - { - markup = strdup(""); - markup = stradd(markup, portion->desc); - markup = stradd(markup, "\n"); - markup = stradd(markup, "\n"); - - } - else markup = strdup(""); - - markup = stradd(markup, "taille : "); - mrange_length_to_string(&portion->range, MDS_UNDEFINED, value, NULL); - markup = stradd(markup, value); - markup = stradd(markup, "\n"); - - /* Localisation */ - - markup = stradd(markup, ""); - markup = stradd(markup, _("Localisation")); - markup = stradd(markup, "\n"); - - markup = stradd(markup, _("physical: from ")); - - mrange_phys_to_string(&portion->range, MDS_UNDEFINED, true, value, NULL); - markup = stradd(markup, value); - markup = stradd(markup, _(" to ")); - mrange_phys_to_string(&portion->range, MDS_UNDEFINED, false, value, NULL); - markup = stradd(markup, value); - markup = stradd(markup, "\n"); - - markup = stradd(markup, _("memory: from ")); - - mrange_virt_to_string(&portion->range, MDS_UNDEFINED, true, value, NULL); - markup = stradd(markup, value); - markup = stradd(markup, _(" to ")); - mrange_virt_to_string(&portion->range, MDS_UNDEFINED, false, value, NULL); - markup = stradd(markup, value); - - markup = stradd(markup, "\n\n"); - - /* Droits d'accès */ - - markup = stradd(markup, ""); - markup = stradd(markup, _("Rights")); - markup = stradd(markup, "\n"); - - snprintf(value, 2 * VMPA_MAX_SIZE, "%s%s%s", - portion->rights & PAC_READ ? "r" : "-", - portion->rights & PAC_WRITE ? "w" : "-", - portion->rights & PAC_EXEC ? "x" : "-"); - - markup = stradd(markup, value); - - /* Impression finale */ - - gtk_tooltip_set_markup(tooltip, markup); - free(markup); - -} - - -#ifdef INCLUDE_GTK_SUPPORT - - -/****************************************************************************** -* * -* Paramètres : portion = portion mère à consulter. * -* full = taille totale de la couche parente. * -* area = étendue de représentation de la portion mère. * -* sub_area = étendue de représentation de la portion fille. * -* * -* Description : Détermine l'aire d'une sous-portion. * -* * -* Retour : true si la sous-surface a été calculée correctement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_binary_portion_compute_sub_area(const GBinPortion *portion, phys_t full, const GdkRectangle *area, GdkRectangle *sub_area) -{ - phys_t length; /* Taille de la portion */ - phys_t start; /* Position de départ */ - - length = get_mrange_length(&portion->range); - - /* On saute les portions comme le segment GNU_STACK... */ - if (length == 0) return false; - - start = get_phy_addr(get_mrange_addr(&portion->range)); - - sub_area->y = area->y; - sub_area->height = area->height; - - sub_area->x = area->x + (start * area->width) / full; - sub_area->width = (length * area->width) / full; - - return true; - -} - - -#endif - - -/****************************************************************************** -* * -* Paramètres : portion = description de partie à consulter. * -* context = contexte graphique associé à la procédure. * -* cr = contexte graphique pour le dessin. * -* area = étendue mise à disposition. * -* * -* Description : Représente la portion sur une bande dédiée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_portion_draw(const GBinPortion *portion, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) -{ - phys_t full; /* Espace total représenté */ - size_t i; /* Boucle de parcours */ - GBinPortion *sub; /* Portion incluse à montrer */ - GdkRectangle sub_area; /* Etendue d'une sous-portion */ - - /* Dessin de la portion courante */ - - cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); - - gtk_style_context_save(context); - - if (portion->code != NULL) - gtk_style_context_add_class(context, portion->code); - - gtk_render_background(context, cr, area->x, area->y, area->width, area->height); - - gtk_render_frame(context, cr, area->x, area->y, area->width, area->height); - - gtk_style_context_restore(context); - - /* Dessin des portions contenues */ - - full = get_mrange_length(&portion->range); - - for (i = 0; i < portion->count; i++) - { - sub = portion->subs[i]; - - if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) - continue; - - g_binary_portion_draw(sub, context, cr, &sub_area); - - } - -} - - -#endif - - -/****************************************************************************** -* * -* Paramètres : portion = portion principale à compléter. * -* sub = portion à inclure dans la définition courante. * -* * -* Description : Procède à l'inclusion d'une portion dans une autre. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_binary_portion_include(GBinPortion *portion, GBinPortion *sub) -{ - bool found; /* Zone d'accueil trouvée ? */ - size_t best; /* Meilleur point d'insertion */ - size_t missed; /* Indice de zone à déplacer */ - const mrange_t *brange; /* Raccourci de confort d'usage*/ - vmpa2t end; /* Fin de la zone commune */ - phys_t overlapping; /* Taille de la zone commune */ - bool continued; /* Suite d'une découpe ? */ - GBinPortion *left_part; /* Partie intégrable */ - vmpa2t start; /* Départ de la seconde partie */ - GBinPortion *right_part; /* Partie restante */ - - int g_binary_portion_is_included(const GBinPortion **a, const GBinPortion **b) - { - int result; /* Bilan à retourner */ - - result = mrange_includes_mrange(&(*b)->range, &(*a)->range); - - return result; - - } - - found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinPortion *), - (__compar_fn_t)g_binary_portion_is_included, &best); - - if (!found) - { - /** - * On se prépare à réaliser une insertion au niveau courant. Mais des - * portions précédentes sont peut-être à déplacer dans la nouvelle zone : - * - * EXIDX 0x001178 0x00009178 0x00009178 0x00008 0x00008 R 0x4 - * PHDR 0x000034 0x00008034 0x00008034 0x00120 0x00120 R E 0x4 - * INTERP 0x000154 0x00008154 0x00008154 0x00019 0x00019 R 0x1 - * LOAD 0x000000 0x00008000 0x00008000 0x01184 0x01184 R E 0x8000 - * - * On refait donc une passe sur toutes les sous-portions du niveau. - * - * Cette approche a le mérite de traiter également et naturellement les - * sections définies dans le désordre : - * - * [21] .bss NOBITS 00088240 07823c 0018c8 00 WA 0 0 8 - * [22] __libc_freeres_ptrs NOBITS 00089b08 07823c 000018 00 WA 0 0 4 - * [23] .comment PROGBITS 00000000 07823c 000022 01 MS 0 0 1 - * - * Quant aux cas de figure où les portions sont identiques, l'ordre d'appel - * induit l'ordre d'inclusion. - * - * Cela concerne par exemple les zones de données : - * - * En-têtes de section: - * [Nr] Nom Type Adr Décala.Taille ES Fan LN Inf Al - * ... - * [ 2] .data PROGBITS 00010098 000098 00000c 00 WA 0 0 1 - * - * En-têtes de programme: - * Type Décalage Adr. vir. Adr.phys. T.Fich. T.Mém. Fan Alignement - * ... - * LOAD 0x000098 0x00010098 0x00010098 0x0000c 0x0000c RW 0x8000 - * - */ - - int g_binary_portion_track_missed_inclusion(const GBinPortion **a, const GBinPortion **b) - { - int result; /* Bilan à retourner */ - - result = mrange_includes_mrange(&(*a)->range, &(*b)->range); - - return result; - - } - - do - { - found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinPortion *), - (__compar_fn_t)g_binary_portion_track_missed_inclusion, &missed); - - if (found) - { - g_binary_portion_include(sub, portion->subs[missed]); - - portion->subs = _qdelete(portion->subs, &portion->count, sizeof(GBinPortion *), missed); - - } - - } - while (found); - - /** - * Il peut arriver que certaines portions débordent de leur zone d'inclusion : - * - * [24] .bss NOBITS 00012088 002084 000044 00 WA 0 0 8 - * [25] .ARM.attributes ARM_ATTRIBUTES 00000000 002084 000037 00 0 0 1 - * [26] .shstrtab STRTAB 00000000 0020bb 0000ed 00 0 0 1 - * - * Afin de respecter une certaine cohérence dans l'arbre des portions, on choisit - * de découper la portion qui déborde. - */ - - int g_binary_portion_track_partial_inclusion(const GBinPortion **a, const GBinPortion **b) - { - int result; /* Bilan à retourner */ - - result = cmp_mrange_with_vmpa(&(*b)->range, get_mrange_addr(&(*a)->range)); - - return result; - - } - - found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinPortion *), - (__compar_fn_t)g_binary_portion_track_partial_inclusion, &best); - - if (found) - { - brange = &portion->subs[best]->range; - - compute_mrange_end_addr(brange, &end); - overlapping = compute_vmpa_diff(get_mrange_addr(&sub->range), &end); - - continued = g_binary_portion_is_continuation(sub); - - /* Partie contenue */ - - left_part = g_binary_portion_new(sub->code, get_mrange_addr(&sub->range), overlapping); - - g_binary_portion_set_desc(left_part, sub->desc); - g_binary_portion_mark_as_continued(left_part, continued); - g_binary_portion_set_rights(left_part, sub->rights); - - /* Partie qui déborde... */ - - /** - * Comme la portion incluante peut avoir une définition d'adresse - * virtuelle différente de celle de la portion incluse, on recalcule - * la position de départ de la seconde partie de la portion découpée - * à partir des données d'origine. - */ - - copy_vmpa(&start, get_mrange_addr(&sub->range)); - advance_vmpa(&start, overlapping); - - right_part = g_binary_portion_new(sub->code, &start, get_mrange_length(&sub->range) - overlapping); - - if (!continued) - g_binary_portion_mark_as_continued(right_part, true); - - g_binary_portion_set_desc(right_part, sub->desc); - - if (continued) - g_binary_portion_mark_as_continued(right_part, true); - - g_binary_portion_set_rights(right_part, sub->rights); - - /* Inclusions des parties */ - - g_binary_portion_include(portion, left_part); - g_binary_portion_include(portion, right_part); - - g_object_unref(G_OBJECT(sub)); - - } - - else - portion->subs = qinsert(portion->subs, &portion->count, sizeof(GBinPortion *), - (__compar_fn_t)g_binary_portion_compare, &sub); - - } - - /* Poursuite de l'inclusion dans la sous-portion adaptée... */ - else - g_binary_portion_include(portion->subs[best], sub); - -} - - -/****************************************************************************** -* * -* Paramètres : portion = première couche amorçant la visite. * -* visitor = fonction à appeler à chaque étape de la descente. * -* data = adresse pointant vers des données de l'utilisateur.* -* * -* Description : Parcourt un ensemble de portions binaires. * -* * -* Retour : true si la visite a été jusqu'à son terme, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void *data) -{ - bool result; /* Etat à retourner */ - - bool visit_portion(GBinPortion *p, GBinPortion *pp) - { - bool ret; /* Etat à retourner */ - size_t i; /* Boucle de parcours */ - - if (p->count == 0) - ret = visitor(p, pp, BPV_SHOW, data); - - else - { - ret = visitor(p, pp, BPV_ENTER, data); - - for (i = 0; i < p->count && ret; i++) - ret = visit_portion(p->subs[i], p); - - if (ret) - ret = visitor(p, pp, BPV_EXIT, data); - - } - - return ret; - - } - - result = visit_portion(portion, NULL); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* OFFRE DE CAPACITES DE GENERATION */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : portion = générateur à consulter. * -* * -* Description : Indique le nombre de ligne prêtes à être générées. * -* * -* Retour : Nombre de lignes devant apparaître au final. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static size_t g_binary_portion_count_lines(const GBinPortion *portion) -{ - return portion->lcount; - -} - - -#ifdef INCLUDE_GTK_SUPPORT - - -/****************************************************************************** -* * -* Paramètres : portion = générateur à consulter. * -* x = position géographique sur la ligne concernée. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* cursor = emplacement à constituer. [OUT] * -* * -* Description : Retrouve l'emplacement correspondant à une position donnée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_portion_compute_cursor(const GBinPortion *portion, gint x, size_t index, size_t repeat, GLineCursor **cursor) -{ - *cursor = g_binary_cursor_new(); - - g_binary_cursor_update(G_BINARY_CURSOR(*cursor), get_mrange_addr(&portion->range)); - -} - - -/****************************************************************************** -* * -* Paramètres : portion = générateur à consulter. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* cursor = emplacement à analyser. * -* * -* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * -* * -* Retour : Bilan de la détermination, utilisable en comparaisons. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int g_binary_portion_contain_cursor(const GBinPortion *portion, size_t index, size_t repeat, const GLineCursor *cursor) -{ - int result; /* Conclusion à retourner */ - vmpa2t addr; /* Autre emplacement à comparer*/ - - assert(G_IS_BINARY_CURSOR(cursor)); - - g_binary_cursor_retrieve(G_BINARY_CURSOR(cursor), &addr); - - result = cmp_vmpa(&addr, get_mrange_addr(&portion->range)); - - return result; - -} - - -#endif - - -/****************************************************************************** -* * -* Paramètres : portion = générateur à consulter. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* * -* Description : Renseigne sur les propriétés liées à un générateur. * -* * -* Retour : Propriétés particulières associées. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static BufferLineFlags g_binary_portion_get_flags(const GBinPortion *portion, size_t index, size_t repeat) -{ - return (repeat == 0 ? BLF_WIDTH_MANAGER : BLF_NONE); - -} - - -/****************************************************************************** -* * -* Paramètres : portion = générateur à utiliser pour l'impression. * -* line = ligne de rendu à compléter. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* content = éventuel contenu binaire brut à imprimer. * -* * -* Description : Imprime dans une ligne de rendu le contenu représenté. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_binary_portion_print(GBinPortion *portion, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) -{ - assert(repeat < portion->lcount); - - g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&portion->range)); - - g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&portion->range)); - - if (portion->text[repeat] != NULL) - { - g_buffer_line_start_merge_at(line, DLC_ASSEMBLY_LABEL); - - g_buffer_line_append_text(line, DLC_ASSEMBLY_LABEL, SL(portion->text[repeat]), RTT_COMMENT, NULL); - - } - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* PARCOURS D'ENSEMBLES DE PORTIONS */ -/* ---------------------------------------------------------------------------------- */ - - -#ifdef INCLUDE_GTK_SUPPORT - - -/****************************************************************************** -* * -* Paramètres : portion = couche de portions à parcourir pour les recherches.* -* * -* Description : Compte le nombre de portions présentes dans une arborescence.* -* * -* Retour : Quantité de portions présentes. * -* * -* Remarques : - * -* * -******************************************************************************/ - -size_t g_binary_portion_count(const GBinPortion *portion) -{ - size_t result; /* Quantité à retourner */ - - - size_t measure_portion_size(const GBinPortion *root) - { - size_t count; /* Nombre de trouvailles */ - size_t i; /* Boucle de parcours */ - - count = 1; - - for (i = 0; i < root->count; i++) - count += measure_portion_size(root->subs[i]); - - return count; - - } - - - result = measure_portion_size(portion); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = couche de portions à parcourir pour les recherches.* -* x = abscisse du point de recherche. * -* area = étendue de portion mère, puis celle trouvée. [OUT] * -* * -* Description : Recherche la portion présente à un point donné. * -* * -* Retour : Portion trouvée à l'endroit indiqué. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBinPortion *g_binary_portion_find_at_pos(GBinPortion *portion, gint x, GdkRectangle *area) -{ - GBinPortion *result; /* Portion à retourner */ - phys_t full; /* Espace total représenté */ - size_t i; /* Boucle de parcours */ - GBinPortion *sub; /* Portion incluse à traiter */ - GdkRectangle sub_area; /* Etendue d'une sous-portion */ - - result = NULL; - - full = get_mrange_length(&portion->range); - - for (i = 0; i < portion->count && result == NULL; i++) - { - sub = portion->subs[i]; - - if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) - continue; - - if (sub_area.x <= x && x < (sub_area.x + sub_area.width)) - { - result = g_binary_portion_find_at_pos(sub, x, &sub_area); - - if (result != NULL) - *area = sub_area; - - } - - } - - if (result == NULL) - { - result = portion; - g_object_ref(G_OBJECT(result)); - } - - return result; - -} - - -#endif - - -/****************************************************************************** -* * -* Paramètres : portion = portion mère à consulter. * -* addr = adresse du point de recherche. * -* * -* Description : Détermine si une portion contient une adresse donnée. * -* * -* Retour : true ou false selon le résultat. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_binary_portion_contains_vmpa(const GBinPortion *portion, const vmpa2t *addr) -{ - bool result; /* Bilan à retourner */ - const mrange_t *range; /* Emplacement de portion */ - - result = false; - - range = g_binary_portion_get_range(portion); - - /* Portion non allouée en mémoire : on écarte */ - if (!has_virt_addr(get_mrange_addr(range))) - goto not_found; - - result = mrange_contains_addr(range, addr); - - not_found: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = couche de portions à parcourir pour les recherches.* -* addr = adresse du point de recherche. * -* * -* Description : Recherche la portion présente à une adresse donnée. * -* * -* Retour : Portion trouvée à l'endroit indiqué. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *addr) -{ - GBinPortion *result; /* Portion à retourner */ - phys_t full; /* Espace total représenté */ - size_t i; /* Boucle de parcours #1 */ - GBinPortion *sub; /* Portion incluse à traiter */ - - result = NULL; - - full = get_mrange_length(&portion->range); - - for (i = 0; i < portion->count && result == NULL; i++) - { - sub = portion->subs[i]; - - if (!g_binary_portion_contains_vmpa(sub, addr)) - continue; - - result = g_binary_portion_find_at_addr(sub, addr); - - } - - if (result == NULL) - { - result = portion; - g_object_ref(G_OBJECT(result)); - } - - return result; - -} - - -#ifdef INCLUDE_GTK_SUPPORT - - -/****************************************************************************** -* * -* Paramètres : portion = couche de portions à parcourir pour les recherches.* -* addr = adresse du point de recherche. * -* area = étendue de portion mère, puis celle trouvée. [OUT] * -* * -* Description : Recherche la portion présente à une adresse donnée. * -* * -* Retour : Portion trouvée à l'endroit indiqué. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GBinPortion *g_binary_portion_find_with_area_at_addr(GBinPortion *portion, const vmpa2t *addr, GdkRectangle *area) -{ - GBinPortion *result; /* Portion à retourner */ - phys_t full; /* Espace total représenté */ - size_t i; /* Boucle de parcours #1 */ - GBinPortion *sub; /* Portion incluse à traiter */ - GdkRectangle sub_area; /* Etendue d'une sous-portion */ - - result = NULL; - - full = get_mrange_length(&portion->range); - - for (i = 0; i < portion->count && result == NULL; i++) - { - sub = portion->subs[i]; - - if (!g_binary_portion_contains_vmpa(sub, addr)) - continue; - - if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) - continue; - - result = g_binary_portion_find_with_area_at_addr(sub, addr, &sub_area); - - if (result != NULL) - *area = sub_area; - - } - - if (result == NULL) - { - result = portion; - g_object_ref(G_OBJECT(result)); - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : root = couche de portions à parcourir pour les recherches. * -* x = abscisse du point de recherche. * -* area = étendue de représentation de la portion mère. * -* addr = adresse correspondante. [OUT] * -* * -* Description : Fournit la position correspondant à une adresse donnée. * -* * -* Retour : Succès de la traduction. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool get_binary_portion_addr_from_pos(GBinPortion *root, gint x, const GdkRectangle *area, vmpa2t *addr) -{ - GdkRectangle owner_area; /* Aire de contenance */ - GBinPortion *owner; /* Conteneur propriétaire */ - - owner_area = *area; - - owner = g_binary_portion_find_at_pos(root, x, &owner_area); - if (owner == NULL) return false; - - copy_vmpa(addr, get_mrange_addr(&owner->range)); - - advance_vmpa(addr, (get_mrange_length(&owner->range) * (x - owner_area.x)) / owner_area.width); - - g_object_unref(G_OBJECT(owner)); - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : root = couche de portions à parcourir pour les recherches. * -* addr = adresse du point de recherche. * -* area = étendue de représentation de la portion mère. * -* x = position correspondante. [OUT] * -* * -* Description : Fournit l'adresse correspondant à une position donnée. * -* * -* Retour : Succès de la traduction. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool get_binary_portion_pos_from_addr(GBinPortion *root, const vmpa2t *addr, const GdkRectangle *area, gint *x) -{ - GdkRectangle owner_area; /* Aire de contenance */ - GBinPortion *owner; /* Conteneur propriétaire */ - phys_t diff; /* Décalage à appliquer */ - - owner_area = *area; - - owner = g_binary_portion_find_with_area_at_addr(root, addr, &owner_area); - if (owner == NULL) return false; - - diff = compute_vmpa_diff(addr, get_mrange_addr(&owner->range)); - - *x = owner_area.x + (diff * owner_area.width) / get_mrange_length(&owner->range); - - g_object_unref(G_OBJECT(owner)); - - return true; - -} - - -/****************************************************************************** -* * -* Paramètres : layer = couche de portions à consulter. * -* x = abscisse du point de recherche. * -* y = ordonnée du point de recherche. * -* area = étendue de représentation de la portion mère. * -* tooltip = astuce à compléter. [OUT] * -* * -* Description : Prépare une astuce concernant une portion pour son affichage.* -* * -* Retour : TRUE pour valider l'affichage. * -* * -* Remarques : - * -* * -******************************************************************************/ - -gboolean query_tooltip_for_binary_portion(GBinPortion *root, gint x, gint y, const GdkRectangle *area, GtkTooltip *tooltip) -{ - GBinPortion *selected; /* Portion à décrire ici */ - - selected = g_binary_portion_find_at_pos(root, x, (GdkRectangle []) { *area }); - if (selected == NULL) return FALSE; - - g_binary_portion_query_tooltip(selected, tooltip); - - g_object_unref(G_OBJECT(selected)); - - return TRUE; - -} - - -#endif - - -/****************************************************************************** -* * -* Paramètres : portion = portion mère à consulter. * -* off = position physique du point de recherche. * -* * -* Description : Détermine si une portion contient une position donnée. * -* * -* Retour : true ou false selon le résultat. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_binary_portion_contains_physical(const GBinPortion *portion, phys_t off) -{ - bool result; /* Bilan à retourner */ - const mrange_t *range; /* Emplacement de portion */ - const vmpa2t *addr; /* Départ de la portion */ - - range = g_binary_portion_get_range(portion); - addr = get_mrange_addr(range); - - if (!has_phys_addr(addr)) - result = false; - - else - result = (addr->physical <= off && off < (addr->physical + range->length)); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = couche de portions à parcourir pour les recherches.* -* off = position physique à retrouver. * -* pos = position correspondante. [OUT] * -* * -* Description : Fournit l'emplacement correspondant à une position physique. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_binary_portion_translate_offset_into_vmpa(const GBinPortion *portion, phys_t off, vmpa2t *pos) -{ - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours #1 */ - GBinPortion *sub; /* Portion incluse à traiter */ - const mrange_t *range; /* Emplacement de portion */ - const vmpa2t *addr; /* Départ de la portion */ - - result = false; - - for (i = 0; i < portion->count; i++) - { - sub = portion->subs[i]; - - if (!g_binary_portion_contains_physical(sub, off)) - continue; - - result = g_binary_portion_translate_offset_into_vmpa(sub, off, pos); - - break; - - } - - if (i == portion->count) - { - result = g_binary_portion_contains_physical(portion, off); - - if (result) - { - range = g_binary_portion_get_range(portion); - addr = get_mrange_addr(range); - - if (has_virt_addr(get_mrange_addr(range))) - init_vmpa(pos, off, addr->virtual + off - addr->physical); - - else - init_vmpa(pos, off, VMPA_NO_VIRTUAL); - - } - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = portion mère à consulter. * -* virt = adresse virtuelle du point de recherche. * -* * -* Description : Détermine si une portion contient une adresse donnée. * -* * -* Retour : true ou false selon le résultat. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_binary_portion_contains_virtual(const GBinPortion *portion, virt_t virt) -{ - bool result; /* Bilan à retourner */ - const mrange_t *range; /* Emplacement de portion */ - const vmpa2t *addr; /* Départ de la portion */ - - range = g_binary_portion_get_range(portion); - addr = get_mrange_addr(range); - - if (!has_virt_addr(addr)) - result = false; - - else - result = (addr->virtual <= virt && virt < (addr->virtual + range->length)); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : portion = couche de portions à parcourir pour les recherches.* -* virt = adresse virtuelle à retrouver. * -* pos = position correspondante. [OUT] * -* * -* Description : Fournit l'emplacement correspondant à une adresse virtuelle. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_binary_portion_translate_address_into_vmpa(const GBinPortion *portion, virt_t virt, vmpa2t *pos) -{ - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours #1 */ - GBinPortion *sub; /* Portion incluse à traiter */ - const mrange_t *range; /* Emplacement de portion */ - const vmpa2t *addr; /* Départ de la portion */ - - result = false; - - for (i = 0; i < portion->count; i++) - { - sub = portion->subs[i]; - - if (!g_binary_portion_contains_virtual(sub, virt)) - continue; - - result = g_binary_portion_translate_address_into_vmpa(sub, virt, pos); - - break; - - } - - if (i == portion->count) - { - result = g_binary_portion_contains_virtual(portion, virt); - - if (result) - { - range = g_binary_portion_get_range(portion); - addr = get_mrange_addr(range); - - if (has_phys_addr(addr) && has_virt_addr(addr)) - init_vmpa(pos, addr->physical + virt - addr->virtual, virt); - - else - init_vmpa(pos, VMPA_NO_PHYSICAL, virt); - - } - - } - - return result; - -} diff --git a/src/glibext/gbinportion.h b/src/glibext/gbinportion.h deleted file mode 100644 index ea4b4aa..0000000 --- a/src/glibext/gbinportion.h +++ /dev/null @@ -1,194 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * binportion.h - prototypes pour la représentation graphique de portions de binaire - * - * Copyright (C) 2013-2019 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 Chrysalide. If not, see . - */ - - -#ifndef _GLIBEXT_BINPORTION_H -#define _GLIBEXT_BINPORTION_H - - -#include -#include -#ifdef INCLUDE_GTK_SUPPORT -# include -#endif - - -#include "../arch/vmpa.h" -#include "../common/fnv1a.h" - - - -/* ------------------------------- PORTION DE BINAIRE ------------------------------- */ - - -/** - * Couleurs de représentation. - */ - -#define BPC_RAW "binportion-raw" -#define BPC_CODE "binportion-code" -#define BPC_DATA "binportion-data" -#define BPC_DATA_RO "binportion-data-ro" -#define BPC_DISASS_ERROR "binportion-disassembly-error" - - -#define G_TYPE_BIN_PORTION (g_binary_portion_get_type()) -#define G_BIN_PORTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BIN_PORTION, GBinPortion)) -#define G_IS_BIN_PORTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BIN_PORTION)) -#define G_BIN_PORTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BIN_PORTION, GBinPortionClass)) -#define G_IS_BIN_PORTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BIN_PORTION)) -#define G_BIN_PORTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BIN_PORTION, GBinPortionClass)) - - -/* Portion de données binaires quelconques (instance) */ -typedef struct _GBinPortion GBinPortion; - -/* Portion de données binaires quelconques (classe) */ -typedef struct _GBinPortionClass GBinPortionClass; - - -/* Droits d'accès à une portion */ -typedef enum _PortionAccessRights -{ - PAC_NONE = (0 << 0), /* Aucun */ - PAC_READ = (1 << 0), /* Lecture */ - PAC_WRITE = (1 << 1), /* Ecriture */ - PAC_EXEC = (1 << 2) /* Exécution */ - -} PortionAccessRights; - - -#define PAC_ALL ((PortionAccessRights)(PAC_READ | PAC_WRITE | PAC_EXEC)) - - -/* Indique le type défini par la GLib pour les portions de données binaires. */ -GType g_binary_portion_get_type(void); - -/* Crée une description de partie de code vierge. */ -GBinPortion *g_binary_portion_new(const char *, const vmpa2t *, phys_t); - -/* Etablit la comparaison ascendante entre deux portions. */ -int g_binary_portion_compare(const GBinPortion **, const GBinPortion **); - -#ifdef INCLUDE_GTK_SUPPORT - -/* Attribue à la portion une éventuelle image de représentation. */ -void g_binary_portion_set_icon(GBinPortion *, cairo_surface_t *); - -/* Fournit une éventuelle image de représentation de portion. */ -cairo_surface_t *g_binary_portion_get_icon(const GBinPortion *); - -#endif - -/* Attribue une description humaine à une partie de code. */ -void g_binary_portion_set_desc(GBinPortion *, const char *); - -/* Fournit la description attribuée à une partie de code. */ -const char *g_binary_portion_get_desc(const GBinPortion *); - -/* Fournit l'emplacement d'une partie de code binaire. */ -const mrange_t *g_binary_portion_get_range(const GBinPortion *); - -/* Assure qu'une portion ne dépasse pas une position donnée. */ -bool g_binary_portion_limit_range(GBinPortion *, phys_t); - -/* Définit la nature de la portion en terme d'originalité. */ -void g_binary_portion_mark_as_continued(GBinPortion *, bool); - -/* Indique la nature de la portion en terme d'originalité. */ -bool g_binary_portion_is_continuation(const GBinPortion *); - -/* Définit les droits associés à une partie de code. */ -void g_binary_portion_set_rights(GBinPortion *, PortionAccessRights); - -/* Fournit les droits associés à une partie de code. */ -PortionAccessRights g_binary_portion_get_rights(const GBinPortion *); - -#ifdef INCLUDE_GTK_SUPPORT - -/* Prépare une astuce concernant une portion pour son affichage. */ -void g_binary_portion_query_tooltip(GBinPortion *, GtkTooltip *); - -/* Représente la portion sur une bande dédiée. */ -void g_binary_portion_draw(const GBinPortion *, GtkStyleContext *, cairo_t *, const GdkRectangle *); - -#endif - -/* Procède à l'inclusion d'une portion dans une autre. */ -void g_binary_portion_include(GBinPortion *, GBinPortion *); - -/* Sens des visites */ -typedef enum _BinaryPortionVisit -{ - BPV_ENTER, /* Arrivée sur une branche */ - BPV_SHOW, /* Visite d'une feuille */ - BPV_EXIT /* Départ d'une branche */ - -} BinaryPortionVisit; - - -/* Fonction appelée à chaque visite de portion.*/ -typedef bool (* visit_portion_fc) (GBinPortion *, GBinPortion *, BinaryPortionVisit, void *); - -/* Parcourt un ensemble de portions binaires. */ -bool g_binary_portion_visit(GBinPortion *, visit_portion_fc, void *); - - - -/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ - - -#ifdef INCLUDE_GTK_SUPPORT - -/* Compte le nombre de portions présentes dans une arborescence. */ -size_t g_binary_portion_count(const GBinPortion *); - -/* Recherche la portion présente à un point donné. */ -GBinPortion *g_binary_portion_find_at_pos(GBinPortion *, gint, GdkRectangle *); - -#endif - -/* Recherche la portion présente à une adresse donnée. */ -GBinPortion *g_binary_portion_find_at_addr(GBinPortion *, const vmpa2t *); - -#ifdef INCLUDE_GTK_SUPPORT - -/* Fournit la position correspondant à une adresse donnée. */ -bool get_binary_portion_addr_from_pos(GBinPortion *, gint, const GdkRectangle *, vmpa2t *); - -/* Fournit l'adresse correspondant à une position donnée. */ -bool get_binary_portion_pos_from_addr(GBinPortion *, const vmpa2t *, const GdkRectangle *, gint *); - -/* Prépare une astuce concernant une portion pour son affichage. */ -gboolean query_tooltip_for_binary_portion(GBinPortion *, gint, gint, const GdkRectangle *, GtkTooltip *); - -#endif - -/* Fournit l'emplacement correspondant à une position physique. */ -bool g_binary_portion_translate_offset_into_vmpa(const GBinPortion *, phys_t, vmpa2t *); - -/* Fournit l'emplacement correspondant à une adresse virtuelle. */ -bool g_binary_portion_translate_address_into_vmpa(const GBinPortion *, virt_t, vmpa2t *); - - - -#endif /* _GLIBEXT_BINPORTION_H */ diff --git a/src/glibext/portion-int-ui.h b/src/glibext/portion-int-ui.h new file mode 100644 index 0000000..a29f53c --- /dev/null +++ b/src/glibext/portion-int-ui.h @@ -0,0 +1,66 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * binportion.h - prototypes pour la définition interne des portions de binaire + * + * Copyright (C) 2019 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 Chrysalide. If not, see . + */ + + +#ifndef _GLIBEXT_BINPORTION_INT_H +#define _GLIBEXT_BINPORTION_INT_H + + +#include "gbinportion.h" + + + +/* Portion de données binaires quelconques (instance) */ +struct _GBinPortion +{ + GObject parent; /* A laisser en premier */ + + char *code; /* Code de la couleur de fond */ + +#ifdef INCLUDE_GTK_SUPPORT + cairo_surface_t *icon; /* Image de représentation */ +#endif + + char *desc; /* Désignation humaine */ + char **text; /* Lignes brutes à représenter */ + size_t lcount; /* Quantité de ces lignes */ + + mrange_t range; /* Emplacement dans le code */ + bool continued; /* Suite d'une découpe ? */ + + PortionAccessRights rights; /* Droits d'accès */ + + GBinPortion **subs; /* Portions incluses */ + size_t count; /* Quantité d'inclusions */ + +}; + +/* Portion de données binaires quelconques (classe) */ +struct _GBinPortionClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _GLIBEXT_BINPORTION_INT_H */ diff --git a/src/glibext/portion-int.h b/src/glibext/portion-int.h new file mode 100644 index 0000000..a29f53c --- /dev/null +++ b/src/glibext/portion-int.h @@ -0,0 +1,66 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * binportion.h - prototypes pour la définition interne des portions de binaire + * + * Copyright (C) 2019 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 Chrysalide. If not, see . + */ + + +#ifndef _GLIBEXT_BINPORTION_INT_H +#define _GLIBEXT_BINPORTION_INT_H + + +#include "gbinportion.h" + + + +/* Portion de données binaires quelconques (instance) */ +struct _GBinPortion +{ + GObject parent; /* A laisser en premier */ + + char *code; /* Code de la couleur de fond */ + +#ifdef INCLUDE_GTK_SUPPORT + cairo_surface_t *icon; /* Image de représentation */ +#endif + + char *desc; /* Désignation humaine */ + char **text; /* Lignes brutes à représenter */ + size_t lcount; /* Quantité de ces lignes */ + + mrange_t range; /* Emplacement dans le code */ + bool continued; /* Suite d'une découpe ? */ + + PortionAccessRights rights; /* Droits d'accès */ + + GBinPortion **subs; /* Portions incluses */ + size_t count; /* Quantité d'inclusions */ + +}; + +/* Portion de données binaires quelconques (classe) */ +struct _GBinPortionClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _GLIBEXT_BINPORTION_INT_H */ diff --git a/src/glibext/portion-ui.c b/src/glibext/portion-ui.c new file mode 100644 index 0000000..12e12fb --- /dev/null +++ b/src/glibext/portion-ui.c @@ -0,0 +1,1724 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * binportion.c - représentation graphique de portions de binaire + * + * Copyright (C) 2013-2019 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 Chrysalide. If not, see . + */ + + +#include "gbinportion.h" + + +#include +#include +#include +#include +#include + + +#include + + +#include "gbinportion-int.h" +#include "../analysis/human/asm/lang.h" +#include "../common/extstr.h" +#include "../common/sort.h" +#include "../core/columns.h" +#include "../glibext/gbinarycursor.h" +#include "../glibext/linegen-int.h" + + + +/* ------------------------------- PORTION DE BINAIRE ------------------------------- */ + + +/* Initialise la classe des portions de données binaires. */ +static void g_binary_portion_class_init(GBinPortionClass *); + +/* Initialise une instance de portion de données binaires. */ +static void g_binary_portion_init(GBinPortion *); + +/* Procède à l'initialisation de l'interface de génération. */ +static void g_binary_portion_interface_init(GLineGeneratorInterface *); + +/* Supprime toutes les références externes. */ +static void g_binary_portion_dispose(GBinPortion *); + +/* Procède à la libération totale de la mémoire. */ +static void g_binary_portion_finalize(GBinPortion *); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Détermine l'aire d'une sous-portion. */ +static bool g_binary_portion_compute_sub_area(const GBinPortion *, phys_t, const GdkRectangle *, GdkRectangle *); + +#endif + + + +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t g_binary_portion_count_lines(const GBinPortion *); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_binary_portion_compute_cursor(const GBinPortion *, gint, size_t, size_t, GLineCursor **); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_binary_portion_contain_cursor(const GBinPortion *, size_t, size_t, const GLineCursor *); + +#endif + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_binary_portion_get_flags(const GBinPortion *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static void g_binary_portion_print(GBinPortion *, GBufferLine *, size_t, size_t, const GBinContent *); + + + +/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ + + +/* Détermine si une portion contient une adresse donnée. */ +static bool g_binary_portion_contains_vmpa(const GBinPortion *, const vmpa2t *); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Recherche la portion présente à une adresse donnée. */ +static GBinPortion *g_binary_portion_find_with_area_at_addr(GBinPortion *, const vmpa2t *, GdkRectangle *); + +/* Détermine si une portion contient une position donnée. */ +static bool g_binary_portion_contains_physical(const GBinPortion *, phys_t); + +/* Détermine si une portion contient une adresse donnée. */ +static bool g_binary_portion_contains_virtual(const GBinPortion *, virt_t); + +#endif + + + +/* ---------------------------------------------------------------------------------- */ +/* PORTION DE BINAIRE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour les portions de données binaires. */ +G_DEFINE_TYPE_WITH_CODE(GBinPortion, g_binary_portion, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_binary_portion_interface_init)); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des portions de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_class_init(GBinPortionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_portion_dispose; + object->finalize = (GObjectFinalizeFunc)g_binary_portion_finalize; + + +} + + +/****************************************************************************** +* * +* Paramètres : portion = instance à initialiser. * +* * +* Description : Initialise une instance de portion de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_init(GBinPortion *portion) +{ + vmpa2t dummy; /* Coquille presque vide */ + + portion->code = NULL; + +#ifdef INCLUDE_GTK_SUPPORT + portion->icon = NULL; +#endif + + portion->desc = NULL; + portion->text = NULL; + portion->lcount = 0; + + init_vmpa(&dummy, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + init_mrange(&portion->range, &dummy, VMPA_NO_VIRTUAL); + + portion->continued = false; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_interface_init(GLineGeneratorInterface *iface) +{ + iface->count = (linegen_count_lines_fc)g_binary_portion_count_lines; +#ifdef INCLUDE_GTK_SUPPORT + iface->compute = (linegen_compute_fc)g_binary_portion_compute_cursor; + iface->contain = (linegen_contain_fc)g_binary_portion_contain_cursor; +#endif + iface->get_flags = (linegen_get_flags_fc)g_binary_portion_get_flags; + iface->print = (linegen_print_fc)g_binary_portion_print; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_dispose(GBinPortion *portion) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < portion->count; i++) + g_clear_object(&portion->subs[i]); + + G_OBJECT_CLASS(g_binary_portion_parent_class)->dispose(G_OBJECT(portion)); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_finalize(GBinPortion *portion) +{ + size_t i; /* Boucle de parcours */ + + if (portion->code != NULL) + free(portion->code); + +#ifdef INCLUDE_GTK_SUPPORT + if (portion->icon != NULL) + cairo_surface_destroy(portion->icon); +#endif + + if (portion->desc != NULL) + free(portion->desc); + + for (i = 0; i < portion->lcount; i++) + free(portion->text[i]); + + if (portion->text != NULL) + free(portion->text); + + if (portion->subs != NULL) + free(portion->subs); + + G_OBJECT_CLASS(g_binary_portion_parent_class)->finalize(G_OBJECT(portion)); + +} + + +/****************************************************************************** +* * +* Paramètres : code = désignation humaine de la couleur de fond. * +* addr = emplacement de la section à conserver. * +* size = taille de la section à conserver. * +* * +* Description : Crée une description de partie de code vierge. * +* * +* Retour : Instance mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPortion *g_binary_portion_new(const char *code, const vmpa2t *addr, phys_t size) +{ + GBinPortion *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_BIN_PORTION, NULL); + + result->code = strdup(code); + + init_mrange(&result->range, addr, size); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : a = premières informations à consulter. * +* b = secondes informations à consulter. * +* * +* Description : Etablit la comparaison ascendante entre deux portions. * +* * +* Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_binary_portion_compare(const GBinPortion **a, const GBinPortion **b) +{ + int result; /* Bilan à retourner */ + const vmpa2t *addr_a; /* Adresse de la portion 'a' */ + const vmpa2t *addr_b; /* Adresse de la portion 'b' */ + + addr_a = get_mrange_addr(&(*a)->range); + addr_b = get_mrange_addr(&(*b)->range); + + result = cmp_vmpa(addr_a, addr_b); + + return result; + +} + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* icon = image miniature de représentation à associer. * +* * +* Description : Attribue à la portion une éventuelle image de représentation.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_set_icon(GBinPortion *portion, cairo_surface_t *icon) +{ + if (icon != NULL) + portion->icon = cairo_surface_reference(icon); + + else + portion->icon = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à consulter. * +* * +* Description : Fournit une éventuelle image de représentation de portion. * +* * +* Retour : Image miniature de représentation associée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +cairo_surface_t *g_binary_portion_get_icon(const GBinPortion *portion) +{ + cairo_surface_t *result; + + result = portion->icon; + + if (result != NULL) + cairo_surface_reference(result); + + return result; + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* desc = nom à donner à la partie. * +* * +* Description : Attribue une description humaine à une partie de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_set_desc(GBinPortion *portion, const char *desc) +{ + size_t i; /* Boucle de parcours */ + GCodingLanguage *lang; /* Langage de sortie préféré */ + + if (portion->desc != NULL) + { + free(portion->desc); + + for (i = 0; i < portion->lcount; i++) + free(portion->text[i]); + + if (portion->text != NULL) + { + free(portion->text); + portion->text = NULL; + } + + } + + if (desc == NULL) + portion->desc = NULL; + + else + { + portion->desc = strdup(desc); + + if (portion->continued) + portion->desc = stradd(portion->desc, _(" (continued)")); + + /* Constitution du rendu */ + + portion->text = calloc(5, sizeof(char *)); + portion->lcount = 5; + + portion->text[0] = strdup("======================================================"); + portion->text[1] = strdup(""); + + asprintf(&portion->text[2], "%s (%s%s%s%s)", portion->desc, _("rights: "), + portion->rights & PAC_READ ? "r" : "-", + portion->rights & PAC_WRITE ? "w" : "-", + portion->rights & PAC_EXEC ? "x" : "-"); + + portion->text[3] = strdup(""); + portion->text[4] = strdup("======================================================"); + + /* Ajout de la touche "commentaires" */ + + lang = g_asm_language_new(); + + g_coding_language_encapsulate_comments(lang, &portion->text, &portion->lcount); + + g_object_unref(G_OBJECT(lang)); + + /* Ajout de deux bordures vides */ + + portion->lcount += 2; + portion->text = realloc(portion->text, portion->lcount * sizeof(char *)); + + memmove(&portion->text[1], &portion->text[0], (portion->lcount - 2) * sizeof(char *)); + + portion->text[0] = NULL; + portion->text[portion->lcount - 1] = NULL; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à consulter. * +* * +* Description : Fournit la description attribuée à une partie de code. * +* * +* Retour : Nom donné à la partie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_binary_portion_get_desc(const GBinPortion *portion) +{ + return portion->desc; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* * +* Description : Fournit l'emplacement d'une partie de code binaire. * +* * +* Retour : Espace de couverture associé à la portion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const mrange_t *g_binary_portion_get_range(const GBinPortion *portion) +{ + return &portion->range; + +} + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* max = taille maximale accordée à la portion. * +* * +* Description : Assure qu'une portion ne dépasse pas une position donnée. * +* * +* Retour : true si la portion a été modifiée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_portion_limit_range(GBinPortion *portion, phys_t max) +{ + bool result; /* Bilan à retourner */ + phys_t current; /* Taille courante */ + + current = get_mrange_length(&portion->range); + + result = (current > max); + + if (result) + set_mrange_length(&portion->range, max); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = portion dont la définition est à metre à jour. * +* * +* Description : Définit la nature de la portion en terme d'originalité. * +* * +* Retour : - * +* * +* Remarques : L'action ne modifie aucunement la description courante. * +* C'est le changement de description qui s'appuie sur la * +* notée ici. * +* * +******************************************************************************/ + +void g_binary_portion_mark_as_continued(GBinPortion *portion, bool continued) +{ + portion->continued = continued; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = portion dont la définition est à consulter. * +* * +* Description : Indique la nature de la portion en terme d'originalité. * +* * +* Retour : true si la portion est la suite d'une portion découpée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_portion_is_continuation(const GBinPortion *portion) +{ + return portion->continued; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* rights = droits d'accès de la partie. * +* * +* Description : Définit les droits associés à une partie de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_set_rights(GBinPortion *portion, PortionAccessRights rights) +{ + portion->rights = rights; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à consulter. * +* * +* Description : Fournit les droits associés à une partie de code. * +* * +* Retour : Droits d'accès de la partie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PortionAccessRights g_binary_portion_get_rights(const GBinPortion *portion) +{ + return portion->rights; + +} + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* tooltip = astuce à compléter. [OUT] * +* * +* Description : Prépare une astuce concernant une portion pour son affichage.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_query_tooltip(GBinPortion *portion, GtkTooltip *tooltip) +{ + char *markup; /* Description à construire */ + VMPA_BUFFER(value); /* Traduction en texte */ + + /* Nom */ + + if (portion->desc != NULL) + { + markup = strdup(""); + markup = stradd(markup, portion->desc); + markup = stradd(markup, "\n"); + markup = stradd(markup, "\n"); + + } + else markup = strdup(""); + + markup = stradd(markup, "taille : "); + mrange_length_to_string(&portion->range, MDS_UNDEFINED, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, "\n"); + + /* Localisation */ + + markup = stradd(markup, ""); + markup = stradd(markup, _("Localisation")); + markup = stradd(markup, "\n"); + + markup = stradd(markup, _("physical: from ")); + + mrange_phys_to_string(&portion->range, MDS_UNDEFINED, true, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, _(" to ")); + mrange_phys_to_string(&portion->range, MDS_UNDEFINED, false, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, "\n"); + + markup = stradd(markup, _("memory: from ")); + + mrange_virt_to_string(&portion->range, MDS_UNDEFINED, true, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, _(" to ")); + mrange_virt_to_string(&portion->range, MDS_UNDEFINED, false, value, NULL); + markup = stradd(markup, value); + + markup = stradd(markup, "\n\n"); + + /* Droits d'accès */ + + markup = stradd(markup, ""); + markup = stradd(markup, _("Rights")); + markup = stradd(markup, "\n"); + + snprintf(value, 2 * VMPA_MAX_SIZE, "%s%s%s", + portion->rights & PAC_READ ? "r" : "-", + portion->rights & PAC_WRITE ? "w" : "-", + portion->rights & PAC_EXEC ? "x" : "-"); + + markup = stradd(markup, value); + + /* Impression finale */ + + gtk_tooltip_set_markup(tooltip, markup); + free(markup); + +} + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = portion mère à consulter. * +* full = taille totale de la couche parente. * +* area = étendue de représentation de la portion mère. * +* sub_area = étendue de représentation de la portion fille. * +* * +* Description : Détermine l'aire d'une sous-portion. * +* * +* Retour : true si la sous-surface a été calculée correctement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_portion_compute_sub_area(const GBinPortion *portion, phys_t full, const GdkRectangle *area, GdkRectangle *sub_area) +{ + phys_t length; /* Taille de la portion */ + phys_t start; /* Position de départ */ + + length = get_mrange_length(&portion->range); + + /* On saute les portions comme le segment GNU_STACK... */ + if (length == 0) return false; + + start = get_phy_addr(get_mrange_addr(&portion->range)); + + sub_area->y = area->y; + sub_area->height = area->height; + + sub_area->x = area->x + (start * area->width) / full; + sub_area->width = (length * area->width) / full; + + return true; + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à consulter. * +* context = contexte graphique associé à la procédure. * +* cr = contexte graphique pour le dessin. * +* area = étendue mise à disposition. * +* * +* Description : Représente la portion sur une bande dédiée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_draw(const GBinPortion *portion, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) +{ + phys_t full; /* Espace total représenté */ + size_t i; /* Boucle de parcours */ + GBinPortion *sub; /* Portion incluse à montrer */ + GdkRectangle sub_area; /* Etendue d'une sous-portion */ + + /* Dessin de la portion courante */ + + cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); + + gtk_style_context_save(context); + + if (portion->code != NULL) + gtk_style_context_add_class(context, portion->code); + + gtk_render_background(context, cr, area->x, area->y, area->width, area->height); + + gtk_render_frame(context, cr, area->x, area->y, area->width, area->height); + + gtk_style_context_restore(context); + + /* Dessin des portions contenues */ + + full = get_mrange_length(&portion->range); + + for (i = 0; i < portion->count; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) + continue; + + g_binary_portion_draw(sub, context, cr, &sub_area); + + } + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = portion principale à compléter. * +* sub = portion à inclure dans la définition courante. * +* * +* Description : Procède à l'inclusion d'une portion dans une autre. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_include(GBinPortion *portion, GBinPortion *sub) +{ + bool found; /* Zone d'accueil trouvée ? */ + size_t best; /* Meilleur point d'insertion */ + size_t missed; /* Indice de zone à déplacer */ + const mrange_t *brange; /* Raccourci de confort d'usage*/ + vmpa2t end; /* Fin de la zone commune */ + phys_t overlapping; /* Taille de la zone commune */ + bool continued; /* Suite d'une découpe ? */ + GBinPortion *left_part; /* Partie intégrable */ + vmpa2t start; /* Départ de la seconde partie */ + GBinPortion *right_part; /* Partie restante */ + + int g_binary_portion_is_included(const GBinPortion **a, const GBinPortion **b) + { + int result; /* Bilan à retourner */ + + result = mrange_includes_mrange(&(*b)->range, &(*a)->range); + + return result; + + } + + found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinPortion *), + (__compar_fn_t)g_binary_portion_is_included, &best); + + if (!found) + { + /** + * On se prépare à réaliser une insertion au niveau courant. Mais des + * portions précédentes sont peut-être à déplacer dans la nouvelle zone : + * + * EXIDX 0x001178 0x00009178 0x00009178 0x00008 0x00008 R 0x4 + * PHDR 0x000034 0x00008034 0x00008034 0x00120 0x00120 R E 0x4 + * INTERP 0x000154 0x00008154 0x00008154 0x00019 0x00019 R 0x1 + * LOAD 0x000000 0x00008000 0x00008000 0x01184 0x01184 R E 0x8000 + * + * On refait donc une passe sur toutes les sous-portions du niveau. + * + * Cette approche a le mérite de traiter également et naturellement les + * sections définies dans le désordre : + * + * [21] .bss NOBITS 00088240 07823c 0018c8 00 WA 0 0 8 + * [22] __libc_freeres_ptrs NOBITS 00089b08 07823c 000018 00 WA 0 0 4 + * [23] .comment PROGBITS 00000000 07823c 000022 01 MS 0 0 1 + * + * Quant aux cas de figure où les portions sont identiques, l'ordre d'appel + * induit l'ordre d'inclusion. + * + * Cela concerne par exemple les zones de données : + * + * En-têtes de section: + * [Nr] Nom Type Adr Décala.Taille ES Fan LN Inf Al + * ... + * [ 2] .data PROGBITS 00010098 000098 00000c 00 WA 0 0 1 + * + * En-têtes de programme: + * Type Décalage Adr. vir. Adr.phys. T.Fich. T.Mém. Fan Alignement + * ... + * LOAD 0x000098 0x00010098 0x00010098 0x0000c 0x0000c RW 0x8000 + * + */ + + int g_binary_portion_track_missed_inclusion(const GBinPortion **a, const GBinPortion **b) + { + int result; /* Bilan à retourner */ + + result = mrange_includes_mrange(&(*a)->range, &(*b)->range); + + return result; + + } + + do + { + found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinPortion *), + (__compar_fn_t)g_binary_portion_track_missed_inclusion, &missed); + + if (found) + { + g_binary_portion_include(sub, portion->subs[missed]); + + portion->subs = _qdelete(portion->subs, &portion->count, sizeof(GBinPortion *), missed); + + } + + } + while (found); + + /** + * Il peut arriver que certaines portions débordent de leur zone d'inclusion : + * + * [24] .bss NOBITS 00012088 002084 000044 00 WA 0 0 8 + * [25] .ARM.attributes ARM_ATTRIBUTES 00000000 002084 000037 00 0 0 1 + * [26] .shstrtab STRTAB 00000000 0020bb 0000ed 00 0 0 1 + * + * Afin de respecter une certaine cohérence dans l'arbre des portions, on choisit + * de découper la portion qui déborde. + */ + + int g_binary_portion_track_partial_inclusion(const GBinPortion **a, const GBinPortion **b) + { + int result; /* Bilan à retourner */ + + result = cmp_mrange_with_vmpa(&(*b)->range, get_mrange_addr(&(*a)->range)); + + return result; + + } + + found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinPortion *), + (__compar_fn_t)g_binary_portion_track_partial_inclusion, &best); + + if (found) + { + brange = &portion->subs[best]->range; + + compute_mrange_end_addr(brange, &end); + overlapping = compute_vmpa_diff(get_mrange_addr(&sub->range), &end); + + continued = g_binary_portion_is_continuation(sub); + + /* Partie contenue */ + + left_part = g_binary_portion_new(sub->code, get_mrange_addr(&sub->range), overlapping); + + g_binary_portion_set_desc(left_part, sub->desc); + g_binary_portion_mark_as_continued(left_part, continued); + g_binary_portion_set_rights(left_part, sub->rights); + + /* Partie qui déborde... */ + + /** + * Comme la portion incluante peut avoir une définition d'adresse + * virtuelle différente de celle de la portion incluse, on recalcule + * la position de départ de la seconde partie de la portion découpée + * à partir des données d'origine. + */ + + copy_vmpa(&start, get_mrange_addr(&sub->range)); + advance_vmpa(&start, overlapping); + + right_part = g_binary_portion_new(sub->code, &start, get_mrange_length(&sub->range) - overlapping); + + if (!continued) + g_binary_portion_mark_as_continued(right_part, true); + + g_binary_portion_set_desc(right_part, sub->desc); + + if (continued) + g_binary_portion_mark_as_continued(right_part, true); + + g_binary_portion_set_rights(right_part, sub->rights); + + /* Inclusions des parties */ + + g_binary_portion_include(portion, left_part); + g_binary_portion_include(portion, right_part); + + g_object_unref(G_OBJECT(sub)); + + } + + else + portion->subs = qinsert(portion->subs, &portion->count, sizeof(GBinPortion *), + (__compar_fn_t)g_binary_portion_compare, &sub); + + } + + /* Poursuite de l'inclusion dans la sous-portion adaptée... */ + else + g_binary_portion_include(portion->subs[best], sub); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = première couche amorçant la visite. * +* visitor = fonction à appeler à chaque étape de la descente. * +* data = adresse pointant vers des données de l'utilisateur.* +* * +* Description : Parcourt un ensemble de portions binaires. * +* * +* Retour : true si la visite a été jusqu'à son terme, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void *data) +{ + bool result; /* Etat à retourner */ + + bool visit_portion(GBinPortion *p, GBinPortion *pp) + { + bool ret; /* Etat à retourner */ + size_t i; /* Boucle de parcours */ + + if (p->count == 0) + ret = visitor(p, pp, BPV_SHOW, data); + + else + { + ret = visitor(p, pp, BPV_ENTER, data); + + for (i = 0; i < p->count && ret; i++) + ret = visit_portion(p->subs[i], p); + + if (ret) + ret = visitor(p, pp, BPV_EXIT, data); + + } + + return ret; + + } + + result = visit_portion(portion, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OFFRE DE CAPACITES DE GENERATION */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_binary_portion_count_lines(const GBinPortion *portion) +{ + return portion->lcount; + +} + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* cursor = emplacement à constituer. [OUT] * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_compute_cursor(const GBinPortion *portion, gint x, size_t index, size_t repeat, GLineCursor **cursor) +{ + *cursor = g_binary_cursor_new(); + + g_binary_cursor_update(G_BINARY_CURSOR(*cursor), get_mrange_addr(&portion->range)); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* cursor = emplacement à analyser. * +* * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* * +* Retour : Bilan de la détermination, utilisable en comparaisons. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int g_binary_portion_contain_cursor(const GBinPortion *portion, size_t index, size_t repeat, const GLineCursor *cursor) +{ + int result; /* Conclusion à retourner */ + vmpa2t addr; /* Autre emplacement à comparer*/ + + assert(G_IS_BINARY_CURSOR(cursor)); + + g_binary_cursor_retrieve(G_BINARY_CURSOR(cursor), &addr); + + result = cmp_vmpa(&addr, get_mrange_addr(&portion->range)); + + return result; + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Renseigne sur les propriétés liées à un générateur. * +* * +* Retour : Propriétés particulières associées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static BufferLineFlags g_binary_portion_get_flags(const GBinPortion *portion, size_t index, size_t repeat) +{ + return (repeat == 0 ? BLF_WIDTH_MANAGER : BLF_NONE); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à utiliser pour l'impression. * +* line = ligne de rendu à compléter. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* content = éventuel contenu binaire brut à imprimer. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_print(GBinPortion *portion, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) +{ + assert(repeat < portion->lcount); + + g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&portion->range)); + + g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&portion->range)); + + if (portion->text[repeat] != NULL) + { + g_buffer_line_start_merge_at(line, DLC_ASSEMBLY_LABEL); + + g_buffer_line_append_text(line, DLC_ASSEMBLY_LABEL, SL(portion->text[repeat]), RTT_COMMENT, NULL); + + } + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* PARCOURS D'ENSEMBLES DE PORTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* * +* Description : Compte le nombre de portions présentes dans une arborescence.* +* * +* Retour : Quantité de portions présentes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_binary_portion_count(const GBinPortion *portion) +{ + size_t result; /* Quantité à retourner */ + + + size_t measure_portion_size(const GBinPortion *root) + { + size_t count; /* Nombre de trouvailles */ + size_t i; /* Boucle de parcours */ + + count = 1; + + for (i = 0; i < root->count; i++) + count += measure_portion_size(root->subs[i]); + + return count; + + } + + + result = measure_portion_size(portion); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* x = abscisse du point de recherche. * +* area = étendue de portion mère, puis celle trouvée. [OUT] * +* * +* Description : Recherche la portion présente à un point donné. * +* * +* Retour : Portion trouvée à l'endroit indiqué. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPortion *g_binary_portion_find_at_pos(GBinPortion *portion, gint x, GdkRectangle *area) +{ + GBinPortion *result; /* Portion à retourner */ + phys_t full; /* Espace total représenté */ + size_t i; /* Boucle de parcours */ + GBinPortion *sub; /* Portion incluse à traiter */ + GdkRectangle sub_area; /* Etendue d'une sous-portion */ + + result = NULL; + + full = get_mrange_length(&portion->range); + + for (i = 0; i < portion->count && result == NULL; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) + continue; + + if (sub_area.x <= x && x < (sub_area.x + sub_area.width)) + { + result = g_binary_portion_find_at_pos(sub, x, &sub_area); + + if (result != NULL) + *area = sub_area; + + } + + } + + if (result == NULL) + { + result = portion; + g_object_ref(G_OBJECT(result)); + } + + return result; + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = portion mère à consulter. * +* addr = adresse du point de recherche. * +* * +* Description : Détermine si une portion contient une adresse donnée. * +* * +* Retour : true ou false selon le résultat. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_portion_contains_vmpa(const GBinPortion *portion, const vmpa2t *addr) +{ + bool result; /* Bilan à retourner */ + const mrange_t *range; /* Emplacement de portion */ + + result = false; + + range = g_binary_portion_get_range(portion); + + /* Portion non allouée en mémoire : on écarte */ + if (!has_virt_addr(get_mrange_addr(range))) + goto not_found; + + result = mrange_contains_addr(range, addr); + + not_found: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* addr = adresse du point de recherche. * +* * +* Description : Recherche la portion présente à une adresse donnée. * +* * +* Retour : Portion trouvée à l'endroit indiqué. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *addr) +{ + GBinPortion *result; /* Portion à retourner */ + phys_t full; /* Espace total représenté */ + size_t i; /* Boucle de parcours #1 */ + GBinPortion *sub; /* Portion incluse à traiter */ + + result = NULL; + + full = get_mrange_length(&portion->range); + + for (i = 0; i < portion->count && result == NULL; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_contains_vmpa(sub, addr)) + continue; + + result = g_binary_portion_find_at_addr(sub, addr); + + } + + if (result == NULL) + { + result = portion; + g_object_ref(G_OBJECT(result)); + } + + return result; + +} + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* addr = adresse du point de recherche. * +* area = étendue de portion mère, puis celle trouvée. [OUT] * +* * +* Description : Recherche la portion présente à une adresse donnée. * +* * +* Retour : Portion trouvée à l'endroit indiqué. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBinPortion *g_binary_portion_find_with_area_at_addr(GBinPortion *portion, const vmpa2t *addr, GdkRectangle *area) +{ + GBinPortion *result; /* Portion à retourner */ + phys_t full; /* Espace total représenté */ + size_t i; /* Boucle de parcours #1 */ + GBinPortion *sub; /* Portion incluse à traiter */ + GdkRectangle sub_area; /* Etendue d'une sous-portion */ + + result = NULL; + + full = get_mrange_length(&portion->range); + + for (i = 0; i < portion->count && result == NULL; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_contains_vmpa(sub, addr)) + continue; + + if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) + continue; + + result = g_binary_portion_find_with_area_at_addr(sub, addr, &sub_area); + + if (result != NULL) + *area = sub_area; + + } + + if (result == NULL) + { + result = portion; + g_object_ref(G_OBJECT(result)); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : root = couche de portions à parcourir pour les recherches. * +* x = abscisse du point de recherche. * +* area = étendue de représentation de la portion mère. * +* addr = adresse correspondante. [OUT] * +* * +* Description : Fournit la position correspondant à une adresse donnée. * +* * +* Retour : Succès de la traduction. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_binary_portion_addr_from_pos(GBinPortion *root, gint x, const GdkRectangle *area, vmpa2t *addr) +{ + GdkRectangle owner_area; /* Aire de contenance */ + GBinPortion *owner; /* Conteneur propriétaire */ + + owner_area = *area; + + owner = g_binary_portion_find_at_pos(root, x, &owner_area); + if (owner == NULL) return false; + + copy_vmpa(addr, get_mrange_addr(&owner->range)); + + advance_vmpa(addr, (get_mrange_length(&owner->range) * (x - owner_area.x)) / owner_area.width); + + g_object_unref(G_OBJECT(owner)); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : root = couche de portions à parcourir pour les recherches. * +* addr = adresse du point de recherche. * +* area = étendue de représentation de la portion mère. * +* x = position correspondante. [OUT] * +* * +* Description : Fournit l'adresse correspondant à une position donnée. * +* * +* Retour : Succès de la traduction. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_binary_portion_pos_from_addr(GBinPortion *root, const vmpa2t *addr, const GdkRectangle *area, gint *x) +{ + GdkRectangle owner_area; /* Aire de contenance */ + GBinPortion *owner; /* Conteneur propriétaire */ + phys_t diff; /* Décalage à appliquer */ + + owner_area = *area; + + owner = g_binary_portion_find_with_area_at_addr(root, addr, &owner_area); + if (owner == NULL) return false; + + diff = compute_vmpa_diff(addr, get_mrange_addr(&owner->range)); + + *x = owner_area.x + (diff * owner_area.width) / get_mrange_length(&owner->range); + + g_object_unref(G_OBJECT(owner)); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : layer = couche de portions à consulter. * +* x = abscisse du point de recherche. * +* y = ordonnée du point de recherche. * +* area = étendue de représentation de la portion mère. * +* tooltip = astuce à compléter. [OUT] * +* * +* Description : Prépare une astuce concernant une portion pour son affichage.* +* * +* Retour : TRUE pour valider l'affichage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gboolean query_tooltip_for_binary_portion(GBinPortion *root, gint x, gint y, const GdkRectangle *area, GtkTooltip *tooltip) +{ + GBinPortion *selected; /* Portion à décrire ici */ + + selected = g_binary_portion_find_at_pos(root, x, (GdkRectangle []) { *area }); + if (selected == NULL) return FALSE; + + g_binary_portion_query_tooltip(selected, tooltip); + + g_object_unref(G_OBJECT(selected)); + + return TRUE; + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = portion mère à consulter. * +* off = position physique du point de recherche. * +* * +* Description : Détermine si une portion contient une position donnée. * +* * +* Retour : true ou false selon le résultat. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_portion_contains_physical(const GBinPortion *portion, phys_t off) +{ + bool result; /* Bilan à retourner */ + const mrange_t *range; /* Emplacement de portion */ + const vmpa2t *addr; /* Départ de la portion */ + + range = g_binary_portion_get_range(portion); + addr = get_mrange_addr(range); + + if (!has_phys_addr(addr)) + result = false; + + else + result = (addr->physical <= off && off < (addr->physical + range->length)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* off = position physique à retrouver. * +* pos = position correspondante. [OUT] * +* * +* Description : Fournit l'emplacement correspondant à une position physique. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_portion_translate_offset_into_vmpa(const GBinPortion *portion, phys_t off, vmpa2t *pos) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours #1 */ + GBinPortion *sub; /* Portion incluse à traiter */ + const mrange_t *range; /* Emplacement de portion */ + const vmpa2t *addr; /* Départ de la portion */ + + result = false; + + for (i = 0; i < portion->count; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_contains_physical(sub, off)) + continue; + + result = g_binary_portion_translate_offset_into_vmpa(sub, off, pos); + + break; + + } + + if (i == portion->count) + { + result = g_binary_portion_contains_physical(portion, off); + + if (result) + { + range = g_binary_portion_get_range(portion); + addr = get_mrange_addr(range); + + if (has_virt_addr(get_mrange_addr(range))) + init_vmpa(pos, off, addr->virtual + off - addr->physical); + + else + init_vmpa(pos, off, VMPA_NO_VIRTUAL); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = portion mère à consulter. * +* virt = adresse virtuelle du point de recherche. * +* * +* Description : Détermine si une portion contient une adresse donnée. * +* * +* Retour : true ou false selon le résultat. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_portion_contains_virtual(const GBinPortion *portion, virt_t virt) +{ + bool result; /* Bilan à retourner */ + const mrange_t *range; /* Emplacement de portion */ + const vmpa2t *addr; /* Départ de la portion */ + + range = g_binary_portion_get_range(portion); + addr = get_mrange_addr(range); + + if (!has_virt_addr(addr)) + result = false; + + else + result = (addr->virtual <= virt && virt < (addr->virtual + range->length)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* virt = adresse virtuelle à retrouver. * +* pos = position correspondante. [OUT] * +* * +* Description : Fournit l'emplacement correspondant à une adresse virtuelle. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_portion_translate_address_into_vmpa(const GBinPortion *portion, virt_t virt, vmpa2t *pos) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours #1 */ + GBinPortion *sub; /* Portion incluse à traiter */ + const mrange_t *range; /* Emplacement de portion */ + const vmpa2t *addr; /* Départ de la portion */ + + result = false; + + for (i = 0; i < portion->count; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_contains_virtual(sub, virt)) + continue; + + result = g_binary_portion_translate_address_into_vmpa(sub, virt, pos); + + break; + + } + + if (i == portion->count) + { + result = g_binary_portion_contains_virtual(portion, virt); + + if (result) + { + range = g_binary_portion_get_range(portion); + addr = get_mrange_addr(range); + + if (has_phys_addr(addr) && has_virt_addr(addr)) + init_vmpa(pos, addr->physical + virt - addr->virtual, virt); + + else + init_vmpa(pos, VMPA_NO_PHYSICAL, virt); + + } + + } + + return result; + +} diff --git a/src/glibext/portion-ui.h b/src/glibext/portion-ui.h new file mode 100644 index 0000000..ea4b4aa --- /dev/null +++ b/src/glibext/portion-ui.h @@ -0,0 +1,194 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * binportion.h - prototypes pour la représentation graphique de portions de binaire + * + * Copyright (C) 2013-2019 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 Chrysalide. If not, see . + */ + + +#ifndef _GLIBEXT_BINPORTION_H +#define _GLIBEXT_BINPORTION_H + + +#include +#include +#ifdef INCLUDE_GTK_SUPPORT +# include +#endif + + +#include "../arch/vmpa.h" +#include "../common/fnv1a.h" + + + +/* ------------------------------- PORTION DE BINAIRE ------------------------------- */ + + +/** + * Couleurs de représentation. + */ + +#define BPC_RAW "binportion-raw" +#define BPC_CODE "binportion-code" +#define BPC_DATA "binportion-data" +#define BPC_DATA_RO "binportion-data-ro" +#define BPC_DISASS_ERROR "binportion-disassembly-error" + + +#define G_TYPE_BIN_PORTION (g_binary_portion_get_type()) +#define G_BIN_PORTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BIN_PORTION, GBinPortion)) +#define G_IS_BIN_PORTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BIN_PORTION)) +#define G_BIN_PORTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BIN_PORTION, GBinPortionClass)) +#define G_IS_BIN_PORTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BIN_PORTION)) +#define G_BIN_PORTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BIN_PORTION, GBinPortionClass)) + + +/* Portion de données binaires quelconques (instance) */ +typedef struct _GBinPortion GBinPortion; + +/* Portion de données binaires quelconques (classe) */ +typedef struct _GBinPortionClass GBinPortionClass; + + +/* Droits d'accès à une portion */ +typedef enum _PortionAccessRights +{ + PAC_NONE = (0 << 0), /* Aucun */ + PAC_READ = (1 << 0), /* Lecture */ + PAC_WRITE = (1 << 1), /* Ecriture */ + PAC_EXEC = (1 << 2) /* Exécution */ + +} PortionAccessRights; + + +#define PAC_ALL ((PortionAccessRights)(PAC_READ | PAC_WRITE | PAC_EXEC)) + + +/* Indique le type défini par la GLib pour les portions de données binaires. */ +GType g_binary_portion_get_type(void); + +/* Crée une description de partie de code vierge. */ +GBinPortion *g_binary_portion_new(const char *, const vmpa2t *, phys_t); + +/* Etablit la comparaison ascendante entre deux portions. */ +int g_binary_portion_compare(const GBinPortion **, const GBinPortion **); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Attribue à la portion une éventuelle image de représentation. */ +void g_binary_portion_set_icon(GBinPortion *, cairo_surface_t *); + +/* Fournit une éventuelle image de représentation de portion. */ +cairo_surface_t *g_binary_portion_get_icon(const GBinPortion *); + +#endif + +/* Attribue une description humaine à une partie de code. */ +void g_binary_portion_set_desc(GBinPortion *, const char *); + +/* Fournit la description attribuée à une partie de code. */ +const char *g_binary_portion_get_desc(const GBinPortion *); + +/* Fournit l'emplacement d'une partie de code binaire. */ +const mrange_t *g_binary_portion_get_range(const GBinPortion *); + +/* Assure qu'une portion ne dépasse pas une position donnée. */ +bool g_binary_portion_limit_range(GBinPortion *, phys_t); + +/* Définit la nature de la portion en terme d'originalité. */ +void g_binary_portion_mark_as_continued(GBinPortion *, bool); + +/* Indique la nature de la portion en terme d'originalité. */ +bool g_binary_portion_is_continuation(const GBinPortion *); + +/* Définit les droits associés à une partie de code. */ +void g_binary_portion_set_rights(GBinPortion *, PortionAccessRights); + +/* Fournit les droits associés à une partie de code. */ +PortionAccessRights g_binary_portion_get_rights(const GBinPortion *); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Prépare une astuce concernant une portion pour son affichage. */ +void g_binary_portion_query_tooltip(GBinPortion *, GtkTooltip *); + +/* Représente la portion sur une bande dédiée. */ +void g_binary_portion_draw(const GBinPortion *, GtkStyleContext *, cairo_t *, const GdkRectangle *); + +#endif + +/* Procède à l'inclusion d'une portion dans une autre. */ +void g_binary_portion_include(GBinPortion *, GBinPortion *); + +/* Sens des visites */ +typedef enum _BinaryPortionVisit +{ + BPV_ENTER, /* Arrivée sur une branche */ + BPV_SHOW, /* Visite d'une feuille */ + BPV_EXIT /* Départ d'une branche */ + +} BinaryPortionVisit; + + +/* Fonction appelée à chaque visite de portion.*/ +typedef bool (* visit_portion_fc) (GBinPortion *, GBinPortion *, BinaryPortionVisit, void *); + +/* Parcourt un ensemble de portions binaires. */ +bool g_binary_portion_visit(GBinPortion *, visit_portion_fc, void *); + + + +/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ + + +#ifdef INCLUDE_GTK_SUPPORT + +/* Compte le nombre de portions présentes dans une arborescence. */ +size_t g_binary_portion_count(const GBinPortion *); + +/* Recherche la portion présente à un point donné. */ +GBinPortion *g_binary_portion_find_at_pos(GBinPortion *, gint, GdkRectangle *); + +#endif + +/* Recherche la portion présente à une adresse donnée. */ +GBinPortion *g_binary_portion_find_at_addr(GBinPortion *, const vmpa2t *); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Fournit la position correspondant à une adresse donnée. */ +bool get_binary_portion_addr_from_pos(GBinPortion *, gint, const GdkRectangle *, vmpa2t *); + +/* Fournit l'adresse correspondant à une position donnée. */ +bool get_binary_portion_pos_from_addr(GBinPortion *, const vmpa2t *, const GdkRectangle *, gint *); + +/* Prépare une astuce concernant une portion pour son affichage. */ +gboolean query_tooltip_for_binary_portion(GBinPortion *, gint, gint, const GdkRectangle *, GtkTooltip *); + +#endif + +/* Fournit l'emplacement correspondant à une position physique. */ +bool g_binary_portion_translate_offset_into_vmpa(const GBinPortion *, phys_t, vmpa2t *); + +/* Fournit l'emplacement correspondant à une adresse virtuelle. */ +bool g_binary_portion_translate_address_into_vmpa(const GBinPortion *, virt_t, vmpa2t *); + + + +#endif /* _GLIBEXT_BINPORTION_H */ diff --git a/src/glibext/portion.c b/src/glibext/portion.c new file mode 100644 index 0000000..12e12fb --- /dev/null +++ b/src/glibext/portion.c @@ -0,0 +1,1724 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * binportion.c - représentation graphique de portions de binaire + * + * Copyright (C) 2013-2019 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 Chrysalide. If not, see . + */ + + +#include "gbinportion.h" + + +#include +#include +#include +#include +#include + + +#include + + +#include "gbinportion-int.h" +#include "../analysis/human/asm/lang.h" +#include "../common/extstr.h" +#include "../common/sort.h" +#include "../core/columns.h" +#include "../glibext/gbinarycursor.h" +#include "../glibext/linegen-int.h" + + + +/* ------------------------------- PORTION DE BINAIRE ------------------------------- */ + + +/* Initialise la classe des portions de données binaires. */ +static void g_binary_portion_class_init(GBinPortionClass *); + +/* Initialise une instance de portion de données binaires. */ +static void g_binary_portion_init(GBinPortion *); + +/* Procède à l'initialisation de l'interface de génération. */ +static void g_binary_portion_interface_init(GLineGeneratorInterface *); + +/* Supprime toutes les références externes. */ +static void g_binary_portion_dispose(GBinPortion *); + +/* Procède à la libération totale de la mémoire. */ +static void g_binary_portion_finalize(GBinPortion *); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Détermine l'aire d'une sous-portion. */ +static bool g_binary_portion_compute_sub_area(const GBinPortion *, phys_t, const GdkRectangle *, GdkRectangle *); + +#endif + + + +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Indique le nombre de ligne prêtes à être générées. */ +static size_t g_binary_portion_count_lines(const GBinPortion *); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_binary_portion_compute_cursor(const GBinPortion *, gint, size_t, size_t, GLineCursor **); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_binary_portion_contain_cursor(const GBinPortion *, size_t, size_t, const GLineCursor *); + +#endif + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_binary_portion_get_flags(const GBinPortion *, size_t, size_t); + +/* Imprime dans une ligne de rendu le contenu représenté. */ +static void g_binary_portion_print(GBinPortion *, GBufferLine *, size_t, size_t, const GBinContent *); + + + +/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ + + +/* Détermine si une portion contient une adresse donnée. */ +static bool g_binary_portion_contains_vmpa(const GBinPortion *, const vmpa2t *); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Recherche la portion présente à une adresse donnée. */ +static GBinPortion *g_binary_portion_find_with_area_at_addr(GBinPortion *, const vmpa2t *, GdkRectangle *); + +/* Détermine si une portion contient une position donnée. */ +static bool g_binary_portion_contains_physical(const GBinPortion *, phys_t); + +/* Détermine si une portion contient une adresse donnée. */ +static bool g_binary_portion_contains_virtual(const GBinPortion *, virt_t); + +#endif + + + +/* ---------------------------------------------------------------------------------- */ +/* PORTION DE BINAIRE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour les portions de données binaires. */ +G_DEFINE_TYPE_WITH_CODE(GBinPortion, g_binary_portion, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_binary_portion_interface_init)); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des portions de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_class_init(GBinPortionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_portion_dispose; + object->finalize = (GObjectFinalizeFunc)g_binary_portion_finalize; + + +} + + +/****************************************************************************** +* * +* Paramètres : portion = instance à initialiser. * +* * +* Description : Initialise une instance de portion de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_init(GBinPortion *portion) +{ + vmpa2t dummy; /* Coquille presque vide */ + + portion->code = NULL; + +#ifdef INCLUDE_GTK_SUPPORT + portion->icon = NULL; +#endif + + portion->desc = NULL; + portion->text = NULL; + portion->lcount = 0; + + init_vmpa(&dummy, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + init_mrange(&portion->range, &dummy, VMPA_NO_VIRTUAL); + + portion->continued = false; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_interface_init(GLineGeneratorInterface *iface) +{ + iface->count = (linegen_count_lines_fc)g_binary_portion_count_lines; +#ifdef INCLUDE_GTK_SUPPORT + iface->compute = (linegen_compute_fc)g_binary_portion_compute_cursor; + iface->contain = (linegen_contain_fc)g_binary_portion_contain_cursor; +#endif + iface->get_flags = (linegen_get_flags_fc)g_binary_portion_get_flags; + iface->print = (linegen_print_fc)g_binary_portion_print; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_dispose(GBinPortion *portion) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < portion->count; i++) + g_clear_object(&portion->subs[i]); + + G_OBJECT_CLASS(g_binary_portion_parent_class)->dispose(G_OBJECT(portion)); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_finalize(GBinPortion *portion) +{ + size_t i; /* Boucle de parcours */ + + if (portion->code != NULL) + free(portion->code); + +#ifdef INCLUDE_GTK_SUPPORT + if (portion->icon != NULL) + cairo_surface_destroy(portion->icon); +#endif + + if (portion->desc != NULL) + free(portion->desc); + + for (i = 0; i < portion->lcount; i++) + free(portion->text[i]); + + if (portion->text != NULL) + free(portion->text); + + if (portion->subs != NULL) + free(portion->subs); + + G_OBJECT_CLASS(g_binary_portion_parent_class)->finalize(G_OBJECT(portion)); + +} + + +/****************************************************************************** +* * +* Paramètres : code = désignation humaine de la couleur de fond. * +* addr = emplacement de la section à conserver. * +* size = taille de la section à conserver. * +* * +* Description : Crée une description de partie de code vierge. * +* * +* Retour : Instance mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPortion *g_binary_portion_new(const char *code, const vmpa2t *addr, phys_t size) +{ + GBinPortion *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_BIN_PORTION, NULL); + + result->code = strdup(code); + + init_mrange(&result->range, addr, size); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : a = premières informations à consulter. * +* b = secondes informations à consulter. * +* * +* Description : Etablit la comparaison ascendante entre deux portions. * +* * +* Retour : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b). * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_binary_portion_compare(const GBinPortion **a, const GBinPortion **b) +{ + int result; /* Bilan à retourner */ + const vmpa2t *addr_a; /* Adresse de la portion 'a' */ + const vmpa2t *addr_b; /* Adresse de la portion 'b' */ + + addr_a = get_mrange_addr(&(*a)->range); + addr_b = get_mrange_addr(&(*b)->range); + + result = cmp_vmpa(addr_a, addr_b); + + return result; + +} + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* icon = image miniature de représentation à associer. * +* * +* Description : Attribue à la portion une éventuelle image de représentation.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_set_icon(GBinPortion *portion, cairo_surface_t *icon) +{ + if (icon != NULL) + portion->icon = cairo_surface_reference(icon); + + else + portion->icon = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à consulter. * +* * +* Description : Fournit une éventuelle image de représentation de portion. * +* * +* Retour : Image miniature de représentation associée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +cairo_surface_t *g_binary_portion_get_icon(const GBinPortion *portion) +{ + cairo_surface_t *result; + + result = portion->icon; + + if (result != NULL) + cairo_surface_reference(result); + + return result; + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* desc = nom à donner à la partie. * +* * +* Description : Attribue une description humaine à une partie de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_set_desc(GBinPortion *portion, const char *desc) +{ + size_t i; /* Boucle de parcours */ + GCodingLanguage *lang; /* Langage de sortie préféré */ + + if (portion->desc != NULL) + { + free(portion->desc); + + for (i = 0; i < portion->lcount; i++) + free(portion->text[i]); + + if (portion->text != NULL) + { + free(portion->text); + portion->text = NULL; + } + + } + + if (desc == NULL) + portion->desc = NULL; + + else + { + portion->desc = strdup(desc); + + if (portion->continued) + portion->desc = stradd(portion->desc, _(" (continued)")); + + /* Constitution du rendu */ + + portion->text = calloc(5, sizeof(char *)); + portion->lcount = 5; + + portion->text[0] = strdup("======================================================"); + portion->text[1] = strdup(""); + + asprintf(&portion->text[2], "%s (%s%s%s%s)", portion->desc, _("rights: "), + portion->rights & PAC_READ ? "r" : "-", + portion->rights & PAC_WRITE ? "w" : "-", + portion->rights & PAC_EXEC ? "x" : "-"); + + portion->text[3] = strdup(""); + portion->text[4] = strdup("======================================================"); + + /* Ajout de la touche "commentaires" */ + + lang = g_asm_language_new(); + + g_coding_language_encapsulate_comments(lang, &portion->text, &portion->lcount); + + g_object_unref(G_OBJECT(lang)); + + /* Ajout de deux bordures vides */ + + portion->lcount += 2; + portion->text = realloc(portion->text, portion->lcount * sizeof(char *)); + + memmove(&portion->text[1], &portion->text[0], (portion->lcount - 2) * sizeof(char *)); + + portion->text[0] = NULL; + portion->text[portion->lcount - 1] = NULL; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à consulter. * +* * +* Description : Fournit la description attribuée à une partie de code. * +* * +* Retour : Nom donné à la partie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_binary_portion_get_desc(const GBinPortion *portion) +{ + return portion->desc; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* * +* Description : Fournit l'emplacement d'une partie de code binaire. * +* * +* Retour : Espace de couverture associé à la portion. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const mrange_t *g_binary_portion_get_range(const GBinPortion *portion) +{ + return &portion->range; + +} + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* max = taille maximale accordée à la portion. * +* * +* Description : Assure qu'une portion ne dépasse pas une position donnée. * +* * +* Retour : true si la portion a été modifiée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_portion_limit_range(GBinPortion *portion, phys_t max) +{ + bool result; /* Bilan à retourner */ + phys_t current; /* Taille courante */ + + current = get_mrange_length(&portion->range); + + result = (current > max); + + if (result) + set_mrange_length(&portion->range, max); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = portion dont la définition est à metre à jour. * +* * +* Description : Définit la nature de la portion en terme d'originalité. * +* * +* Retour : - * +* * +* Remarques : L'action ne modifie aucunement la description courante. * +* C'est le changement de description qui s'appuie sur la * +* notée ici. * +* * +******************************************************************************/ + +void g_binary_portion_mark_as_continued(GBinPortion *portion, bool continued) +{ + portion->continued = continued; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = portion dont la définition est à consulter. * +* * +* Description : Indique la nature de la portion en terme d'originalité. * +* * +* Retour : true si la portion est la suite d'une portion découpée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_portion_is_continuation(const GBinPortion *portion) +{ + return portion->continued; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* rights = droits d'accès de la partie. * +* * +* Description : Définit les droits associés à une partie de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_set_rights(GBinPortion *portion, PortionAccessRights rights) +{ + portion->rights = rights; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à consulter. * +* * +* Description : Fournit les droits associés à une partie de code. * +* * +* Retour : Droits d'accès de la partie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PortionAccessRights g_binary_portion_get_rights(const GBinPortion *portion) +{ + return portion->rights; + +} + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à mettre à jour. * +* tooltip = astuce à compléter. [OUT] * +* * +* Description : Prépare une astuce concernant une portion pour son affichage.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_query_tooltip(GBinPortion *portion, GtkTooltip *tooltip) +{ + char *markup; /* Description à construire */ + VMPA_BUFFER(value); /* Traduction en texte */ + + /* Nom */ + + if (portion->desc != NULL) + { + markup = strdup(""); + markup = stradd(markup, portion->desc); + markup = stradd(markup, "\n"); + markup = stradd(markup, "\n"); + + } + else markup = strdup(""); + + markup = stradd(markup, "taille : "); + mrange_length_to_string(&portion->range, MDS_UNDEFINED, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, "\n"); + + /* Localisation */ + + markup = stradd(markup, ""); + markup = stradd(markup, _("Localisation")); + markup = stradd(markup, "\n"); + + markup = stradd(markup, _("physical: from ")); + + mrange_phys_to_string(&portion->range, MDS_UNDEFINED, true, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, _(" to ")); + mrange_phys_to_string(&portion->range, MDS_UNDEFINED, false, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, "\n"); + + markup = stradd(markup, _("memory: from ")); + + mrange_virt_to_string(&portion->range, MDS_UNDEFINED, true, value, NULL); + markup = stradd(markup, value); + markup = stradd(markup, _(" to ")); + mrange_virt_to_string(&portion->range, MDS_UNDEFINED, false, value, NULL); + markup = stradd(markup, value); + + markup = stradd(markup, "\n\n"); + + /* Droits d'accès */ + + markup = stradd(markup, ""); + markup = stradd(markup, _("Rights")); + markup = stradd(markup, "\n"); + + snprintf(value, 2 * VMPA_MAX_SIZE, "%s%s%s", + portion->rights & PAC_READ ? "r" : "-", + portion->rights & PAC_WRITE ? "w" : "-", + portion->rights & PAC_EXEC ? "x" : "-"); + + markup = stradd(markup, value); + + /* Impression finale */ + + gtk_tooltip_set_markup(tooltip, markup); + free(markup); + +} + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = portion mère à consulter. * +* full = taille totale de la couche parente. * +* area = étendue de représentation de la portion mère. * +* sub_area = étendue de représentation de la portion fille. * +* * +* Description : Détermine l'aire d'une sous-portion. * +* * +* Retour : true si la sous-surface a été calculée correctement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_portion_compute_sub_area(const GBinPortion *portion, phys_t full, const GdkRectangle *area, GdkRectangle *sub_area) +{ + phys_t length; /* Taille de la portion */ + phys_t start; /* Position de départ */ + + length = get_mrange_length(&portion->range); + + /* On saute les portions comme le segment GNU_STACK... */ + if (length == 0) return false; + + start = get_phy_addr(get_mrange_addr(&portion->range)); + + sub_area->y = area->y; + sub_area->height = area->height; + + sub_area->x = area->x + (start * area->width) / full; + sub_area->width = (length * area->width) / full; + + return true; + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = description de partie à consulter. * +* context = contexte graphique associé à la procédure. * +* cr = contexte graphique pour le dessin. * +* area = étendue mise à disposition. * +* * +* Description : Représente la portion sur une bande dédiée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_draw(const GBinPortion *portion, GtkStyleContext *context, cairo_t *cr, const GdkRectangle *area) +{ + phys_t full; /* Espace total représenté */ + size_t i; /* Boucle de parcours */ + GBinPortion *sub; /* Portion incluse à montrer */ + GdkRectangle sub_area; /* Etendue d'une sous-portion */ + + /* Dessin de la portion courante */ + + cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); + + gtk_style_context_save(context); + + if (portion->code != NULL) + gtk_style_context_add_class(context, portion->code); + + gtk_render_background(context, cr, area->x, area->y, area->width, area->height); + + gtk_render_frame(context, cr, area->x, area->y, area->width, area->height); + + gtk_style_context_restore(context); + + /* Dessin des portions contenues */ + + full = get_mrange_length(&portion->range); + + for (i = 0; i < portion->count; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) + continue; + + g_binary_portion_draw(sub, context, cr, &sub_area); + + } + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = portion principale à compléter. * +* sub = portion à inclure dans la définition courante. * +* * +* Description : Procède à l'inclusion d'une portion dans une autre. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_portion_include(GBinPortion *portion, GBinPortion *sub) +{ + bool found; /* Zone d'accueil trouvée ? */ + size_t best; /* Meilleur point d'insertion */ + size_t missed; /* Indice de zone à déplacer */ + const mrange_t *brange; /* Raccourci de confort d'usage*/ + vmpa2t end; /* Fin de la zone commune */ + phys_t overlapping; /* Taille de la zone commune */ + bool continued; /* Suite d'une découpe ? */ + GBinPortion *left_part; /* Partie intégrable */ + vmpa2t start; /* Départ de la seconde partie */ + GBinPortion *right_part; /* Partie restante */ + + int g_binary_portion_is_included(const GBinPortion **a, const GBinPortion **b) + { + int result; /* Bilan à retourner */ + + result = mrange_includes_mrange(&(*b)->range, &(*a)->range); + + return result; + + } + + found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinPortion *), + (__compar_fn_t)g_binary_portion_is_included, &best); + + if (!found) + { + /** + * On se prépare à réaliser une insertion au niveau courant. Mais des + * portions précédentes sont peut-être à déplacer dans la nouvelle zone : + * + * EXIDX 0x001178 0x00009178 0x00009178 0x00008 0x00008 R 0x4 + * PHDR 0x000034 0x00008034 0x00008034 0x00120 0x00120 R E 0x4 + * INTERP 0x000154 0x00008154 0x00008154 0x00019 0x00019 R 0x1 + * LOAD 0x000000 0x00008000 0x00008000 0x01184 0x01184 R E 0x8000 + * + * On refait donc une passe sur toutes les sous-portions du niveau. + * + * Cette approche a le mérite de traiter également et naturellement les + * sections définies dans le désordre : + * + * [21] .bss NOBITS 00088240 07823c 0018c8 00 WA 0 0 8 + * [22] __libc_freeres_ptrs NOBITS 00089b08 07823c 000018 00 WA 0 0 4 + * [23] .comment PROGBITS 00000000 07823c 000022 01 MS 0 0 1 + * + * Quant aux cas de figure où les portions sont identiques, l'ordre d'appel + * induit l'ordre d'inclusion. + * + * Cela concerne par exemple les zones de données : + * + * En-têtes de section: + * [Nr] Nom Type Adr Décala.Taille ES Fan LN Inf Al + * ... + * [ 2] .data PROGBITS 00010098 000098 00000c 00 WA 0 0 1 + * + * En-têtes de programme: + * Type Décalage Adr. vir. Adr.phys. T.Fich. T.Mém. Fan Alignement + * ... + * LOAD 0x000098 0x00010098 0x00010098 0x0000c 0x0000c RW 0x8000 + * + */ + + int g_binary_portion_track_missed_inclusion(const GBinPortion **a, const GBinPortion **b) + { + int result; /* Bilan à retourner */ + + result = mrange_includes_mrange(&(*a)->range, &(*b)->range); + + return result; + + } + + do + { + found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinPortion *), + (__compar_fn_t)g_binary_portion_track_missed_inclusion, &missed); + + if (found) + { + g_binary_portion_include(sub, portion->subs[missed]); + + portion->subs = _qdelete(portion->subs, &portion->count, sizeof(GBinPortion *), missed); + + } + + } + while (found); + + /** + * Il peut arriver que certaines portions débordent de leur zone d'inclusion : + * + * [24] .bss NOBITS 00012088 002084 000044 00 WA 0 0 8 + * [25] .ARM.attributes ARM_ATTRIBUTES 00000000 002084 000037 00 0 0 1 + * [26] .shstrtab STRTAB 00000000 0020bb 0000ed 00 0 0 1 + * + * Afin de respecter une certaine cohérence dans l'arbre des portions, on choisit + * de découper la portion qui déborde. + */ + + int g_binary_portion_track_partial_inclusion(const GBinPortion **a, const GBinPortion **b) + { + int result; /* Bilan à retourner */ + + result = cmp_mrange_with_vmpa(&(*b)->range, get_mrange_addr(&(*a)->range)); + + return result; + + } + + found = bsearch_index(&sub, portion->subs, portion->count, sizeof(GBinPortion *), + (__compar_fn_t)g_binary_portion_track_partial_inclusion, &best); + + if (found) + { + brange = &portion->subs[best]->range; + + compute_mrange_end_addr(brange, &end); + overlapping = compute_vmpa_diff(get_mrange_addr(&sub->range), &end); + + continued = g_binary_portion_is_continuation(sub); + + /* Partie contenue */ + + left_part = g_binary_portion_new(sub->code, get_mrange_addr(&sub->range), overlapping); + + g_binary_portion_set_desc(left_part, sub->desc); + g_binary_portion_mark_as_continued(left_part, continued); + g_binary_portion_set_rights(left_part, sub->rights); + + /* Partie qui déborde... */ + + /** + * Comme la portion incluante peut avoir une définition d'adresse + * virtuelle différente de celle de la portion incluse, on recalcule + * la position de départ de la seconde partie de la portion découpée + * à partir des données d'origine. + */ + + copy_vmpa(&start, get_mrange_addr(&sub->range)); + advance_vmpa(&start, overlapping); + + right_part = g_binary_portion_new(sub->code, &start, get_mrange_length(&sub->range) - overlapping); + + if (!continued) + g_binary_portion_mark_as_continued(right_part, true); + + g_binary_portion_set_desc(right_part, sub->desc); + + if (continued) + g_binary_portion_mark_as_continued(right_part, true); + + g_binary_portion_set_rights(right_part, sub->rights); + + /* Inclusions des parties */ + + g_binary_portion_include(portion, left_part); + g_binary_portion_include(portion, right_part); + + g_object_unref(G_OBJECT(sub)); + + } + + else + portion->subs = qinsert(portion->subs, &portion->count, sizeof(GBinPortion *), + (__compar_fn_t)g_binary_portion_compare, &sub); + + } + + /* Poursuite de l'inclusion dans la sous-portion adaptée... */ + else + g_binary_portion_include(portion->subs[best], sub); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = première couche amorçant la visite. * +* visitor = fonction à appeler à chaque étape de la descente. * +* data = adresse pointant vers des données de l'utilisateur.* +* * +* Description : Parcourt un ensemble de portions binaires. * +* * +* Retour : true si la visite a été jusqu'à son terme, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void *data) +{ + bool result; /* Etat à retourner */ + + bool visit_portion(GBinPortion *p, GBinPortion *pp) + { + bool ret; /* Etat à retourner */ + size_t i; /* Boucle de parcours */ + + if (p->count == 0) + ret = visitor(p, pp, BPV_SHOW, data); + + else + { + ret = visitor(p, pp, BPV_ENTER, data); + + for (i = 0; i < p->count && ret; i++) + ret = visit_portion(p->subs[i], p); + + if (ret) + ret = visitor(p, pp, BPV_EXIT, data); + + } + + return ret; + + } + + result = visit_portion(portion, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OFFRE DE CAPACITES DE GENERATION */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* * +* Description : Indique le nombre de ligne prêtes à être générées. * +* * +* Retour : Nombre de lignes devant apparaître au final. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_binary_portion_count_lines(const GBinPortion *portion) +{ + return portion->lcount; + +} + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* x = position géographique sur la ligne concernée. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* cursor = emplacement à constituer. [OUT] * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_compute_cursor(const GBinPortion *portion, gint x, size_t index, size_t repeat, GLineCursor **cursor) +{ + *cursor = g_binary_cursor_new(); + + g_binary_cursor_update(G_BINARY_CURSOR(*cursor), get_mrange_addr(&portion->range)); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* cursor = emplacement à analyser. * +* * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* * +* Retour : Bilan de la détermination, utilisable en comparaisons. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int g_binary_portion_contain_cursor(const GBinPortion *portion, size_t index, size_t repeat, const GLineCursor *cursor) +{ + int result; /* Conclusion à retourner */ + vmpa2t addr; /* Autre emplacement à comparer*/ + + assert(G_IS_BINARY_CURSOR(cursor)); + + g_binary_cursor_retrieve(G_BINARY_CURSOR(cursor), &addr); + + result = cmp_vmpa(&addr, get_mrange_addr(&portion->range)); + + return result; + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à consulter. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Renseigne sur les propriétés liées à un générateur. * +* * +* Retour : Propriétés particulières associées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static BufferLineFlags g_binary_portion_get_flags(const GBinPortion *portion, size_t index, size_t repeat) +{ + return (repeat == 0 ? BLF_WIDTH_MANAGER : BLF_NONE); + +} + + +/****************************************************************************** +* * +* Paramètres : portion = générateur à utiliser pour l'impression. * +* line = ligne de rendu à compléter. * +* index = indice de cette même ligne dans le tampon global. * +* repeat = indice d'utilisations successives du générateur. * +* content = éventuel contenu binaire brut à imprimer. * +* * +* Description : Imprime dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_binary_portion_print(GBinPortion *portion, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) +{ + assert(repeat < portion->lcount); + + g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&portion->range)); + + g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&portion->range)); + + if (portion->text[repeat] != NULL) + { + g_buffer_line_start_merge_at(line, DLC_ASSEMBLY_LABEL); + + g_buffer_line_append_text(line, DLC_ASSEMBLY_LABEL, SL(portion->text[repeat]), RTT_COMMENT, NULL); + + } + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* PARCOURS D'ENSEMBLES DE PORTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* * +* Description : Compte le nombre de portions présentes dans une arborescence.* +* * +* Retour : Quantité de portions présentes. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_binary_portion_count(const GBinPortion *portion) +{ + size_t result; /* Quantité à retourner */ + + + size_t measure_portion_size(const GBinPortion *root) + { + size_t count; /* Nombre de trouvailles */ + size_t i; /* Boucle de parcours */ + + count = 1; + + for (i = 0; i < root->count; i++) + count += measure_portion_size(root->subs[i]); + + return count; + + } + + + result = measure_portion_size(portion); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* x = abscisse du point de recherche. * +* area = étendue de portion mère, puis celle trouvée. [OUT] * +* * +* Description : Recherche la portion présente à un point donné. * +* * +* Retour : Portion trouvée à l'endroit indiqué. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPortion *g_binary_portion_find_at_pos(GBinPortion *portion, gint x, GdkRectangle *area) +{ + GBinPortion *result; /* Portion à retourner */ + phys_t full; /* Espace total représenté */ + size_t i; /* Boucle de parcours */ + GBinPortion *sub; /* Portion incluse à traiter */ + GdkRectangle sub_area; /* Etendue d'une sous-portion */ + + result = NULL; + + full = get_mrange_length(&portion->range); + + for (i = 0; i < portion->count && result == NULL; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) + continue; + + if (sub_area.x <= x && x < (sub_area.x + sub_area.width)) + { + result = g_binary_portion_find_at_pos(sub, x, &sub_area); + + if (result != NULL) + *area = sub_area; + + } + + } + + if (result == NULL) + { + result = portion; + g_object_ref(G_OBJECT(result)); + } + + return result; + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = portion mère à consulter. * +* addr = adresse du point de recherche. * +* * +* Description : Détermine si une portion contient une adresse donnée. * +* * +* Retour : true ou false selon le résultat. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_portion_contains_vmpa(const GBinPortion *portion, const vmpa2t *addr) +{ + bool result; /* Bilan à retourner */ + const mrange_t *range; /* Emplacement de portion */ + + result = false; + + range = g_binary_portion_get_range(portion); + + /* Portion non allouée en mémoire : on écarte */ + if (!has_virt_addr(get_mrange_addr(range))) + goto not_found; + + result = mrange_contains_addr(range, addr); + + not_found: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* addr = adresse du point de recherche. * +* * +* Description : Recherche la portion présente à une adresse donnée. * +* * +* Retour : Portion trouvée à l'endroit indiqué. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *addr) +{ + GBinPortion *result; /* Portion à retourner */ + phys_t full; /* Espace total représenté */ + size_t i; /* Boucle de parcours #1 */ + GBinPortion *sub; /* Portion incluse à traiter */ + + result = NULL; + + full = get_mrange_length(&portion->range); + + for (i = 0; i < portion->count && result == NULL; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_contains_vmpa(sub, addr)) + continue; + + result = g_binary_portion_find_at_addr(sub, addr); + + } + + if (result == NULL) + { + result = portion; + g_object_ref(G_OBJECT(result)); + } + + return result; + +} + + +#ifdef INCLUDE_GTK_SUPPORT + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* addr = adresse du point de recherche. * +* area = étendue de portion mère, puis celle trouvée. [OUT] * +* * +* Description : Recherche la portion présente à une adresse donnée. * +* * +* Retour : Portion trouvée à l'endroit indiqué. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBinPortion *g_binary_portion_find_with_area_at_addr(GBinPortion *portion, const vmpa2t *addr, GdkRectangle *area) +{ + GBinPortion *result; /* Portion à retourner */ + phys_t full; /* Espace total représenté */ + size_t i; /* Boucle de parcours #1 */ + GBinPortion *sub; /* Portion incluse à traiter */ + GdkRectangle sub_area; /* Etendue d'une sous-portion */ + + result = NULL; + + full = get_mrange_length(&portion->range); + + for (i = 0; i < portion->count && result == NULL; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_contains_vmpa(sub, addr)) + continue; + + if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area)) + continue; + + result = g_binary_portion_find_with_area_at_addr(sub, addr, &sub_area); + + if (result != NULL) + *area = sub_area; + + } + + if (result == NULL) + { + result = portion; + g_object_ref(G_OBJECT(result)); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : root = couche de portions à parcourir pour les recherches. * +* x = abscisse du point de recherche. * +* area = étendue de représentation de la portion mère. * +* addr = adresse correspondante. [OUT] * +* * +* Description : Fournit la position correspondant à une adresse donnée. * +* * +* Retour : Succès de la traduction. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_binary_portion_addr_from_pos(GBinPortion *root, gint x, const GdkRectangle *area, vmpa2t *addr) +{ + GdkRectangle owner_area; /* Aire de contenance */ + GBinPortion *owner; /* Conteneur propriétaire */ + + owner_area = *area; + + owner = g_binary_portion_find_at_pos(root, x, &owner_area); + if (owner == NULL) return false; + + copy_vmpa(addr, get_mrange_addr(&owner->range)); + + advance_vmpa(addr, (get_mrange_length(&owner->range) * (x - owner_area.x)) / owner_area.width); + + g_object_unref(G_OBJECT(owner)); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : root = couche de portions à parcourir pour les recherches. * +* addr = adresse du point de recherche. * +* area = étendue de représentation de la portion mère. * +* x = position correspondante. [OUT] * +* * +* Description : Fournit l'adresse correspondant à une position donnée. * +* * +* Retour : Succès de la traduction. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_binary_portion_pos_from_addr(GBinPortion *root, const vmpa2t *addr, const GdkRectangle *area, gint *x) +{ + GdkRectangle owner_area; /* Aire de contenance */ + GBinPortion *owner; /* Conteneur propriétaire */ + phys_t diff; /* Décalage à appliquer */ + + owner_area = *area; + + owner = g_binary_portion_find_with_area_at_addr(root, addr, &owner_area); + if (owner == NULL) return false; + + diff = compute_vmpa_diff(addr, get_mrange_addr(&owner->range)); + + *x = owner_area.x + (diff * owner_area.width) / get_mrange_length(&owner->range); + + g_object_unref(G_OBJECT(owner)); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : layer = couche de portions à consulter. * +* x = abscisse du point de recherche. * +* y = ordonnée du point de recherche. * +* area = étendue de représentation de la portion mère. * +* tooltip = astuce à compléter. [OUT] * +* * +* Description : Prépare une astuce concernant une portion pour son affichage.* +* * +* Retour : TRUE pour valider l'affichage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gboolean query_tooltip_for_binary_portion(GBinPortion *root, gint x, gint y, const GdkRectangle *area, GtkTooltip *tooltip) +{ + GBinPortion *selected; /* Portion à décrire ici */ + + selected = g_binary_portion_find_at_pos(root, x, (GdkRectangle []) { *area }); + if (selected == NULL) return FALSE; + + g_binary_portion_query_tooltip(selected, tooltip); + + g_object_unref(G_OBJECT(selected)); + + return TRUE; + +} + + +#endif + + +/****************************************************************************** +* * +* Paramètres : portion = portion mère à consulter. * +* off = position physique du point de recherche. * +* * +* Description : Détermine si une portion contient une position donnée. * +* * +* Retour : true ou false selon le résultat. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_portion_contains_physical(const GBinPortion *portion, phys_t off) +{ + bool result; /* Bilan à retourner */ + const mrange_t *range; /* Emplacement de portion */ + const vmpa2t *addr; /* Départ de la portion */ + + range = g_binary_portion_get_range(portion); + addr = get_mrange_addr(range); + + if (!has_phys_addr(addr)) + result = false; + + else + result = (addr->physical <= off && off < (addr->physical + range->length)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* off = position physique à retrouver. * +* pos = position correspondante. [OUT] * +* * +* Description : Fournit l'emplacement correspondant à une position physique. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_portion_translate_offset_into_vmpa(const GBinPortion *portion, phys_t off, vmpa2t *pos) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours #1 */ + GBinPortion *sub; /* Portion incluse à traiter */ + const mrange_t *range; /* Emplacement de portion */ + const vmpa2t *addr; /* Départ de la portion */ + + result = false; + + for (i = 0; i < portion->count; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_contains_physical(sub, off)) + continue; + + result = g_binary_portion_translate_offset_into_vmpa(sub, off, pos); + + break; + + } + + if (i == portion->count) + { + result = g_binary_portion_contains_physical(portion, off); + + if (result) + { + range = g_binary_portion_get_range(portion); + addr = get_mrange_addr(range); + + if (has_virt_addr(get_mrange_addr(range))) + init_vmpa(pos, off, addr->virtual + off - addr->physical); + + else + init_vmpa(pos, off, VMPA_NO_VIRTUAL); + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = portion mère à consulter. * +* virt = adresse virtuelle du point de recherche. * +* * +* Description : Détermine si une portion contient une adresse donnée. * +* * +* Retour : true ou false selon le résultat. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_portion_contains_virtual(const GBinPortion *portion, virt_t virt) +{ + bool result; /* Bilan à retourner */ + const mrange_t *range; /* Emplacement de portion */ + const vmpa2t *addr; /* Départ de la portion */ + + range = g_binary_portion_get_range(portion); + addr = get_mrange_addr(range); + + if (!has_virt_addr(addr)) + result = false; + + else + result = (addr->virtual <= virt && virt < (addr->virtual + range->length)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : portion = couche de portions à parcourir pour les recherches.* +* virt = adresse virtuelle à retrouver. * +* pos = position correspondante. [OUT] * +* * +* Description : Fournit l'emplacement correspondant à une adresse virtuelle. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_binary_portion_translate_address_into_vmpa(const GBinPortion *portion, virt_t virt, vmpa2t *pos) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours #1 */ + GBinPortion *sub; /* Portion incluse à traiter */ + const mrange_t *range; /* Emplacement de portion */ + const vmpa2t *addr; /* Départ de la portion */ + + result = false; + + for (i = 0; i < portion->count; i++) + { + sub = portion->subs[i]; + + if (!g_binary_portion_contains_virtual(sub, virt)) + continue; + + result = g_binary_portion_translate_address_into_vmpa(sub, virt, pos); + + break; + + } + + if (i == portion->count) + { + result = g_binary_portion_contains_virtual(portion, virt); + + if (result) + { + range = g_binary_portion_get_range(portion); + addr = get_mrange_addr(range); + + if (has_phys_addr(addr) && has_virt_addr(addr)) + init_vmpa(pos, addr->physical + virt - addr->virtual, virt); + + else + init_vmpa(pos, VMPA_NO_PHYSICAL, virt); + + } + + } + + return result; + +} diff --git a/src/glibext/portion.h b/src/glibext/portion.h new file mode 100644 index 0000000..ea4b4aa --- /dev/null +++ b/src/glibext/portion.h @@ -0,0 +1,194 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * binportion.h - prototypes pour la représentation graphique de portions de binaire + * + * Copyright (C) 2013-2019 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 Chrysalide. If not, see . + */ + + +#ifndef _GLIBEXT_BINPORTION_H +#define _GLIBEXT_BINPORTION_H + + +#include +#include +#ifdef INCLUDE_GTK_SUPPORT +# include +#endif + + +#include "../arch/vmpa.h" +#include "../common/fnv1a.h" + + + +/* ------------------------------- PORTION DE BINAIRE ------------------------------- */ + + +/** + * Couleurs de représentation. + */ + +#define BPC_RAW "binportion-raw" +#define BPC_CODE "binportion-code" +#define BPC_DATA "binportion-data" +#define BPC_DATA_RO "binportion-data-ro" +#define BPC_DISASS_ERROR "binportion-disassembly-error" + + +#define G_TYPE_BIN_PORTION (g_binary_portion_get_type()) +#define G_BIN_PORTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BIN_PORTION, GBinPortion)) +#define G_IS_BIN_PORTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_BIN_PORTION)) +#define G_BIN_PORTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BIN_PORTION, GBinPortionClass)) +#define G_IS_BIN_PORTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BIN_PORTION)) +#define G_BIN_PORTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BIN_PORTION, GBinPortionClass)) + + +/* Portion de données binaires quelconques (instance) */ +typedef struct _GBinPortion GBinPortion; + +/* Portion de données binaires quelconques (classe) */ +typedef struct _GBinPortionClass GBinPortionClass; + + +/* Droits d'accès à une portion */ +typedef enum _PortionAccessRights +{ + PAC_NONE = (0 << 0), /* Aucun */ + PAC_READ = (1 << 0), /* Lecture */ + PAC_WRITE = (1 << 1), /* Ecriture */ + PAC_EXEC = (1 << 2) /* Exécution */ + +} PortionAccessRights; + + +#define PAC_ALL ((PortionAccessRights)(PAC_READ | PAC_WRITE | PAC_EXEC)) + + +/* Indique le type défini par la GLib pour les portions de données binaires. */ +GType g_binary_portion_get_type(void); + +/* Crée une description de partie de code vierge. */ +GBinPortion *g_binary_portion_new(const char *, const vmpa2t *, phys_t); + +/* Etablit la comparaison ascendante entre deux portions. */ +int g_binary_portion_compare(const GBinPortion **, const GBinPortion **); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Attribue à la portion une éventuelle image de représentation. */ +void g_binary_portion_set_icon(GBinPortion *, cairo_surface_t *); + +/* Fournit une éventuelle image de représentation de portion. */ +cairo_surface_t *g_binary_portion_get_icon(const GBinPortion *); + +#endif + +/* Attribue une description humaine à une partie de code. */ +void g_binary_portion_set_desc(GBinPortion *, const char *); + +/* Fournit la description attribuée à une partie de code. */ +const char *g_binary_portion_get_desc(const GBinPortion *); + +/* Fournit l'emplacement d'une partie de code binaire. */ +const mrange_t *g_binary_portion_get_range(const GBinPortion *); + +/* Assure qu'une portion ne dépasse pas une position donnée. */ +bool g_binary_portion_limit_range(GBinPortion *, phys_t); + +/* Définit la nature de la portion en terme d'originalité. */ +void g_binary_portion_mark_as_continued(GBinPortion *, bool); + +/* Indique la nature de la portion en terme d'originalité. */ +bool g_binary_portion_is_continuation(const GBinPortion *); + +/* Définit les droits associés à une partie de code. */ +void g_binary_portion_set_rights(GBinPortion *, PortionAccessRights); + +/* Fournit les droits associés à une partie de code. */ +PortionAccessRights g_binary_portion_get_rights(const GBinPortion *); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Prépare une astuce concernant une portion pour son affichage. */ +void g_binary_portion_query_tooltip(GBinPortion *, GtkTooltip *); + +/* Représente la portion sur une bande dédiée. */ +void g_binary_portion_draw(const GBinPortion *, GtkStyleContext *, cairo_t *, const GdkRectangle *); + +#endif + +/* Procède à l'inclusion d'une portion dans une autre. */ +void g_binary_portion_include(GBinPortion *, GBinPortion *); + +/* Sens des visites */ +typedef enum _BinaryPortionVisit +{ + BPV_ENTER, /* Arrivée sur une branche */ + BPV_SHOW, /* Visite d'une feuille */ + BPV_EXIT /* Départ d'une branche */ + +} BinaryPortionVisit; + + +/* Fonction appelée à chaque visite de portion.*/ +typedef bool (* visit_portion_fc) (GBinPortion *, GBinPortion *, BinaryPortionVisit, void *); + +/* Parcourt un ensemble de portions binaires. */ +bool g_binary_portion_visit(GBinPortion *, visit_portion_fc, void *); + + + +/* ------------------------ PARCOURS D'ENSEMBLES DE PORTIONS ------------------------ */ + + +#ifdef INCLUDE_GTK_SUPPORT + +/* Compte le nombre de portions présentes dans une arborescence. */ +size_t g_binary_portion_count(const GBinPortion *); + +/* Recherche la portion présente à un point donné. */ +GBinPortion *g_binary_portion_find_at_pos(GBinPortion *, gint, GdkRectangle *); + +#endif + +/* Recherche la portion présente à une adresse donnée. */ +GBinPortion *g_binary_portion_find_at_addr(GBinPortion *, const vmpa2t *); + +#ifdef INCLUDE_GTK_SUPPORT + +/* Fournit la position correspondant à une adresse donnée. */ +bool get_binary_portion_addr_from_pos(GBinPortion *, gint, const GdkRectangle *, vmpa2t *); + +/* Fournit l'adresse correspondant à une position donnée. */ +bool get_binary_portion_pos_from_addr(GBinPortion *, const vmpa2t *, const GdkRectangle *, gint *); + +/* Prépare une astuce concernant une portion pour son affichage. */ +gboolean query_tooltip_for_binary_portion(GBinPortion *, gint, gint, const GdkRectangle *, GtkTooltip *); + +#endif + +/* Fournit l'emplacement correspondant à une position physique. */ +bool g_binary_portion_translate_offset_into_vmpa(const GBinPortion *, phys_t, vmpa2t *); + +/* Fournit l'emplacement correspondant à une adresse virtuelle. */ +bool g_binary_portion_translate_address_into_vmpa(const GBinPortion *, virt_t, vmpa2t *); + + + +#endif /* _GLIBEXT_BINPORTION_H */ -- cgit v0.11.2-87-g4458