From f80c4c6ee0479070f7319a5ce7e30e05406cdb8f Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 3 Apr 2016 14:48:41 +0200 Subject: Reorganized the whole disassembling process and displayed the relative progression. --- ChangeLog | 44 ++++ src/analysis/disass/Makefile.am | 1 + src/analysis/disass/area.c | 34 +-- src/analysis/disass/area.h | 6 +- src/analysis/disass/disassembler.c | 421 ++++++++++++++----------------------- src/analysis/disass/fetch.c | 49 ++--- src/analysis/disass/fetch.h | 4 +- src/analysis/disass/instructions.c | 312 +++++++++++++++++++++++++++ src/analysis/disass/instructions.h | 68 ++++++ src/analysis/disass/limit.c | 355 +++---------------------------- src/analysis/disass/limit.h | 9 +- src/analysis/disass/links.c | 54 +---- src/analysis/disass/links.h | 15 +- src/analysis/disass/routines.c | 89 +++++--- src/analysis/disass/routines.h | 12 +- src/arch/arm/v7/post.c | 12 ++ src/arch/instruction.h | 3 +- src/arch/processor.c | 52 +++++ src/arch/processor.h | 6 + src/gtkext/gtkstatusstack.c | 49 +++-- src/gtkext/gtkstatusstack.h | 6 +- src/main.c | 21 +- 22 files changed, 866 insertions(+), 756 deletions(-) create mode 100644 src/analysis/disass/instructions.c create mode 100644 src/analysis/disass/instructions.h diff --git a/ChangeLog b/ChangeLog index 6b45152..067a186 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,47 @@ +16-04-03 Cyrille Bagard + + * 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 * 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 . + */ + + +#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 . + */ + + +#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 - - -#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(" 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); diff --git a/src/main.c b/src/main.c index 2de2379..bd98b32 100644 --- a/src/main.c +++ b/src/main.c @@ -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 */ -- cgit v0.11.2-87-g4458