diff options
Diffstat (limited to 'src')
31 files changed, 849 insertions, 228 deletions
| diff --git a/src/analysis/disass/instructions.c b/src/analysis/disass/instructions.c index 7e76a5d..b88d69f 100644 --- a/src/analysis/disass/instructions.c +++ b/src/analysis/disass/instructions.c @@ -112,7 +112,7 @@ static void g_instructions_study_class_init(GInstructionsStudyClass *klass)  /******************************************************************************  *                                                                             * -*  Paramètres  : computing = instance à initialiser.                          * +*  Paramètres  : study = instance à initialiser.                              *  *                                                                             *  *  Description : Initialise une tâche d'étude d'instructions.                 *  *                                                                             * @@ -130,7 +130,7 @@ static void g_instructions_study_init(GInstructionsStudy *study)  /******************************************************************************  *                                                                             * -*  Paramètres  : computing = instance d'objet GLib à traiter.                 * +*  Paramètres  : study = instance d'objet GLib à traiter.                     *  *                                                                             *  *  Description : Supprime toutes les références externes.                     *  *                                                                             * @@ -140,16 +140,16 @@ static void g_instructions_study_init(GInstructionsStudy *study)  *                                                                             *  ******************************************************************************/ -static void g_instructions_study_dispose(GInstructionsStudy *computing) +static void g_instructions_study_dispose(GInstructionsStudy *study)  { -    G_OBJECT_CLASS(g_instructions_study_parent_class)->dispose(G_OBJECT(computing)); +    G_OBJECT_CLASS(g_instructions_study_parent_class)->dispose(G_OBJECT(study));  }  /******************************************************************************  *                                                                             * -*  Paramètres  : computing = instance d'objet GLib à traiter.                 * +*  Paramètres  : study = instance d'objet GLib à traiter.                     *  *                                                                             *  *  Description : Procède à la libération totale de la mémoire.                *  *                                                                             * @@ -159,9 +159,9 @@ static void g_instructions_study_dispose(GInstructionsStudy *computing)  *                                                                             *  ******************************************************************************/ -static void g_instructions_study_finalize(GInstructionsStudy *computing) +static void g_instructions_study_finalize(GInstructionsStudy *study)  { -    G_OBJECT_CLASS(g_instructions_study_parent_class)->finalize(G_OBJECT(computing)); +    G_OBJECT_CLASS(g_instructions_study_parent_class)->finalize(G_OBJECT(study));  } diff --git a/src/analysis/disass/routines.c b/src/analysis/disass/routines.c index 94afbe4..de515d0 100644 --- a/src/analysis/disass/routines.c +++ b/src/analysis/disass/routines.c @@ -117,7 +117,7 @@ static void g_routines_study_class_init(GRoutinesStudyClass *klass)  /******************************************************************************  *                                                                             * -*  Paramètres  : computing = instance à initialiser.                          * +*  Paramètres  : study = instance à initialiser.                              *  *                                                                             *  *  Description : Initialise une tâche d'étude de routines.                    *  *                                                                             * @@ -135,7 +135,7 @@ static void g_routines_study_init(GRoutinesStudy *study)  /******************************************************************************  *                                                                             * -*  Paramètres  : computing = instance d'objet GLib à traiter.                 * +*  Paramètres  : study = instance d'objet GLib à traiter.                     *  *                                                                             *  *  Description : Supprime toutes les références externes.                     *  *                                                                             * @@ -145,16 +145,16 @@ static void g_routines_study_init(GRoutinesStudy *study)  *                                                                             *  ******************************************************************************/ -static void g_routines_study_dispose(GRoutinesStudy *computing) +static void g_routines_study_dispose(GRoutinesStudy *study)  { -    G_OBJECT_CLASS(g_routines_study_parent_class)->dispose(G_OBJECT(computing)); +    G_OBJECT_CLASS(g_routines_study_parent_class)->dispose(G_OBJECT(study));  }  /******************************************************************************  *                                                                             * -*  Paramètres  : computing = instance d'objet GLib à traiter.                 * +*  Paramètres  : study = instance d'objet GLib à traiter.                     *  *                                                                             *  *  Description : Procède à la libération totale de la mémoire.                *  *                                                                             * @@ -164,9 +164,9 @@ static void g_routines_study_dispose(GRoutinesStudy *computing)  *                                                                             *  ******************************************************************************/ -static void g_routines_study_finalize(GRoutinesStudy *computing) +static void g_routines_study_finalize(GRoutinesStudy *study)  { -    G_OBJECT_CLASS(g_routines_study_parent_class)->finalize(G_OBJECT(computing)); +    G_OBJECT_CLASS(g_routines_study_parent_class)->finalize(G_OBJECT(study));  } diff --git a/src/core/formats.c b/src/core/formats.c index 5543331..c6b664c 100644 --- a/src/core/formats.c +++ b/src/core/formats.c @@ -368,6 +368,7 @@ FormatMatchStatus find_matching_format(GBinContent *content, GExeFormat *parent,  *                                                                             *  *  Paramètres  : key     = nom technique du processeur recherché.             *  *                content = contenu binaire pré-chargé à traiter.              * +*                parent  = contenu binaire principal éventuel déjà chargé.    *  *                                                                             *  *  Description : Charge le format binaire correspondant à un type.            *  *                                                                             * @@ -389,7 +390,12 @@ GBinFormat *load_new_named_format(const char *key, GBinContent *content, GExeFor      if (def == NULL)          result = NULL;      else -        result = def->func(content, parent); +    { +        extern GtkStatusStack *get_global_status(void); + +        result = def->func(content, parent, get_global_status()); + +    }      g_rw_lock_reader_unlock(&_formats_lock); diff --git a/src/core/formats.h b/src/core/formats.h index 76b57d0..e3dc871 100644 --- a/src/core/formats.h +++ b/src/core/formats.h @@ -31,6 +31,7 @@  #include "../format/format.h"  #include "../format/executable.h" +#include "../gtkext/gtkstatusstack.h" @@ -50,7 +51,7 @@ typedef enum _FormatMatchStatus  typedef FormatMatchStatus (* format_match_fc) (GBinContent *, GExeFormat *, void *, char **);  /* Méthode de chargement d'un format */ -typedef GBinFormat * (* format_load_fc) (GBinContent *, GExeFormat *); +typedef GBinFormat * (* format_load_fc) (GBinContent *, GExeFormat *, GtkStatusStack *);  /* Enregistre un détection de format(s) binaire(s). */ diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c index 2897ee3..3388861 100755 --- a/src/format/dex/dex.c +++ b/src/format/dex/dex.c @@ -233,6 +233,7 @@ static void g_dex_format_finalize(GDexFormat *format)  *                                                                             *  *  Paramètres  : content = contenu binaire à parcourir.                       *  *                parent  = éventuel format exécutable déjà chargé.            * +                 status  = barre de statut à tenir informée.                  *  *                                                                             *  *  Description : Prend en charge un nouveau format Dex.                       *  *                                                                             * @@ -242,7 +243,7 @@ static void g_dex_format_finalize(GDexFormat *format)  *                                                                             *  ******************************************************************************/ -GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent) +GBinFormat *g_dex_format_new(GBinContent *content, GExeFormat *parent, GtkStatusStack *status)  {      GDexFormat *result;                     /* Structure à retourner       */      GBinFormat *base;                       /* Version basique du format   */ diff --git a/src/format/dex/dex.h b/src/format/dex/dex.h index 28d2a49..0283a0c 100755 --- a/src/format/dex/dex.h +++ b/src/format/dex/dex.h @@ -56,7 +56,7 @@ FormatMatchStatus dex_is_matching(GBinContent *, GExeFormat *, void *, char **);  GType g_dex_format_get_type(void);  /* Prend en charge un nouveau format DEX. */ -GBinFormat *g_dex_format_new(GBinContent *, GExeFormat *); +GBinFormat *g_dex_format_new(GBinContent *, GExeFormat *, GtkStatusStack *);  /* Présente l'en-tête DEX du format chargé. */  const dex_header *g_dex_format_get_header(const GDexFormat *); diff --git a/src/format/dwarf/v2/dwarf.c b/src/format/dwarf/v2/dwarf.c index ccef01f..5e417c3 100644 --- a/src/format/dwarf/v2/dwarf.c +++ b/src/format/dwarf/v2/dwarf.c @@ -153,6 +153,7 @@ static void g_dwarfv2_format_finalize(GDwarfV2Format *format)  *                                                                             *  *  Paramètres  : content = contenu binaire à parcourir.                       *  *                parent  = éventuel format exécutable déjà chargé.            * +                 status  = barre de statut à tenir informée.                  *  *                                                                             *  *  Description : Prend en charge un nouveau format DWARF (v2).                *  *                                                                             * @@ -162,7 +163,7 @@ static void g_dwarfv2_format_finalize(GDwarfV2Format *format)  *                                                                             *  ******************************************************************************/ -GBinFormat *g_dwarfv2_format_new(GBinContent *content, GExeFormat *parent) +GBinFormat *g_dwarfv2_format_new(GBinContent *content, GExeFormat *parent, GtkStatusStack *status)  {      GDwarfV2Format *result;                 /* Structure à retourner       */ diff --git a/src/format/dwarf/v2/dwarf.h b/src/format/dwarf/v2/dwarf.h index 360a2e6..732007b 100644 --- a/src/format/dwarf/v2/dwarf.h +++ b/src/format/dwarf/v2/dwarf.h @@ -52,7 +52,7 @@ typedef struct _GDwarfV2FormatClass GDwarfV2FormatClass;  GType g_dwarfv2_format_get_type(void);  /* Prend en charge un nouveau format DWARF (v2). */ -GBinFormat *g_dwarfv2_format_new(GBinContent *, GExeFormat *); +GBinFormat *g_dwarfv2_format_new(GBinContent *, GExeFormat *, GtkStatusStack *); diff --git a/src/format/dwarf/v3/dwarf.c b/src/format/dwarf/v3/dwarf.c index d6198f7..0fcd38f 100644 --- a/src/format/dwarf/v3/dwarf.c +++ b/src/format/dwarf/v3/dwarf.c @@ -145,6 +145,7 @@ static void g_dwarfv3_format_finalize(GDwarfV3Format *format)  *                                                                             *  *  Paramètres  : content = contenu binaire à parcourir.                       *  *                parent  = éventuel format exécutable déjà chargé.            * +                 status  = barre de statut à tenir informée.                  *  *                                                                             *  *  Description : Prend en charge un nouveau format DWARF (v3).                *  *                                                                             * @@ -154,7 +155,7 @@ static void g_dwarfv3_format_finalize(GDwarfV3Format *format)  *                                                                             *  ******************************************************************************/ -GBinFormat *g_dwarfv3_format_new(GBinContent *content, GExeFormat *parent) +GBinFormat *g_dwarfv3_format_new(GBinContent *content, GExeFormat *parent, GtkStatusStack *status)  {      GDwarfV3Format *result;                 /* Structure à retourner       */ diff --git a/src/format/dwarf/v3/dwarf.h b/src/format/dwarf/v3/dwarf.h index 2aaf891..e316a52 100644 --- a/src/format/dwarf/v3/dwarf.h +++ b/src/format/dwarf/v3/dwarf.h @@ -52,7 +52,7 @@ typedef struct _GDwarfV3FormatClass GDwarfV3FormatClass;  GType g_dwarfv3_format_get_type(void);  /* Prend en charge un nouveau format DWARF (v3). */ -GBinFormat *g_dwarfv3_format_new(GBinContent *, GExeFormat *); +GBinFormat *g_dwarfv3_format_new(GBinContent *, GExeFormat *, GtkStatusStack *); diff --git a/src/format/dwarf/v4/dwarf.c b/src/format/dwarf/v4/dwarf.c index 52345e8..995d4f7 100644 --- a/src/format/dwarf/v4/dwarf.c +++ b/src/format/dwarf/v4/dwarf.c @@ -153,6 +153,7 @@ static void g_dwarfv4_format_finalize(GDwarfV4Format *format)  *                                                                             *  *  Paramètres  : content = contenu binaire à parcourir.                       *  *                parent  = éventuel format exécutable déjà chargé.            * +                 status  = barre de statut à tenir informée.                  *  *                                                                             *  *  Description : Prend en charge un nouveau format DWARF (v4).                *  *                                                                             * @@ -162,7 +163,7 @@ static void g_dwarfv4_format_finalize(GDwarfV4Format *format)  *                                                                             *  ******************************************************************************/ -GBinFormat *g_dwarfv4_format_new(GBinContent *content, GExeFormat *parent) +GBinFormat *g_dwarfv4_format_new(GBinContent *content, GExeFormat *parent, GtkStatusStack *status)  {      GDwarfV4Format *result;                 /* Structure à retourner       */ diff --git a/src/format/dwarf/v4/dwarf.h b/src/format/dwarf/v4/dwarf.h index af3c2c4..d0f5b7a 100644 --- a/src/format/dwarf/v4/dwarf.h +++ b/src/format/dwarf/v4/dwarf.h @@ -52,7 +52,7 @@ typedef struct _GDwarfV4FormatClass GDwarfV4FormatClass;  GType g_dwarfv4_format_get_type(void);  /* Prend en charge un nouveau format DWARF (v4). */ -GBinFormat *g_dwarfv4_format_new(GBinContent *, GExeFormat *); +GBinFormat *g_dwarfv4_format_new(GBinContent *, GExeFormat *, GtkStatusStack *); diff --git a/src/format/elf/Makefile.am b/src/format/elf/Makefile.am index 4317e1d..78dabcd 100644 --- a/src/format/elf/Makefile.am +++ b/src/format/elf/Makefile.am @@ -8,6 +8,7 @@ libformatelf_la_SOURCES =				\  	dynamic.h dynamic.c					\  	helper_arm.h helper_arm.c			\  	helper_x86.h helper_x86.c			\ +	loading.h loading.c					\  	program.h program.c					\  	section.h section.c					\  	strings.h strings.c					\ diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c index 0c7760c..d09b845 100644 --- a/src/format/elf/elf.c +++ b/src/format/elf/elf.c @@ -230,6 +230,7 @@ static void g_elf_format_finalize(GElfFormat *format)  *                                                                             *  *  Paramètres  : content = contenu binaire à parcourir.                       *  *                parent  = éventuel format exécutable déjà chargé.            * +                 status  = barre de statut à tenir informée.                  *  *                                                                             *  *  Description : Prend en charge un nouveau format ELF.                       *  *                                                                             * @@ -239,7 +240,7 @@ static void g_elf_format_finalize(GElfFormat *format)  *                                                                             *  ******************************************************************************/ -GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent) +GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent, GtkStatusStack *status)  {      GElfFormat *result;                     /* Structure à retourner       */ @@ -287,7 +288,7 @@ GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent) -    if (!load_elf_symbols(result)) +    if (!load_elf_symbols(result, status))      {          /* TODO */          return NULL; diff --git a/src/format/elf/elf.h b/src/format/elf/elf.h index d6f631e..3343927 100644 --- a/src/format/elf/elf.h +++ b/src/format/elf/elf.h @@ -56,7 +56,7 @@ FormatMatchStatus elf_is_matching(GBinContent *, GExeFormat *, void *, char **);  GType g_elf_format_get_type(void);  /* Prend en charge un nouveau format ELF. */ -GBinFormat *g_elf_format_new(GBinContent *, GExeFormat *); +GBinFormat *g_elf_format_new(GBinContent *, GExeFormat *, GtkStatusStack *);  /* Présente l'en-tête ELF du format chargé. */  const elf_header *g_elf_format_get_header(const GElfFormat *); diff --git a/src/format/elf/loading.c b/src/format/elf/loading.c new file mode 100644 index 0000000..b833720 --- /dev/null +++ b/src/format/elf/loading.c @@ -0,0 +1,291 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * loading.c - chargements parallèles des symboles de format ELF + * + * Copyright (C) 2016 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  OpenIDA 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. + * + *  OpenIDA 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 <http://www.gnu.org/licenses/>. + */ + + +#include "loading.h" + + +#include <i18n.h> + + +#include "elf-int.h" +#include "section.h" +#include "../../glibext/delayed-int.h" +#include "../../gui/panels/log.h" + + + +/* Fraction de routines à limiter (instance) */ +struct _GElfLoading +{ +    GDelayedWork parent;                    /* A laisser en premier        */ + +    GElfFormat *format;                     /* Format à faire évoluer      */ + +    union +    { +        struct +        { +            const elf_shdr *section;        /* Section à éplucher          */ +            bool use_virt;                  /* Représentatio par défaut    */ + +            elf_shdr strtab;                /* Section .strtab trouvée     */ +            bool has_strtab;                /* Présence de cette section   */ + +        }; + +    }; + +    elf_loading_cb callback;                /* Routine de traitement finale*/ +    phys_t first;                           /* Position du premier élément */ +    phys_t begin;                           /* Point de départ du parcours */ +    phys_t end;                             /* Point d'arrivée exclu       */ + +    activity_id_t id;                       /* Identifiant pour messages   */ + +}; + +/* Fraction de routines à limiter (classe) */ +struct _GElfLoadingClass +{ +    GDelayedWorkClass parent;               /* A laisser en premier        */ + +}; + + +/* Initialise la classe des tâches des chargements pour ELF. */ +static void g_elf_loading_class_init(GElfLoadingClass *); + +/* Initialise une tâche de chargements pour ELF. */ +static void g_elf_loading_init(GElfLoading *); + +/* Supprime toutes les références externes. */ +static void g_elf_loading_dispose(GElfLoading *); + +/* Procède à la libération totale de la mémoire. */ +static void g_elf_loading_finalize(GElfLoading *); + +/* Assure le chargement pour un format ELF en différé. */ +static void g_elf_loading_process(GElfLoading *, GtkStatusStack *); + + + +/* Indique le type défini pour les tâches de chargements pour format ELF. */ +G_DEFINE_TYPE(GElfLoading, g_elf_loading, G_TYPE_DELAYED_WORK); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des tâches des chargements pour ELF.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_elf_loading_class_init(GElfLoadingClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GDelayedWorkClass *work;                /* Version en classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_elf_loading_dispose; +    object->finalize = (GObjectFinalizeFunc)g_elf_loading_finalize; + +    work = G_DELAYED_WORK_CLASS(klass); + +    work->run = (run_task_fc)g_elf_loading_process; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : loading = instance à initialiser.                            * +*                                                                             * +*  Description : Initialise une tâche de chargements pour ELF.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_elf_loading_init(GElfLoading *loading) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : loading = instance d'objet GLib à traiter.                   * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_elf_loading_dispose(GElfLoading *loading) +{ +    G_OBJECT_CLASS(g_elf_loading_parent_class)->dispose(G_OBJECT(loading)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : loading = instance d'objet GLib à traiter.                   * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_elf_loading_finalize(GElfLoading *loading) +{ +    G_OBJECT_CLASS(g_elf_loading_parent_class)->finalize(G_OBJECT(loading)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = = ensemble d'instructions désassemblées.            * +*                section  = prototypes existants à insérer.                   * +*                use_virt = quantité de ces prototypes.                       * +*                first    = position du premier élément.                      * +*                begin    = point de départ du parcours de liste.             * +*                end      = point d'arrivée exclu du parcours.                * +*                id       = identifiant du message affiché à l'utilisateur.   * +*                callback = routine de traitements particuliers.              * +*                                                                             * +*  Description : Crée une tâche de chargement pour ELF différée.              * +*                                                                             * +*  Retour      : Tâche créée.                                                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GElfLoading *g_elf_loading_new(GElfFormat *format, const elf_shdr *section, bool use_virt, phys_t first, phys_t begin, phys_t end, activity_id_t id, elf_loading_cb callback) +{ +    GElfLoading *result;                    /* Tâche à retourner           */ + +    result = g_object_new(G_TYPE_ELF_LOADING, NULL); + +    result->format = format; + +    result->section = section; +    result->use_virt = use_virt; + +    result->has_strtab = find_elf_section_by_index(format, +                                                   ELF_SHDR(format, *section, sh_link), +                                                   &result->strtab); + +    result->callback = callback; +    result->first = first; +    result->begin = begin; +    result->end = end; + +    result->id = id; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : study  = étude de routines à mener.                          * +*                status = barre de statut à tenir informée.                   * +*                                                                             * +*  Description : Assure le chargement pour un format ELF en différé.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status) +{ +    phys_t iter;                            /* Boucle de parcours          */ +    phys_t old;                             /* Sauvegarde du point d'avant */ +    bool ret;                               /* Bilan d'un appel            */ + +    for (iter = loading->begin; iter < loading->end; ) +    { +        old = iter; +        ret = loading->callback(loading, loading->format, &iter); + +        if (!ret) +        { +            log_variadic_message(LMT_ERROR, _("Error while loading ELF data @ 0x%08x!"), old); +            break; +        } + +        gtk_status_stack_update_activity_value(status, loading->id, 1); + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : loading    = chargement pour ELF à mener.                    * +*                section    = prototypes existants à insérer. [OUT]           * +*                use_virt   = quantité de ces prototypes. [OUT]               * +*                strtab     = informations quant à la table des chaînes. [OUT]* +*                has_strtab = validité du champ précédemment renseigné. [OUT] * +*                first      = position du premier élément. [OUT]              * +*                                                                             * +*  Description : Fournit les infos utiles au chargement de symbols internes.  * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_elf_loading_get_internal_info(GElfLoading *loading, const elf_shdr **section, bool *use_virt, const elf_shdr **strtab, bool *has_strtab, phys_t *first) +{ +    *section = loading->section; +    *use_virt = loading->use_virt; + +    *strtab = &loading->strtab; +    *has_strtab = loading->has_strtab; + +    *first = loading->first; + +} diff --git a/src/format/elf/loading.h b/src/format/elf/loading.h new file mode 100644 index 0000000..ac7701f --- /dev/null +++ b/src/format/elf/loading.h @@ -0,0 +1,71 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * loading.h - prototypes pour les chargements parallèles des symboles de format ELF + * + * Copyright (C) 2016 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  OpenIDA 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. + * + *  OpenIDA 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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _FORMAT_ELF_LOADING_H +#define _FORMAT_ELF_LOADING_H + + +#include "elf.h" +#include "../../gtkext/gtkstatusstack.h" + + + + +//#include "../routine.h" +//#include "../../arch/processor.h" +//#include "../../format/executable.h" +//#include "../../gtkext/gtkstatusstack.h" + + + +#define G_TYPE_ELF_LOADING              g_elf_loading_get_type() +#define G_ELF_LOADING(obj)              (G_TYPE_CHECK_INSTANCE_CAST((obj), g_elf_loading_get_type(), GElfLoading)) +#define G_IS_ELF_LOADING(obj)           (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_elf_loading_get_type())) +#define G_ELF_LOADING_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ELF_LOADING, GElfLoadingClass)) +#define G_IS_ELF_LOADING_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ELF_LOADING)) +#define G_ELF_LOADING_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ELF_LOADING, GElfLoadingClass)) + + +/* Fraction de loading à limiter (instance) */ +typedef struct _GElfLoading GElfLoading; + +/* Fraction de loading à limiter (classe) */ +typedef struct _GElfLoadingClass GElfLoadingClass; + + +/* Assure un chargement pour ELF en différé. */ +typedef bool (* elf_loading_cb) (GElfLoading *, GElfFormat *, phys_t *); + + +/* Indique le type défini pour les tâches de chargements pour format ELF. */ +GType g_elf_loading_get_type(void); + +/* Crée une tâche de chargement pour ELF différée. */ +GElfLoading *g_elf_loading_new(GElfFormat *, const elf_shdr *, bool, phys_t, phys_t, phys_t, activity_id_t, elf_loading_cb); + +/* Fournit les infos utiles au chargement de symbols internes. */ +void g_elf_loading_get_internal_info(GElfLoading *, const elf_shdr **, bool *, const elf_shdr **, bool *, phys_t *); + + + +#endif  /* _FORMAT_ELF_LOADING_H */ diff --git a/src/format/elf/symbols.c b/src/format/elf/symbols.c index 29a8c3c..cfd0a09 100644 --- a/src/format/elf/symbols.c +++ b/src/format/elf/symbols.c @@ -36,6 +36,7 @@  #include "elf-int.h"  #include "helper_arm.h"  #include "helper_x86.h" +#include "loading.h"  #include "program.h"  #include "section.h"  #include "../mangling/demangler.h" @@ -47,6 +48,12 @@ + + + + + +  /* Enregistre un point d'entrée au sein d'un binaire ELF. */  static void register_elf_entry_point(GElfFormat *, virt_t, phys_t, GBinRoutine *); @@ -64,8 +71,11 @@ static bool load_all_elf_basic_entry_points(GElfFormat *);  /* -------------------------- DETAIL DES SYMBOLES INTERNES -------------------------- */ +/* Assure le chargement des symboles internes ELF en différé. */ +static bool do_elf_internal_symbol_loading(GElfLoading *, GElfFormat *, phys_t *); +  /* Charge tous les symboles internes possibles. */ -static bool load_elf_internal_symbols(GElfFormat *); +static bool load_elf_internal_symbols(GElfFormat *, wgroup_id_t, GtkStatusStack *); @@ -87,9 +97,13 @@ static bool load_elf_external_symbols(GElfFormat *, const elf_shdr *); + + +  /******************************************************************************  *                                                                             *  *  Paramètres  : format = description de l'exécutable à compléter.            * +                 status = barre de statut à tenir informée.                   *  *                                                                             *  *  Description : Charge en mémoire la liste humaine des symboles.             *  *                                                                             * @@ -99,18 +113,21 @@ static bool load_elf_external_symbols(GElfFormat *, const elf_shdr *);  *                                                                             *  ******************************************************************************/ -bool load_elf_symbols(GElfFormat *format) +bool load_elf_symbols(GElfFormat *format, GtkStatusStack *status)  {      bool result;                            /* Bilan à retourner           */ +    wgroup_id_t gid;                        /* Identifiant pour les tâches */      elf_shdr *sections;                     /* Groupe de sections trouvées */      size_t count;                           /* Quantité de données         */      result = true; +    gid = g_work_queue_define_work_group(get_work_queue()); +      /* Symboles internes */ -    result &= load_elf_internal_symbols(format); +    result &= load_elf_internal_symbols(format, gid, status); @@ -150,6 +167,9 @@ bool load_elf_symbols(GElfFormat *format)  } + + +  /******************************************************************************  *                                                                             *  *  Paramètres  : format  = description de l'exécutable à compléter.           * @@ -493,200 +513,262 @@ const char *get_elf_symbol_name(GElfFormat *format, const elf_shdr *sym, const e  /******************************************************************************  *                                                                             * -*  Paramètres  : format = description de l'exécutable à compléter.            * +*  Paramètres  : loading = chargement de symboles internes en cours.          * +*                format  = format ELF à compléter.                            * +*                iter    = tête de lecture évoluant avec le temps. [OUT]      *  *                                                                             * -*  Description : Charge tous les symboles internes possibles.                 * +*  Description : Assure le chargement des symboles internes ELF en différé.   *  *                                                                             * -*  Retour      : Bilan de l'opération.                                        * +*  Retour      : -                                                            *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static bool load_elf_internal_symbols(GElfFormat *format) +static bool do_elf_internal_symbol_loading(GElfLoading *loading, GElfFormat *format, phys_t *iter)  {      bool result;                            /* Bilan à retourner           */ -    bool no_name;                           /* Choix de construction de nom*/ -    elf_shdr *sections;                      /* Groupe de sections trouvées */ -    size_t count;                           /* Quantité de données         */ -    size_t i;                               /* Boucle de parcours          */ +    elf_sym sym;                            /* Symbole aux infos visées    */ +    virt_t virt;                            /* Adresse virtuelle           */ +    const elf_shdr *section;                /* Groupe de sections trouvées */ +    bool use_virt;                          /* Choix de construction de nom*/ +    const elf_shdr *strtab;                 /* Section .strtab trouvée     */ +    bool has_strtab;                        /* Présence de cette section   */ +    phys_t first;                           /* Position du premier élément */ +    const char *name;                       /* Nom du symbole trouvé       */ +    GBinFormat *base;                       /* Version basique du format   */ +    vmpa2t addr;                            /* Localisation d'une routine  */ +    GBinSymbol *symbol;                     /* Nouveau symbole construit   */ +    char alt_name[6 + VMPA_MAX_LEN];        /* Nom abstrait de substitution*/ +    virt_t final_virt;                      /* Adresse virtuelle retenue   */ +    mrange_t range;                         /* Couverture mémoire associée */ +    GBinRoutine *routine;                   /* Nouvelle routine trouvée    */ -    result = true; +    result = read_elf_symbol(format, iter, &sym); +    if (!result) goto geslp_done; -    /* Charge tous les symboles définis dans une section */ -    bool add_all_symbols_from_section(GElfFormat *format, const elf_shdr *section, bool use_virt) -    { -        GBinFormat *base;                   /* Version basique du format   */ -        elf_shdr strtab;                    /* Section .strtab trouvée     */ -        bool has_strtab;                    /* Présence de cette section   */ -        phys_t start;                       /* Début de la zone à traiter  */ -        phys_t size;                        /* Taille de cette même zone   */ -        phys_t iter;                        /* Boucle de parcours          */ -        elf_sym sym;                        /* Symbole aux infos visées    */ -        virt_t virt;                        /* Adresse virtuelle           */ -        virt_t final_virt;                  /* Adresse virtuelle retenue   */ -        vmpa2t addr;                        /* Localisation d'une routine  */ -        mrange_t range;                     /* Couverture mémoire associée */ -        const char *name;                   /* Nom du symbole trouvé       */ -        char alt_name[6 + VMPA_MAX_LEN];    /* Nom abstrait de substitution*/ -        GBinRoutine *routine;               /* Nouvelle routine trouvée    */ -        GBinSymbol *symbol;                 /* Nouveau symbole construit   */ +    /* On rejette les symboles qui ne sont pas définis au sein du binaire */ -        base = G_BIN_FORMAT(format); +    if (ELF_SYM(format, sym, st_shndx) == 0) goto geslp_done; -        has_strtab = find_elf_section_by_index(format, ELF_SHDR(format, *section, sh_link), &strtab); +    /* Résolution précise d'adresse */ -        get_elf_section_content(format, section, &start, &size, NULL); +    virt = ELF_SYM(format, sym, st_value); +    if (virt == 0) goto geslp_done; -        for (iter = start; iter < (start + size); ) -        { -            result = read_elf_symbol(format, &iter, &sym); -            if (!result) break; -            /* On rejette les symboles qui ne sont pas définis au sein du binaire */ -            if (ELF_SYM(format, sym, st_shndx) == 0) continue; +    /* TODO */ -#if 0 +    //init_vmpa(&addr, VMPA_NO_PHYSICAL, ELF_SYM(format, sym, st_value)); -            Elf64_Word    st_name;                /* Symbol name (string tbl index) */ -  unsigned char st_info;                /* Symbol type and binding */ -  unsigned char st_other;               /* Symbol visibility */ -  Elf64_Section st_shndx;               /* Section index */ -  Elf64_Addr    st_value;               /* Symbol value */ -  Elf64_Xword   st_size;                /* Symbol size */ -#endif +    //init_mrange(&range, &addr, 0); -            if (ELF_SYM(format, sym, st_value) == 0) continue; +    /* Première ébauche de nom */ -            /* Résolution précise d'adresse */ +    g_elf_loading_get_internal_info(loading, §ion, &use_virt, &strtab, &has_strtab, &first); +    if (!has_strtab) +        name = NULL; -            /* TODO */ +    else +        name = get_elf_symbol_name(format, section, strtab, +                                   ((*iter - first) / ELF_SIZEOF_SYM(format)) - 1); -            //init_vmpa(&addr, VMPA_NO_PHYSICAL, ELF_SYM(format, sym, st_value)); +    /* Traitements particuliers */ -            virt = ELF_SYM(format, sym, st_value); +    base = G_BIN_FORMAT(format); -            //init_mrange(&range, &addr, 0); +    switch (ELF_ST_TYPE(format, sym)) +    { +        case STT_OBJECT: +            /* Ajustement de la position */ -            /* Première ébauche de nom */ +            if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), virt, &addr)) +            { +                symbol = NULL; +                break; +            } -            if (!has_strtab) name = NULL; -            else name = get_elf_symbol_name(format, section, &strtab, -                                            ((iter - start) / ELF_SIZEOF_SYM(format)) - 1); +            /* Création d'un nom unique ? */ -            /* Traitements particuliers */ +            if (name == NULL) +            { +                strcpy(alt_name, "obj_"); -            switch (ELF_ST_TYPE(format, sym)) +                if (use_virt) +                    vmpa2_virt_to_string(&addr, MDS_UNDEFINED, alt_name + 4, NULL); +                else +                    vmpa2_phys_to_string(&addr, MDS_UNDEFINED, alt_name + 4, NULL); + +                name = alt_name; + +            } + + +            /* TODO */ + +            symbol = NULL; + + +            break; + +        case STT_FUNC: + +            /* Ajustement de la position */ + +            if (ELF_HDR(format, format->header, e_machine) == EM_ARM) +                final_virt = virt & ~0x1; +            else +                final_virt = virt; + +            if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_virt, &addr))              { -                case STT_OBJECT: +                symbol = NULL; +                break; +            } -                    /* Ajustement de la position */ +            init_mrange(&range, &addr, ELF_SYM(format, sym, st_size)); -                    if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), virt, &addr)) -                    { -                        symbol = NULL; -                        break; -                    } +            /* Création d'un nom unique ? */ -                    /* Création d'un nom unique ? */ +            if (name == NULL) +            { +                strcpy(alt_name, "func_"); -                    if (name != NULL) -                    { -                        strcpy(alt_name, "obj_"); +                if (use_virt) +                    vmpa2_virt_to_string(&addr, MDS_UNDEFINED, alt_name + 5, NULL); +                else +                    vmpa2_phys_to_string(&addr, MDS_UNDEFINED, alt_name + 5, NULL); -                        if (use_virt) -                            vmpa2_virt_to_string(&addr, MDS_UNDEFINED, alt_name + 4, NULL); -                        else -                            vmpa2_phys_to_string(&addr, MDS_UNDEFINED, alt_name + 4, NULL); +                name = alt_name; -                    } +            } +            /* Routine */ -                    /* TODO */ +            routine = try_to_demangle_routine(name); -                    symbol = NULL; +            g_binary_routine_set_range(routine, &range); +            /* Symbole uniquement */ -                    break; +            symbol = g_binary_symbol_new(STP_ROUTINE); +            g_binary_symbol_attach_routine(symbol, routine); -                case STT_FUNC: +            /* Comptabilisation pour le désassemblage brut */ -                    /* Ajustement de la position */ +            g_binary_format_register_code_point(G_BIN_FORMAT(format), virt, false); -                    if (ELF_HDR(format, format->header, e_machine) == EM_ARM) -                        final_virt = virt & ~0x1; -                    else -                        final_virt = virt; +            break; -                    if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_virt, &addr)) -                    { -                        symbol = NULL; -                        break; -                    } +        default: +            symbol = NULL; +            break; -                    init_mrange(&range, &addr, ELF_SYM(format, sym, st_size)); +    } -                    /* Création d'un nom unique ? */ +    if (symbol != NULL) +        g_binary_format_add_symbol(base, symbol); -                    if (name != NULL) -                    { -                        strcpy(alt_name, "func_"); + geslp_done: -                        if (use_virt) -                            vmpa2_virt_to_string(&addr, MDS_UNDEFINED, alt_name + 5, NULL); -                        else -                            vmpa2_phys_to_string(&addr, MDS_UNDEFINED, alt_name + 5, NULL); +    return result; -                    } +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : format = description de l'exécutable à compléter.            * +*                gid    = groupe de travail impliqué.                         * +                 status = barre de statut à tenir informée.                   * +*                                                                             * +*  Description : Charge tous les symboles internes possibles.                 * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ -                    /* Routine */ +static bool load_elf_internal_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status) +{ +    bool result;                            /* Bilan à retourner           */ +    bool no_name;                           /* Choix de construction de nom*/ +    activity_id_t msg;                      /* Message de progression      */ +    GWorkQueue *queue;                      /* Gestionnaire de différés    */ +    elf_shdr *dynsym_sections;              /* Groupe de sections trouvées */ +    size_t count;                           /* Quantité de données         */ +    elf_shdr *symtab_sections;              /* Groupe de sections trouvées */ +    size_t i;                               /* Boucle de parcours          */ -					printf("SYM ADDING>> '%s' @ 0x%08x\n", name, (unsigned int)virt); +    result = true; -                    routine = try_to_demangle_routine(name); +    /* Charge tous les symboles définis dans une section */ +    void add_all_symbols_from_section(const elf_shdr *section, bool use_virt, GWorkQueue *wq, activity_id_t id) +    { +        phys_t start;                       /* Début de la zone à traiter  */ +        phys_t size;                        /* Taille de cette même zone   */ +        phys_t sym_size;                    /* Taille de chaque symbole lu */ +        guint runs_count;                   /* Qté d'exécutions parallèles */ +        phys_t run_size;                    /* Volume réparti par exécution*/ +        guint i;                            /* Boucle de parcours          */ +        phys_t begin;                       /* Début de zone de traitement */ +        phys_t end;                         /* Fin d'un zone de traitement */ +        GElfLoading *loading;               /* Tâche de chargement à lancer*/ -                    g_binary_routine_set_range(routine, &range); +        get_elf_section_content(format, section, &start, &size, NULL); -                    /* Symbole uniquement */ +        sym_size = ELF_SIZEOF_SYM(format); -                    symbol = g_binary_symbol_new(STP_ROUTINE); -                    g_binary_symbol_attach_routine(symbol, routine); +        runs_count = g_get_num_processors(); -                    /* Comptabilisation pour le désassemblage brut */ +        run_size = size / (sym_size * runs_count); -                    g_binary_format_register_code_point(base, virt, false); +        gtk_status_stack_extend_activity(status, id, size / sym_size); -                    break; +        for (i = 0; i < runs_count; i++) +        { +            begin = start + i * run_size * sym_size; -                default: -                    symbol = NULL; -                    break; +            if ((i + 1) == runs_count) +                end = start + size; +            else +                end = begin + run_size * sym_size; -            } +            loading = g_elf_loading_new(format, section, use_virt, start, begin, end, +                                        id, do_elf_internal_symbol_loading); -            if (symbol != NULL) -                g_binary_format_add_symbol(base, symbol); +            g_work_queue_schedule_work(wq, G_DELAYED_WORK(loading), gid);          } -        return true; -      }      if (!g_generic_config_get_value(get_main_configuration(), MPK_FORMAT_NO_NAME, &no_name))          return false; -    if (find_elf_sections_by_type(format, SHT_DYNSYM, §ions, &count)) -        for (i = 0; i < count && result; i++) -            result = add_all_symbols_from_section(format, §ions[i], no_name); +    msg = gtk_status_stack_add_activity(status, _("Loading internal symbols..."), 0); + +    queue = get_work_queue(); + +    if (find_elf_sections_by_type(format, SHT_DYNSYM, &dynsym_sections, &count)) +        for (i = 0; i < count; i++) +            add_all_symbols_from_section(&dynsym_sections[i], no_name, queue, msg); + +    if (find_elf_sections_by_type(format, SHT_SYMTAB, &symtab_sections, &count)) +        for (i = 0; i < count; i++) +            add_all_symbols_from_section(&symtab_sections[i], no_name, queue, msg); + +    g_work_queue_wait_for_completion(get_work_queue(), gid); + +    gtk_status_stack_remove_activity(status, msg); -    if (find_elf_sections_by_type(format, SHT_SYMTAB, §ions, &count)) -        for (i = 0; i < count && result; i++) -            result = add_all_symbols_from_section(format, §ions[i], no_name); +    if (dynsym_sections != NULL) free(dynsym_sections); +    if (symtab_sections != NULL) free(symtab_sections);      return result; diff --git a/src/format/elf/symbols.h b/src/format/elf/symbols.h index 086cb0d..77ff373 100644 --- a/src/format/elf/symbols.h +++ b/src/format/elf/symbols.h @@ -28,8 +28,12 @@  #include "elf.h" +#include "../../gtkext/gtkstatusstack.h" + + +  /* Charge en mémoire la liste humaine des symboles. */ -bool load_elf_symbols(GElfFormat *); +bool load_elf_symbols(GElfFormat *, GtkStatusStack *);  /* Récupère la définition complète d'un symbole donné. */  bool get_elf_symbol_by_index(GElfFormat *, const elf_shdr *, off_t, elf_sym *); diff --git a/src/format/format-int.h b/src/format/format-int.h index f8a7204..b19749d 100644 --- a/src/format/format-int.h +++ b/src/format/format-int.h @@ -57,6 +57,8 @@ struct _GBinFormat      size_t xp_allocated;                    /* Taille d'inscription allouée*/      size_t xp_count;                        /* Nombre de points enregistrés*/ +    GRWLock pt_lock;                        /* Accès à la liste des points */ +      GBinSymbol **symbols;                   /* Liste des symboles trouvés  */      size_t symbols_count;                   /* Quantité de ces symboles    */      GRWLock syms_lock;                      /* Accès à la liste de symboles*/ diff --git a/src/format/format.c b/src/format/format.c index 1ee3001..ea67d2d 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -97,6 +97,8 @@ static void g_binary_format_class_init(GBinFormatClass *klass)  static void g_binary_format_init(GBinFormat *format)  { +    g_rw_lock_init(&format->pt_lock); +      g_rw_lock_init(&format->syms_lock);  } @@ -212,6 +214,8 @@ SourceEndian g_binary_format_get_endianness(const GBinFormat *format)  void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, bool entry)  { +    g_rw_lock_writer_lock(&format->pt_lock); +      if (entry)      {          format->entry_points = (virt_t *)realloc(format->entry_points, @@ -235,6 +239,8 @@ void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, bool ent      } +    g_rw_lock_writer_unlock(&format->pt_lock); +  } @@ -251,16 +257,20 @@ void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, bool ent  *                                                                             *  ******************************************************************************/ -void g_binary_format_setup_disassembling_context(const GBinFormat *format, GProcContext *ctx) +void g_binary_format_setup_disassembling_context(GBinFormat *format, GProcContext *ctx)  {      size_t i;                               /* Boucle de parcours          */ +    g_rw_lock_reader_lock(&format->pt_lock); +      for (i = 0; i < format->ep_count; i++)          g_proc_context_push_drop_point(ctx, 0, format->entry_points[i]);      for (i = 0; i < format->xp_count; i++)          g_proc_context_push_drop_point(ctx, 0, format->extra_points[i]); +    g_rw_lock_reader_unlock(&format->pt_lock); +  } diff --git a/src/format/format.h b/src/format/format.h index 19c2b0a..e21e478 100644 --- a/src/format/format.h +++ b/src/format/format.h @@ -65,7 +65,7 @@ SourceEndian g_binary_format_get_endianness(const GBinFormat *);  void g_binary_format_register_code_point(GBinFormat *, virt_t, bool);  /* Fournit un contexte initialisé pour un désassemblage. */ -void g_binary_format_setup_disassembling_context(const GBinFormat *, GProcContext *); +void g_binary_format_setup_disassembling_context(GBinFormat *, GProcContext *);  /* Ajoute un symbole à la collection du format binaire. */  void g_binary_format_add_symbol(GBinFormat *, GBinSymbol *); diff --git a/src/glibext/delayed.c b/src/glibext/delayed.c index 37b3ed7..f0aa141 100644 --- a/src/glibext/delayed.c +++ b/src/glibext/delayed.c @@ -814,7 +814,7 @@ static void g_work_queue_finalize(GWorkQueue *queue)  /******************************************************************************  *                                                                             * -*  Paramètres  : ref = espace de référencements global.                       * +*  Paramètres  : status = barre de statut à tenir informée.                   *  *                                                                             *  *  Description : Procède au chargement du gestionnaire d'analyse différées.   *  *                                                                             * @@ -824,19 +824,16 @@ static void g_work_queue_finalize(GWorkQueue *queue)  *                                                                             *  ******************************************************************************/ -bool init_work_queue(GObject *ref) +bool init_work_queue(GtkStatusStack *status)  {      GWorkQueue *queue;                      /* Singleton à mettre en place */      queue = g_object_new(G_TYPE_WORK_QUEUE, NULL); -    if (ref != NULL) -    { -        queue->status = g_object_get_data(ref, "statusbar"); +    queue->status = status; + +    if (status != NULL)          g_object_ref(G_OBJECT(queue->status)); -    } -    else -        queue->status = NULL;      if (queue != NULL)          _get_work_queue(queue); diff --git a/src/glibext/delayed.h b/src/glibext/delayed.h index 4902e68..14d54a1 100644 --- a/src/glibext/delayed.h +++ b/src/glibext/delayed.h @@ -30,6 +30,11 @@ +/* Abstration d'une gestion de barre de statut (instance) */ +typedef struct _GtkStatusStack GtkStatusStack; + + +  /* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */ @@ -88,7 +93,7 @@ typedef unsigned long long wgroup_id_t;  GType g_work_queue_get_type(void);  /* Procède au chargement du gestionnaire d'analyse différées. */ -bool init_work_queue(GObject *); +bool init_work_queue(GtkStatusStack *);  /* Fournit le gestionnaire de traitements parallèles courant. */  GWorkQueue *_get_work_queue(GWorkQueue *); diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c index d84f179..95166d7 100644 --- a/src/gtkext/gtkstatusstack.c +++ b/src/gtkext/gtkstatusstack.c @@ -24,6 +24,7 @@  #include "gtkstatusstack.h" +#include <assert.h>  #include <inttypes.h>  #include <malloc.h>  #include <string.h> @@ -878,6 +879,43 @@ activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *m  } + +/****************************************************************************** +*                                                                             * +*  Paramètres  : stack = barre de statut à actualiser.                        * +*                id    = identifiant de l'activité à cibler.                  * +*                extra = nouvelle échéance supplémentaire des traitements.    * +*                                                                             * +*  Description : Etend la portée des travaux d'une nouvelle activité.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void gtk_status_stack_extend_activity(GtkStatusStack *stack, activity_id_t id, unsigned long extra) +{ +    progress_info *info;                    /* Informations à consulter    */ +    size_t i;                               /* Boucle de parcours          */ + +    info = stack->prog_info; + +    g_mutex_lock(&info->access); + +    for (i = 0; i < info->count; i++) +        if (info->statuses[i].id == id) +            break; + +    assert(i < info->count); + +    info->statuses[i].max += extra; + +    g_mutex_unlock(&info->access); + +} + +  /******************************************************************************  *                                                                             *  *  Paramètres  : stack = barre de statut à actualiser.                        * @@ -907,38 +945,36 @@ void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, c          if (info->statuses[i].id == id)              break; -    if (i < info->count) -    { -        /* Intitulé */ +    assert(i < info->count); -        if (info->statuses[i].message != NULL) -        { -            if (msg == NULL) -                msg_changed = true; -            else -                msg_changed = (strcmp(info->statuses[i].message, msg) != 0); - -            free(info->statuses[i].message); - -        } -        else -            msg_changed = (msg != NULL); +    /* Intitulé */ +    if (info->statuses[i].message != NULL) +    {          if (msg == NULL) -            info->statuses[i].message = NULL; +            msg_changed = true;          else -            info->statuses[i].message = strdup(msg); +            msg_changed = (strcmp(info->statuses[i].message, msg) != 0); -        /* On n'actualise que le sommet de la pile */ +        free(info->statuses[i].message); -        if ((i + 1) == info->count) -        { -            if (info->tag != 0) -                g_source_remove(info->tag); +    } +    else +        msg_changed = (msg != NULL); -            info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); +    if (msg == NULL) +        info->statuses[i].message = NULL; +    else +        info->statuses[i].message = strdup(msg); -        } +    /* On n'actualise que le sommet de la pile */ + +    if ((i + 1) == info->count) +    { +        if (info->tag != 0) +            g_source_remove(info->tag); + +        info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack);      } @@ -977,30 +1013,28 @@ void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t          if (info->statuses[i].id == id)              break; -    if (i < info->count) -    { -        status = &info->statuses[i]; +    assert(i < info->count); -        /* Valeur */ +    status = &info->statuses[i]; -        status->current += inc; +    /* Valeur */ -        new = (status->current * 1.0) / status->max; +    status->current += inc; -        /* On n'actualise que le sommet de la pile */ +    new = (status->current * 1.0) / status->max; +    /* On n'actualise que le sommet de la pile */ -        //fprintf(stderr, "PROG %g -> %g <=> %g ==> %d\n", old, new, new - old, (new - old) > 0.1); +    //fprintf(stderr, "PROG %g -> %g <=> %g ==> %d\n", old, new, new - old, (new - old) > 0.1); -        if ((i + 1) == info->count && (new - status->last_updated) > 0.1) -        { -            if (info->tag != 0) -                g_source_remove(info->tag); -            info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); +    if ((i + 1) == info->count && (new - status->last_updated) > 0.1) +    { +        if (info->tag != 0) +            g_source_remove(info->tag); -        } +        info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack);      } @@ -1034,40 +1068,38 @@ void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id)          if (info->statuses[i].id == id)              break; -    if (i < info->count) -    { -        if (info->tag != 0) -            g_source_remove(info->tag); +    assert(i < info->count); -        if (info->statuses[i].message != NULL) -            free(info->statuses[i].message); +    if (info->tag != 0) +        g_source_remove(info->tag); -        if (info->count == 1) -        { -            free(info->statuses); -            info->statuses = NULL; -        } -        else -        { -            memmove(&info->statuses[i], &info->statuses[i + 1], -                    (info->count - i - 1) * sizeof(progress_status)); +    if (info->statuses[i].message != NULL) +        free(info->statuses[i].message); -            info->statuses = (progress_status *)realloc(info->statuses, -                                                        (info->count - 1) * sizeof(progress_status)); +    if (info->count == 1) +    { +        free(info->statuses); +        info->statuses = NULL; +    } +    else +    { +        memmove(&info->statuses[i], &info->statuses[i + 1], +                (info->count - i - 1) * sizeof(progress_status)); -        } +        info->statuses = (progress_status *)realloc(info->statuses, +                                                    (info->count - 1) * sizeof(progress_status)); -        info->count--; +    } -        if (info->count == 0) -        { -            info->tag = 0; -            g_idle_add((GSourceFunc)gtk_status_stack_show_current_instruction, stack); -        } -        else -            info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); +    info->count--; +    if (info->count == 0) +    { +        info->tag = 0; +        g_idle_add((GSourceFunc)gtk_status_stack_show_current_instruction, stack);      } +    else +        info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack);      g_mutex_unlock(&info->access); diff --git a/src/gtkext/gtkstatusstack.h b/src/gtkext/gtkstatusstack.h index 590f562..1701d77 100644 --- a/src/gtkext/gtkstatusstack.h +++ b/src/gtkext/gtkstatusstack.h @@ -79,6 +79,9 @@ typedef unsigned long activity_id_t;  /* Démarre le suivi d'une nouvelle activité. */  activity_id_t gtk_status_stack_add_activity(GtkStatusStack *, const char *, unsigned long); +/* Etend la portée des travaux d'une nouvelle activité. */ +void gtk_status_stack_extend_activity(GtkStatusStack *, activity_id_t, unsigned long); +  /* Actualise les informations concernant une activité. */  void gtk_status_stack_update_activity(GtkStatusStack *, activity_id_t, const char *); diff --git a/src/gui/core/Makefile.am b/src/gui/core/Makefile.am index 2000f58..75b342f 100755 --- a/src/gui/core/Makefile.am +++ b/src/gui/core/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libguicore.la  libguicore_la_SOURCES =					\  	core.h core.c						\ +	global.h global.c					\  	panels.h panels.c  libguicore_la_LDFLAGS = $(LIBGTK_LIBS) $(LIBXML_LIBS) diff --git a/src/gui/core/global.c b/src/gui/core/global.c new file mode 100644 index 0000000..10db31a --- /dev/null +++ b/src/gui/core/global.c @@ -0,0 +1,68 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * global.c - conservation de variables globales à vocation graphique + * + * Copyright (C) 2016 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  OpenIDA 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. + * + *  OpenIDA 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 <http://www.gnu.org/licenses/>. + */ + + +#include "global.h" + + + +/* Barre de statut principale */ +static GtkStatusStack *_status = NULL; + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : status  = barre de statut à tenir informée.                  * +*                                                                             * +*  Description : Note l'adresse de la barre de statut principale.             * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void set_global_status(GtkStatusStack *status) +{ +    _status = status; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit l'adresse de la barre de statut principale.          * +*                                                                             * +*  Retour      : barre de statut à tenir informée.                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GtkStatusStack *get_global_status(void) +{ +    return _status; + +} diff --git a/src/gui/core/global.h b/src/gui/core/global.h new file mode 100644 index 0000000..dfd5cc2 --- /dev/null +++ b/src/gui/core/global.h @@ -0,0 +1,40 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * global.h - prototypes pour la conservation de variables globales à vocation graphique + * + * Copyright (C) 2016 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  OpenIDA 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. + * + *  OpenIDA 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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _GUI_CORE_GLOBAL_H +#define _GUI_CORE_GLOBAL_H + + +#include "../../gtkext/gtkstatusstack.h" + + + +/* Note l'adresse de la barre de statut principale. */ +void set_global_status(GtkStatusStack *); + +/* Fournit l'adresse de la barre de statut principale. */ +GtkStatusStack *get_global_status(void); + + + +#endif  /* _GUI_CORE_GLOBAL_H */ diff --git a/src/gui/status.c b/src/gui/status.c index f1171bd..0a3572a 100644 --- a/src/gui/status.c +++ b/src/gui/status.c @@ -34,6 +34,7 @@  #include "editem-int.h" +#include "core/global.h"  #include "../common/extstr.h"  #include "../gtkext/gtkbufferview.h"  #include "../gtkext/gtkblockview.h" @@ -199,7 +200,7 @@ GEditorItem *g_status_info_new(GObject *ref)      g_object_ref(ref);      item->ref = ref; -    g_object_set_data(ref, "statusbar", item->widget); +    set_global_status(GTK_STATUS_STACK(item->widget));      return G_EDITOR_ITEM(result); @@ -38,6 +38,7 @@  #include "gtkext/theme.h"  #include "gui/editor.h"  #include "gui/core/core.h" +#include "gui/core/global.h"  #include "plugins/pglist.h" @@ -172,7 +173,7 @@ int main(int argc, char **argv)      editor = create_editor();      gtk_widget_show_now(editor); -    init_work_queue(G_OBJECT(editor)); +    init_work_queue(get_global_status());      init_all_plugins(G_OBJECT(editor)); | 
