From 23b9c6e68bbe5f0531f9a9408c2deb9f897701dc Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 13 Jan 2018 23:37:31 +0100 Subject: Created a real iterator for symbols. --- ChangeLog | 40 +++++ plugins/pychrysa/format/Makefile.am | 3 +- plugins/pychrysa/format/format.c | 228 +--------------------------- plugins/pychrysa/format/module.c | 3 +- plugins/pychrysa/format/symiter.c | 276 ++++++++++++++++++++++++++++++++++ plugins/pychrysa/format/symiter.h | 42 ++++++ src/analysis/disass/disassembler.c | 19 ++- src/analysis/disass/output.c | 48 +++--- src/analysis/disass/routines.c | 42 ++++-- src/analysis/disass/routines.h | 4 +- src/arch/processor.c | 4 + src/format/Makefile.am | 1 + src/format/format-int.h | 6 +- src/format/format.c | 239 +++++++++++++++++++++++------ src/format/format.h | 32 +++- src/format/symiter.c | 289 ++++++++++++++++++++++++++++++++++++ src/format/symiter.h | 56 +++++++ src/gui/dialogs/gotox.c | 26 ++-- src/gui/panels/strings.c | 31 ++-- src/gui/panels/symbols.c | 65 ++++---- 20 files changed, 1095 insertions(+), 359 deletions(-) create mode 100644 plugins/pychrysa/format/symiter.c create mode 100644 plugins/pychrysa/format/symiter.h create mode 100644 src/format/symiter.c create mode 100644 src/format/symiter.h diff --git a/ChangeLog b/ChangeLog index 2cfb140..416027c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,45 @@ 18-01-13 Cyrille Bagard + * plugins/pychrysa/format/Makefile.am: + Add the 'symiter.[ch]' files to libpychrysaformat_la_SOURCES. + + * plugins/pychrysa/format/format.c: + Delete the previous version of symbol iterators and update code. + + * plugins/pychrysa/format/module.c: + Update code. + + * plugins/pychrysa/format/symiter.c: + * plugins/pychrysa/format/symiter.h: + New entries: provide Python bindings for the new symbol iterator. + + * src/analysis/disass/disassembler.c: + * src/analysis/disass/output.c: + * src/analysis/disass/routines.c: + * src/analysis/disass/routines.h: + + * src/arch/processor.c: + Fix a compilation bug when NDEBUG is defined. + + * src/format/Makefile.am: + Add the 'symiter.[ch]' files to libformat_la_SOURCES. + + * src/format/format-int.h: + * src/format/format.c: + * src/format/format.h: + Rewrite all accesses to symbols. + + * src/format/symiter.c: + * src/format/symiter.h: + New entries: create a real iterator for symbols. + + * src/gui/dialogs/gotox.c: + * src/gui/panels/strings.c: + * src/gui/panels/symbols.c: + Update code. + +18-01-13 Cyrille Bagard + * plugins/dex/loading.c: * plugins/elf/format.c: * plugins/elf/loading.c: diff --git a/plugins/pychrysa/format/Makefile.am b/plugins/pychrysa/format/Makefile.am index e59cf8a..325206c 100644 --- a/plugins/pychrysa/format/Makefile.am +++ b/plugins/pychrysa/format/Makefile.am @@ -5,7 +5,8 @@ libpychrysaformat_la_SOURCES = \ executable.h executable.c \ format.h format.c \ module.h module.c \ - symbol.h symbol.c + symbol.h symbol.c \ + symiter.h symiter.c libpychrysaformat_la_LIBADD = diff --git a/plugins/pychrysa/format/format.c b/plugins/pychrysa/format/format.c index aed9664..5920b27 100644 --- a/plugins/pychrysa/format/format.c +++ b/plugins/pychrysa/format/format.c @@ -31,36 +31,12 @@ #include +#include "symiter.h" #include "../helpers.h" #include "../arch/vmpa.h" -/* ------------------------ PARCOURS DE SYMBOLES DE BINAIRES ------------------------ */ - - -/* Parcours des symboles présents dans un binaire */ -typedef struct _pyBinSymbolIterator -{ - PyObject_HEAD /* A laisser en premier */ - - GBinFormat *format; /* Format binaire à consulter */ - size_t next; /* Symbole binaire à présenter */ - -} pyBinSymbolIterator; - - -/* Prend acte d'un compteur de référence à 0. */ -static void py_binary_symbol_iterator_dealloc(PyObject *); - -/* Fournit un itérateur pour symboles de format binaire. */ -static PyObject *py_binary_symbol_iterator_next(PyObject *); - -/* Initialise un objet Python de type 'BinSymbolIterator'. */ -static int py_binary_symbol_iterator_init(PyObject *, PyObject *, PyObject *); - - - /* ---------------------------- FORMAT BINAIRE GENERIQUE ---------------------------- */ @@ -104,195 +80,6 @@ static bool define_python_binary_format_constants(PyTypeObject *); /* ---------------------------------------------------------------------------------- */ -/* PARCOURS DE SYMBOLES DE BINAIRES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : self = instance Python à libérer de la mémoire. * -* * -* Description : Prend acte d'un compteur de référence à 0. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void py_binary_symbol_iterator_dealloc(PyObject *self) -{ - pyBinSymbolIterator *iterator; /* Références pour le parcours */ - - /** - * Il aurait été sans doute mieux de reposer ici sur .tp_finalize, - * mais cela semble impliquer de mettre en place tous les mécanismes de GC... - * - * cf. https://docs.python.org/3/extending/newtypes.html#finalization-and-de-allocation - */ - - iterator = (pyBinSymbolIterator *)self; - - g_object_unref(G_OBJECT(iterator->format)); - - Py_TYPE(self)->tp_free((PyObject *)self); - -} - - -/****************************************************************************** -* * -* Paramètres : self = itérateur à manipuler. * -* * -* Description : Fournit un itérateur pour symboles de format binaire. * -* * -* Retour : Instance Python prête à emploi. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_binary_symbol_iterator_next(PyObject *self) -{ - PyObject *result; /* Instance à retourner */ - pyBinSymbolIterator *iterator; /* Références pour le parcours */ - size_t count; /* Nombre de symboles présents */ - GBinSymbol **symbols; /* Liste de ces mêmes symboles */ - - iterator = (pyBinSymbolIterator *)self; - - symbols = g_binary_format_get_symbols(iterator->format, &count); - - if (iterator->next < count) - { - result = pygobject_new(G_OBJECT(symbols[iterator->next])); - iterator->next++; - } - else - { - PyErr_SetNone(PyExc_StopIteration); - result = NULL; - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : self = objet instancié à initialiser. * -* args = arguments fournis à l'appel. * -* kwds = arguments de type key=val fournis. * -* * -* Description : Initialise un objet Python de type 'BinSymbolIterator'. * -* * -* Retour : Instance Python mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int py_binary_symbol_iterator_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - pyBinSymbolIterator *iterator; /* Références pour le parcours */ - PyObject *format; /* Format binaire en Python */ - int ret; /* Bilan de lecture des args. */ - - ret = PyArg_ParseTuple(args, "O", &format); - if (!ret) return -1; - - ret = PyObject_IsInstance(format, (PyObject *)get_python_binary_format_type()); - if (!ret) return -1; - - iterator = (pyBinSymbolIterator *)self; - - iterator->format = G_BIN_FORMAT(pygobject_get(format)); - g_object_ref(G_OBJECT(iterator->format)); - - iterator->next = 0; - - 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_symbol_iterator_type(void) -{ - static PyTypeObject py_binary_symbol_iterator_type = { - - PyVarObject_HEAD_INIT(NULL, 0) - - .tp_name = "pychrysalide.format.BinSymbolIterator", - .tp_basicsize = sizeof(pyBinSymbolIterator), - - .tp_dealloc = py_binary_symbol_iterator_dealloc, - - .tp_flags = Py_TPFLAGS_DEFAULT, - - .tp_doc = "Iterator for binary symbols", - - .tp_iter = PyObject_SelfIter, - .tp_iternext = py_binary_symbol_iterator_next, - - .tp_init = py_binary_symbol_iterator_init, - - .tp_new = PyType_GenericNew, - - }; - - return &py_binary_symbol_iterator_type; - -} - - -/****************************************************************************** -* * -* Paramètres : module = module dont la définition est à compléter. * -* * -* Description : Prend en charge l'objet 'pychrysalide...BinSymbolIterator'. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool register_python_binary_symbol_iterator(PyObject *module) -{ - PyTypeObject *py_binary_symbol_iterator_type; /* Type Python 'BinSymbolIterator' */ - int ret; /* Bilan d'un appel */ - - py_binary_symbol_iterator_type = get_python_binary_symbol_iterator_type(); - - py_binary_symbol_iterator_type->tp_base = &PyBaseObject_Type; - - if (PyType_Ready(py_binary_symbol_iterator_type) != 0) - return false; - - Py_INCREF(py_binary_symbol_iterator_type); - ret = PyModule_AddObject(module, "BinSymbolIterator", (PyObject *)py_binary_symbol_iterator_type); - if (ret != 0) return false; - - return true; - -} - - - -/* ---------------------------------------------------------------------------------- */ /* FORMAT BINAIRE GENERIQUE */ /* ---------------------------------------------------------------------------------- */ @@ -539,18 +326,17 @@ static PyObject *py_binary_format_get_content(PyObject *self, void *closure) static PyObject *py_binary_format_get_symbols(PyObject *self, void *closure) { - PyObject *result; /* Instance à retourner */ + PyObject *result; /* Instance Python à retourner */ PyTypeObject *iterator_type; /* Type Python de l'itérateur */ - PyObject *args_list; /* Arguments de mise en place */ + PyObject *args; /* Liste des arguments d'appel */ - iterator_type = get_python_binary_symbol_iterator_type(); + iterator_type = get_python_sym_iterator_type(); - Py_INCREF(self); + args = Py_BuildValue("On", self, 0); - args_list = Py_BuildValue("(O)", self); - result = PyObject_CallObject((PyObject *)iterator_type, args_list); + result = PyObject_CallObject((PyObject *)iterator_type, args); - Py_DECREF(args_list); + Py_DECREF(args); return result; diff --git a/plugins/pychrysa/format/module.c b/plugins/pychrysa/format/module.c index 642b1dc..1daeb3f 100644 --- a/plugins/pychrysa/format/module.c +++ b/plugins/pychrysa/format/module.c @@ -31,6 +31,7 @@ #include "executable.h" #include "format.h" #include "symbol.h" +#include "symiter.h" #include "../access.h" @@ -81,10 +82,10 @@ bool add_format_module_to_python_module(PyObject *super) result = true; - result &= register_python_binary_symbol_iterator(module); result &= register_python_binary_format(module); result &= register_python_executable_format(module); result &= register_python_binary_symbol(module); + result &= register_python_sym_iterator(module); if (result) register_access_to_python_module("pychrysalide.format", module); diff --git a/plugins/pychrysa/format/symiter.c b/plugins/pychrysa/format/symiter.c new file mode 100644 index 0000000..db0b744 --- /dev/null +++ b/plugins/pychrysa/format/symiter.c @@ -0,0 +1,276 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * symiter.c - équivalent Python du fichier "format/symiter.c" + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "symiter.h" + + +#include + + +#include + + +#include "format.h" + + + +/* Transcription d'un itérateur en Python */ +typedef struct _PySymIterator +{ + PyObject_HEAD; /* A laisser en premier */ + + sym_iter_t *native; /* Version native de l'objet */ + bool first_time; /* Premier élément retourné ? */ + +} PySymIterator; + + +/* Libère de la mémoire un itérateur sur des symboles. */ +static void py_sym_iterator_dealloc(PySymIterator *); + +/* Fournit le symbole qui en suit un autr. */ +static PyObject *py_sym_iterator_next(PySymIterator *); + +/* Initialise un nouvel itérateur. */ +static int py_sym_iterator_init(PySymIterator *, PyObject *, PyObject *); + +/* Construit un nouvel itérateur. */ +static PyObject *py_sym_iterator_new(PyTypeObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = itérateur à supprimer. * +* * +* Description : Libère de la mémoire un itérateur sur des symboles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_sym_iterator_dealloc(PySymIterator *self) +{ + delete_symbol_iterator(self->native); + + Py_TYPE(self)->tp_free((PyObject *)self); + +} + + +/****************************************************************************** +* * +* Paramètres : self = itérateur à manipuler. * +* * +* Description : Fournit le symbole qui en suit un autre. * +* * +* Retour : Symbole suivant trouvé, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_sym_iterator_next(PySymIterator *self) +{ + PyObject *result; /* Résultat à retourner */ + GBinSymbol *next; /* Symbole suivant */ + + if (self->first_time) + { + next = get_symbol_iterator_current(self->native); + self->first_time = false; + } + + else + next = get_symbol_iterator_next(self->native); + + if (next != NULL) + { + result = pygobject_new(G_OBJECT(next)); + g_object_unref(G_OBJECT(next)); + } + + else + { + PyErr_SetNone(PyExc_StopIteration); + result = NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = instance d'objet à initialiser. * +* args = arguments passés pour l'appel. * +* kwds = mots clefs éventuellement fournis en complément. * +* * +* Description : Initialise un nouvel itérateur. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_sym_iterator_init(PySymIterator *self, PyObject *args, PyObject *kwds) +{ + int result; /* Bilan à retourner */ + PyObject *fmt_obj; /* Format version Python */ + unsigned long index; /* Indice de premier symbole */ + int ret; /* Bilan de lecture des args. */ + GBinFormat *format; /* Version native du format */ + + result = -1; + + ret = PyArg_ParseTuple(args, "Ok", &fmt_obj, &index); + if (ret == 0) goto psii_exit; + + ret = PyObject_IsInstance(fmt_obj, (PyObject *)get_python_binary_format_type()); + if (!ret) goto psii_exit; + + format = G_BIN_FORMAT(pygobject_get(fmt_obj)); + + self->native = create_symbol_iterator(format, index); + self->first_time = true; + + result = 0; + + psii_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type d'objet à mettre en place. * +* args = arguments passés pour l'appel. * +* kwds = mots clefs éventuellement fournis en complément. * +* * +* Description : Construit un nouvel itérateur. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_sym_iterator_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PySymIterator *result; /* Nouvelle instance à renvoyer*/ + int ret; /* Bilan de l'initialisation */ + + result = (PySymIterator *)type->tp_alloc(type, 0); + + if (result != NULL) + { + ret = py_sym_iterator_init(result, args, kwds); + + if (ret != 0) + { + Py_DECREF(result); + result = NULL; + } + + } + + return (PyObject *)result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_sym_iterator_type(void) +{ + static PyTypeObject py_sym_iterator_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.format.SymIterator", + .tp_basicsize = sizeof(PySymIterator), + + .tp_dealloc = (destructor)py_sym_iterator_dealloc, + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "Iterator for Chrysalide symbols registered in a given format.", + + .tp_iter = PyObject_SelfIter, + .tp_iternext = (iternextfunc)py_sym_iterator_next, + + .tp_init = (initproc)py_sym_iterator_init, + .tp_new = py_sym_iterator_new, + + }; + + return &py_sym_iterator_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.format.SymIterator'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_sym_iterator(PyObject *module) +{ + PyTypeObject *py_sym_iterator_type; /* Type Python 'BinContent' */ + int ret; /* Bilan d'un appel */ + + py_sym_iterator_type = get_python_sym_iterator_type(); + + if (PyType_Ready(py_sym_iterator_type) < 0) + return false; + + Py_INCREF(py_sym_iterator_type); + ret = PyModule_AddObject(module, "SymIterator", (PyObject *)py_sym_iterator_type); + + return (ret == 0); + +} diff --git a/plugins/pychrysa/format/symiter.h b/plugins/pychrysa/format/symiter.h new file mode 100644 index 0000000..6cc1d29 --- /dev/null +++ b/plugins/pychrysa/format/symiter.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * symiter.h - prototypes pour l'équivalent Python du fichier "format/symiter.h" + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_FORMAT_SYMITER_H +#define _PLUGINS_PYCHRYSALIDE_FORMAT_SYMITER_H + + +#include +#include + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_sym_iterator_type(void); + +/* Prend en charge l'objet 'pychrysalide.format.SymIterator'. */ +bool register_python_sym_iterator(PyObject *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_FORMAT_SYMITER_H */ diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index bb69c0e..ae60602 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -92,7 +92,7 @@ static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *, GBufferCa static void process_all_instructions(wgroup_id_t, GtkStatusStack *, const char *, ins_fallback_cb, GArchProcessor *, GProcContext *, GExeFormat *); /* Opère sur toutes les routines. */ -static void process_all_routines(wgroup_id_t, GtkStatusStack *, const char *, rtn_fallback_cb, GArchProcessor *, GExeFormat *); +static void process_all_routines(wgroup_id_t, GtkStatusStack *, const char *, rtn_fallback_cb, GArchProcessor *, GBinFormat *); /* Assure le désassemblage en différé. */ static void g_delayed_disassembly_process(GDelayedDisassembly *, GtkStatusStack *); @@ -318,10 +318,9 @@ static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, co * * ******************************************************************************/ -static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const char *msg, rtn_fallback_cb fallback, GArchProcessor *proc, GExeFormat *format) +static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const char *msg, rtn_fallback_cb fallback, GArchProcessor *proc, GBinFormat *format) { GBinPortion *portions; /* Couche première de portions */ - GBinSymbol **symbols; /* Liste des symboles trouvés */ size_t sym_count; /* Nombre de ces symboles */ guint runs_count; /* Qté d'exécutions parallèles */ size_t run_size; /* Volume réparti par exécution*/ @@ -332,9 +331,11 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const size_t end; /* Fin d'un bloc de traitement */ GRoutinesStudy *study; /* Tâche d'étude à programmer */ - portions = g_exe_format_get_portions(format); + portions = g_exe_format_get_portions(G_EXE_FORMAT(format)); - symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count); + g_binary_format_lock_symbols_rd(format); + + sym_count = g_binary_format_count_symbols(format); runs_count = g_get_num_processors(); @@ -353,7 +354,7 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const else end = begin + run_size; - study = g_routines_study_new(proc, portions, symbols, sym_count, + study = g_routines_study_new(proc, format, portions, begin, end, id, fallback); g_work_queue_schedule_work(queue, G_DELAYED_WORK(study), gid); @@ -364,6 +365,8 @@ static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const gtk_status_stack_remove_activity(status, id); + g_binary_format_unlock_symbols_rd(format); + g_object_unref(G_OBJECT(portions)); } @@ -471,7 +474,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus process_all_routines(gid, status, _("Finding remaining limits..."), - g_routines_study_compute_limits, proc, disass->format); + g_routines_study_compute_limits, proc, G_BIN_FORMAT(disass->format)); @@ -525,7 +528,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus #if 1 process_all_routines(gid, status, _("Control-flow analysis for routines..."), - g_routines_study_handle_blocks, proc, disass->format); + g_routines_study_handle_blocks, proc, G_BIN_FORMAT(disass->format)); #endif diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index 3cc282a..19c7de9 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -32,6 +32,7 @@ #include "../../core/logs.h" #include "../../format/format.h" +#include "../../format/symiter.h" #include "../../glibext/generators/rborder.h" @@ -60,9 +61,8 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, GBinPortion **portions; /* Morceaux d'encadrement */ size_t portions_count; /* Taille de cette liste */ size_t portion_index; /* Prochaine portion à traiter */ - GBinSymbol **symbols; /* Symboles à représenter */ - size_t sym_count; /* Qté de symboles présents */ - size_t sym_index; /* Prochain symbole non traité */ + sym_iter_t *siter; /* Parcours des symboles */ + GBinSymbol *symbol; /* Symbole manipulé */ MemoryDataSize msize; /* Taille du bus d'adresses */ const GBinContent *content; /* Contenu binaire global */ size_t count; /* Nombre total d'instructions */ @@ -127,8 +127,9 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, g_object_unref(G_OBJECT(root)); - symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count); - sym_index = 0; + siter = create_symbol_iterator(G_BIN_FORMAT(format), 0); + + symbol = get_symbol_iterator_current(siter); msize = g_arch_processor_get_memory_size(proc); @@ -205,21 +206,24 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, /* Début d'un nouveau symbole ? */ - if (sym_index == sym_count) + if (symbol == NULL) compared = -1; else { iaddr = get_mrange_addr(g_arch_instruction_get_range(instr)); - for ( ; sym_index < sym_count; sym_index++) + for ( ; symbol != NULL; symbol = get_symbol_iterator_next(siter)) { - sym_status = g_binary_symbol_get_status(symbols[sym_index]); + sym_status = g_binary_symbol_get_status(symbol); if (sym_status == SSS_IMPORTED) + { + g_object_unref(G_OBJECT(symbol)); continue; + } - saddr = get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index])); + saddr = get_mrange_addr(g_binary_symbol_get_range(symbol)); compared = cmp_vmpa(iaddr, saddr); @@ -228,10 +232,10 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, log_variadic_message(LMT_BAD_BINARY, _("Unable to find a proper location for symbol '%s' @ 0x%08x"), - g_binary_symbol_get_label(symbols[sym_index]), get_phy_addr(saddr)); + g_binary_symbol_get_label(symbol), get_phy_addr(saddr)); asprintf(&errmsg, _("Unable to find a proper location for symbol '%s'"), - g_binary_symbol_get_label(symbols[sym_index])); + g_binary_symbol_get_label(symbol)); g_arch_processor_add_error(proc, APE_LABEL, saddr, errmsg); @@ -239,22 +243,24 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, _missing++; + g_object_unref(G_OBJECT(symbol)); + } - if (sym_index == sym_count) + if (symbol == NULL) goto no_more_symbol_finally; if (compared == 0) { /* Coupure pour une nouvelle routine */ - stype = g_binary_symbol_get_target_type(symbols[sym_index]); + stype = g_binary_symbol_get_target_type(symbol); if (stype == STP_ROUTINE || stype == STP_ENTRY_POINT) { /* Impression de la marque de début */ - copy_vmpa(&intro_addr, get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index]))); + copy_vmpa(&intro_addr, get_mrange_addr(g_binary_symbol_get_range(symbol))); border = g_border_generator_new(lang, &intro_addr, true, msize); g_buffer_cache_append(cache, G_LINE_GENERATOR(border), BLF_NONE); @@ -273,7 +279,7 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, * est nécessaire pour imprimer cette marque de clôture. */ - compute_mrange_end_addr(g_binary_symbol_get_range(symbols[sym_index]), &outro_addr); + compute_mrange_end_addr(g_binary_symbol_get_range(symbol), &outro_addr); expect_outro = true; @@ -281,7 +287,7 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, /* Etiquette ? */ - generator = g_binary_symbol_produce_label(symbols[sym_index]); + generator = g_binary_symbol_produce_label(symbol); if (generator != NULL) g_buffer_cache_append(cache, generator, BLF_NONE); @@ -298,7 +304,7 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, { /* Point d'entrée ? */ - if (g_binary_symbol_get_target_type(symbols[sym_index]) == STP_ENTRY_POINT) + if (g_binary_symbol_get_target_type(symbol) == STP_ENTRY_POINT) flags |= BLF_ENTRYPOINT; /** @@ -311,7 +317,8 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, flags |= BLF_WIDTH_MANAGER; - sym_index++; + g_object_unref(G_OBJECT(symbol)); + symbol = get_symbol_iterator_next(siter); } @@ -369,6 +376,11 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, g_object_unref(G_OBJECT(content)); + if (symbol != NULL) + g_object_unref(G_OBJECT(symbol)); + + delete_symbol_iterator(siter); + if (portions != NULL) free(portions); diff --git a/src/analysis/disass/routines.c b/src/analysis/disass/routines.c index bc4247c..661e136 100644 --- a/src/analysis/disass/routines.c +++ b/src/analysis/disass/routines.c @@ -38,12 +38,11 @@ struct _GRoutinesStudy { GDelayedWork parent; /* A laisser en premier */ - GArchProcessor *proc; /* Processeurs avec ses instr. */ - + GArchProcessor *proc; /* Processeur avec ses instr. */ + GBinFormat *format; /* Format de fichier manipulé */ GBinPortion *portions; /* Couches de binaire bornées */ - GBinSymbol **symbols; /* Liste de symboles à traiter */ - size_t count; /* Taille de cette liste */ + size_t count; /* Nombre de symboles à traiter*/ rtn_fallback_cb fallback; /* Routine de traitement finale*/ size_t begin; /* Point de départ du parcours */ @@ -148,6 +147,11 @@ static void g_routines_study_dispose(GRoutinesStudy *study) { g_object_unref(G_OBJECT(study->portions)); + g_binary_format_unlock_symbols_rd(study->format); + + g_object_unref(G_OBJECT(study->format)); + g_object_unref(G_OBJECT(study->proc)); + G_OBJECT_CLASS(g_routines_study_parent_class)->dispose(G_OBJECT(study)); } @@ -175,9 +179,8 @@ static void g_routines_study_finalize(GRoutinesStudy *study) /****************************************************************************** * * * Paramètres : proc = ensemble d'instructions désassemblées. * +* format = format de fichier à manipuler. * * portions = ensemble de couches binaires bornées. * -* symbols = liste de symboles à parcourir. * -* count = quantité de ces prototypes. * * begin = point de départ du parcours de liste. * * end = point d'arrivée exclu du parcours. * * id = identifiant du message affiché à l'utilisateur. * @@ -191,19 +194,24 @@ static void g_routines_study_finalize(GRoutinesStudy *study) * * ******************************************************************************/ -GRoutinesStudy *g_routines_study_new(GArchProcessor *proc, GBinPortion *portions, GBinSymbol **symbols, size_t count, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback) +GRoutinesStudy *g_routines_study_new(GArchProcessor *proc, GBinFormat *format, GBinPortion *portions, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback) { GRoutinesStudy *result; /* Tâche à retourner */ result = g_object_new(G_TYPE_ROUTINES_STUDY, NULL); result->proc = proc; + g_object_ref(G_OBJECT(proc)); + + result->format = format; + g_object_ref(G_OBJECT(format)); result->portions = portions; g_object_ref(G_OBJECT(portions)); - result->symbols = symbols; - result->count = count; + g_binary_format_lock_symbols_rd(format); + + result->count = g_binary_format_count_symbols(format); result->fallback = fallback; result->begin = begin; @@ -238,12 +246,12 @@ static void g_routines_study_process(GRoutinesStudy *study, GtkStatusStack *stat for (i = study->begin; i < study->end; i++) { - symbol = study->symbols[i]; + symbol = g_binary_format_get_symbol(study->format, i); sym_status = g_binary_symbol_get_status(symbol); if (sym_status == SSS_IMPORTED) - continue; + goto grsp_next; type = g_binary_symbol_get_target_type(symbol); @@ -252,6 +260,10 @@ static void g_routines_study_process(GRoutinesStudy *study, GtkStatusStack *stat gtk_status_stack_update_activity_value(status, study->id, 1); + grsp_next: + + g_object_unref(G_OBJECT(symbol)); + } } @@ -274,6 +286,7 @@ static void g_routines_study_process(GRoutinesStudy *study, GtkStatusStack *stat void g_routines_study_compute_limits(GRoutinesStudy *study, GBinRoutine *routine, size_t index) { GBinSymbol *symbol; /* Version alternative */ + GBinSymbol *next_symbol; /* Eventuel symbole suivant */ const mrange_t *range; /* Zone du symbole suivant */ const vmpa2t *next; /* Début de la zone suivante */ @@ -281,8 +294,13 @@ void g_routines_study_compute_limits(GRoutinesStudy *study, GBinRoutine *routine if ((index + 1) < study->count) { - range = g_binary_symbol_get_range(study->symbols[index + 1]); + next_symbol = g_binary_format_get_symbol(study->format, index + 1); + + range = g_binary_symbol_get_range(next_symbol); next = get_mrange_addr(range); + + g_object_unref(G_OBJECT(next_symbol)); + } else diff --git a/src/analysis/disass/routines.h b/src/analysis/disass/routines.h index 4b3efa9..db8144d 100644 --- a/src/analysis/disass/routines.h +++ b/src/analysis/disass/routines.h @@ -28,7 +28,7 @@ #include "../routine.h" #include "../../arch/processor.h" #include "../../format/executable.h" -#include "../../format/symbol.h" +#include "../../format/format.h" #include "../../gtkext/gtkstatusstack.h" @@ -53,7 +53,7 @@ typedef void (* rtn_fallback_cb) (GRoutinesStudy *, GBinRoutine *, size_t); /* Crée une tâche d'étude de routines différée. */ -GRoutinesStudy *g_routines_study_new(GArchProcessor *, GBinPortion *, GBinSymbol **, size_t, size_t, size_t, activity_id_t, rtn_fallback_cb); +GRoutinesStudy *g_routines_study_new(GArchProcessor *, GBinFormat *, GBinPortion *, size_t, size_t, activity_id_t, rtn_fallback_cb); /* Détermine si besoin est les bornes des routines. */ void g_routines_study_compute_limits(GRoutinesStudy *, GBinRoutine *, size_t); diff --git a/src/arch/processor.c b/src/arch/processor.c index 21b6c49..78ded34 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -374,11 +374,15 @@ void g_arch_processor_lock_unlock(GArchProcessor *proc, bool state) if (state) { g_mutex_lock(&proc->mutex); +#ifndef NDEBUG g_atomic_int_set(&proc->locked, 1); +#endif } else { +#ifndef NDEBUG g_atomic_int_set(&proc->locked, 0); +#endif g_mutex_unlock(&proc->mutex); } diff --git a/src/format/Makefile.am b/src/format/Makefile.am index dfb9624..9b42ab0 100644 --- a/src/format/Makefile.am +++ b/src/format/Makefile.am @@ -10,6 +10,7 @@ libformat_la_SOURCES = \ format.h format.c \ preload-int.h \ preload.h preload.c \ + symiter.h symiter.c \ symbol-int.h \ symbol.h symbol.c diff --git a/src/format/format-int.h b/src/format/format-int.h index 0ab0e85..f377ca3 100644 --- a/src/format/format-int.h +++ b/src/format/format-int.h @@ -77,8 +77,12 @@ struct _GBinFormat GPreloadInfo *info; /* Préchargements du format */ GBinSymbol **symbols; /* Liste des symboles trouvés */ - size_t symbols_count; /* Quantité de ces symboles */ + size_t sym_count; /* Quantité de ces symboles */ + unsigned int sym_stamp; /* Marque de suivi des modifs */ GRWLock syms_lock; /* Accès à la liste de symboles*/ +#ifndef NDEBUG + gint sym_locked; /* Statut d'accès à la liste */ +#endif const char **src_files; /* Nom des fichiers source */ size_t src_count; /* Taille de la liste */ diff --git a/src/format/format.c b/src/format/format.c index 1ab7efa..a188204 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -50,6 +50,11 @@ static void g_binary_format_dispose(GBinFormat *); /* Procède à la libération totale de la mémoire. */ static void g_binary_format_finalize(GBinFormat *); + + +/* ---------------------- RASSEMBLEMENT ET GESTION DE SYMBOLES ---------------------- */ + + /* Retire un symbole de la collection du format binaire. */ static void _g_binary_format_remove_symbol(GBinFormat *, size_t); @@ -108,6 +113,9 @@ static void g_binary_format_init(GBinFormat *format) format->info = g_preload_info_new(); g_rw_lock_init(&format->syms_lock); +#ifndef DEBUG + g_atomic_int_set(&format->sym_locked, 0); +#endif format->errors = NULL; format->error_count = 0; @@ -361,6 +369,161 @@ void g_binary_format_activate_disassembling_context(GBinFormat *format, GProcCon } + +/* ---------------------------------------------------------------------------------- */ +/* RASSEMBLEMENT ET GESTION DE SYMBOLES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : format = architecture à manipuler. * +* state = nouvel état de l'accès aux symboles. * +* * +* Description : Protège ou lève la protection de l'accès aux symboles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_format_lock_unlock_symbols_rd(GBinFormat *format, bool state) +{ +#ifndef NDEBUG + gint test; /* Test de valeur courante */ +#endif + + if (state) + { + g_rw_lock_reader_lock(&format->syms_lock); +#ifndef NDEBUG + g_atomic_int_inc(&format->sym_locked); +#endif + } + else + { +#ifndef NDEBUG + test = g_atomic_int_add(&format->sym_locked, -1); + assert(test > 0); +#endif + g_rw_lock_reader_unlock(&format->syms_lock); + } + +} + + +/****************************************************************************** +* * +* Paramètres : format = architecture à manipuler. * +* state = nouvel état de l'accès aux symboles. * +* * +* Description : Protège ou lève la protection de l'accès aux symboles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_format_lock_unlock_symbols_wr(GBinFormat *format, bool state) +{ + if (state) + { + g_rw_lock_writer_lock(&format->syms_lock); +#ifndef NDEBUG + g_atomic_int_set(&format->sym_locked, 1); +#endif + } + else + { +#ifndef NDEBUG + g_atomic_int_set(&format->sym_locked, 0); +#endif + g_rw_lock_writer_unlock(&format->syms_lock); + } + +} + + +/****************************************************************************** +* * +* Paramètres : format = architecture à consulter via la procédure. * +* * +* Description : Fournit la marque de dernière modification des symboles. * +* * +* Retour : Marque de la dernière modification de la liste de symboles. * +* * +* Remarques : - * +* * +******************************************************************************/ + +unsigned int g_binary_format_get_symbols_stamp(const GBinFormat *format) +{ + return format->sym_stamp; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format visé par la procédure. * +* * +* Description : Compte le nombre de symboles représentés. * +* * +* Retour : Nombre de symboles présents. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_binary_format_count_symbols(const GBinFormat *format) +{ + assert(g_atomic_int_get(&format->sym_locked) > 0); + + return format->sym_count; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format visé par la procédure. * +* index = indice du symbole visé. * +* * +* Description : Fournit un symbole lié à un format. * +* * +* Retour : Symbole conservé trouvé ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinSymbol *g_binary_format_get_symbol(const GBinFormat *format, size_t index) +{ + GBinSymbol *result; /* Symbole à retourner */ + + assert(g_atomic_int_get(&format->sym_locked) > 0); + + if (format->sym_count == 0) + result = NULL; + + else + { + assert(index < format->sym_count); + + result = format->symbols[index]; + assert(result != NULL); + + g_object_ref(G_OBJECT(result)); + + } + + return result; + +} + + /****************************************************************************** * * * Paramètres : format = informations chargées à compléter. * @@ -409,7 +572,7 @@ bool g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol) assert(has_phys_addr(addr) || g_binary_symbol_get_status(symbol) == SSS_IMPORTED); #endif - g_rw_lock_writer_lock(&format->syms_lock); + g_binary_format_lock_unlock_symbols_wr(format, true); /** * Avec tous les traitements parallèles, il est possible que plusieurs chemins d'exécution @@ -421,21 +584,22 @@ bool g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol) * construction du symbole dans les cas peu fréquents où le symbole était déjà en place. */ - result = bsearch_index(&symbol, format->symbols, format->symbols_count, + result = bsearch_index(&symbol, format->symbols, format->sym_count, sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp, &index); if (!result) { - format->symbols = _qinsert(format->symbols, &format->symbols_count, + format->symbols = _qinsert(format->symbols, &format->sym_count, sizeof(GBinSymbol *), &symbol, index); + format->sym_stamp++; result = true; } else g_object_unref(G_OBJECT(symbol)); - g_rw_lock_writer_unlock(&format->syms_lock); + g_binary_format_lock_unlock_symbols_wr(format, false); return result; @@ -459,17 +623,18 @@ static void _g_binary_format_remove_symbol(GBinFormat *format, size_t index) { /** * TODO : envoyer un signal pour avertir les opérandes concernées. - * TODO : vérifier les conditions d'accès (verrou). */ - assert(index < format->symbols_count); + assert(g_atomic_int_get(&format->sym_locked) == 1); + + assert(index < format->sym_count); - if ((index + 1) < format->symbols_count) + if ((index + 1) < format->sym_count) memmove(&format->symbols[index], &format->symbols[index + 1], - (format->symbols_count - index - 1) * sizeof(GBinSymbol *)); + (format->sym_count - index - 1) * sizeof(GBinSymbol *)); format->symbols = (GBinSymbol **)realloc(format->symbols, - --format->symbols_count * sizeof(GBinSymbol *)); + --format->sym_count * sizeof(GBinSymbol *)); } @@ -493,7 +658,7 @@ void g_binary_format_remove_symbol(GBinFormat *format, GBinSymbol *symbol) // FIXME : dicho - for (i = 0; i < format->symbols_count; i++) + for (i = 0; i < format->sym_count; i++) if (format->symbols[i] == symbol) break; @@ -521,15 +686,15 @@ static void g_binary_format_delete_duplicated_symbols(GBinFormat *format) mrange_t last; /* Dernière localisation vue */ size_t index; /* Indice de suppression */ - g_rw_lock_writer_lock(&format->syms_lock); + g_binary_format_lock_unlock_symbols_wr(format, true); - if (format->symbols_count > 1) + if (format->sym_count > 1) { range = g_binary_symbol_get_range(format->symbols[0]); copy_mrange(&last, range); } - for (i = 1; i < format->symbols_count; i++) + for (i = 1; i < format->sym_count; i++) { range = g_binary_symbol_get_range(format->symbols[i]); @@ -554,29 +719,7 @@ static void g_binary_format_delete_duplicated_symbols(GBinFormat *format) } - g_rw_lock_writer_unlock(&format->syms_lock); - -} - - -/****************************************************************************** -* * -* Paramètres : format = informations chargées à consulter. * -* count = taille du tableau créé. [OUT] * -* * -* Description : Fournit la liste de tous les symboles détectés. * -* * -* Retour : Tableau créé ou NULL si aucun symbole trouvé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBinSymbol **g_binary_format_get_symbols(const GBinFormat *format, size_t *count) -{ - *count = format->symbols_count; - - return format->symbols; + g_binary_format_lock_unlock_symbols_wr(format, false); } @@ -693,9 +836,9 @@ bool g_binary_format_find_symbol_by_label(GBinFormat *format, const char *label, result = false; - g_rw_lock_reader_lock(&format->syms_lock); + g_binary_format_lock_symbols_rd(format); - for (i = 0; i < format->symbols_count && !result; i++) + for (i = 0; i < format->sym_count && !result; i++) { cur_lbl = g_binary_symbol_get_label(format->symbols[i]); if (cur_lbl == NULL) continue; @@ -711,7 +854,7 @@ bool g_binary_format_find_symbol_by_label(GBinFormat *format, const char *label, } - g_rw_lock_reader_unlock(&format->syms_lock); + g_binary_format_unlock_symbols_rd(format); return result; @@ -739,6 +882,8 @@ static bool _g_binary_format_find_symbol(const GBinFormat *format, const vmpa2t bool result; /* Bilan à retourner */ void *found; /* Résultat de recherches */ + assert(g_atomic_int_get(&format->sym_locked) > 0); + /** * Pour ce qui est des justifications quant à la vérification suivante, * se référer aux commentaires placés dans g_binary_format_add_symbol(). @@ -746,7 +891,7 @@ static bool _g_binary_format_find_symbol(const GBinFormat *format, const vmpa2t assert(has_phys_addr(addr)); - found = bsearch(addr, format->symbols, format->symbols_count, sizeof(GBinSymbol *), fn); + found = bsearch(addr, format->symbols, format->sym_count, sizeof(GBinSymbol *), fn); if (found != NULL) { @@ -802,11 +947,11 @@ bool g_binary_format_find_symbol_at(GBinFormat *format, const vmpa2t *addr, GBin } - g_rw_lock_reader_lock(&format->syms_lock); + g_binary_format_lock_symbols_rd(format); result = _g_binary_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, NULL, symbol); - g_rw_lock_reader_unlock(&format->syms_lock); + g_binary_format_unlock_symbols_rd(format); return result; @@ -841,11 +986,11 @@ bool g_binary_format_find_symbol_for(GBinFormat *format, const vmpa2t *addr, GBi } - g_rw_lock_reader_lock(&format->syms_lock); + g_binary_format_lock_symbols_rd(format); result = _g_binary_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, NULL, symbol); - g_rw_lock_reader_unlock(&format->syms_lock); + g_binary_format_unlock_symbols_rd(format); return result; @@ -881,11 +1026,11 @@ bool g_binary_format_find_next_symbol_at(GBinFormat *format, const vmpa2t *addr, } - g_rw_lock_reader_lock(&format->syms_lock); + g_binary_format_lock_symbols_rd(format); result = _g_binary_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, &index, NULL); - if (result && (index + 1) < format->symbols_count) + if (result && (index + 1) < format->sym_count) { *symbol = format->symbols[index + 1]; g_object_ref(G_OBJECT(*symbol)); @@ -898,7 +1043,7 @@ bool g_binary_format_find_next_symbol_at(GBinFormat *format, const vmpa2t *addr, result = false; } - g_rw_lock_reader_unlock(&format->syms_lock); + g_binary_format_unlock_symbols_rd(format); return result; diff --git a/src/format/format.h b/src/format/format.h index 8247478..9a3a6e3 100644 --- a/src/format/format.h +++ b/src/format/format.h @@ -70,15 +70,38 @@ void g_binary_format_preload_disassembling_context(GBinFormat *, GProcContext *, /* Définit les points de départ d'un contexte de désassemblage. */ void g_binary_format_activate_disassembling_context(GBinFormat *, GProcContext *, GtkStatusStack *); + + +/* ---------------------- RASSEMBLEMENT ET GESTION DE SYMBOLES ---------------------- */ + + +/* Protège ou lève la protection de l'accès aux symboles. */ +void g_binary_format_lock_unlock_symbols_rd(GBinFormat *, bool); + +#define g_binary_format_lock_symbols_rd(f) g_binary_format_lock_unlock_symbols_rd(f, true) +#define g_binary_format_unlock_symbols_rd(f) g_binary_format_lock_unlock_symbols_rd(f, false) + +/* Protège ou lève la protection de l'accès aux symboles. */ +void g_binary_format_lock_unlock_symbols_wr(GBinFormat *, bool); + +#define g_binary_format_lock_symbols_wr(f) g_binary_format_lock_unlock_symbols_wr(f, true) +#define g_binary_format_unlock_symbols_wr(f) g_binary_format_lock_unlock_symbols_wr(f, false) + +/* Fournit la marque de dernière modification des symboles. */ +unsigned int g_binary_format_get_symbols_stamp(const GBinFormat *); + +/* Compte le nombre de symboles représentés. */ +size_t g_binary_format_count_symbols(const GBinFormat *); + +/* Fournit un symbole lié à un format. */ +GBinSymbol *g_binary_format_get_symbol(const GBinFormat *, size_t); + /* Ajoute un symbole à la collection du format binaire. */ bool g_binary_format_add_symbol(GBinFormat *, GBinSymbol *); /* Retire un symbole de la collection du format binaire. */ void g_binary_format_remove_symbol(GBinFormat *, GBinSymbol *); -/* Fournit la liste de tous les symboles détectés. */ -GBinSymbol **g_binary_format_get_symbols(const GBinFormat *, size_t *); - /* Construit une désignation pour chaîne de caractères. */ char *create_string_label(GBinFormat *, const vmpa2t *, size_t); @@ -97,6 +120,9 @@ bool g_binary_format_find_next_symbol_at(GBinFormat *, const vmpa2t *, GBinSymbo /* Recherche le symbole correspondant à une adresse. */ bool g_binary_format_resolve_symbol(GBinFormat *, const vmpa2t *, bool, GBinSymbol **, phys_t *); + + + /* Fournit la liste des fichiers source détectés. */ const char * const *g_binary_format_get_source_files(const GBinFormat *, size_t *, size_t *); diff --git a/src/format/symiter.c b/src/format/symiter.c new file mode 100644 index 0000000..74b4abb --- /dev/null +++ b/src/format/symiter.c @@ -0,0 +1,289 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * symiter.c - prototypes pour le parcours simplifié d'un ensemble de symboles + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include "symiter.h" + + +#include + + +#include "format.h" + + + +/* Suivi d'un parcours de symboles */ +typedef struct _sym_iter_t +{ + GBinFormat *format; /* Conteneur associé */ + unsigned int stamp; /* Suivi d'évolutions externes */ + + size_t index; /* Symbole courant */ + + mrange_t restriction; /* Enventuelle limite de zone */ + bool is_restricted; /* Validité de l'étendue */ + +} sym_iter_t; + + + +/****************************************************************************** +* * +* Paramètres : format = processeur recensant divers symboles. * +* index = indice du premier symbole à fournir. * +* * +* Description : Construit un itérateur pour parcourir des symboles. * +* * +* Retour : Itérateur prêt à emploi. * +* * +* Remarques : - * +* * +******************************************************************************/ + +sym_iter_t *create_symbol_iterator(GBinFormat *format, size_t index) +{ + sym_iter_t *result; /* Structure à retourner */ + + result = (sym_iter_t *)malloc(sizeof(sym_iter_t)); + + g_object_ref(G_OBJECT(format)); + + result->format = format; + result->stamp = g_binary_format_get_symbols_stamp(format); + + result->index = index; + + result->is_restricted = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : iter = itérateur à traiter. * +* * +* Description : Détruit un itérateur mis en place. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_symbol_iterator(sym_iter_t *iter) +{ + g_object_unref(G_OBJECT(iter->format)); + + free(iter); + +} + + +/****************************************************************************** +* * +* Paramètres : iter = itérateur à traiter. * +* range = bornes de l'espace de parcours. * +* * +* Description : Limite le parcours des symboles à une zone donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void restrict_symbol_iterator(sym_iter_t *iter, const mrange_t *range) +{ + copy_mrange(&iter->restriction, range); + + iter->is_restricted = true; + +} + + +/****************************************************************************** +* * +* Paramètres : iter = itérateur à manipuler. * +* * +* Description : Fournit le symbole courant de l'itérateur. * +* * +* Retour : Symbole suivant trouvé, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinSymbol *get_symbol_iterator_current(sym_iter_t *iter) +{ + GBinSymbol *result; /* Résultat à retourner */ + const mrange_t *irange; /* Emplacement de symbole */ + + g_binary_format_lock_symbols_rd(iter->format); + + if (iter->stamp != g_binary_format_get_symbols_stamp(iter->format)) + result = NULL; + + else + { + if (iter->index < g_binary_format_count_symbols(iter->format)) + { + result = g_binary_format_get_symbol(iter->format, iter->index); + + /* Le symbole sort-il des clous ? */ + if (iter->is_restricted) + { + irange = g_binary_symbol_get_range(result); + + if (!mrange_contains_mrange(&iter->restriction, irange)) + { + g_object_unref(G_OBJECT(result)); + result = NULL; + } + + } + + } + + else + result = NULL; + + } + + g_binary_format_unlock_symbols_rd(iter->format); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : iter = itérateur à manipuler. * +* * +* Description : Fournit le symbole qui en précède un autre. * +* * +* Retour : Symbole suivant trouvé, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinSymbol *get_symbol_iterator_prev(sym_iter_t *iter) +{ + GBinSymbol *result; /* Résultat à retourner */ + const mrange_t *irange; /* Emplacement de symbole */ + + g_binary_format_lock_symbols_rd(iter->format); + + if (iter->stamp != g_binary_format_get_symbols_stamp(iter->format)) + result = NULL; + + else + { + if (iter->index > 1) + { + iter->index--; + result = g_binary_format_get_symbol(iter->format, iter->index); + + /* Le symbole sort-il des clous ? */ + if (iter->is_restricted) + { + irange = g_binary_symbol_get_range(result); + + if (!mrange_contains_mrange(&iter->restriction, irange)) + { + g_object_unref(G_OBJECT(result)); + result = NULL; + } + + } + + } + + else + result = NULL; + + } + + g_binary_format_unlock_symbols_rd(iter->format); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : iter = itérateur à manipuler. * +* * +* Description : Fournit le symbole qui en suit un autre. * +* * +* Retour : Symbole suivant trouvé, ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinSymbol *get_symbol_iterator_next(sym_iter_t *iter) +{ + GBinSymbol *result; /* Résultat à retourner */ + const mrange_t *irange; /* Emplacement de symbole */ + + g_binary_format_lock_symbols_rd(iter->format); + + if (iter->stamp != g_binary_format_get_symbols_stamp(iter->format)) + result = NULL; + + else + { + if ((iter->index + 1) < g_binary_format_count_symbols(iter->format)) + { + iter->index++; + result = g_binary_format_get_symbol(iter->format, iter->index); + + /* Le symbole sort-il des clous ? */ + if (iter->is_restricted) + { + irange = g_binary_symbol_get_range(result); + + if (!mrange_contains_mrange(&iter->restriction, irange)) + { + g_object_unref(G_OBJECT(result)); + result = NULL; + } + + } + + } + + else + result = NULL; + + } + + g_binary_format_unlock_symbols_rd(iter->format); + + return result; + +} diff --git a/src/format/symiter.h b/src/format/symiter.h new file mode 100644 index 0000000..32f4af7 --- /dev/null +++ b/src/format/symiter.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * symiter.h - prototypes pour le parcours simplifié d'un ensemble de symboles + * + * Copyright (C) 2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#ifndef _FORMAT_SYMITER_H +#define _FORMAT_SYMITER_H + + +#include "format.h" + + + +/* Suivi d'un parcours de symboles */ +typedef struct _sym_iter_t sym_iter_t; + + +/* Construit un itérateur pour parcourir des symboles. */ +sym_iter_t *create_symbol_iterator(GBinFormat *, size_t); + +/* Détruit un itérateur mis en place. */ +void delete_symbol_iterator(sym_iter_t *); + +/* Limite le parcours des symboles à une zone donnée. */ +void restrict_symbol_iterator(sym_iter_t *, const mrange_t *); + +/* Fournit le symbole courant de l'itérateur. */ +GBinSymbol *get_symbol_iterator_current(sym_iter_t *); + +/* Fournit le symbole qui en précède un autre. */ +GBinSymbol *get_symbol_iterator_prev(sym_iter_t *); + +/* Fournit le symbole qui en suit un autre. */ +GBinSymbol *get_symbol_iterator_next(sym_iter_t *); + + + +#endif /* _FORMAT_SYMITER_H */ diff --git a/src/gui/dialogs/gotox.c b/src/gui/dialogs/gotox.c index 00ad356..31123ff 100644 --- a/src/gui/dialogs/gotox.c +++ b/src/gui/dialogs/gotox.c @@ -32,6 +32,7 @@ #include "../../format/format.h" +#include "../../format/symiter.h" #include "../../gtkext/easygtk.h" #include "../../gtkext/support.h" @@ -213,10 +214,9 @@ GtkWidget *create_gotox_dialog_for_entry_points(GtkWindow *parent, GLoadedBinary GtkWidget *result; /* Fenêtre à renvoyer */ GtkTreeStore *store; /* Modèle de gestion */ GBinFormat *format; /* Format associé au binaire */ - GBinSymbol **symbols; /* Symboles à représenter */ - size_t sym_count; /* Qté de symboles présents */ + sym_iter_t *siter; /* Parcours des symboles */ + GBinSymbol *symbol; /* Symbole manipulé */ bool has_entry_points; /* Présences d'insertions ? */ - size_t i; /* Boucle de parcours */ vmpa2t addr; /* Localisation de symbole */ /* Mise en place de la boîte de dialogue */ @@ -229,23 +229,31 @@ GtkWidget *create_gotox_dialog_for_entry_points(GtkWindow *parent, GLoadedBinary format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); - symbols = g_binary_format_get_symbols(format, &sym_count); + siter = create_symbol_iterator(format, 0); has_entry_points = false; - for (i = 0; i < sym_count; i++) + for (symbol = get_symbol_iterator_current(siter); + symbol != NULL; + symbol = get_symbol_iterator_next(siter)) { - if (g_binary_symbol_get_target_type(symbols[i]) != STP_ENTRY_POINT) - continue; + if (g_binary_symbol_get_target_type(symbol) != STP_ENTRY_POINT) + goto cgdfep_next; - copy_vmpa(&addr, get_mrange_addr(g_binary_symbol_get_range(symbols[i]))); + copy_vmpa(&addr, get_mrange_addr(g_binary_symbol_get_range(symbol))); - add_new_location_to_list(store, binary, &addr, symbols[i]); + add_new_location_to_list(store, binary, &addr, symbol); has_entry_points = true; + cgdfep_next: + + g_object_unref(G_OBJECT(symbol)); + } + delete_symbol_iterator(siter); + g_object_unref(G_OBJECT(format)); g_object_unref(G_OBJECT(store)); diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c index 23383a1..5942d03 100644 --- a/src/gui/panels/strings.c +++ b/src/gui/panels/strings.c @@ -35,6 +35,7 @@ #include "../../common/extstr.h" #include "../../core/params.h" #include "../../format/format.h" +#include "../../format/symiter.h" #include "../../gtkext/easygtk.h" #include "../../gtkext/gtkdockable-int.h" @@ -468,9 +469,8 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin GExeFormat *format; /* Format de travail */ GBinPortion *portions; /* Couche première de portions */ GBinContent *content; /* Contenu binaire en mémoire */ - size_t count; /* Nombre des chaînes */ - GBinSymbol **symbols; /* Liste des chaînes trouvées */ - size_t i; /* Boucle de parcours */ + sym_iter_t *siter; /* Parcours des symboles */ + GBinSymbol *symbol; /* Symbole manipulé */ const mrange_t *range; /* Couverture mémoire */ const vmpa2t *addr; /* Adressse liée à la chaîne */ VMPA_BUFFER(phys); /* Position physique */ @@ -509,13 +509,16 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin portions = g_exe_format_get_portions(format); content = g_binary_format_get_content(G_BIN_FORMAT(format)); - symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &count); + siter = create_symbol_iterator(G_BIN_FORMAT(format), 0); - for (i = 0; i < count; i++) + for (symbol = get_symbol_iterator_current(siter); + symbol != NULL; + symbol = get_symbol_iterator_next(siter)) { - if (g_binary_symbol_get_target_type(symbols[i]) != STP_RO_STRING) continue; + if (g_binary_symbol_get_target_type(symbol) != STP_RO_STRING) + goto cspcb_next; - range = g_binary_symbol_get_range(symbols[i]); + range = g_binary_symbol_get_range(symbol); addr = get_mrange_addr(range); vmpa2_phys_to_string(addr, msize, phys, NULL); @@ -525,7 +528,7 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin area = g_binary_portion_get_desc(portion); g_object_unref(G_OBJECT(portion)); - label = g_binary_symbol_get_label(symbols[i]); + label = g_binary_symbol_get_label(symbol); text = (char *)calloc(get_mrange_length(range) + 1, sizeof(char)); @@ -534,13 +537,13 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin if (!g_binary_content_read_raw(content, &pos, get_mrange_length(range), (uint8_t *)text)) { free(text); - continue; + goto cspcb_next; } if (is_string_filtered(panel, label, text)) { free(text); - continue; + goto cspcb_next; } text = strrpl(text, "&", "&"); @@ -551,7 +554,7 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin gtk_tree_store_append(store, &iter, NULL); gtk_tree_store_set(store, &iter, - STC_STRING, symbols[i], + STC_STRING, symbol, STC_PHYSICAL, phys, STC_VIRTUAL, virt, STC_AREA, area, @@ -561,8 +564,14 @@ static void change_strings_panel_current_binary(GStringsPanel *panel, GLoadedBin free(text); + cspcb_next: + + g_object_unref(G_OBJECT(symbol)); + } + delete_symbol_iterator(siter); + g_object_unref(G_OBJECT(content)); g_object_unref(G_OBJECT(portions)); g_object_unref(G_OBJECT(format)); diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c index f64f087..dee03b5 100644 --- a/src/gui/panels/symbols.c +++ b/src/gui/panels/symbols.c @@ -39,6 +39,7 @@ #include "panel-int.h" #include "../core/global.h" #include "../../format/format.h" +#include "../../format/symiter.h" #include "../../gtkext/easygtk.h" #include "../../gtkext/support.h" #include "../../gtkext/tmgt.h" @@ -649,11 +650,10 @@ static void change_symbols_panel_current_binary(GSymbolsPanel *panel, GLoadedBin static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) { GExeFormat *format; /* Format associé au binaire */ - GBinSymbol **symbols; /* Symboles à représenter */ - size_t sym_count; /* Qté de symboles présents */ GArchProcessor *proc; /* Architecture utilisée */ MemoryDataSize size; /* Taille des localisations */ - size_t i; /* Boucle de parcours */ + sym_iter_t *siter; /* Parcours des symboles */ + GBinSymbol *symbol; /* Symbole manipulé */ regmatch_t match; /* Récupération des trouvailles*/ cairo_surface_t *icon; /* Image associée au symbole */ const char *original; /* Etiquette brute d'origine */ @@ -664,18 +664,20 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) format = g_loaded_binary_get_format(panel->binary); - symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count); - proc = g_loaded_binary_get_processor(panel->binary); size = g_arch_processor_get_memory_size(proc); g_object_unref(G_OBJECT(proc)); - for (i = 0; i < sym_count; i++) + siter = create_symbol_iterator(G_BIN_FORMAT(format), 0); + + for (symbol = get_symbol_iterator_current(siter); + symbol != NULL; + symbol = get_symbol_iterator_next(siter)) { - if (!is_symbol_matching(panel, symbols[i], &match)) - continue; + if (!is_symbol_matching(panel, symbol, &match)) + goto rsfnlv_next; - switch (g_binary_symbol_get_target_type(symbols[i])) + switch (g_binary_symbol_get_target_type(symbol)) { case STP_ROUTINE: case STP_ENTRY_POINT: @@ -689,15 +691,15 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) break; } - original = g_binary_symbol_get_label(symbols[i]); + original = g_binary_symbol_get_label(symbol); name = build_highlighted_name(original, &match, 0); - addr = get_mrange_addr(g_binary_symbol_get_range(symbols[i])); + addr = get_mrange_addr(g_binary_symbol_get_range(symbol)); vmpa2_virt_to_string(addr, size, virt, NULL); gtk_tree_store_append(panel->store, &iter, NULL); gtk_tree_store_set(panel->store, &iter, - SBC_SYMBOL, symbols[i], + SBC_SYMBOL, symbol, SBC_PICTURE, icon, SBC_NAME, name, SBC_ORIGINAL, original, @@ -706,8 +708,14 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) free(name); + rsfnlv_next: + + g_object_unref(G_OBJECT(symbol)); + } + delete_symbol_iterator(siter); + g_object_unref(G_OBJECT(format)); } @@ -849,11 +857,10 @@ static bool find_parent_for_symbol(GSymbolsPanel *panel, const GBinSymbol *symbo static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel) { GExeFormat *format; /* Format associé au binaire */ - GBinSymbol **symbols; /* Symboles à représenter */ - size_t sym_count; /* Qté de symboles présents */ GArchProcessor *proc; /* Architecture utilisée */ MemoryDataSize size; /* Taille des localisations */ - size_t i; /* Boucle de parcours */ + sym_iter_t *siter; /* Parcours des symboles */ + GBinSymbol *symbol; /* Symbole manipulé */ regmatch_t match; /* Récupération des trouvailles*/ GtkTreeIter parent; /* Point d'insertion parent */ size_t last; /* Position du dernier élément */ @@ -866,18 +873,20 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel) format = g_loaded_binary_get_format(panel->binary); - symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count); - proc = g_loaded_binary_get_processor(panel->binary); size = g_arch_processor_get_memory_size(proc); g_object_unref(G_OBJECT(proc)); - for (i = 0; i < sym_count; i++) + siter = create_symbol_iterator(G_BIN_FORMAT(format), 0); + + for (symbol = get_symbol_iterator_current(siter); + symbol != NULL; + symbol = get_symbol_iterator_next(siter)) { - if (!is_symbol_matching(panel, symbols[i], &match)) - continue; + if (!is_symbol_matching(panel, symbol, &match)) + goto rsfntv_next; - if (find_parent_for_symbol(panel, symbols[i], &parent, &match, &last)) + if (find_parent_for_symbol(panel, symbol, &parent, &match, &last)) { gtk_tree_store_set(panel->store, &parent, SBC_PICTURE, G_SYMBOLS_PANEL_GET_CLASS(panel)->class_img, @@ -890,7 +899,7 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel) else gtk_tree_store_append(panel->store, &iter, NULL); - switch (g_binary_symbol_get_target_type(symbols[i])) + switch (g_binary_symbol_get_target_type(symbol)) { case STP_ROUTINE: case STP_ENTRY_POINT: @@ -904,14 +913,14 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel) break; } - original = g_binary_symbol_get_label(symbols[i]); + original = g_binary_symbol_get_label(symbol); name = build_highlighted_name(original + last, &match, last); - addr = get_mrange_addr(g_binary_symbol_get_range(symbols[i])); + addr = get_mrange_addr(g_binary_symbol_get_range(symbol)); vmpa2_virt_to_string(addr, size, virt, NULL); gtk_tree_store_set(panel->store, &iter, - SBC_SYMBOL, symbols[i], + SBC_SYMBOL, symbol, SBC_PICTURE, icon, SBC_NAME, name, SBC_ORIGINAL, original + last, @@ -920,8 +929,14 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel) free(name); + rsfntv_next: + + g_object_unref(G_OBJECT(symbol)); + } + delete_symbol_iterator(siter); + g_object_unref(G_OBJECT(format)); } -- cgit v0.11.2-87-g4458