diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2017-05-05 21:58:46 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2017-05-05 21:59:01 (GMT) | 
| commit | a66f854ce4e19dc0f772fc55a3899643252afa3d (patch) | |
| tree | 52e46f77acc199904a73e2260117a3a5198aeb86 /src | |
| parent | 07768223823d8c2b0071be8d8e6dfc5ccb891b17 (diff) | |
Inserted preloaded format information from instructions instead of symbols.
Diffstat (limited to 'src')
| -rw-r--r-- | src/analysis/db/items/comment.c | 2 | ||||
| -rw-r--r-- | src/analysis/db/items/comment.h | 2 | ||||
| -rw-r--r-- | src/analysis/disass/area.c | 354 | ||||
| -rw-r--r-- | src/analysis/disass/area.h | 7 | ||||
| -rw-r--r-- | src/analysis/disass/disassembler.c | 4 | ||||
| -rw-r--r-- | src/analysis/disass/fetch.c | 4 | ||||
| -rw-r--r-- | src/analysis/disass/output.c | 75 | ||||
| -rw-r--r-- | src/analysis/disass/output.h | 3 | ||||
| -rw-r--r-- | src/arch/arm/v7/fetch.c | 81 | ||||
| -rw-r--r-- | src/arch/context-int.h | 7 | ||||
| -rw-r--r-- | src/arch/context.c | 2 | ||||
| -rw-r--r-- | src/arch/instruction.c | 10 | ||||
| -rw-r--r-- | src/arch/instruction.h | 4 | ||||
| -rw-r--r-- | src/common/array.c | 61 | ||||
| -rw-r--r-- | src/common/array.h | 4 | ||||
| -rw-r--r-- | src/format/Makefile.am | 2 | ||||
| -rw-r--r-- | src/format/format.c | 6 | ||||
| -rw-r--r-- | src/format/format.h | 3 | ||||
| -rw-r--r-- | src/format/preload-int.h | 54 | ||||
| -rw-r--r-- | src/format/preload.c | 534 | ||||
| -rw-r--r-- | src/format/preload.h | 98 | ||||
| -rw-r--r-- | src/plugins/pglist.h | 3 | ||||
| -rw-r--r-- | src/plugins/plugin-def.h | 3 | ||||
| -rw-r--r-- | src/plugins/plugin-int.h | 5 | ||||
| -rw-r--r-- | src/plugins/plugin.c | 29 | ||||
| -rw-r--r-- | src/plugins/plugin.h | 4 | 
26 files changed, 1153 insertions, 208 deletions
| diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index beec629..3e1c06f 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -1095,7 +1095,7 @@ static bool g_db_comment_load(GDbComment *comment, const bound_value *values, si  *                                                                             *  ******************************************************************************/ -const vmpa2t *g_db_comment_get_address(GDbComment *comment) +const vmpa2t *g_db_comment_get_address(const GDbComment *comment)  {      return &comment->addr; diff --git a/src/analysis/db/items/comment.h b/src/analysis/db/items/comment.h index ee68491..9fdfa32 100644 --- a/src/analysis/db/items/comment.h +++ b/src/analysis/db/items/comment.h @@ -64,7 +64,7 @@ GDbComment *g_db_comment_new_inlined(const vmpa2t *, BufferLineFlags, bool);  GDbComment *g_db_comment_new_area(const vmpa2t *, BufferLineFlags, const char *, bool);  /* Fournit l'adresse associée à un commentaire. */ -const vmpa2t *g_db_comment_get_address(GDbComment *); +const vmpa2t *g_db_comment_get_address(const GDbComment *);  /* Fournit le commentaire associé à un commentaire. */  char *g_db_comment_get_text(GDbComment *); diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index 5dab3ab..130a7f0 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -96,6 +96,8 @@ static void fill_mem_area(mem_area *, mem_area *, size_t, GProcContext *, GtkSta  /* Rassemble les instructions conservées dans une zone donnée. */  static GArchInstruction **get_instructions_from_mem_area(const mem_area *, GArchInstruction **, size_t *); +/* Insère une instruction dans un découpage en aires. */ +static void insert_extra_instr_into_mem_areas(mem_area *, size_t, GArchInstruction *);  /* ----------------------- MANIPULATIONS PARALLELES DES ZONES ----------------------- */ @@ -123,7 +125,7 @@ typedef struct _GAreaCollector      {          struct          { -            size_t acount;                  /* Nombre de zones créées      */ +            size_t created;                 /* Nombre de zones créées      */              GLoadedBinary *binary;          /* Binaire à associer aux zones*/ @@ -136,6 +138,17 @@ typedef struct _GAreaCollector          struct          { +            size_t available;               /* Nombre de zones créées      */ + +            GPreloadInfo *info;             /* Préchargements à intégrer   */ + +            size_t start;                   /* Départ des intégrations     */ +            size_t stop;                    /* Fin des intégrations        */ + +        }; + +        struct +        {              size_t begin;                   /* Début du parcours à mener   */              size_t end;                     /* Fin de ce même parcours     */ @@ -180,6 +193,12 @@ static GAreaCollector *g_area_collector_new_intro(activity_id_t, GLoadedBinary *  /* Construit une liste bornée de zones contigües. */  static void g_area_collector_do_compute(GAreaCollector *, GtkStatusStack *); +/* Crée une tâche de calcul des zones binaires à remplir. */ +static GAreaCollector *g_area_collector_new_insert(activity_id_t, mem_area *, size_t, GPreloadInfo *, size_t, size_t); + +/* Insère dans les zones contigües les instructions préchargées. */ +static void g_area_collector_do_insert(GAreaCollector *, GtkStatusStack *); +  /* Crée une tâche de récupération d'instructions différée. */  static GAreaCollector *g_area_collector_new_outro(activity_id_t, mem_area *, size_t, size_t); @@ -388,12 +407,19 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, GArchInstruction              if (old != NULL)              {                  g_object_unref(G_OBJECT(old)); -                area->instructions[offset + 1] = NULL; +                area->instructions[offset + i] = NULL;                  g_atomic_pointer_add(&area->count, -1);              }          } +#ifndef NDEBUG + +        for (i = 0; i < len; i++) +            assert(area->instructions[offset + i] == NULL); + +#endif +          area->instructions[offset] = instr;          g_atomic_pointer_add(&area->count, 1); @@ -593,10 +619,7 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, GProc      bool done;                              /* Enregistrement effectué ?   */ -    vmpa2t sym_addr;                        /* Adresse de nouveau symbole  */ -    bool has_new_sym;                       /* Statut d'un dépilement      */ - -    GBinSymbol *symbol;                     /* Symbole créé en parallèle   */ +    GArchInstruction *extra;                /* Instruction supplémentaire  */ @@ -679,18 +702,11 @@ void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, GProc          /* Insertion des symboles découverts en parallèle */ -        for (has_new_sym = g_proc_context_pop_new_symbol_at(ctx, &sym_addr); -             has_new_sym; -             has_new_sym = g_proc_context_pop_new_symbol_at(ctx, &sym_addr)) +        for (extra = g_preload_info_pop_instruction(G_PRELOAD_INFO(ctx)); +             extra != NULL; +             extra = g_preload_info_pop_instruction(G_PRELOAD_INFO(ctx)))          { -            has_new_sym = g_binary_format_find_symbol_at(format, &sym_addr, &symbol); - -            if (has_new_sym) -            { -                insert_extra_symbol_into_mem_areas(list, count, symbol); -                g_object_unref(G_OBJECT(symbol)); -            } - +            insert_extra_instr_into_mem_areas(list, count, extra);          }          /* Rupture du flot d'exécution ? */ @@ -932,11 +948,11 @@ mem_area *find_memory_area_by_addr(mem_area *list, size_t count, const vmpa2t *a  /******************************************************************************  *                                                                             * -*  Paramètres  : areas  = liste de zones délimitant des contenus à traiter.   * -*                count  = nombre de zones à disposition.                      * -*                symbol = élément nouveau à venir insérer dans les zones.     * +*  Paramètres  : areas = liste de zones délimitant des contenus à traiter.    * +*                count = nombre de zones à disposition.                       * +*                instr = nouvelle instruction à venir insérer dans les zones. *  *                                                                             * -*  Description : Insère un symbole dans un découpage en aires.                * +*  Description : Insère une instruction dans un découpage en aires.           *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -944,22 +960,16 @@ mem_area *find_memory_area_by_addr(mem_area *list, size_t count, const vmpa2t *a  *                                                                             *  ******************************************************************************/ -void insert_extra_symbol_into_mem_areas(mem_area *areas, size_t count, const GBinSymbol *symbol) +static void insert_extra_instr_into_mem_areas(mem_area *areas, size_t count, GArchInstruction *instr)  { -    SymbolType type;                        /* Type de symbole             */ -    GArchInstruction *instr;                /* Instruction à insérer       */      const mrange_t *range;                  /* Emplacement d'instruction   */      const vmpa2t *addr;                     /* Départ de cet emplacement   */      mem_area *area;                         /* Zone d'accueil désignée     */      VMPA_BUFFER(loc);                       /* Description d'un emplacement*/      phys_t start;                           /* Point de départ             */ - -    type = g_binary_symbol_get_target_type(symbol); - -    if (!HAS_DATA_INSTR(type)) -        return; - -    instr = g_binary_symbol_get_instruction(symbol); +#ifndef NDEBUG +    bool status;                            /* Validation d'une insertion  */ +#endif      range = g_arch_instruction_get_range(instr);      addr = get_mrange_addr(range); @@ -972,13 +982,13 @@ void insert_extra_symbol_into_mem_areas(mem_area *areas, size_t count, const GBi      {          vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL); -        log_variadic_message(LMT_WARNING, _("No place found for symbol located at %s."), loc); -        return; +        log_variadic_message(LMT_WARNING, _("No place found for an instruction located at %s."), loc); +        goto ieiima_failed;      }      /** -     * Un symbole (au sens large) ne peut avoir une adresse virtuelle que s'il +     * Une instruction ne peut avoir une adresse virtuelle que s'il       * est compris dans une zone chargée en mémoire (en toute logique).       */      assert(has_virt_addr(get_mrange_addr(&area->range)) == has_virt_addr(addr)); @@ -991,16 +1001,25 @@ void insert_extra_symbol_into_mem_areas(mem_area *areas, size_t count, const GBi      {          vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL); -        log_variadic_message(LMT_WARNING, _("The symbol located at %s is too big for one place only."), loc); -        return; +        log_variadic_message(LMT_WARNING, _("The instruction located at %s is too big for one place only."), loc); +        goto ieiima_failed;      } -    /* Inscription d'une instruction de symbole (sans retour arrière possible :/ ) */ +    /* Inscription d'une instruction (sans retour arrière possible :/ ) */ +#ifndef NDEBUG +    status = mark_range_in_mem_area_as_processed(area, instr, true); +    assert(status); +#else      mark_range_in_mem_area_as_processed(area, instr, true); +#endif + +    return; -    g_object_ref(G_OBJECT(instr)); + ieiima_failed: + +    g_object_unref(G_OBJECT(instr));  } @@ -1106,6 +1125,9 @@ static void g_area_collector_dispose(GAreaCollector *collector)      if (collector->run == (run_task_fc)g_area_collector_do_compute)          g_object_unref(G_OBJECT(collector->binary)); +    else if (collector->run == (run_task_fc)g_area_collector_do_insert) +        g_object_unref(G_OBJECT(collector->info)); +      G_OBJECT_CLASS(g_area_collector_parent_class)->dispose(G_OBJECT(collector));  } @@ -1160,6 +1182,7 @@ static void g_area_collector_process(GAreaCollector *collector, GtkStatusStack *  *                                                                             *  *  Paramètres  : id      = identifiant pour signaler la progression courante. *  *                binary  = binaire chargé à conserver dans les zones définies.* +*                info    = préchargements effectués via le format binaire.    *  *                first   = localisation du début de la portion à traiter.     *  *                last    = localisation de la fin de la portion à traiter.    *  *                closing = indique si la tâche doit terminer l'analyse.       * @@ -1183,7 +1206,7 @@ static GAreaCollector *g_area_collector_new_intro(activity_id_t id, GLoadedBinar      result->areas = NULL; -    result->acount = 0; +    result->created = 0;      result->binary = binary;      g_object_ref(G_OBJECT(binary)); @@ -1220,60 +1243,8 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac      GExeFormat *format;                     /* Format du binaire           */      vmpa2t prev;                            /* Dernière bordure rencontrée */      bool state;                             /* Bilan d'une conversion      */ -    GBinSymbol **symbols;                   /* Symboles à représenter      */ -    size_t sym_count;                       /* Qté de symboles présents    */ -    bool has_sym_index;                     /* Détermine une validité      */ -    size_t sym_index;                       /* Prochain symbole non traité */      GBinPortion *portions;                  /* Couche première de portions */ -    void populate_with_symbols(const vmpa2t *limit) -    { -        GBinSymbol *symbol;                 /* Symbole en cours d'analyse  */ -        SymbolType type;                    /* Nature d'un symbole         */ -        const mrange_t *range;              /* Couverture d'un symbole     */ -        vmpa2t end;                         /* Adresse de fin du symbole   */ - -        for (; sym_index < sym_count; sym_index++) -        { -            symbol = symbols[sym_index]; - -            type = g_binary_symbol_get_target_type(symbol); - -            /** -             * On ne garde que les symboles renvoyant directement une ou -             * plusieurs instructions, c'est à dire les symboles valides -             * pour un appel à g_binary_symbol_get_instruction(). -             * -             * Les instructions des autres symboles sont obtenues et mises -             * en place durant la procédure de désassemblage. -             */ - -            if (type == STP_ROUTINE || type == STP_ENTRY_POINT || type == STP_CODE_LABEL) -                continue; - -            range = g_binary_symbol_get_range(symbol); - -            if (get_mrange_length(range) == 0) -                continue; - -            if (cmp_vmpa(get_mrange_addr(range), limit) >= 0) -                break; - -            compute_mrange_end_addr(range, &end); - -            /** -             * Si un symbole est à cheval entre deux zones, tant pis pour lui ! -             */ - -            if (cmp_vmpa(&end, limit) > 0) -                break; - -            insert_extra_symbol_into_mem_areas(*list, *count, symbol); - -        } - -    } -      void fill_gap(vmpa2t *old, vmpa2t *new, bool alloc, bool exec)      {          phys_t diff;                        /* Espace entre bordures       */ @@ -1300,24 +1271,6 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac              init_mem_area_from_addr(area, old, diff, collector->binary);              area->is_exec = exec; -            /* Insertion des symboles existants */ - -            if (!has_sym_index) -            { -                int cmp_vmpa_with_symbol(const vmpa2t *a, const GBinSymbol **s) -                { -                    return g_binary_symbol_cmp_with_vmpa(*s, a); -                } - -                bsearch_index(old, symbols, sym_count, sizeof(GBinSymbol *), -                              (__compar_fn_t)cmp_vmpa_with_symbol, &sym_index); - -                has_sym_index = true; - -            } - -            populate_with_symbols(new); -              /* Avancée du curseur */              copy_vmpa(old, new); @@ -1423,7 +1376,7 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac      }      list = &collector->areas; -    count = &collector->acount; +    count = &collector->created;      init_vmpa(&first, collector->first, VMPA_NO_VIRTUAL);      init_vmpa(&last, collector->last, VMPA_NO_VIRTUAL); @@ -1437,10 +1390,6 @@ static void g_area_collector_do_compute(GAreaCollector *collector, GtkStatusStac      g_exe_format_translate_offset_into_vmpa(format, 0, &prev);  #endif -    symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count); - -    has_sym_index = false; -      portions = g_exe_format_get_portions(format);      g_binary_portion_visit(portions, (visit_portion_fc)build_area_from_portion, NULL); @@ -1518,10 +1467,10 @@ mem_area *collect_memory_areas(wgroup_id_t gid, GtkStatusStack *status, GLoadedB      for (i = 0; i < runs_count; i++)      { -        result = (mem_area *)realloc(result, (*count + collectors[i]->acount) * sizeof(mem_area)); +        result = (mem_area *)realloc(result, (*count + collectors[i]->created) * sizeof(mem_area)); -        memcpy(&result[*count], collectors[i]->areas, collectors[i]->acount * sizeof(mem_area)); -        *count += collectors[i]->acount; +        memcpy(&result[*count], collectors[i]->areas, collectors[i]->created * sizeof(mem_area)); +        *count += collectors[i]->created;          g_object_unref(G_OBJECT(collectors[i])); @@ -1540,6 +1489,177 @@ mem_area *collect_memory_areas(wgroup_id_t gid, GtkStatusStack *status, GLoadedB  /******************************************************************************  *                                                                             * +*  Paramètres  : id        = identifiant pour signaler la progression.        * +*                areas     = liste des zones en place à parcourir.            * +*                available = nombre de zones disponibles pour les traitements.* +*                info      = préchargements effectués via le format binaire.  * +*                start     = indice de la première instruction à insérer.     * +*                stop      = indice de la première instruction à ignorer.     * +*                                                                             * +*  Description : Crée une tâche de calcul des zones binaires à remplir.       * +*                                                                             * +*  Retour      : Tâche créée.                                                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static GAreaCollector *g_area_collector_new_insert(activity_id_t id, mem_area *areas, size_t available, GPreloadInfo *info, size_t start, size_t stop) +{ +    GAreaCollector *result;            /* Tâche à retourner           */ + +    result = g_object_new(G_TYPE_AREA_COLLECTOR, NULL); + +    result->id = id; +    result->run = (run_task_fc)g_area_collector_do_insert; + +    result->areas = areas; + +    result->available = available; + +    result->info = info; +    g_object_ref(G_OBJECT(info)); + +    result->start = start; +    result->stop = stop; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : fetching = récupération à mener.                             * +*                status   = barre de statut à tenir informée.                 * +*                                                                             * +*  Description : Insère dans les zones contigües les instructions préchargées.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_area_collector_do_insert(GAreaCollector *collector, GtkStatusStack *status) +{ +    mem_area *area;                         /* Zone d'appartenance         */ +    size_t i;                               /* Boucle de parcours          */ +    GArchInstruction *instr;                /* Instruction à analyser      */ +    const mrange_t *range;                  /* Emplacement d'instruction   */ +    const vmpa2t *addr;                     /* Localisation précise        */ +#ifndef NDEBUG +    bool inserted;                          /* Validation d'une insertion  */ +#endif + +    area = NULL; + +    for (i = collector->start; i < collector->stop; i++) +    { +        instr = _g_preload_info_get_instruction(collector->info, i); +        range = g_arch_instruction_get_range(instr); +        addr = get_mrange_addr(range); + +        if (area != NULL) +        { +            if (!mrange_contains_addr(&area->range, addr)) +                area = NULL; +        } + +        if (area == NULL) +            area = find_memory_area_by_addr(collector->areas, collector->available, addr); + +        assert(area != NULL); + +#ifndef NDEBUG +        inserted = mark_range_in_mem_area_as_processed(area, instr, false); +        assert(inserted); +#else +        mark_range_in_mem_area_as_processed(area, instr, false); +#endif + +        gtk_status_stack_update_activity_value(status, collector->id, 1); + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : gid    = groupe de travail impliqué.                         * +*                status = barre de statut à tenir informée.                   * +*                area   = nombre de zones mises en place.                     * +*                count  = quantité de ces zones.                              * +*                info   = préchargements effectués via le format binaire.     * +*                                                                             * +*  Description : Intègre toutes les instructions préchargées dans des zones.  * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void populate_fresh_memory_areas(wgroup_id_t gid, GtkStatusStack *status, mem_area *areas, size_t count, GPreloadInfo *info) +{ +    size_t icount;                          /* Quantité d'instructions     */ +    guint runs_count;                       /* Qté d'exécutions parallèles */ +    GAreaCollector **collectors;            /* Collecteurs à suivre        */ +    phys_t run_size;                        /* Volume réparti par exécution*/ +    GWorkQueue *queue;                      /* Gestionnaire de différés    */ +    activity_id_t id;                       /* Identifiant de progression  */ +    guint i;                                /* Boucle de parcours          */ +    size_t start;                           /* Premier indice à traiter    */ +    size_t stop;                            /* Premier indice à ignorer    */ + +    g_preload_info_lock_instructions(info); + +    icount = _g_preload_info_count_instructions(info); + +    runs_count = g_get_num_processors(); + +    collectors = (GAreaCollector **)calloc(runs_count, sizeof(GAreaCollector *)); + +    run_size = icount / runs_count; + +    queue = get_work_queue(); + +    id = gtk_status_stack_add_activity(status, _("Inserting all preloaded instructions"), icount); + +    for (i = 0; i < runs_count; i++) +    { +        start = i * run_size; + +        if ((i + 1) == runs_count) +            stop = icount; +        else +            stop = start + run_size; + +        collectors[i] = g_area_collector_new_insert(id, areas, count, info, start, stop); + +        g_object_ref(G_OBJECT(collectors[i])); +        g_work_queue_schedule_work(queue, G_DELAYED_WORK(collectors[i]), gid); + +    } + +    g_work_queue_wait_for_completion(queue, gid); + +    /* Fin */ + +    free(collectors); + +    _g_preload_info_drain_instructions(info); + +    g_preload_info_unlock_instructions(info); + +    gtk_status_stack_remove_activity(status, id); + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : id    = identifiant pour signaler la progression courante.   *  *                list  = liste des zones en place à parcourir.                *  *                begin = indice de la première zone à traiter.                * diff --git a/src/analysis/disass/area.h b/src/analysis/disass/area.h index 173f4be..5ee71a3 100644 --- a/src/analysis/disass/area.h +++ b/src/analysis/disass/area.h @@ -27,6 +27,7 @@  #include "../binary.h"  #include "../../arch/instruction.h" +#include "../../format/preload.h"  #include "../../format/symbol.h"  #include "../../glibext/delayed.h"  #include "../../gtkext/gtkstatusstack.h" @@ -46,9 +47,6 @@ void load_code_from_mem_area(mem_area *, mem_area *, size_t, GProcContext *, con  /* Détermine une liste de zones contigües à traiter. */  mem_area *find_memory_area_by_addr(mem_area *, size_t, const vmpa2t *); -/* Insère un symbole dans un découpage en aires. */ -void insert_extra_symbol_into_mem_areas(mem_area *, size_t, const GBinSymbol *); -  /* S'assure que l'ensemble des aires est entièrement décodé. */  void ensure_all_mem_areas_are_filled(mem_area *, size_t, GProcContext *, GtkStatusStack *, activity_id_t); @@ -59,6 +57,9 @@ void ensure_all_mem_areas_are_filled(mem_area *, size_t, GProcContext *, GtkStat  /* Détermine une liste de zones contigües à traiter. */  mem_area *collect_memory_areas(wgroup_id_t, GtkStatusStack *, GLoadedBinary *, phys_t, size_t *); +/* Intègre toutes les instructions préchargées dans des zones. */ +void populate_fresh_memory_areas(wgroup_id_t, GtkStatusStack *, mem_area *, size_t, GPreloadInfo *); +  /* Rassemble les instructions conservées dans des zones données. */  GArchInstruction **collect_disassembled_instructions(wgroup_id_t, GtkStatusStack *, mem_area *, size_t, size_t *); diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index c9aa472..0ffcccd 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -409,8 +409,6 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus - -      /* Première étape */      //id = gtk_extended_status_bar_push(statusbar, _("Disassembling..."), true); @@ -576,7 +574,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatus -    print_disassembled_instructions(disass->cache, disass->lang, disass->binary, status); +    print_disassembled_instructions(disass->cache, disass->lang, disass->binary, G_PRELOAD_INFO(ctx), status); diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c index 211ed31..c5489d6 100644 --- a/src/analysis/disass/fetch.c +++ b/src/analysis/disass/fetch.c @@ -417,6 +417,8 @@ GArchInstruction **disassemble_binary_content(GLoadedBinary *binary, GProcContex      template.areas = collect_memory_areas(gid, status, binary, length, &template.count); +    populate_fresh_memory_areas(gid, status, template.areas, template.count, G_PRELOAD_INFO(ctx)); +      template.status = status;      /* Amorce des traitements */ @@ -443,7 +445,7 @@ GArchInstruction **disassemble_binary_content(GLoadedBinary *binary, GProcContex                                                  _("Disassembling following the execution flow..."),                                                  length); -    g_binary_format_setup_disassembling_context(format, template.ctx); +    g_binary_format_setup_disassembling_context(format, template.ctx, status);      g_work_queue_wait_for_completion(queue, gid); diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index fcbc0c6..5a74d92 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -38,6 +38,7 @@  *  Paramètres  : cache  = tampon de récueil des résultats d'impression.       *  *                lang   = langage de haut niveau préféré pour l'impression.   *  *                binary = tampon de récueil des résultats d'impression.       * +*                info   = informations complémentaires à intégrer.            *  *                status = barre de statut avec progression à mettre à jour.   *  *                                                                             *  *  Description : Transcrit du code désassemblé en texte humainement lisible.  * @@ -48,7 +49,7 @@  *                                                                             *  ******************************************************************************/ -void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, GLoadedBinary *binary, GtkStatusStack *status) +void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang, GLoadedBinary *binary, GPreloadInfo *info, GtkStatusStack *status)  {      GExeFormat *format;                     /* Format associé au binaire   */      GArchProcessor *proc;                   /* Processeur de l'architecture*/ @@ -64,6 +65,11 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang,      size_t count;                           /* Nombre total d'instructions */      activity_id_t id;                       /* Identifiant de progression  */      bool expect_outro;                      /* Fin de zone de code définie */ + + +    GDbComment *comment;                    /* Commentaire à ajouter       */ +    const vmpa2t *caddr;                    /* Localisation du commentaire */ +      size_t i;                               /* Boucle de parcours          */      GArchInstruction *instr;                /* Instruction à traiter       */      const vmpa2t *iaddr;                    /* Adresse d'instruction       */ @@ -78,7 +84,7 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang,      BufferLineFlags flags;                  /* Propriétés pour la ligne    */      //mrange_t range;                         /* Couverture sans surface     */ -    GDbComment *comment;                    /* Commentaire à ajouter       */ +    GDbComment *_comment;                    /* Commentaire à ajouter       */ @@ -131,6 +137,20 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang,      expect_outro = false; +    comment = g_preload_info_pop_comment(info); + +    if (comment != NULL) +        caddr = g_db_comment_get_address(comment); + + +    /* +    if (comment != NULL) +        log_variadic_message(LMT_BAD_BINARY, +                             _("Got comment '%s' @ 0x%08x"), +                             g_db_comment_get_text(comment), get_phy_addr(caddr)); +    */ + +      for (i = 0; i < count; i++)      {          instr = g_arch_processor_get_instruction(proc, i); @@ -184,7 +204,7 @@ 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_virt_addr(saddr)); +                                     g_binary_symbol_get_label(symbols[sym_index]), get_phy_addr(saddr));                  _missing++; @@ -261,18 +281,61 @@ void print_disassembled_instructions(GBufferCache *cache, GCodingLanguage *lang,          g_buffer_cache_append(cache, G_LINE_GENERATOR(instr), flags); + + +        //////////////////////////////////          if (compared == 0)          {              /* Commentaire ? */ -            comment = g_binary_symbol_get_comment(symbols[sym_index]); +            _comment = g_binary_symbol_get_comment(symbols[sym_index]); -            if (comment != NULL) -                g_db_item_apply(G_DB_ITEM(comment), binary); +            if (_comment != NULL) +                g_db_item_apply(G_DB_ITEM(_comment), binary);              sym_index++;          } +        /////////////////////////////////////// + + + +        /* Commentaire en bout de ligne ? */ + +        if (comment != NULL) +        { +            compared = cmp_vmpa(iaddr, caddr); + +            if (compared == 0) +            { +                if (g_loaded_binary_add_to_collection(binary, G_DB_ITEM(comment))) +                    g_db_item_apply(G_DB_ITEM(comment), binary); + +                else +                    g_object_unref(G_OBJECT(comment)); + +            } + +            else if (compared > 0) +            { +                log_variadic_message(LMT_BAD_BINARY, +                                     _("Unable to find a proper location for comment '%s' @ 0x%08x"), +                                     g_db_comment_get_text(comment), get_phy_addr(caddr)); + +                g_object_unref(G_OBJECT(comment)); + +            } + +            if (compared >= 0) +            { +                comment = g_preload_info_pop_comment(info); + +                if (comment != NULL) +                    caddr = g_db_comment_get_address(comment); + +            } + +        }          g_object_unref(G_OBJECT(instr)); diff --git a/src/analysis/disass/output.h b/src/analysis/disass/output.h index 7a4cf8f..a05a3c4 100644 --- a/src/analysis/disass/output.h +++ b/src/analysis/disass/output.h @@ -27,13 +27,14 @@  #include "../binary.h"  #include "../human/lang.h" +#include "../../format/preload.h"  #include "../../glibext/gbuffercache.h"  #include "../../gtkext/gtkstatusstack.h"  /* Transcrit du code désassemblé en texte humainement lisible. */ -void print_disassembled_instructions(GBufferCache *, GCodingLanguage *, GLoadedBinary *, GtkStatusStack *); +void print_disassembled_instructions(GBufferCache *, GCodingLanguage *, GLoadedBinary *, GPreloadInfo *, GtkStatusStack *); diff --git a/src/arch/arm/v7/fetch.c b/src/arch/arm/v7/fetch.c index 11864f6..788d7ab 100644 --- a/src/arch/arm/v7/fetch.c +++ b/src/arch/arm/v7/fetch.c @@ -25,7 +25,7 @@  #include <assert.h> -#include <malloc.h> +#include <stdio.h>  #include <i18n.h> @@ -36,6 +36,7 @@  #include "../../raw.h"  #include "../../sharing/container.h"  #include "../../../format/format.h" +#include "../../../format/preload.h" @@ -361,18 +362,15 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst      uint32_t offset;                        /* Décallage encodé en dur     */      bool ret;                               /* Bilan d'une récupération    */      off_t val_offset;                       /* Position de valeur à lire   */ -    vmpa2t sym_addr;                        /* Adresse de nouveau symbole  */ +    vmpa2t loaded_addr;                     /* Adresse de valeur chargée   */ +    mrange_t loaded_range;                  /* Espace de chargement        */      GBinContent *content;                   /* Contenu binaire à relire    */      uint32_t target;                        /* Adresse virtuelle visée     */      vmpa2t pos;                             /* Tête de lecture de valeur   */ -    mrange_t sym_range;                     /* Espace du nouveau symbole   */      VMPA_BUFFER(loc);                       /* Adresse au format texte     */ -    size_t name_len;                        /* Taille de nomination finale */ -    char *name;                             /* Désignation humaine         */ -    GArchInstruction *sym_instr;            /* Instruction de symbole      */ -    GBinSymbol *symbol;                     /* Nouveau symbole construit   */ +    GArchInstruction *loaded;               /* Instruction de valeur       */ +    char *desc;                             /* Description d'accompagnement*/      GDbComment *comment;                    /* Définition de commentaire   */ -    bool added;                             /* Bilan de l'insertion        */      GArchOperand *new;                      /* Instruction de ciblage      */      /* Récupération de l'adresse visée par le chargement */ @@ -410,32 +408,24 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst          return;      } -    /* Transformations et conservation d'une position de symbole */ +    /* Transformations et conservation d'une position de chargement */      val_offset = phys_pc + offset; -    if (!g_exe_format_translate_offset_into_vmpa(format, val_offset, &sym_addr)) +    if (!g_exe_format_translate_offset_into_vmpa(format, val_offset, &loaded_addr))      {          assert(0);          g_arch_instruction_unlock_operands(instr);          return;      } -    //init_vmpa(&sym_addr, val_offset, VMPA_NO_VIRTUAL); -    init_mrange(&sym_range, &sym_addr, 4); - - - - - - - +    init_mrange(&loaded_range, &loaded_addr, 4);      /* Lecture de la valeur vers laquelle renvoyer */      content = g_binary_format_get_content(G_BIN_FORMAT(format)); -    copy_vmpa(&pos, &sym_addr); +    copy_vmpa(&pos, &loaded_addr);      ret = g_binary_content_read_u32(content, &pos, SRE_LITTLE /* FIXME */, &target);      g_object_unref(G_OBJECT(content)); @@ -446,55 +436,24 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst          return;      } -    /* Réalise l'intégration du symbole associé */ +    /* Réalise l'intégration de la valeur chargée */ -    sym_instr = g_raw_instruction_new_from_value(&sym_addr, MDS_32_BITS_UNSIGNED, target); +    copy_vmpa(&pos, &loaded_addr); -    name_len = strlen(_("Value used @ %s")) + VMPA_MAX_LEN + 1; +    loaded = g_raw_instruction_new_from_value(&pos, MDS_32_BITS_UNSIGNED, target); -    name = (char *)calloc(name_len, sizeof(char)); +    g_preload_info_add_instruction(G_PRELOAD_INFO(context), loaded);      vmpa2_virt_to_string(get_mrange_addr(range), MDS_32_BITS, loc, NULL); -    snprintf(name, name_len, _("Value used @ %s"), loc); - -    added = ADD_RAW_AS_SYM(G_BIN_FORMAT(format), symbol, sym_instr, comment, name); - -    free(name); - - - -    if (added) -        g_proc_context_push_new_symbol_at(G_PROC_CONTEXT(context), &sym_addr); - - - -    //g_proc_context_push_new_symbol_at(context, &sym_addr); - - - - - - - - - - - - - - - - - - -    //g_imm_operand_set_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, target, G_SHARE_CONTAINER(instr)); - +    asprintf(&desc, _("Value used @ %s"), loc); -    /// FIXME ?! -    //if (target < 0x8000) return; +    comment = g_db_comment_new_inlined(&loaded_addr, BLF_HAS_CODE, false); +    g_db_comment_add_static_text(comment, desc); +    g_db_item_set_volatile(G_DB_ITEM(comment), true); -    //if (target > 0x6966c) return; +    g_preload_info_add_comment(G_PRELOAD_INFO(context), comment); +    /* Mise à jour de l'affichage et conclusion */      new = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, target);      _g_arch_instruction_replace_operand(instr, op, new); diff --git a/src/arch/context-int.h b/src/arch/context-int.h index 4e188cc..3a5c7ee 100644 --- a/src/arch/context-int.h +++ b/src/arch/context-int.h @@ -31,6 +31,9 @@  #include <stdarg.h> +#include "../format/preload-int.h" + +  /* Granularité des allocations */  #define DP_ALLOC_BLOCK 10 @@ -43,7 +46,7 @@ typedef void (* push_drop_point_fc) (GProcContext *, DisassPriorityLevel, virt_t  /* Définition d'un contexte pour processeur (instance) */  struct _GProcContext  { -    GObject parent;                         /* A laisser en premier        */ +    GPreloadInfo parent;                    /* A laisser en premier        */      virt_t *drop_points[DPL_COUNT];         /* Liste de points de départ   */      size_t dp_allocated[DPL_COUNT];         /* Taille de liste allouée     */ @@ -67,7 +70,7 @@ struct _GProcContext  /* Définition d'un contexte pour processeur (classe) */  struct _GProcContextClass  { -    GObjectClass parent;                    /* A laisser en premier        */ +    GPreloadInfoClass parent;               /* A laisser en premier        */  	push_drop_point_fc push_point;			/* Inclusion de points de chute*/ diff --git a/src/arch/context.c b/src/arch/context.c index ddb74fd..c7a59da 100644 --- a/src/arch/context.c +++ b/src/arch/context.c @@ -55,7 +55,7 @@ static void _g_proc_context_push_drop_point(GProcContext *, DisassPriorityLevel,  /* Indique le type définit par la GLib pour le contexte de processeur. */ -G_DEFINE_TYPE(GProcContext, g_proc_context, G_TYPE_OBJECT); +G_DEFINE_TYPE(GProcContext, g_proc_context, G_TYPE_PRELOAD_INFO); diff --git a/src/arch/instruction.c b/src/arch/instruction.c index a9bc4f2..807bbbb 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -463,7 +463,7 @@ void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchReg  *                                                                             *  *  Paramètres  : instr = instruction à mettre à jour.                         *  *                                                                             * -*  Description : Verrouille les accès la liste des opérandes.                 * +*  Description : Verrouille les accès à la liste des opérandes.               *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -482,7 +482,7 @@ void g_arch_instruction_lock_operands(GArchInstruction *instr)  *                                                                             *  *  Paramètres  : instr = instruction à mettre à jour.                         *  *                                                                             * -*  Description : Déverrouille les accès la liste des opérandes.               * +*  Description : Déverrouille les accès à la liste des opérandes.             *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -546,12 +546,12 @@ size_t _g_arch_instruction_count_operands(const GArchInstruction *instr)  /******************************************************************************  *                                                                             * -*  Paramètres  : instr = instance à mettre à jour.                            * -*                index = indice de l'opérande concernée.                      * +*  Paramètres  : instr = instance à consulter.                                * +*                index = indice de l'opérande concerné.                       *  *                                                                             *  *  Description : Fournit un opérande donné d'une instruction.                 *  *                                                                             * -*  Retour      : Opérande trouvée ou NULL si aucune.                          * +*  Retour      : Opérande trouvée.                                            *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             * diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 55c845e..64b8dd5 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -131,10 +131,10 @@ void g_arch_instruction_get_rw_registers(const GArchInstruction *, GArchRegister  /* --------------------------- MANIPULATION DES OPERANDES --------------------------- */ -/* Verrouille les accès la liste des opérandes. */ +/* Verrouille les accès à la liste des opérandes. */  void g_arch_instruction_lock_operands(GArchInstruction *); -/* Déverrouille les accès la liste des opérandes. */ +/* Déverrouille les accès à la liste des opérandes. */  void g_arch_instruction_unlock_operands(GArchInstruction *);  /* Attache un opérande supplémentaire à une instruction. */ diff --git a/src/common/array.c b/src/common/array.c index 641a885..e4e7bb1 100644 --- a/src/common/array.c +++ b/src/common/array.c @@ -34,6 +34,9 @@  #include <string.h> +#include "sort.h" + +  /**   * L'expression du besoin d'une gestion optimisée des tableaux se base sur la @@ -259,6 +262,64 @@ void add_item_to_flat_array(flat_array_t **array, const void *item, size_t size)  /******************************************************************************  *                                                                             * +*  Paramètres  : array  = tableau compressé à mettre à jour. [OUT]            * +*                item   = adresse de l'élément à rajouter.                    * +*                size   = taille de ce nouvel élément.                        * +*                compar = méthode de comparaison entre éléments.              * +*                                                                             * +*  Description : Ajoute un élément supplémentaire à un tableau trié.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void insert_item_into_flat_array(flat_array_t **array, void *item, size_t size, __compar_fn_t compar) +{ +    ext_flat_array_t *extended;             /* Version de tableau étendue  */ + +    assert(FLAT_ARRAY_IS_LOCKED(*array)); + +    if (FLAT_ARRAY_IS_EMPTY(*array)) +    { +        *array = malloc(size); +        memcpy(*array, item, size); + +        lock_flat_array(array); + +    } + +    else +    { +        if (FLAT_ARRAY_HAS_NO_INDEX(*array)) +        { +            extended = (ext_flat_array_t *)malloc(sizeof(ext_flat_array_t)); + +            extended->items = malloc(size); +            extended->count = 1; + +            memcpy(extended->items, GET_LONELY_ITEM(*array), size); + +            FLAT_ARRAY_SET_INDEX(extended); + +            *array = (flat_array_t *)extended; + +            lock_flat_array(array); + +        } + +        extended = EXTENDED_ARRAY(*array); + +        extended->items = qinsert(extended->items, &extended->count, size, compar, item); + +    } + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : array = tableau compressé à mettre à jour.                   *  *                index = indice de l'élément à remplacer.                     *  *                new   = adresse de l'élément à rajouter.                     * diff --git a/src/common/array.h b/src/common/array.h index 416800d..2dd5b9f 100644 --- a/src/common/array.h +++ b/src/common/array.h @@ -25,6 +25,7 @@  #define _COMMON_ARRAY_H +#include <stdlib.h>  #include <sys/types.h> @@ -45,6 +46,9 @@ size_t count_flat_array_items(const flat_array_t *);  /* Ajoute un élément supplémentaire à un tableau. */  void add_item_to_flat_array(flat_array_t **, const void *, size_t); +/* Ajoute un élément supplémentaire à un tableau trié. */ +void insert_item_into_flat_array(flat_array_t **, void *, size_t, __compar_fn_t); +  /* Remplace un élément d'un tableau compressé par un autre. */  void rpl_item_in_flat_array(flat_array_t *, size_t, void *, size_t); diff --git a/src/format/Makefile.am b/src/format/Makefile.am index 3f18b88..2fef6c6 100644 --- a/src/format/Makefile.am +++ b/src/format/Makefile.am @@ -8,6 +8,8 @@ libformat_la_SOURCES =					\  	executable.h executable.c			\  	format-int.h						\  	format.h format.c					\ +	preload-int.h						\ +	preload.h preload.c					\  	symbol.h symbol.c  libformat_la_LIBADD =					\ diff --git a/src/format/format.c b/src/format/format.c index 978a3d2..11216a2 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -31,6 +31,7 @@  #include "format-int.h" +#include "preload.h"  #include "dex/dex.h"  #include "dwarf/dwarf.h"  #include "elf/elf.h" @@ -247,6 +248,7 @@ void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, bool ent  *                                                                             *  *  Paramètres  : format = description de l'exécutable à consulter.            *  *                ctx    = contexte de désassemblage à préparer.               * +*                status = barre de statut à tenir informée.                   *  *                                                                             *  *  Description : Fournit un contexte initialisé pour un désassemblage.        *  *                                                                             * @@ -256,10 +258,12 @@ void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, bool ent  *                                                                             *  ******************************************************************************/ -void g_binary_format_setup_disassembling_context(GBinFormat *format, GProcContext *ctx) +void g_binary_format_setup_disassembling_context(GBinFormat *format, GProcContext *ctx, GtkStatusStack *status)  {      size_t i;                               /* Boucle de parcours          */ +    preload_binary_format(PGA_FORMAT_PRELOAD, format, G_PRELOAD_INFO(ctx), status); +      g_rw_lock_reader_lock(&format->pt_lock);      for (i = 0; i < format->ep_count; i++) diff --git a/src/format/format.h b/src/format/format.h index c2ef895..b04f11b 100644 --- a/src/format/format.h +++ b/src/format/format.h @@ -34,6 +34,7 @@  #include "../analysis/content.h"  #include "../analysis/routine.h"  #include "../arch/context.h" +#include "../gtkext/gtkstatusstack.h" @@ -65,7 +66,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(GBinFormat *, GProcContext *); +void g_binary_format_setup_disassembling_context(GBinFormat *, GProcContext *, GtkStatusStack *);  /* Ajoute un symbole à la collection du format binaire. */  bool g_binary_format_add_symbol(GBinFormat *, GBinSymbol *); diff --git a/src/format/preload-int.h b/src/format/preload-int.h new file mode 100644 index 0000000..ccc59e3 --- /dev/null +++ b/src/format/preload-int.h @@ -0,0 +1,54 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * preload.c - préchargement d'instructions à partir d'un format + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _FORMAT_PRELOAD_INT_H +#define _FORMAT_PRELOAD_INT_H + + +#include "preload.h" + + +#include "../common/array.h" + + + +/* Préchargement d'origine formatée (instance) */ +struct _GPreloadInfo +{ +    GObject parent;                         /* A laisser en premier        */ + +    flat_array_t *instructions;             /* Liste d'instructions        */ +    flat_array_t *comments;                 /* Liste de commentaires       */ + +}; + +/* Préchargement d'origine formatée (classe) */ +struct _GPreloadInfoClass +{ +    GObjectClass parent;                    /* A laisser en premier        */ + +}; + + + +#endif  /* _FORMAT_PRELOAD_INT_H */ diff --git a/src/format/preload.c b/src/format/preload.c new file mode 100644 index 0000000..145dfd9 --- /dev/null +++ b/src/format/preload.c @@ -0,0 +1,534 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * preload.c - préchargement d'instructions à partir d'un format + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#include "preload.h" + + +#include "preload-int.h" + + + +/* Initialise la classe des préchargements à partir d'un format. */ +static void g_preload_info_class_init(GPreloadInfoClass *); + +/* Initialise une instance de préchargement à partir de format. */ +static void g_preload_info_init(GPreloadInfo *); + +/* Supprime toutes les références externes. */ +static void g_preload_info_dispose(GPreloadInfo *); + +/* Procède à la libération totale de la mémoire. */ +static void g_preload_info_finalize(GPreloadInfo *); + + + +/* Indique le type défini pour un préchargement à partir d'un format. */ +G_DEFINE_TYPE(GPreloadInfo, g_preload_info, G_TYPE_OBJECT); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des préchargements à partir d'un format.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_preload_info_class_init(GPreloadInfoClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_preload_info_dispose; +    object->finalize = (GObjectFinalizeFunc)g_preload_info_finalize; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = instance à initialiser.                               * +*                                                                             * +*  Description : Initialise une instance de préchargement à partir de format. * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_preload_info_init(GPreloadInfo *info) +{ +    info->instructions = NULL; + +    info->comments = NULL; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_preload_info_dispose(GPreloadInfo *info) +{ +    GArchInstruction *instr;                /* Instruction à libérer       */ +    GDbComment *comment;                    /* Commentaire à libérer       */ + +    g_preload_info_lock_instructions(info); + +    _g_preload_info_drain_instructions(info); + +    g_preload_info_unlock_instructions(info); + +    g_preload_info_lock_comments(info); + +    while (_g_preload_info_count_comments(info) > 0) +    { +        comment = _g_preload_info_get_comment(info, 0); + +        rem_item_from_flat_array(&info->comments, 0, sizeof(GDbComment *)); + +        g_object_unref(G_OBJECT(comment)); + +    } + +    g_preload_info_unlock_comments(info); + +    G_OBJECT_CLASS(g_preload_info_parent_class)->dispose(G_OBJECT(info)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = instance d'objet GLib à traiter.                      * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_preload_info_finalize(GPreloadInfo *info) +{ +    G_OBJECT_CLASS(g_preload_info_parent_class)->finalize(G_OBJECT(info)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Crée une nouvelle collecte d'informations préchargées.       * +*                                                                             * +*  Retour      : Adresse de l'instance mise en place ou NULL en cas d'échec.  * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GPreloadInfo *g_preload_info_new(void) +{ +    GPreloadInfo *result;                   /* Nouveau preloade à renvoyer */ + +    result = g_object_new(G_TYPE_PRELOAD_INFO, NULL); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = préchargements à mettre à jour.                       * +*                                                                             * +*  Description : Verrouille les accès à la liste des instructions.            * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_preload_info_lock_instructions(GPreloadInfo *info) +{ +    lock_flat_array(&info->instructions); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = préchargements à mettre à jour.                       * +*                                                                             * +*  Description : Déverrouille les accès à la liste des instructions.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_preload_info_unlock_instructions(GPreloadInfo *info) +{ +    unlock_flat_array(&info->instructions); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info  = instance à mettre à jour.                            * +*                instr = instruction à venir associer.                        * +*                                                                             * +*  Description : Ajoute une instruction supplémentaire aux préchargements.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_preload_info_add_instruction(GPreloadInfo *info, GArchInstruction *instr) +{ +    int cmp_instr_by_addr(const GArchInstruction **a, const GArchInstruction **b) +    { +        const mrange_t *range_a;            /* Emplacement pour l'instr. A */ +        const mrange_t *range_b;            /* Emplacement pour l'instr. B */ + +        range_a = g_arch_instruction_get_range(*a); +        range_b = g_arch_instruction_get_range(*b); + +        return cmp_vmpa(get_mrange_addr(range_a), get_mrange_addr(range_b)); + +    } + +    g_preload_info_lock_instructions(info); + +    insert_item_into_flat_array(&info->instructions, &instr, sizeof(GArchInstruction *), +                                (__compar_fn_t)cmp_instr_by_addr); + +    g_preload_info_unlock_instructions(info); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = instance à consulter.                                 * +*                                                                             * +*  Description : Indique la quantité d'instructions préchargées disponibles.  * +*                                                                             * +*  Retour      : Nombre d'instructions attachées.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +size_t _g_preload_info_count_instructions(const GPreloadInfo *info) +{ +    size_t result;                          /* Décompte à retourner        */ + +    result = count_flat_array_items(info->instructions); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info  = instance à consulter.                                * +*                index = indice de l'instruction concernée.                   * +*                                                                             * +*  Description : Fournit une instruction préchargée donnée.                   * +*                                                                             * +*  Retour      : Instruction trouvée.                                         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *_g_preload_info_get_instruction(const GPreloadInfo *info, size_t index) +{ +    GArchInstruction *result;               /* Opérande à retourner        */ +    GArchInstruction **ptr;                 /* Adresse dans le tableau     */ + +    ptr = get_flat_array_item(info->instructions, index, sizeof(GArchInstruction *)); + +    result = *ptr; + +    g_object_ref(G_OBJECT(result)); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = instance à manipuler.                                 * +*                                                                             * +*  Description : Dépile une instruction présente dans les préchargements.     * +*                                                                             * +*  Retour      : Instruction retirée ou NULL si aucune.                       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *g_preload_info_pop_instruction(GPreloadInfo *info) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ +    GArchInstruction **ptr;                 /* Adresse dans le tableau     */ + +    g_preload_info_lock_instructions(info); + +    if (_g_preload_info_count_instructions(info) == 0) +        result = NULL; + +    else +    { +        ptr = get_flat_array_item(info->instructions, 0, sizeof(GArchInstruction *)); +        result = *ptr; + +        rem_item_from_flat_array(&info->instructions, 0, sizeof(GArchInstruction *)); + +    } + +    g_preload_info_unlock_instructions(info); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = instance à manipuler.                                 * +*                                                                             * +*  Description : Retire des préchargements toutes les instructions.           * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void _g_preload_info_drain_instructions(GPreloadInfo *info) +{ +    GArchInstruction *instr;                /* Instruction à libérer       */ + +    while (_g_preload_info_count_instructions(info) > 0) +    { +        instr = _g_preload_info_get_instruction(info, 0); + +        rem_item_from_flat_array(&info->instructions, 0, sizeof(GArchInstruction *)); + +        g_object_unref(G_OBJECT(instr)); + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = préchargements à mettre à jour.                       * +*                                                                             * +*  Description : Verrouille les accès à la liste des commentaires.            * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_preload_info_lock_comments(GPreloadInfo *info) +{ +    lock_flat_array(&info->comments); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = préchargements à mettre à jour.                       * +*                                                                             * +*  Description : Déverrouille les accès à la liste des commentaires.          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_preload_info_unlock_comments(GPreloadInfo *info) +{ +    unlock_flat_array(&info->comments); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info    = instance à mettre à jour.                          * +*                comment = commentaire à venir associer.                      * +*                                                                             * +*  Description : Ajoute un commentaire supplémentaire aux préchargements.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_preload_info_add_comment(GPreloadInfo *info, GDbComment *comment) +{ +    int cmp_comment_by_addr(const GDbComment * const *a, const GDbComment * const *b) +    { +        const vmpa2t *addr_a;               /* Position du commentaire A   */ +        const vmpa2t *addr_b;               /* Position du commentaire B   */ + +        addr_a = g_db_comment_get_address(*a); +        addr_b = g_db_comment_get_address(*b); + +        return cmp_vmpa(addr_a, addr_b); + +    } + +    g_preload_info_lock_comments(info); + +    insert_item_into_flat_array(&info->comments, &comment, sizeof(GDbComment *), +                                (__compar_fn_t)cmp_comment_by_addr); + +    g_preload_info_unlock_comments(info); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = instance à consulter.                                 * +*                                                                             * +*  Description : Indique la quantité de commentaires préchargés disponibles.  * +*                                                                             * +*  Retour      : Nombre de commentaires attachés.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +size_t _g_preload_info_count_comments(const GPreloadInfo *info) +{ +    size_t result;                          /* Décompte à retourner        */ + +    result = count_flat_array_items(info->comments); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info  = instance à consulter.                                * +*                index = indice de l'instruction concernée.                   * +*                                                                             * +*  Description : Fournit un commentaire préchargé donné.                      * +*                                                                             * +*  Retour      : Commentaire trouvé.                                          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GDbComment *_g_preload_info_get_comment(const GPreloadInfo *info, size_t index) +{ +    GDbComment *result;                     /* Opérande à retourner        */ +    GDbComment **ptr;                       /* Adresse dans le tableau     */ + +    ptr = get_flat_array_item(info->comments, index, sizeof(GDbComment *)); + +    result = *ptr; + +    g_object_ref(G_OBJECT(result)); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : info = instance à manipuler.                                 * +*                                                                             * +*  Description : Dépile un commentaire présent dans les préchargements.       * +*                                                                             * +*  Retour      : Commentaire retiré ou NULL si aucune.                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GDbComment *g_preload_info_pop_comment(GPreloadInfo *info) +{ +    GDbComment *result;                     /* Instruction à retourner     */ +    GDbComment **ptr;                       /* Adresse dans le tableau     */ + +    g_preload_info_lock_comments(info); + +    if (_g_preload_info_count_comments(info) == 0) +        result = NULL; + +    else +    { +        ptr = get_flat_array_item(info->comments, 0, sizeof(GDbComment *)); +        result = *ptr; + +        rem_item_from_flat_array(&info->comments, 0, sizeof(GDbComment *)); + +    } + +    g_preload_info_unlock_comments(info); + +    return result; + +} diff --git a/src/format/preload.h b/src/format/preload.h new file mode 100644 index 0000000..a915462 --- /dev/null +++ b/src/format/preload.h @@ -0,0 +1,98 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * preload.h - prototypes pour le préchargement d'instructions à partir d'un format + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _FORMAT_PRELOAD_H +#define _FORMAT_PRELOAD_H + + +#include <glib-object.h> + + +#include "../analysis/db/items/comment.h" +#include "../arch/instruction.h" + + + +#define G_TYPE_PRELOAD_INFO             g_preload_info_get_type() +#define G_PRELOAD_INFO(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PRELOAD_INFO, GPreloadInfo)) +#define G_IS_PRELOAD_INFO(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PRELOAD_INFO)) +#define G_PRELOAD_INFO_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PRELOAD_INFO, GPreloadInfoClass)) +#define G_IS_PRELOAD_INFO_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PRELOAD_INFO)) +#define G_PRELOAD_INFO_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PRELOAD_INFO, GPreloadInfoClass)) + + +/* Préchargement d'origine formatée (instance) */ +typedef struct _GPreloadInfo GPreloadInfo; + +/* Préchargement d'origine formatée (classe) */ +typedef struct _GPreloadInfoClass GPreloadInfoClass; + + +/* Indique le type défini pour un préchargement à partir d'un format. */ +GType g_preload_info_get_type(void); + +/* Crée une nouvelle collecte d'informations préchargées. */ +GPreloadInfo *g_preload_info_new(void); + +/* Verrouille les accès à la liste des instructions. */ +void g_preload_info_lock_instructions(GPreloadInfo *); + +/* Déverrouille les accès à la liste des instructions. */ +void g_preload_info_unlock_instructions(GPreloadInfo *); + +/* Ajoute une instruction supplémentaire aux préchargements. */ +void g_preload_info_add_instruction(GPreloadInfo *, GArchInstruction *); + +/* Indique la quantité d'instructions préchargées disponibles. */ +size_t _g_preload_info_count_instructions(const GPreloadInfo *); + +/* Fournit une instruction préchargée donnée. */ +GArchInstruction *_g_preload_info_get_instruction(const GPreloadInfo *, size_t); + +/* Dépile une instruction présente dans les préchargements. */ +GArchInstruction *g_preload_info_pop_instruction(GPreloadInfo *); + +/* Retire des préchargements toutes les instructions. */ +void _g_preload_info_drain_instructions(GPreloadInfo *); + +/* Verrouille les accès à la liste des commentaires. */ +void g_preload_info_lock_comments(GPreloadInfo *); + +/* Déverrouille les accès à la liste des commentaires. */ +void g_preload_info_unlock_comments(GPreloadInfo *); + +/* Ajoute un commentaire supplémentaire aux préchargements. */ +void g_preload_info_add_comment(GPreloadInfo *, GDbComment *); + +/* Indique la quantité de commentaires préchargés disponibles. */ +size_t _g_preload_info_count_comments(const GPreloadInfo *); + +/* Fournit un commentaire préchargé donné. */ +GDbComment *_g_preload_info_get_comment(const GPreloadInfo *, size_t); + +/* Dépile un commentaire présent dans les préchargements. */ +GDbComment *g_preload_info_pop_comment(GPreloadInfo *); + + + +#endif  /* _FORMAT_PRELOAD_H */ diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h index 53556b3..e085102 100644 --- a/src/plugins/pglist.h +++ b/src/plugins/pglist.h @@ -68,7 +68,8 @@ const GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);  #define handle_binary_format(a, f, s)                                     \      process_all_plugins_for(a, g_plugin_module_handle_binary_format, f, s) - +#define preload_binary_format(a, f, i, s)                                 \ +    process_all_plugins_for(a, g_plugin_module_preload_binary_format, f, i, s)  /* DPS_DISASSEMBLY */ diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h index b0523e1..7344a06 100644 --- a/src/plugins/plugin-def.h +++ b/src/plugins/plugin-def.h @@ -122,6 +122,9 @@ typedef enum _PluginAction      /* Accompagnement du chargement (fin) */      PGA_FORMAT_LOADER_LAST = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(1), +    /* Accompagnement du chargement (fin) */ +    PGA_FORMAT_PRELOAD     = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(2), +      /**       * DPC_BINARY_PROCESSING | DPS_DISASSEMBLY       */ diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h index 6f02369..7ccd2a6 100644 --- a/src/plugins/plugin-int.h +++ b/src/plugins/plugin-int.h @@ -51,6 +51,9 @@ typedef void (* pg_process_disassembly_fc) (const GPluginModule *, PluginAction,  /* Procède à une opération liée au format de fichier uniquement. */  typedef bool (* pg_handle_format) (const GPluginModule *, PluginAction, GBinFormat *, GtkStatusStack *); +/* Procède à un préchargement de format de fichier. */ +typedef bool (* pg_preload_format) (const GPluginModule *, PluginAction, GBinFormat *, GPreloadInfo *, GtkStatusStack *); + @@ -109,7 +112,7 @@ struct _GPluginModule      //pg_format_is_matching is_matching;      /* Recherche de correspondance */      pg_handle_format handle_format;         /* Manipulation du format      */ - +    pg_preload_format preload_format;       /* Préchargement d'un format   */  }; diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 7a5c680..0c287d6 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -279,6 +279,12 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)                                      goto bad_plugin;                                  break; +                            case PGA_FORMAT_PRELOAD: +                                if (!load_plugin_symbol(result->module, +                                                        "preload_binary_format", &result->preload_format)) +                                    goto bad_plugin; +                                break; +                              default:                                  log_variadic_message(LMT_WARNING,                                                       _("Unknown action '0x%02x' in plugin '%s'..."), @@ -509,6 +515,29 @@ bool g_plugin_module_handle_binary_format(const GPluginModule *plugin, PluginAct  *                                                                             *  *  Paramètres  : plugin = greffon à manipuler.                                *  *                action = type d'action attendue.                             * +*                format = format de binaire à manipuler pendant l'opération.  * +*                info   = informations à constituer en avance de phase.       * +*                status = barre de statut à tenir informée.                   * +*                                                                             * +*  Description : Procède à un préchargement de format de fichier.             * +*                                                                             * +*  Retour      : Bilan de l'exécution du traitement.                          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_plugin_module_preload_binary_format(const GPluginModule *plugin, PluginAction action, GBinFormat *format, GPreloadInfo *info, GtkStatusStack *status) +{ +    return plugin->preload_format(plugin, action, format, info, status); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : plugin = greffon à manipuler.                                * +*                action = type d'action attendue.                             *  *                binary = binaire dont le contenu est en cours de traitement. *  *                                                                             *  *  Description : Exécute une action pendant un désassemblage de binaire.      * diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index e09189d..bc52c93 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -32,6 +32,7 @@  #include "plugin-def.h"  #include "../analysis/binary.h"  #include "../format/format.h" +#include "../format/preload.h"  #include "../gtkext/gtkstatusstack.h" @@ -66,6 +67,9 @@ const plugin_interface *g_plugin_module_get_interface(const GPluginModule *);  /* Procède à une opération liée au format de fichier uniquement. */  bool g_plugin_module_handle_binary_format(const GPluginModule *, PluginAction, GBinFormat *, GtkStatusStack *); +/* Procède à un préchargement de format de fichier. */ +bool g_plugin_module_preload_binary_format(const GPluginModule *, PluginAction, GBinFormat *, GPreloadInfo *, GtkStatusStack *); +  /* Exécute une action pendant un désassemblage de binaire. */  void g_plugin_module_process_disassembly_event(const GPluginModule *, PluginAction, GLoadedBinary *); | 
