diff options
| -rw-r--r-- | ChangeLog | 44 | ||||
| -rw-r--r-- | src/analysis/disass/Makefile.am | 1 | ||||
| -rw-r--r-- | src/analysis/disass/area.c | 34 | ||||
| -rw-r--r-- | src/analysis/disass/area.h | 6 | ||||
| -rw-r--r-- | src/analysis/disass/disassembler.c | 421 | ||||
| -rw-r--r-- | src/analysis/disass/fetch.c | 49 | ||||
| -rw-r--r-- | src/analysis/disass/fetch.h | 4 | ||||
| -rw-r--r-- | src/analysis/disass/instructions.c | 312 | ||||
| -rw-r--r-- | src/analysis/disass/instructions.h | 68 | ||||
| -rw-r--r-- | src/analysis/disass/limit.c | 355 | ||||
| -rw-r--r-- | src/analysis/disass/limit.h | 9 | ||||
| -rw-r--r-- | src/analysis/disass/links.c | 54 | ||||
| -rw-r--r-- | src/analysis/disass/links.h | 15 | ||||
| -rw-r--r-- | src/analysis/disass/routines.c | 89 | ||||
| -rw-r--r-- | src/analysis/disass/routines.h | 12 | ||||
| -rw-r--r-- | src/arch/arm/v7/post.c | 12 | ||||
| -rw-r--r-- | src/arch/instruction.h | 3 | ||||
| -rw-r--r-- | src/arch/processor.c | 52 | ||||
| -rw-r--r-- | src/arch/processor.h | 6 | ||||
| -rw-r--r-- | src/gtkext/gtkstatusstack.c | 49 | ||||
| -rw-r--r-- | src/gtkext/gtkstatusstack.h | 6 | ||||
| -rw-r--r-- | src/main.c | 21 | 
22 files changed, 866 insertions, 756 deletions
| @@ -1,3 +1,47 @@ +16-04-03  Cyrille Bagard <nocbos@gmail.com> + +	* src/analysis/disass/Makefile.am: +	Add the 'instructions.[ch]' files to libanalysisdisass_la_SOURCES. + +	* src/analysis/disass/area.c: +	* src/analysis/disass/area.h: +	Update code. + +	* src/analysis/disass/disassembler.c: +	Update code. Reorganize the whole disassembling process and display +	the relative progression. + +	* src/analysis/disass/fetch.c: +	* src/analysis/disass/fetch.h: +	Update code. + +	* src/analysis/disass/instructions.c: +	* src/analysis/disass/instructions.h: +	New entries: handle all instructions disassembling processing in one place. + +	* src/analysis/disass/limit.c: +	* src/analysis/disass/limit.h: +	* src/analysis/disass/links.c: +	* src/analysis/disass/links.h: +	* src/analysis/disass/routines.c: +	* src/analysis/disass/routines.h: +	Update code. + +	* src/arch/instruction.h: +	The g_arch_instruction_find_by_address() function is slow and should not +	be used anymore. + +	* src/arch/processor.c: +	* src/arch/processor.h: +	Provide direct access to collected instructions. + +	* src/gtkext/gtkstatusstack.c: +	* src/gtkext/gtkstatusstack.h: +	Track the progression of an activity in a more clever way. + +	* src/main.c: +	Ensure the main window is shown as soon as possible. +  16-04-02  Cyrille Bagard <nocbos@gmail.com>  	* src/analysis/blocks/flow.c: diff --git a/src/analysis/disass/Makefile.am b/src/analysis/disass/Makefile.am index e901570..7223e5a 100644 --- a/src/analysis/disass/Makefile.am +++ b/src/analysis/disass/Makefile.am @@ -6,6 +6,7 @@ libanalysisdisass_la_SOURCES =			\  	disassembler.h disassembler.c		\  	dragon.h dragon.c					\  	fetch.h fetch.c						\ +	instructions.h instructions.c		\  	limit.h limit.c						\  	links.h links.c						\  	loop.h loop.c						\ diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c index 5f63c82..c1807b7 100644 --- a/src/analysis/disass/area.c +++ b/src/analysis/disass/area.c @@ -77,10 +77,10 @@ static bool mark_range_in_mem_area_as_processed_v2(mem_area_v2 *, GArchInstructi  /* Procède au désassemblage d'un contenu binaire non exécutable. */ -static void load_data_from_mem_area_v2(mem_area_v2 *, GProcContext *, const vmpa2t *, status_blob_info *); +static void load_data_from_mem_area_v2(mem_area_v2 *, GProcContext *, const vmpa2t *, GtkStatusStack *, activity_id_t);  /* S'assure qu'une aire contient toutes ses instructions. */ -static void fill_mem_area_v2(mem_area_v2 *, mem_area_v2 *, size_t, GProcContext *, status_blob_info *); +static void fill_mem_area_v2(mem_area_v2 *, mem_area_v2 *, size_t, GProcContext *, GtkStatusStack *, activity_id_t);  /* Rassemble les instructions conservées dans une zone donnée. */  static GArchInstruction *get_instructions_from_mem_area_v2(const mem_area_v2 *); @@ -280,7 +280,8 @@ static bool mark_range_in_mem_area_as_processed_v2(mem_area_v2 *area, GArchInstr  *                binary = représentation de binaire chargé.                   *  *                ctx    = contexte offert en soutien à un désassemblage.      *  *                start  = démarrage de l'exécution au sein de la zone.        * -*                info   = indications quant à la progression à afficher.      * +*                status = barre de statut à actualiser.                       * +*                id     = identifiant du groupe de progression à l'affichage. *  *                                                                             *  *  Description : Procède au désassemblage d'un contenu binaire exécutable.    *  *                                                                             * @@ -290,7 +291,7 @@ static bool mark_range_in_mem_area_as_processed_v2(mem_area_v2 *area, GArchInstr  *                                                                             *  ******************************************************************************/ -void load_code_from_mem_area_v2(mem_area_v2 *area, mem_area_v2 *list, size_t count, GProcContext *ctx, const vmpa2t *start, status_blob_info *info) +void load_code_from_mem_area_v2(mem_area_v2 *area, mem_area_v2 *list, size_t count, GProcContext *ctx, const vmpa2t *start, GtkStatusStack *status, activity_id_t id)  { @@ -381,7 +382,7 @@ void load_code_from_mem_area_v2(mem_area_v2 *area, mem_area_v2 *list, size_t cou              break;          } -        inc_progessive_status(info, diff); +        gtk_status_stack_update_activity_value(status, id, diff);          assert(!is_range_blank_in_mem_area_v2(area, i, diff)); @@ -421,7 +422,8 @@ void load_code_from_mem_area_v2(mem_area_v2 *area, mem_area_v2 *list, size_t cou  *  Paramètres  : area   = aire représentant à contenu à parcourir.            *  *                ctx    = contexte offert en soutien à un désassemblage.      *  *                start  = démarrage de l'exécution au sein de la zone.        * -*                info   = indications quant à la progression à afficher.      * +*                status = barre de statut à actualiser.                       * +*                id     = identifiant du groupe de progression à l'affichage. *  *                                                                             *  *  Description : Procède au désassemblage d'un contenu binaire non exécutable.*  *                                                                             * @@ -431,7 +433,7 @@ void load_code_from_mem_area_v2(mem_area_v2 *area, mem_area_v2 *list, size_t cou  *                                                                             *  ******************************************************************************/ -static void load_data_from_mem_area_v2(mem_area_v2 *area, GProcContext *ctx, const vmpa2t *start, status_blob_info *info) +static void load_data_from_mem_area_v2(mem_area_v2 *area, GProcContext *ctx, const vmpa2t *start, GtkStatusStack *status, activity_id_t id)  {      GBinContent *content;                   /* Données binaires à lire     */      SourceEndian endianness;                /* Boutisme de cette machine   */ @@ -511,7 +513,7 @@ static void load_data_from_mem_area_v2(mem_area_v2 *area, GProcContext *ctx, con              break;          } -        inc_progessive_status(info, diff); +        gtk_status_stack_update_activity_value(status, id, diff);          assert(!is_range_blank_in_mem_area_v2(area, i, diff)); @@ -531,7 +533,8 @@ static void load_data_from_mem_area_v2(mem_area_v2 *area, GProcContext *ctx, con  *                count  = nombre de zones à disposition.                      *  *                binary = représentation de binaire chargé.                   *  *                ctx    = contexte offert en soutien à un désassemblage.      * -*                info   = indications quant à la progression à afficher.      * +*                status = barre de statut à actualiser.                       * +*                id     = identifiant du groupe de progression à l'affichage. *  *                                                                             *  *  Description : S'assure qu'une aire contient toutes ses instructions.       *  *                                                                             * @@ -541,7 +544,7 @@ static void load_data_from_mem_area_v2(mem_area_v2 *area, GProcContext *ctx, con  *                                                                             *  ******************************************************************************/ -static void fill_mem_area_v2(mem_area_v2 *area, mem_area_v2 *list, size_t count, GProcContext *ctx, status_blob_info *info) +static void fill_mem_area_v2(mem_area_v2 *area, mem_area_v2 *list, size_t count, GProcContext *ctx, GtkStatusStack *status, activity_id_t id)  {      const vmpa2t *addr;                     /* Début de la zone à traiter  */      phys_t len;                             /* Taille de la zone à remplir */ @@ -559,10 +562,10 @@ static void fill_mem_area_v2(mem_area_v2 *area, mem_area_v2 *list, size_t count,              advance_vmpa(&start, i);              if (area->is_exec && get_virt_addr(&start) % area->packing_size == 0) -                load_code_from_mem_area_v2(area, list, count, ctx, &start, info); +                load_code_from_mem_area_v2(area, list, count, ctx, &start, status, id);              if (is_range_blank_in_mem_area_v2(area, i, 1)) -                load_data_from_mem_area_v2(area, ctx, &start, info); +                load_data_from_mem_area_v2(area, ctx, &start, status, id);          } @@ -1039,7 +1042,8 @@ void insert_extra_symbol_into_mem_areas_v2(mem_area_v2 *areas, size_t count, con  *                count  = nombre de zones à disposition.                      *  *                binary = représentation de binaire chargé.                   *  *                ctx    = contexte offert en soutien à un désassemblage.      * -*                info   = indications quant à la progression à afficher.      * +*                status = barre de statut à actualiser.                       * +*                id     = identifiant du groupe de progression à l'affichage. *  *                                                                             *  *  Description : S'assure que l'ensemble des aires est entièrement décodé.    *  *                                                                             * @@ -1049,12 +1053,12 @@ void insert_extra_symbol_into_mem_areas_v2(mem_area_v2 *areas, size_t count, con  *                                                                             *  ******************************************************************************/ -void ensure_all_mem_areas_are_filled(mem_area_v2 *list, size_t count, GProcContext *ctx, status_blob_info *info) +void ensure_all_mem_areas_are_filled(mem_area_v2 *list, size_t count, GProcContext *ctx, GtkStatusStack *status, activity_id_t id)  {      size_t i;                               /* Boucle de parcours          */      for (i = 0; i < count; i++) -        fill_mem_area_v2(&list[i], list, count, ctx, info); +        fill_mem_area_v2(&list[i], list, count, ctx, status, id);  } diff --git a/src/analysis/disass/area.h b/src/analysis/disass/area.h index aa26da0..3ffdbc5 100644 --- a/src/analysis/disass/area.h +++ b/src/analysis/disass/area.h @@ -27,7 +27,7 @@  #include "../binary.h"  #include "../../arch/instruction.h" -#include "../../gtkext/gtkextstatusbar.h" +#include "../../gtkext/gtkstatusstack.h" @@ -40,7 +40,7 @@ typedef struct _mem_area_v2 mem_area_v2;  /* Procède au désassemblage d'un contenu binaire exécutable. */ -void load_code_from_mem_area_v2(mem_area_v2 *, mem_area_v2 *, size_t, GProcContext *, const vmpa2t *, status_blob_info *); +void load_code_from_mem_area_v2(mem_area_v2 *, mem_area_v2 *, size_t, GProcContext *, const vmpa2t *, GtkStatusStack *, activity_id_t); @@ -57,7 +57,7 @@ mem_area_v2 *compute_memory_areas_v2(const GLoadedBinary *, phys_t, size_t *);  void insert_extra_symbol_into_mem_areas_v2(mem_area_v2 *, 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_v2 *, size_t, GProcContext *, status_blob_info *); +void ensure_all_mem_areas_are_filled(mem_area_v2 *, size_t, GProcContext *, GtkStatusStack *, activity_id_t);  /* Rassemble les instructions conservées dans des zones données. */  GArchInstruction *collect_instructions_from_mem_areas_v2(const mem_area_v2 *, size_t); diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index 4e6a13c..5bd9d43 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -33,12 +33,9 @@  #include "fetch.h" -#include "limit.h" -#include "links.h" -#include "loop.h" -#include "macro.h"  #include "output.h" -#include "rank.h" + +#include "instructions.h"  #include "routines.h"  #include "../../decomp/lang/asm.h"  #include "../../format/format.h" @@ -81,8 +78,14 @@ static void g_delayed_disassembly_init(GDelayedDisassembly *);  /* Crée une tâche de désassemblage différé. */  static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *, GArchInstruction **, GCodeBuffer *); +/* Opère sur toutes les instructions. */ +static void process_all_instructions(wgroup_id_t, GtkStatusStack *, const char *, ins_fallback_cb, GArchProcessor *, GExeFormat *); + +/* Opère sur toutes les routines. */ +static void process_all_routines(wgroup_id_t, GtkStatusStack *, const char *, rtn_fallback_cb, GArchProcessor *, GExeFormat *); +  /* Assure le désassemblage en différé. */ -static void g_delayed_disassembly_process(GDelayedDisassembly *, GtkExtStatusBar *); +static void g_delayed_disassembly_process(GDelayedDisassembly *, GtkStatusStack *); @@ -178,10 +181,14 @@ static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GAr  /******************************************************************************  *                                                                             * -*  Paramètres  : disass    = analyse à mener.                                 * -*                statusbar = barre de statut à tenir informée.                * +*  Paramètres  : gid      = groupe de travail impliqué.                       * +                 status   = barre de statut à tenir informée.                 * +*                msg      = message à faire paraître pour la patience.        * +*                fallback = routine de traitements particuliers.              * +*                proc     = ensemble d'instructions désassemblées.            * +*                format   = accès aux données du binaire d'origine.           *  *                                                                             * -*  Description : Assure le désassemblage en différé.                          * +*  Description : Opère sur toutes les instructions.                           *  *                                                                             *  *  Retour      : -                                                            *  *                                                                             * @@ -189,129 +196,204 @@ static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GAr  *                                                                             *  ******************************************************************************/ -static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtStatusBar *statusbar) +static void process_all_instructions(wgroup_id_t gid, GtkStatusStack *status, const char *msg, ins_fallback_cb fallback, GArchProcessor *proc, GExeFormat *format)  { -    wgroup_id_t gid;                        /* Identifiant pour les tâches */ +    guint runs_count;                       /* Qté d'exécutions parallèles */ +    size_t ins_count;                       /* Quantité d'instructions     */ +    size_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 begin;                           /* Début de bloc de traitement */ +    size_t end;                             /* Fin d'un bloc de traitement */ +    GInstructionsStudy *study;              /* Tâche d'étude à programmer  */ -    //GBinFormat *format;                     /* Format du fichier binaire   */ -    GArchProcessor *proc;                   /* Architecture du binaire     */ +    runs_count = g_get_num_processors(); +    ins_count = g_arch_processor_count_disassembled_instructions(proc); -    //size_t i;                               /* Boucle de parcours          */ +    run_size = ins_count / runs_count; -    GBinRoutine **routines;                 /* Liste des routines trouvées */ -    size_t routines_count;                  /* Nombre de ces routines      */ -    activity_id_t id;                        /* Identifiant de statut       */ +    queue = get_work_queue(); +    id = gtk_status_stack_add_activity(status, msg, ins_count); -    //GArchProcessor *proc;                   /* Architecture du binaire     */ +    for (i = 0; i < runs_count; i++) +    { +        begin = i * run_size; +        if ((i + 1) == runs_count) +            end = ins_count; +        else +            end = begin + run_size; +        study = g_instructions_study_new(proc, G_BIN_FORMAT(format), begin, end, id, fallback); -    gid = g_work_queue_define_work_group(get_work_queue()); +        g_work_queue_schedule_work(queue, G_DELAYED_WORK(study), gid); +    } +    g_work_queue_wait_for_completion(queue, gid); +    gtk_status_stack_remove_activity(status, id); +} -    //format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); -    proc = g_loaded_binary_get_processor(disass->binary); +/****************************************************************************** +*                                                                             * +*  Paramètres  : gid      = groupe de travail impliqué.                       * +                 status   = barre de statut à tenir informée.                 * +*                msg      = message à faire paraître pour la patience.        * +*                fallback = routine de traitements particuliers.              * +*                proc     = ensemble d'instructions désassemblées.            * +*                format   = accès aux données du binaire d'origine.           * +*                                                                             * +*  Description : Opère sur toutes les routines.                               * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ -    routines = g_binary_format_get_routines(G_BIN_FORMAT(disass->format), &routines_count); +static void process_all_routines(wgroup_id_t gid, GtkStatusStack *status, const char *msg, rtn_fallback_cb fallback, GArchProcessor *proc, GExeFormat *format) +{ +    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */ +    size_t exe_count;                       /* Nombre de ces zones         */ +    GBinRoutine **routines;                 /* Liste des routines trouvées */ +    size_t routines_count;                  /* Nombre de ces routines      */ +    guint runs_count;                       /* Qté d'exécutions parallèles */ +    size_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 begin;                           /* Début de bloc de traitement */ +    size_t end;                             /* Fin d'un bloc de traitement */ +    GRoutinesStudy *study;                  /* Tâche d'étude à programmer  */ +    exe_ranges = g_exe_format_get_x_ranges(format, &exe_count); -    /* Première étape */ +    routines = g_binary_format_get_routines(G_BIN_FORMAT(format), &routines_count); -    //id = gtk_extended_status_bar_push(statusbar, _("Disassembling..."), true); +    runs_count = g_get_num_processors(); +    run_size = routines_count / runs_count; +    queue = get_work_queue(); -    process_disassembly_event(PGA_DISASSEMBLY_STARTED, disass->binary); +    id = gtk_status_stack_add_activity(status, msg, routines_count); +    for (i = 0; i < runs_count; i++) +    { +        begin = i * run_size; +        if ((i + 1) == runs_count) +            end = routines_count; +        else +            end = begin + run_size; -    *disass->instrs = disassemble_binary_content(disass->binary, gid, statusbar); +        study = g_routines_study_new(proc, exe_ranges, exe_count, routines, routines_count, +                                     begin, end, id, fallback); +        g_work_queue_schedule_work(queue, G_DELAYED_WORK(study), gid); -    g_arch_processor_set_disassembled_instructions(proc, *disass->instrs); +    } +    g_work_queue_wait_for_completion(queue, gid); -    // plugins ////////////////////////// -    process_disassembly_event(PGA_DISASSEMBLY_RAW, disass->binary); +    gtk_status_stack_remove_activity(status, id); +    if (exe_ranges != NULL) +        free(exe_ranges); +} -    /* -    *disass->instrs = disassemble_binary_parts(disass->binary, disass->parts, disass->count, -                                               statusbar, id); -    */ +/****************************************************************************** +*                                                                             * +*  Paramètres  : disass = analyse à mener.                                    * +*                status = barre de statut à tenir informée.                   * +*                                                                             * +*  Description : Assure le désassemblage en différé.                          * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ +static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkStatusStack *status) +{ +    wgroup_id_t gid;                        /* Identifiant pour les tâches */ +    //GBinFormat *format;                     /* Format du fichier binaire   */ +    GArchProcessor *proc;                   /* Architecture du binaire     */ -    do -    { -        GBinFormat *format;                     /* Format du fichier binaire   */ -        GArchInstruction *iter;                 /* Boucle de parcours          */ +    //size_t i;                               /* Boucle de parcours          */ + +    GBinRoutine **routines;                 /* Liste des routines trouvées */ +    size_t routines_count;                  /* Nombre de ces routines      */ + -        format = G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)); -        for (iter = *disass->instrs; -             iter != NULL; -             iter = g_arch_instruction_get_next_iter(*disass->instrs, iter, 0)) -        { -            g_arch_instruction_call_hook(iter, IPH_LINK, proc, /*ctx*/NULL, format); +    gid = g_work_queue_define_work_group(get_work_queue()); -        } +    //format = G_BIN_FORMAT(g_loaded_binary_get_format(binary)); +    proc = g_loaded_binary_get_processor(disass->binary); -    } while (0); +    routines = g_binary_format_get_routines(G_BIN_FORMAT(disass->format), &routines_count); -    // plugins ////////////////////////// -    process_disassembly_event(PGA_DISASSEMBLY_HOOKED_LINK, disass->binary); +    /* Première étape */ +    //id = gtk_extended_status_bar_push(statusbar, _("Disassembling..."), true); -    //gtk_extended_status_bar_remove(statusbar, id); +    process_disassembly_event(PGA_DISASSEMBLY_STARTED, disass->binary); -    //run_plugins_on_binary(disass->binary, PGA_BINARY_DISASSEMBLED, true); -    do -    { -        GBinFormat *format;                     /* Format du fichier binaire   */ -        GArchInstruction *iter;                 /* Boucle de parcours          */ +    *disass->instrs = disassemble_binary_content(disass->binary, gid, status); +    g_arch_processor_set_disassembled_instructions(proc, *disass->instrs); -        format = G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)); -        for (iter = *disass->instrs; -             iter != NULL; -             iter = g_arch_instruction_get_next_iter(*disass->instrs, iter, 0)) -        { +    // plugins ////////////////////////// +    process_disassembly_event(PGA_DISASSEMBLY_RAW, disass->binary); -            g_arch_instruction_call_hook(iter, IPH_POST, proc, /*ctx*/NULL, format); +    process_all_instructions(gid, status, _("Calling 'link' hook on all instructions..."), +                             g_instructions_study_do_link_operation, +                             proc, disass->format); -        } + +    // plugins ////////////////////////// +    process_disassembly_event(PGA_DISASSEMBLY_HOOKED_LINK, disass->binary); + + + +    //gtk_extended_status_bar_remove(statusbar, id); +    //run_plugins_on_binary(disass->binary, PGA_BINARY_DISASSEMBLED, true); -    } while (0); +    process_all_instructions(gid, status, _("Calling 'post' hook on all instructions..."), +                             g_instructions_study_do_post_operation, +                             proc, disass->format); @@ -332,17 +414,13 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta      routines = g_binary_format_get_routines(G_BIN_FORMAT(disass->format), &routines_count); - - -    id = gtk_extended_status_bar_push(statusbar, _("Finding remaining limits..."), true); -      //qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare); -    limit_all_routines(disass->format, proc, routines, routines_count, gid, 0/*id*/); -    gtk_extended_status_bar_remove(statusbar, 0/*id*/); -    //run_plugins_on_binary(disass->binary, PGA_BINARY_BOUNDED, true); +    process_all_routines(gid, status, +                         _("Finding remaining limits..."), +                         g_routines_study_compute_limits, proc, disass->format); @@ -353,24 +431,9 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta      /* Troisième étape */ -    id = gtk_extended_status_bar_push(statusbar, _("Establishing links..."), true); - - -    /** -     * -     * Lequel choisir ??? - -G_BIN_FORMAT(disass->format) -G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary) - -     */ - - -    establish_links_between_instructions(*disass->instrs, G_BIN_FORMAT(disass->format), statusbar, 0/*id*/); - -    gtk_extended_status_bar_remove(statusbar, 0/*id*/); - -    //run_plugins_on_binary(disass->binary, PGA_BINARY_LINKED, true); +    process_all_instructions(gid, status, _("Establishing links betweek all instructions..."), +                             g_instructions_study_do_link_operation, +                             proc, disass->format); @@ -408,58 +471,11 @@ G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)      // Control-flow analysis... - - - - - - - -    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */ -    size_t exe_count;                       /* Nombre de ces zones         */ -    guint runs_count;                       /* Qté d'exécutions parallèles */ -    size_t run_size;                        /* Volume réparti par exécution*/ -    GWorkQueue *queue;                      /* Gestionnaire de différés    */ -    guint i;                                /* Boucle de parcours          */ -    size_t begin;                           /* Début de bloc de traitement */ -    size_t end;                             /* Fin d'un bloc de traitement */ -    GRoutinesStudy *study;                  /* Tâche d'étude à programmer  */ - -    exe_ranges = g_exe_format_get_x_ranges(disass->format, &exe_count); - -    runs_count = g_get_num_processors(); - -    run_size = routines_count / runs_count; - -    queue = get_work_queue(); - -    for (i = 0; i < runs_count; i++) -    { -        begin = i * run_size; - -        if ((i + 1) < runs_count) -            end = routines_count - begin; -        else -            end = begin + run_size; - -        study = g_routines_study_new(proc, exe_ranges, exe_count, routines, routines_count, begin, end, id); - -        g_work_queue_schedule_work(queue, G_DELAYED_WORK(study), gid); - -    } - -    g_work_queue_wait_for_completion(queue, gid); - -    if (exe_ranges != NULL) -        free(exe_ranges); - - - - - - - - +    /* +    process_all_routines(gid, status, +                         _("Control-flow analysis for routines..."), +                         g_routines_study_handle_blocks, proc, disass->format); +    */ @@ -510,7 +526,7 @@ G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)      proc = g_loaded_binary_get_processor(disass->binary);      print_disassembled_instructions(disass->buffer, disass->format, proc, *disass->instrs, -                                    routines, routines_count, statusbar, 0/*id*/); +                                    routines, routines_count, status, 0/*id*/);      g_object_unref(G_OBJECT(proc)); @@ -532,133 +548,6 @@ G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)  } -#if 0 -/****************************************************************************** -*                                                                             * -*  Paramètres  : disass    = analyse à mener.                                 * -*                statusbar = barre de statut à tenir informée.                * -*                                                                             * -*  Description : Assure le désassemblage en différé.                          * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_delayed_disassembly_process_old(GDelayedDisassembly *disass, GtkExtStatusBar *statusbar) -{ -#ifdef DEBUG -    unsigned int valid;                     /* Instructions traduites      */ -    unsigned int db;                        /* Instructions non décodées   */ -    unsigned int valid_sum;                 /* Instructions traduites      */ -    unsigned int instr_sum;                 /* Instructions totales        */ -    size_t i;                               /* Boucle de parcours          */ -#endif -    GBinRoutine **routines;                 /* Liste des routines trouvées */ -    size_t routines_count;                  /* Nombre de ces routines      */ -    bstatus_id_t id;                        /* Identifiant de statut       */ - -    routines = g_binary_format_get_routines(G_BIN_FORMAT(disass->format), &routines_count); - -    /* Première étape */ - -    id = gtk_extended_status_bar_push(statusbar, _("Disassembling..."), true); - -    *disass->instrs = disassemble_binary_parts(disass->binary, disass->parts, disass->count, -                                               statusbar, id); - -    gtk_extended_status_bar_remove(statusbar, id); - -#ifdef DEBUG - -    valid_sum = 0; -    instr_sum = 0; - -    for (i = 0; i < disass->count; i++) -    { -        g_binary_part_get_checkup(disass->parts[i], &valid, &db); -        valid_sum += valid; -        instr_sum += (valid + db); -    } - -    log_variadic_message(LMT_WARNING, _("Disassembled instructions : %u %% (%u / %d)"), -                         (valid_sum * 100) / instr_sum, -                         valid_sum, instr_sum); - -#endif - -    run_plugins_on_binary(disass->binary, PGA_BINARY_DISASSEMBLED, true); - -    /* Seconde étape */ - -    id = gtk_extended_status_bar_push(statusbar, _("Establishing links..."), true); - -    establish_links_between_lines(*disass->instrs, routines, routines_count, statusbar, id); - -    gtk_extended_status_bar_remove(statusbar, id); - -    run_plugins_on_binary(disass->binary, PGA_BINARY_LINKED, true); - -    /* Troisième  étape */ - -    id = gtk_extended_status_bar_push(statusbar, _("Finding remaining limits..."), true); - -    qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare); - -    limit_all_routines(*disass->instrs, routines, routines_count, statusbar, id); - -    gtk_extended_status_bar_remove(statusbar, id); - -    run_plugins_on_binary(disass->binary, PGA_BINARY_BOUNDED, true); - -    /* Quatrième étape */ - -    id = gtk_extended_status_bar_push(statusbar, _("Detecting loops..."), true); - -    detect_loops_in_code(*disass->instrs, routines, routines_count, statusbar, id); - -    gtk_extended_status_bar_remove(statusbar, id); - -    /* Cinquième étape */ - -    id = gtk_extended_status_bar_push(statusbar, _("Grouping routines instructions..."), true); - -    qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare); - -    group_routines_instructions(*disass->instrs, routines, routines_count, statusbar, id); - -    gtk_extended_status_bar_remove(statusbar, id); - -    run_plugins_on_binary(disass->binary, PGA_BINARY_GROUPED, true); - -    /* Sixième étape */ - -    id = gtk_extended_status_bar_push(statusbar, _("Ranking each instructions block..."), true); - -    qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare); - -    rank_routines_blocks(routines, routines_count, statusbar, id); - -    gtk_extended_status_bar_remove(statusbar, id); - -    run_plugins_on_binary(disass->binary, PGA_BINARY_GROUPED, true); - -    /* Septième étape */ - -    id = gtk_extended_status_bar_push(statusbar, _("Printing disassembled code..."), true); - -    qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_compare); - -    print_disassembled_instructions(disass->buffer, disass->format, *disass->instrs, -                                    routines, routines_count, statusbar, id); - -    gtk_extended_status_bar_remove(statusbar, id); - -    run_plugins_on_binary(disass->binary, PGA_BINARY_PRINTED, true); - -} -#endif  /* ---------------------------------------------------------------------------------- */ diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c index 4813111..f484f05 100644 --- a/src/analysis/disass/fetch.c +++ b/src/analysis/disass/fetch.c @@ -64,7 +64,9 @@ typedef struct _GDelayedFetching      GProcContext *ctx;                      /* Contexte de désassemblage   */      mem_area_v2 *areas;                        /* Zone de productions         */      size_t count;                           /* Nombre de ces zones         */ -    status_blob_info *info;                 /* Informations de progression */ + +    GtkStatusStack *status;                 /* Barre de statut             */ +    activity_id_t id;                       /* Groupe de progression       */      virt_t virt;                            /* Adresse de départ dépilée   */ @@ -205,6 +207,8 @@ static void g_delayed_fetching_dispose(GDelayedFetching *fetching)      g_object_unref(G_OBJECT(fetching->ctx)); +    g_object_unref(G_OBJECT(fetching->status)); +      G_OBJECT_CLASS(g_delayed_fetching_parent_class)->dispose(G_OBJECT(fetching));  } @@ -258,7 +262,11 @@ static GDelayedFetching *g_delayed_fetching_new(const GDelayedFetching *template      result->areas = template->areas;      result->count = template->count; -    result->info = template->info; + +    result->status = template->status; +    g_object_ref(G_OBJECT(result->status)); + +    result->id = template->id;      result->virt = virt; @@ -293,7 +301,7 @@ static void g_delayed_fetching_process(GDelayedFetching *fetching, GtkExtStatusB      if (area != NULL)          load_code_from_mem_area_v2(area, fetching->areas, fetching->count, -                                   fetching->ctx, &addr, fetching->info); +                                   fetching->ctx, &addr, fetching->status, fetching->id);  } @@ -467,9 +475,9 @@ static GDelayedFetching template;              /* Patron des tâches à venir  /******************************************************************************  *                                                                             * -*  Paramètres  : binary    = représentation de binaire chargé.                * -*                gid       = identifiant du groupe de travail à utiliser.     * -*                statusbar = barre de statut avec progression à mettre à jour.* +*  Paramètres  : binary = représentation de binaire chargé.                   * +*                gid    = identifiant du groupe de travail à utiliser.        * +*                status = barre de statut avec progression à mettre à jour.   *  *                                                                             *  *  Description : Procède au désassemblage basique d'un contenu binaire.       *  *                                                                             * @@ -479,7 +487,7 @@ static GDelayedFetching template;              /* Patron des tâches à venir  *                                                                             *  ******************************************************************************/ -GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, wgroup_id_t gid, GtkExtStatusBar *statusbar) +GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, wgroup_id_t gid, GtkStatusStack *status)  {      GArchInstruction *result;               /* Instruction désassemblées   */      //GDelayedFetching template;              /* Patron des tâches à venir   */ @@ -489,7 +497,6 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, wgroup      phys_t length;                          /* Taille des données à lire   */      GWorkQueue *queue;                      /* Gestionnaire de différés    */      gint remaining_counter;                 /* Quantité de points restants */ -    double done;                            /* Portion de travail accompli */      /* Constitution du modèle de référence */ @@ -508,6 +515,8 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, wgroup      template.areas = compute_memory_areas_v2(binary, length, &template.count); +    template.status = status; +      /* Amorce des traitements */      queue = get_work_queue(); @@ -528,27 +537,21 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, wgroup      g_signal_connect(template.ctx, "drop-point-pushed", G_CALLBACK(follow_execution_flow_v2), &template); -    template.info = init_progessive_status(statusbar, -                                           _("Disassembling following the execution flow..."), -                                           0, length); +    template.id = gtk_status_stack_add_activity(status, +                                                _("Disassembling following the execution flow..."), +                                                length);      g_binary_format_setup_disassembling_context(format, template.ctx);      g_work_queue_wait_for_completion(queue, gid); -    done = get_current_progessive_status(template.info); - -    fini_progessive_status(template.info); -      /**       * Seconde phase : on comble les trous laissés.       */ -    template.info = init_progessive_status(statusbar, -                                           _("Disassembling the remaining instructions..."), -                                           done, length); +    gtk_status_stack_update_activity(status, template.id, _("Disassembling the remaining instructions...")); -    ensure_all_mem_areas_are_filled(template.areas, template.count, template.ctx, template.info); +    ensure_all_mem_areas_are_filled(template.areas, template.count, template.ctx, status, template.id);      g_work_queue_wait_for_completion(queue, gid); @@ -556,20 +559,14 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, wgroup      g_object_set_data(G_OBJECT(template.ctx), "remaining_counter", NULL); -    fini_progessive_status(template.info); -      /**       * Troisième et dernière phase : récolte des fruits.       */ -    template.info = init_progessive_status(statusbar, -                                           _("Collecting disassembled instructions..."), -                                           0, length); +    gtk_status_stack_update_activity(status, template.id, _("Collecting disassembled instructions..."));      result = collect_instructions_from_mem_areas_v2(template.areas, template.count); -    fini_progessive_status(template.info); -      /* Libérations finales */      //g_object_unref(G_OBJECT(template.format)); diff --git a/src/analysis/disass/fetch.h b/src/analysis/disass/fetch.h index 37dac80..3ebb4d8 100644 --- a/src/analysis/disass/fetch.h +++ b/src/analysis/disass/fetch.h @@ -27,12 +27,12 @@  #include "../binary.h"  #include "../../glibext/delayed.h" -#include "../../gtkext/gtkextstatusbar.h" +#include "../../gtkext/gtkstatusstack.h"  /* Procède au désassemblage basique d'un contenu binaire. */ -GArchInstruction *disassemble_binary_content(const GLoadedBinary *, wgroup_id_t, GtkExtStatusBar *); +GArchInstruction *disassemble_binary_content(const GLoadedBinary *, wgroup_id_t, GtkStatusStack *); diff --git a/src/analysis/disass/instructions.c b/src/analysis/disass/instructions.c new file mode 100644 index 0000000..7e76a5d --- /dev/null +++ b/src/analysis/disass/instructions.c @@ -0,0 +1,312 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instructions.c - étude complémentaire des instructions désassemblées + * + * 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 "instructions.h" + + +#include "dragon.h" +#include "links.h" +#include "loop.h" +#include "macro.h" +#include "rank.h" +#include "../../glibext/delayed-int.h" + + + +/* Fraction d'instructions à limiter (instance) */ +struct _GInstructionsStudy +{ +    GDelayedWork parent;                    /* A laisser en premier        */ + +    GArchProcessor *proc;                   /* Processeurs avec ses instr. */ +    GBinFormat *format;                     /* Format binaire à manipuler  */ + +    ins_fallback_cb fallback;               /* Routine de traitement finale*/ +    size_t begin;                           /* Point de départ du parcours */ +    size_t end;                             /* Point d'arrivée exclu       */ + +    activity_id_t id;                       /* Identifiant pour messages   */ + +}; + +/* Fraction d'instructions à limiter (classe) */ +struct _GInstructionsStudyClass +{ +    GDelayedWorkClass parent;               /* A laisser en premier        */ + +}; + + +/* Indique le type défini pour les tâches d'étude d'instructions. */ +GType g_instructions_study_get_type(void); + +/* Initialise la classe des tâches d'étude d'instructions. */ +static void g_instructions_study_class_init(GInstructionsStudyClass *); + +/* Initialise une tâche d'étude d'instructions. */ +static void g_instructions_study_init(GInstructionsStudy *); + +/* Supprime toutes les références externes. */ +static void g_instructions_study_dispose(GInstructionsStudy *); + +/* Procède à la libération totale de la mémoire. */ +static void g_instructions_study_finalize(GInstructionsStudy *); + +/* Assure l'étude des instructions en différé. */ +static void g_instructions_study_process(GInstructionsStudy *, GtkStatusStack *); + + + +/* Indique le type défini pour les tâches d'étude d'instructions. */ +G_DEFINE_TYPE(GInstructionsStudy, g_instructions_study, G_TYPE_DELAYED_WORK); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des tâches d'étude d'instructions.      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_instructions_study_class_init(GInstructionsStudyClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GDelayedWorkClass *work;                /* Version en classe parente   */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_instructions_study_dispose; +    object->finalize = (GObjectFinalizeFunc)g_instructions_study_finalize; + +    work = G_DELAYED_WORK_CLASS(klass); + +    work->run = (run_task_fc)g_instructions_study_process; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : computing = instance à initialiser.                          * +*                                                                             * +*  Description : Initialise une tâche d'étude d'instructions.                 * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_instructions_study_init(GInstructionsStudy *study) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : computing = instance d'objet GLib à traiter.                 * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_instructions_study_dispose(GInstructionsStudy *computing) +{ +    G_OBJECT_CLASS(g_instructions_study_parent_class)->dispose(G_OBJECT(computing)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : computing = instance d'objet GLib à traiter.                 * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_instructions_study_finalize(GInstructionsStudy *computing) +{ +    G_OBJECT_CLASS(g_instructions_study_parent_class)->finalize(G_OBJECT(computing)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : proc     = ensemble d'instructions désassemblées.            * +*                format   = accès aux données du binaire d'origine.           * +*                begin    = point de départ du parcours de liste.             * +*                end      = point d'arrivée exclu du parcours.                * +*                id       = identifiant du message affiché à l'utilisateur.   * +*                fallback = routine de traitements particuliers.              * +*                                                                             * +*  Description : Crée une tâche d'étude d'instructions différée.              * +*                                                                             * +*  Retour      : Tâche créée.                                                 * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GInstructionsStudy *g_instructions_study_new(GArchProcessor *proc, GBinFormat *format, size_t begin, size_t end, activity_id_t id, ins_fallback_cb fallback) +{ +    GInstructionsStudy *result;                /* Tâche à retourner           */ + +    result = g_object_new(G_TYPE_INSTRUCTIONS_STUDY, NULL); + +    result->proc = proc; +    result->format = format; + +    result->fallback = fallback; +    result->begin = begin; +    result->end = end; + +    result->id = id; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : study  = étude d'instructions à mener.                       * +*                status = barre de statut à tenir informée.                   * +*                                                                             * +*  Description : Assure l'étude des instructions en différé.                  * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_instructions_study_process(GInstructionsStudy *study, GtkStatusStack *status) +{ +    size_t i;                               /* Boucle de parcours          */ + +    for (i = study->begin; i < study->end; i++) +    { +        study->fallback(study, i); + +        gtk_status_stack_update_activity_value(status, study->id, 1); + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : study = étude d'instructions à mener.                        * +*                index = indice de l'insruction visée.                        * +*                                                                             * +*  Description : Réalise l'appel de type IPH_LINK sur une instruction.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_instructions_study_do_link_operation(GInstructionsStudy *study, size_t index) +{ +    GArchInstruction *instr;                /* Instruction en traitement   */ + +    instr = g_arch_processor_get_disassembled_instruction(study->proc, index); + +    g_arch_instruction_call_hook(instr, IPH_LINK, study->proc, NULL, study->format); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : study = étude d'instructions à mener.                        * +*                index = indice de l'insruction visée.                        * +*                                                                             * +*  Description : Réalise l'appel de type IPH_POST sur une instruction.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_instructions_study_do_post_operation(GInstructionsStudy *study, size_t index) +{ +    GArchInstruction *instr;                /* Instruction en traitement   */ + +    instr = g_arch_processor_get_disassembled_instruction(study->proc, index); + +    g_arch_instruction_call_hook(instr, IPH_POST, study->proc, NULL, study->format); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : study = étude d'instructions à mener.                        * +*                index = indice de l'insruction visée.                        * +*                                                                             * +*  Description : Etablit les liens entres les différentes instructions.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_instructions_study_establish_links(GInstructionsStudy *study, size_t index) +{ +    GArchInstruction *instr;                /* Instruction en traitement   */ +    GArchInstruction *prev;                 /* Instruction précédente      */ + +    instr = g_arch_processor_get_disassembled_instruction(study->proc, index); + +    if (index > 0) +    { +        prev = g_arch_processor_get_disassembled_instruction(study->proc, index - 1); + +        establish_natural_link(instr, prev); + +    } + +    establish_links_for_instruction(instr, study->format, study->proc); + +} diff --git a/src/analysis/disass/instructions.h b/src/analysis/disass/instructions.h new file mode 100644 index 0000000..20b853d --- /dev/null +++ b/src/analysis/disass/instructions.h @@ -0,0 +1,68 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instructions.h - prototypes pour l'étude complémentaire des instructions désassemblées + * + * 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 _ANALYSIS_DISASS_INSTRUCTIONS_H +#define _ANALYSIS_DISASS_INSTRUCTIONS_H + + +#include "../routine.h" +#include "../../arch/processor.h" +#include "../../format/executable.h" +#include "../../gtkext/gtkstatusstack.h" + + + +#define G_TYPE_INSTRUCTIONS_STUDY               g_instructions_study_get_type() +#define G_INSTRUCTIONS_STUDY(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_instructions_study_get_type(), GInstructionsStudy)) +#define G_IS_INSTRUCTIONS_STUDY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_instructions_study_get_type())) +#define G_INSTRUCTIONS_STUDY_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_INSTRUCTIONS_STUDY, GInstructionsStudyClass)) +#define G_IS_INSTRUCTIONS_STUDY_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_INSTRUCTIONS_STUDY)) +#define G_INSTRUCTIONS_STUDY_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_INSTRUCTIONS_STUDY, GInstructionsStudyClass)) + + +/* Fraction d'instructions à limiter (instance) */ +typedef struct _GInstructionsStudy GInstructionsStudy; + +/* Fraction d'instructions à limiter (classe) */ +typedef struct _GInstructionsStudyClass GInstructionsStudyClass; + + +/* Assure l'étude d'instructions en différé. */ +typedef void (* ins_fallback_cb) (GInstructionsStudy *, size_t); + + +/* Crée une tâche d'étude de instructions différée. */ +GInstructionsStudy *g_instructions_study_new(GArchProcessor *, GBinFormat *, size_t, size_t, activity_id_t, ins_fallback_cb); + +/* Réalise l'appel de type IPH_LINK sur une instruction. */ +void g_instructions_study_do_link_operation(GInstructionsStudy *, size_t); + +/* Réalise l'appel de type IPH_POST sur une instruction. */ +void g_instructions_study_do_post_operation(GInstructionsStudy *, size_t); + +/* Etablit les liens entres les différentes instructions. */ +void g_instructions_study_establish_links(GInstructionsStudy *, size_t); + + + +#endif  /* _ANALYSIS_DISASS_INSTRUCTIONS_H */ diff --git a/src/analysis/disass/limit.c b/src/analysis/disass/limit.c index 4fd931d..dba62cc 100644 --- a/src/analysis/disass/limit.c +++ b/src/analysis/disass/limit.c @@ -24,209 +24,10 @@  #include "limit.h" -#include <malloc.h> - - -#include "../../glibext/delayed-int.h" - - - -/* ------------------------- CALCULS DE LIMITES DE ROUTINES ------------------------- */ - - -#define G_TYPE_LIMIT_COMPUTING               g_limit_computing_get_type() -#define G_LIMIT_COMPUTING(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_limit_computing_get_type(), GLimitComputing)) -#define G_IS_LIMIT_COMPUTING(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_limit_computing_get_type())) -#define G_LIMIT_COMPUTING_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LIMIT_COMPUTING, GLimitComputingClass)) -#define G_IS_LIMIT_COMPUTING_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LIMIT_COMPUTING)) -#define G_LIMIT_COMPUTING_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LIMIT_COMPUTING, GLimitComputingClass)) - - -/* Fraction de routines à limiter (instance) */ -typedef struct _GLimitComputing -{ -    GDelayedWork parent;                    /* A laisser en premier        */ - -    const GArchProcessor *proc;             /* Processeurs avec ses instr. */ - -    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */ -    size_t exe_count;                       /* Nombre de ces zones         */ - -    GBinRoutine **routines;                 /* Liste de routines à traiter */ -    size_t count;                           /* Taille de cette liste       */ -    size_t begin;                           /* Point de départ du parcours */ -    size_t end;                             /* Point d'arrivée exclu       */ - -    bstatus_id_t id;                        /* Identifiant pour messages   */ - -} GLimitComputing; - -/* Fraction de routines à limiter (classe) */ -typedef struct _GLimitComputingClass -{ -    GDelayedWorkClass parent;               /* A laisser en premier        */ - -} GLimitComputingClass; - - -/* Indique le type défini pour les tâches de calculs de limites. */ -GType g_limit_computing_get_type(void); - -/* Initialise la classe des tâches de calculs de limites. */ -static void g_limit_computing_class_init(GLimitComputingClass *); - -/* Initialise une tâche de calculs de limites. */ -static void g_limit_computing_init(GLimitComputing *); - -/* Supprime toutes les références externes. */ -static void g_limit_computing_dispose(GLimitComputing *); - -/* Procède à la libération totale de la mémoire. */ -static void g_limit_computing_finalize(GLimitComputing *); - -/* Crée une tâche de calculs de limites différée. */ -static GLimitComputing *g_limit_computing_new(const GArchProcessor *, mrange_t *, size_t, GBinRoutine **, size_t, size_t, size_t, bstatus_id_t);  /* Recherche la zone correspond à une adresse donnée. */  static const mrange_t *find_x_range_for_addr(const mrange_t *, size_t, const vmpa2t *); -/* Assure le calcul de limites de routines en différé. */ -static void g_limit_computing_process(GLimitComputing *, GtkExtStatusBar *); - - - -/* ---------------------------------------------------------------------------------- */ -/*                           CALCULS DE LIMITES DE ROUTINES                           */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type défini pour les tâches de calculs de limites. */ -G_DEFINE_TYPE(GLimitComputing, g_limit_computing, G_TYPE_DELAYED_WORK); - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : klass = classe à initialiser.                                * -*                                                                             * -*  Description : Initialise la classe des tâches de calculs de limites.       * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_limit_computing_class_init(GLimitComputingClass *klass) -{ -    GObjectClass *object;                   /* Autre version de la classe  */ -    GDelayedWorkClass *work;                /* Version en classe parente   */ - -    object = G_OBJECT_CLASS(klass); - -    object->dispose = (GObjectFinalizeFunc/* ! */)g_limit_computing_dispose; -    object->finalize = (GObjectFinalizeFunc)g_limit_computing_finalize; - -    work = G_DELAYED_WORK_CLASS(klass); - -    work->run = (run_task_fc)g_limit_computing_process; - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : computing = instance à initialiser.                          * -*                                                                             * -*  Description : Initialise une tâche de calculs de limites.                  * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_limit_computing_init(GLimitComputing *computing) -{ - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : computing = instance d'objet GLib à traiter.                 * -*                                                                             * -*  Description : Supprime toutes les références externes.                     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_limit_computing_dispose(GLimitComputing *computing) -{ -    G_OBJECT_CLASS(g_limit_computing_parent_class)->dispose(G_OBJECT(computing)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : computing = instance d'objet GLib à traiter.                 * -*                                                                             * -*  Description : Procède à la libération totale de la mémoire.                * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static void g_limit_computing_finalize(GLimitComputing *computing) -{ -    G_OBJECT_CLASS(g_limit_computing_parent_class)->finalize(G_OBJECT(computing)); - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : proc     = ensemble d'instructions désassemblées.            * -*                routines = prototypes existants à insérer.                   * -*                count    = quantité de ces prototypes.                       * -*                begin    = point de départ du parcours de liste.             * -*                end      = point d'arrivée exclu du parcours.                * -*                id       = identifiant du message affiché à l'utilisateur.   * -*                                                                             * -*  Description : Crée une tâche de calculs de limites différée.               * -*                                                                             * -*  Retour      : Tâche créée.                                                 * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static GLimitComputing *g_limit_computing_new(const GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count, GBinRoutine **routines, size_t count, size_t begin, size_t end, bstatus_id_t id) -{ -    GLimitComputing *result;                /* Tâche à retourner           */ - -    result = g_object_new(G_TYPE_LIMIT_COMPUTING, NULL); - -    result->proc = proc; - -    result->exe_ranges = exe_ranges; -    result->exe_count = exe_count; - -    result->routines = routines; -    result->count = count; -    result->begin = begin; -    result->end = end; - -    result->id = id; - -    return result; - -}  /****************************************************************************** @@ -260,163 +61,71 @@ static const mrange_t *find_x_range_for_addr(const mrange_t *ranges, size_t coun  /******************************************************************************  *                                                                             * -*  Paramètres  : computing  = récupération à mener.                           * -*                statusbar = barre de statut à tenir informée.                * +*  Paramètres  : proc     = ensemble d'instructions désassemblées.            * +*                routines = prototypes existants à insérer.                   * +*                count    = quantité de ces prototypes.                       * +*                begin    = point de départ du parcours de liste.             * +*                end      = point d'arrivée exclu du parcours.                * +*                id       = identifiant du message affiché à l'utilisateur.   *  *                                                                             * -*  Description : Assure le calcul de limites de routines en différé.          * +*  Description : S'assure qu'une routine est bien bornée.                     *  *                                                                             * -*  Retour      : -                                                            * +*  Retour      : Tâche créée.                                                 *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static void g_limit_computing_process(GLimitComputing *computing, GtkExtStatusBar *statusbar) +void compute_routine_limit(GBinRoutine *routine, GBinRoutine *prev, const GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count)  { -    size_t i;                               /* Boucle de parcours          */ -    GBinRoutine *routine;                   /* Routine en traitement       */      const mrange_t *range;                  /* Emplacement courant         */      vmpa2t addr;                            /* Adresse à conserver         */      GArchInstruction *start;                /* Première instruction        */      phys_t diff;                            /* Taille définie par déduction*/      mrange_t new;                           /* Nouvel emplacement taillé   */ -    for (i = computing->begin; i < computing->end; i++) -    { -        //gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count); - -        routine = computing->routines[i]; - -        range = g_binary_routine_get_range(routine); -        if (get_mrange_length(range) > 0) continue; +    range = g_binary_routine_get_range(routine); +    if (get_mrange_length(range) > 0) goto crl_skip; -        copy_vmpa(&addr, get_mrange_addr(range)); +    copy_vmpa(&addr, get_mrange_addr(range)); -        /* Marquage de la première instruction */ +    /* Marquage de la première instruction */ -        start = g_arch_processor_find_instr_by_address(computing->proc, &addr); +    start = g_arch_processor_find_instr_by_address(proc, &addr); -        if (start == NULL) continue; +    /* FIXME ? */ +    if (start == NULL) goto crl_skip; -        g_arch_instruction_set_flag(start, AIF_ROUTINE_START); +    g_arch_instruction_set_flag(start, AIF_ROUTINE_START); -        /* Si on peut se raccrocher à la routine suivante... */ -        if ((i + 1) < computing->count) -        { -            range = g_binary_routine_get_range(computing->routines[i + 1]); - -            diff = compute_vmpa_diff(&addr, get_mrange_addr(range)); - -        } - -        /* Sinon on va jusqu'à la fin de la zone ! */ -        else -        { -            range = find_x_range_for_addr(computing->exe_ranges, computing->exe_count, &addr); -            if (range == NULL) continue; - -            diff = compute_vmpa_diff(&addr, get_mrange_addr(range)); -            diff = get_mrange_length(range) - diff; - -        } - -        init_mrange(&new, &addr, diff); - -        g_binary_routine_set_range(routine, &new); - -    } - -} - - - -/* ---------------------------------------------------------------------------------- */ -/*                            POINT D'ENTREE ET DECOUPAGES                            */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : format   = format du binaire concerné par la procédure.      * -*                proc     = ensemble d'instructions désassemblées.            * -*                routines = prototypes existants à insérer.                   * -*                count    = quantité de ces prototypes.                       * -*                gid      = identifiant du groupe de travail à utiliser.      * -*                id       = identifiant du message affiché à l'utilisateur.   * -*                                                                             * -*  Description : S'assure que toutes les routines ont une taille définie.     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void limit_all_routines(GExeFormat *format, const GArchProcessor *proc, GBinRoutine **routines, size_t count, wgroup_id_t gid, bstatus_id_t id) -{ -    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */ -    size_t exe_count;                       /* Nombre de ces zones         */ -    guint runs_count;                       /* Qté d'exécutions parallèles */ -    size_t run_size;                        /* Volume réparti par exécution*/ -    GWorkQueue *queue;                      /* Gestionnaire de différés    */ -    guint i;                                /* Boucle de parcours          */ -    size_t begin;                           /* Début de bloc de traitement */ -    size_t end;                             /* Fin d'un bloc de traitement */ -    GLimitComputing *computing;             /* Tâche de calcul à programmer*/ - -    exe_ranges = g_exe_format_get_x_ranges(format, &exe_count); - -    runs_count = g_get_num_processors(); - -    run_size = count / runs_count; - -    queue = get_work_queue(); - -    for (i = 0; i < runs_count; i++) +    /* Si on peut se raccrocher à la routine suivante... */ +    if (prev != NULL)      { -        begin = i * run_size; - -        if ((i + 1) < runs_count) -            end = count - begin; -        else -            end = begin + run_size; +        range = g_binary_routine_get_range(prev); -        computing = g_limit_computing_new(proc, exe_ranges, exe_count, routines, count, begin, end, id); - -        g_work_queue_schedule_work(queue, G_DELAYED_WORK(computing), gid); +        diff = compute_vmpa_diff(&addr, get_mrange_addr(range));      } -    g_work_queue_wait_for_completion(queue, gid); - -    if (exe_ranges != NULL) -        free(exe_ranges); - - - - -    do +    /* Sinon on va jusqu'à la fin de la zone ! */ +    else      { -        const mrange_t *_range; -        vmpa2t _end; +        range = find_x_range_for_addr(exe_ranges, exe_count, &addr); +        if (range == NULL) goto crl_skip; -        printf("LIMIT == %zu routines\n", count); +        diff = compute_vmpa_diff(&addr, get_mrange_addr(range)); +        diff = get_mrange_length(range) - diff; -        for (i = 0; i < count; i++) -        { -            _range = g_binary_routine_get_range(routines[i]); -            compute_mrange_end_addr(_range, &_end); +    } -            printf(" <LIMIT> 0x%08x <-> 0x%08x '%s'\n", -                   (unsigned int)((get_mrange_addr(_range))->virtual), -                   (unsigned int)_end.virtual, -                   g_binary_routine_to_string(routines[i])); +    init_mrange(&new, &addr, diff); -        } +    g_binary_routine_set_range(routine, &new); -    } while (0); + crl_skip: +    ;  } diff --git a/src/analysis/disass/limit.h b/src/analysis/disass/limit.h index 2fa3303..434d4e8 100644 --- a/src/analysis/disass/limit.h +++ b/src/analysis/disass/limit.h @@ -28,16 +28,11 @@  #include "../routine.h"  #include "../../arch/processor.h"  #include "../../format/executable.h" -#include "../../glibext/delayed.h" -#include "../../gtkext/gtkextstatusbar.h" -/* -------------------------- POINT D'ENTREE ET DECOUPAGES -------------------------- */ - - -/* S'assure que toutes les routines ont une taille définie. */ -void limit_all_routines(GExeFormat *, const GArchProcessor *, GBinRoutine **, size_t, wgroup_id_t, bstatus_id_t); +/* S'assure qu'une routine est bien bornée. */ +void compute_routine_limit(GBinRoutine *, GBinRoutine *, const GArchProcessor *, mrange_t *, size_t); diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c index 5e1e483..86663cc 100644 --- a/src/analysis/disass/links.c +++ b/src/analysis/disass/links.c @@ -31,11 +31,8 @@ -/* Rétablit un lien naturel coupé par un autre lien. */ -static void establish_natural_link(GArchInstruction *, GArchInstruction *); -  /* Complète un désassemblage accompli pour une instruction. */ -static void convert_immediate_into_target(GArchInstruction *, size_t, GBinFormat *); +static void convert_immediate_into_target(GArchInstruction *, size_t, const GBinFormat *); @@ -52,7 +49,7 @@ static void convert_immediate_into_target(GArchInstruction *, size_t, GBinFormat  *                                                                             *  ******************************************************************************/ -static void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev) +void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev)  {      GArchInstruction **others;              /* Instructions diverses liées */      InstructionLinkType *types;             /* Types de lien existants     */ @@ -126,7 +123,7 @@ static void establish_natural_link(GArchInstruction *instr, GArchInstruction *pr  *                                                                             *  ******************************************************************************/ -static void convert_immediate_into_target(GArchInstruction *instr, size_t index, GBinFormat *format) +static void convert_immediate_into_target(GArchInstruction *instr, size_t index, const GBinFormat *format)  {      GArchOperand *op;                       /* Opérande numérique en place */      GImmOperand *imm;                       /* Version native de l'opérande*/ @@ -160,8 +157,8 @@ static void convert_immediate_into_target(GArchInstruction *instr, size_t index,  /******************************************************************************  *                                                                             *  *  Paramètres  : instr  = instruction désassemblée à traiter.                 * -*                list   = ensemble d'instructions à relier.                   *  *                format = accès aux données du binaire d'origine.             * +*                proc   = ensemble d'instructions à relier.                   *  *                                                                             *  *  Description : Complète un désassemblage accompli pour une instruction.     *  *                                                                             * @@ -171,7 +168,7 @@ static void convert_immediate_into_target(GArchInstruction *instr, size_t index,  *                                                                             *  ******************************************************************************/ -static void establish_links_for_instruction(GArchInstruction *instr, GArchInstruction *list, GBinFormat *format) +void establish_links_for_instruction(GArchInstruction *instr, const GBinFormat *format, const GArchProcessor *proc)  {      bool skip;                              /* Saut des conversions        */      size_t count;                           /* Nombre d'opérandes présents */ @@ -199,7 +196,7 @@ static void establish_links_for_instruction(GArchInstruction *instr, GArchInstru          virt = g_target_operand_get_addr(G_TARGET_OPERAND(op));          init_vmpa(&addr, VMPA_NO_PHYSICAL, virt); -        target = g_arch_instruction_find_by_address(list, &addr, true); +        target = g_arch_processor_find_instr_by_address(proc, &addr);          if (target != NULL)              g_arch_instruction_link_with(instr, target, ILT_REF); @@ -207,42 +204,3 @@ static void establish_links_for_instruction(GArchInstruction *instr, GArchInstru      }  } - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : list      = ensemble d'instructions à relier.                * -*                format    = accès aux données du binaire d'origine.          * -*                statusbar = barre de statut avec progression à mettre à jour.* -*                id        = identifiant du message affiché à l'utilisateur.  * -*                                                                             * -*  Description : Etablit les liens entres les différentes lignes de code.     * -*                                                                             * -*  Retour      : -                                                            * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -void establish_links_between_instructions(GArchInstruction *list, GBinFormat *format, GtkExtStatusBar *statusbar, bstatus_id_t id) -{ -    GArchInstruction *prev;                 /* Itération précédente        */ -    GArchInstruction *iter;                 /* Boucle de parcours          */ - -    prev = NULL; - -    for (iter = list; -         iter != NULL; -         iter = g_arch_instruction_get_next_iter(list, iter, ~0/* FIXME */)) -    { -        if (prev != NULL) -            establish_natural_link(iter, prev); - -        prev = iter; - -        establish_links_for_instruction(iter, list, format); - - -    } - -} diff --git a/src/analysis/disass/links.h b/src/analysis/disass/links.h index f4092f9..b1f5a71 100644 --- a/src/analysis/disass/links.h +++ b/src/analysis/disass/links.h @@ -25,22 +25,17 @@  #define _ANALYSIS_DISASS_LINKS_H -//#include "../routine.h"  #include "../../arch/instruction.h" +#include "../../arch/processor.h"  #include "../../format/format.h" -#include "../../gtkext/gtkextstatusbar.h" +/* Rétablit un lien naturel coupé par un autre lien. */ +void establish_natural_link(GArchInstruction *, GArchInstruction *); -/* Etablit les liens entres les différentes lignes de code. */ -void establish_links_between_instructions(GArchInstruction *, GBinFormat *, GtkExtStatusBar *, bstatus_id_t); - - - - -/* Etablit les liens entres les différentes lignes de code. */ -//void establish_links_between_lines(GArchInstruction *, GBinRoutine **, size_t, GtkExtStatusBar *, bstatus_id_t); +/* Complète un désassemblage accompli pour une instruction. */ +void establish_links_for_instruction(GArchInstruction *, const GBinFormat *, const GArchProcessor *); diff --git a/src/analysis/disass/routines.c b/src/analysis/disass/routines.c index 280757a..3e0aa71 100644 --- a/src/analysis/disass/routines.c +++ b/src/analysis/disass/routines.c @@ -25,6 +25,7 @@  #include "dragon.h" +#include "limit.h"  #include "loop.h"  #include "macro.h"  #include "rank.h" @@ -44,6 +45,8 @@ struct _GRoutinesStudy      GBinRoutine **routines;                 /* Liste de routines à traiter */      size_t count;                           /* Taille de cette liste       */ + +    rtn_fallback_cb fallback;               /* Routine de traitement finale*/      size_t begin;                           /* Point de départ du parcours */      size_t end;                             /* Point d'arrivée exclu       */ @@ -176,6 +179,7 @@ static void g_routines_study_finalize(GRoutinesStudy *computing)  *                begin    = point de départ du parcours de liste.             *  *                end      = point d'arrivée exclu du parcours.                *  *                id       = identifiant du message affiché à l'utilisateur.   * +*                fallback = routine de traitements particuliers.              *  *                                                                             *  *  Description : Crée une tâche d'étude de routines différée.                 *  *                                                                             * @@ -185,7 +189,7 @@ static void g_routines_study_finalize(GRoutinesStudy *computing)  *                                                                             *  ******************************************************************************/ -GRoutinesStudy *g_routines_study_new(const GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count, GBinRoutine **routines, size_t count, size_t begin, size_t end, activity_id_t id) +GRoutinesStudy *g_routines_study_new(const GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count, GBinRoutine **routines, size_t count, size_t begin, size_t end, activity_id_t id, rtn_fallback_cb fallback)  {      GRoutinesStudy *result;                /* Tâche à retourner           */ @@ -198,6 +202,8 @@ GRoutinesStudy *g_routines_study_new(const GArchProcessor *proc, mrange_t *exe_r      result->routines = routines;      result->count = count; + +    result->fallback = fallback;      result->begin = begin;      result->end = end; @@ -224,55 +230,90 @@ GRoutinesStudy *g_routines_study_new(const GArchProcessor *proc, mrange_t *exe_r  static void g_routines_study_process(GRoutinesStudy *study, GtkStatusStack *status)  {      size_t i;                               /* Boucle de parcours          */ -    GBinRoutine *routine;                   /* Routine en traitement       */ -    const mrange_t *range;                  /* Couverture d'une routine    */ -    const vmpa2t *start;                    /* Adresse de départ           */ -    const instr_coverage *coverage;         /* Instructions couvertes      */ -    dragon_knight *knight;                  /* Complexité de code posée    */ -    //dragon_node *nodes;                     /* Liste des noeuds détectés   */ -    //size_t count;                           /* Taille de cette liste       */      for (i = study->begin; i < study->end; i++)      { -        //gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count); - -        routine = study->routines[i]; +        study->fallback(study, i); -        /* Préparatifs communs */ +        gtk_status_stack_update_activity_value(status, study->id, 1); -        range = g_binary_routine_get_range(routine); -        start = get_mrange_addr(range); - -        coverage = g_arch_processor_find_coverage_by_address(study->proc, start); +    } -        knight = begin_dragon_knight(study->proc, coverage, range, start); +} +/****************************************************************************** +*                                                                             * +*  Paramètres  : study = étude de routines à mener.                           * +*                index = indice de l'insruction visée.                        * +*                                                                             * +*  Description : Détermine si besoin est les bornes des routines.             * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ +void g_routines_study_compute_limits(GRoutinesStudy *study, size_t index) +{ +    GBinRoutine *routine;                   /* Routine à traiter           */ +    GBinRoutine *next;                      /* Routine suivante éventuelle */ -        detect_loops_in_code(knight); +    routine = study->routines[index]; +    if ((index + 1) < study->count) +        next = study->routines[index + 1]; +    else +        next = NULL; +    compute_routine_limit(routine, next, study->proc, study->exe_ranges, study->exe_count); -        /* Phase AAAA : regroupement des instructions par blocs */ +} +/****************************************************************************** +*                                                                             * +*  Paramètres  : study = étude de routines à mener.                           * +*                index = indice de l'insruction visée.                        * +*                                                                             * +*  Description : Procède au traitement des blocs de routines.                 * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ +void g_routines_study_handle_blocks(GRoutinesStudy *study, size_t index) +{ +    GBinRoutine *routine;                   /* Routine à traiter           */ +    const mrange_t *range;                  /* Couverture d'une routine    */ +    const vmpa2t *start;                    /* Adresse de départ           */ +    const instr_coverage *coverage;         /* Instructions couvertes      */ +    dragon_knight *knight;                  /* Complexité de code posée    */ -        group_routine_instructions(routine, knight); +    routine = study->routines[index]; +    /* Préparatifs communs */ +    range = g_binary_routine_get_range(routine); +    start = get_mrange_addr(range); +    coverage = g_arch_processor_find_coverage_by_address(study->proc, start); +    knight = begin_dragon_knight(study->proc, coverage, range, start); -        rank_routine_blocks(routine); +    /* Traitement par blocs */ +    detect_loops_in_code(knight); +    group_routine_instructions(routine, knight); -        /* Nettoyage final */ +    rank_routine_blocks(routine); -        end_dragon_knight(knight); +    /* Nettoyage final */ -    } +    end_dragon_knight(knight);  } diff --git a/src/analysis/disass/routines.h b/src/analysis/disass/routines.h index 7e01928..f85affe 100644 --- a/src/analysis/disass/routines.h +++ b/src/analysis/disass/routines.h @@ -47,8 +47,18 @@ typedef struct _GRoutinesStudy GRoutinesStudy;  typedef struct _GRoutinesStudyClass GRoutinesStudyClass; +/* Assure l'étude des routines en différé. */ +typedef void (* rtn_fallback_cb) (GRoutinesStudy *, size_t); + +  /* Crée une tâche d'étude de routines différée. */ -GRoutinesStudy *g_routines_study_new(const GArchProcessor *, mrange_t *, size_t, GBinRoutine **, size_t, size_t, size_t, activity_id_t); +GRoutinesStudy *g_routines_study_new(const GArchProcessor *, mrange_t *, size_t, GBinRoutine **, size_t, size_t, size_t, activity_id_t, rtn_fallback_cb); + +/* Détermine si besoin est les bornes des routines. */ +void g_routines_study_compute_limits(GRoutinesStudy *, size_t); + +/* Procède au traitement des blocs de routines. */ +void g_routines_study_handle_blocks(GRoutinesStudy *, size_t); diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c index e066bb0..0692cea 100644 --- a/src/arch/arm/v7/post.c +++ b/src/arch/arm/v7/post.c @@ -57,6 +57,10 @@ void post_process_branch_instructions(GArchInstruction *instr, GArchProcessor *p      op = g_arch_instruction_get_operand(instr, 0); + +    if (!G_IS_IMM_OPERAND(op)) return; + +      if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr)          && g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), addr, &target))      { @@ -121,6 +125,10 @@ void post_process_branch_and_link_instructions(GArchInstruction *instr, GArchPro      op = g_arch_instruction_get_operand(instr, 0); + +    if (!G_IS_IMM_OPERAND(op)) return; + +      if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr)          && g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), addr, &target))      { @@ -195,6 +203,10 @@ void post_process_comp_and_branch_instructions(GArchInstruction *instr, GArchPro      op = g_arch_instruction_get_operand(instr, 1); + +    if (!G_IS_IMM_OPERAND(op)) return; + +      if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr)          && g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), addr, &target))      { diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 0db68c7..d75cf54 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -248,7 +248,8 @@ GArchInstruction *g_arch_instruction_get_next_iter(const GArchInstruction *, con  GArchInstruction *g_arch_instruction_find_by_range(GArchInstruction *, const mrange_t *);  /* Recherche une instruction d'après son adresse. */ -GArchInstruction *g_arch_instruction_find_by_address(GArchInstruction *, const vmpa2t *, bool); +GArchInstruction *g_arch_instruction_find_by_address(GArchInstruction *, const vmpa2t *, bool) __attribute__ ((deprecated)); +/* -> g_arch_processor_find_instr_by_address */ diff --git a/src/arch/processor.c b/src/arch/processor.c index 21db869..da5ddce 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -520,6 +520,58 @@ GArchInstruction *g_arch_processor_get_disassembled_instructions(const GArchProc  /******************************************************************************  *                                                                             * +*  Paramètres  : proc = architecture visée par la procédure.                  * +*                index = indice de l'instruction visée.                       * +*                                                                             * +*  Description : Fournit une instruction désassemblée pour une architecture.  * +*                                                                             * +*  Retour      : Instructions désassemblée trouvée ou NULL si aucune.         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchInstruction *g_arch_processor_get_disassembled_instruction(const GArchProcessor *proc, size_t index) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ + +    if (proc->instr_count == 0) +        result = NULL; + +    else +    { +        assert(index < proc->instr_count); + +        result = proc->instructions[index]; + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : proc = architecture visée par la procédure.                  * +*                                                                             * +*  Description : Compte le nombre d'instructions représentées.                * +*                                                                             * +*  Retour      : Nombre d'instructions présentes.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +size_t g_arch_processor_count_disassembled_instructions(const GArchProcessor *proc) +{ +    return proc->instr_count; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : proc   = processeur recensant diverses instructions.         *  *                addr   = position en mémoire ou physique à chercher.         *  *                nearby = la recherche s'effectue-t-elle de façon stricte ?   * diff --git a/src/arch/processor.h b/src/arch/processor.h index 82c4f18..9dee9f6 100644 --- a/src/arch/processor.h +++ b/src/arch/processor.h @@ -91,6 +91,12 @@ void g_arch_processor_set_disassembled_instructions(GArchProcessor *, GArchInstr  /* Fournit les instructions désassemblées pour une architecture. */  GArchInstruction *g_arch_processor_get_disassembled_instructions(const GArchProcessor *); +/* Fournit une instruction désassemblée pour une architecture. */ +GArchInstruction *g_arch_processor_get_disassembled_instruction(const GArchProcessor *, size_t); + +/* Compte le nombre d'instructions représentées. */ +size_t g_arch_processor_count_disassembled_instructions(const GArchProcessor *); +  /* Recherche un groupe d'instruction d'après son adresse. */  const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProcessor *, const vmpa2t *); diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c index 9177399..880f4ed 100644 --- a/src/gtkext/gtkstatusstack.c +++ b/src/gtkext/gtkstatusstack.c @@ -134,7 +134,11 @@ typedef struct _progress_status      activity_id_t id;                       /* Identifiant unique          */      char *message;                          /* Indication à faire valoir   */ -    double value;                           /* Centième de pourcentage     */ + +    unsigned long current;                  /* Position courante           */ +    unsigned long max;                      /* Couverture à parcourir      */ + +    double last_updated;                    /* Dernière valeur poussée     */  } progress_status; @@ -802,6 +806,7 @@ static GtkWidget *build_progress_status_stack(GtkStatusStack *stack)      progress = gtk_progress_bar_new();      g_object_set_data(ref, "progress", progress);      gtk_widget_set_size_request(progress, 200, -1); +    gtk_widget_set_valign(progress, GTK_ALIGN_CENTER);      gtk_widget_show(progress);      gtk_box_pack_start(GTK_BOX(result), progress, FALSE, TRUE, 8); @@ -817,7 +822,7 @@ static GtkWidget *build_progress_status_stack(GtkStatusStack *stack)  *                                                                             *  *  Paramètres  : stack = barre de statut à actualiser.                        *  *                msg   = nouveau message de statut à copier.                  * -*                value = nouvelle valeur pour une progression donnée.         * +*                max   = taille de la plage à parcourir.                      *  *                                                                             *  *  Description : Démarre le suivi d'une nouvelle activité.                    *  *                                                                             * @@ -827,7 +832,7 @@ static GtkWidget *build_progress_status_stack(GtkStatusStack *stack)  *                                                                             *  ******************************************************************************/ -activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *msg, double value) +activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *msg, unsigned long max)  {      activity_id_t result;                   /* Numéro unique à renvoyer    */      progress_info *info;                    /* Informations à consulter    */ @@ -844,7 +849,7 @@ activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *m      info->statuses = (progress_status *)realloc(info->statuses,                                                  info->count * sizeof(progress_status)); -    info->statuses[new].id = new; +    info->statuses[new].id = result;      /* Intitulé */ @@ -855,7 +860,8 @@ activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *m      /* Valeur */ -    info->statuses[new].value = value; +    info->statuses[new].current = 0; +    info->statuses[new].max = max;      /* Actualisation */ @@ -876,7 +882,6 @@ 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.                  *  *                msg   = nouveau message de statut à copier.                  * -*                value = nouvelle valeur pour une progression donnée.         *  *                                                                             *  *  Description : Actualise les informations concernant une activité.          *  *                                                                             * @@ -886,7 +891,7 @@ activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *m  *                                                                             *  ******************************************************************************/ -void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, const char *msg, double value) +void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, const char *msg)  {      progress_info *info;                    /* Informations à consulter    */      size_t i;                               /* Boucle de parcours          */ @@ -923,15 +928,9 @@ void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, c          else              info->statuses[i].message = strdup(msg); -        /* Valeur */ - -        old = info->statuses[i].value; - -        info->statuses[i].value = value; -          /* On n'actualise que le sommet de la pile */ -        if ((i + 1) == info->count && (msg_changed || (value - old) > 1.0)) +        if ((i + 1) == info->count)          {              if (info->tag != 0)                  g_source_remove(info->tag); @@ -951,7 +950,7 @@ void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, c  *                                                                             *  *  Paramètres  : stack = barre de statut à actualiser.                        *  *                id    = identifiant de l'activité à cibler.                  * -*                value = nouvelle valeur pour une progression donnée.         * +*                inc   = nouvelle valeur pour une progression donnée.         *  *                                                                             *  *  Description : Actualise la progression d'une activité.                     *  *                                                                             * @@ -961,11 +960,13 @@ void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, c  *                                                                             *  ******************************************************************************/ -void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t id, double value) +void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t id, unsigned long inc)  {      progress_info *info;                    /* Informations à consulter    */      size_t i;                               /* Boucle de parcours          */ -    double old;                             /* Conservation pour la diff.  */ +    progress_status *status;                /* Raccourci de confort        */ +    double old;                             /* Ancienne progression        */ +    double new;                             /* Nouvelle progression        */      info = stack->prog_info; @@ -977,15 +978,21 @@ void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t      if (i < info->count)      { +        status = &info->statuses[i]; +          /* Valeur */ -        old = info->statuses[i].value; +        status->current += inc; -        info->statuses[i].value = value; +        new = (status->current * 1.0) / status->max;          /* On n'actualise que le sommet de la pile */ -        if ((i + 1) == info->count && (value - old) > 1.0) + +        //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); @@ -1099,7 +1106,7 @@ static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *stack)              last = &info->statuses[info->count - 1];              progress = GTK_PROGRESS_BAR(g_object_get_data(ref, "progress")); -            gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), last->value); +            gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), (last->current * 1.0) / last->max);              label = GTK_LABEL(g_object_get_data(ref, "message"));              gtk_label_set_text(label, last->message); diff --git a/src/gtkext/gtkstatusstack.h b/src/gtkext/gtkstatusstack.h index afc3213..590f562 100644 --- a/src/gtkext/gtkstatusstack.h +++ b/src/gtkext/gtkstatusstack.h @@ -77,13 +77,13 @@ 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 *, double); +activity_id_t gtk_status_stack_add_activity(GtkStatusStack *, const char *, unsigned long);  /* Actualise les informations concernant une activité. */ -void gtk_status_stack_update_activity(GtkStatusStack *, activity_id_t, const char *, double); +void gtk_status_stack_update_activity(GtkStatusStack *, activity_id_t, const char *);  /* Actualise la progression d'une activité. */ -void gtk_status_stack_update_activity_value(GtkStatusStack *, activity_id_t, double); +void gtk_status_stack_update_activity_value(GtkStatusStack *, activity_id_t, unsigned long);  /* Met fin au suivi d'une activité donnée. */  void gtk_status_stack_remove_activity(GtkStatusStack *, activity_id_t); @@ -165,7 +165,7 @@ int main(int argc, char **argv)      editor = create_editor(); -    gtk_widget_show(editor); +    gtk_widget_show_now(editor);      init_work_queue(G_OBJECT(editor)); @@ -181,13 +181,22 @@ int main(int argc, char **argv)      /* Charge le dernier projet */ -    if (!g_generic_config_get_value(config, MPK_LAST_PROJECT, &filename)) -        filename = NULL; +    gboolean load_last_project(GGenConfig *cfg) +    { + +        if (!g_generic_config_get_value(cfg, MPK_LAST_PROJECT, &filename)) +            filename = NULL; + +        if (filename == NULL) project = g_study_project_new(G_OBJECT(editor)); +        else project = g_study_project_open(G_OBJECT(editor), filename); -    if (filename == NULL) project = g_study_project_new(G_OBJECT(editor)); -    else project = g_study_project_open(G_OBJECT(editor), filename); +        set_current_project(project); + +        return G_SOURCE_REMOVE; + +    } -    set_current_project(project); +    g_idle_add((GSourceFunc)load_last_project, config);      /* Exécution du programme */ | 
