summaryrefslogtreecommitdiff
path: root/src/analysis/disass
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-04-03 12:48:41 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-04-03 12:48:41 (GMT)
commitf80c4c6ee0479070f7319a5ce7e30e05406cdb8f (patch)
tree94bc363a6d1aeac29c1985a9627ceda962d1c38a /src/analysis/disass
parent36a5b2577d67ab7c9f2c5817f6dba7a9601d1f20 (diff)
Reorganized the whole disassembling process and displayed the relative progression.
Diffstat (limited to 'src/analysis/disass')
-rw-r--r--src/analysis/disass/Makefile.am1
-rw-r--r--src/analysis/disass/area.c34
-rw-r--r--src/analysis/disass/area.h6
-rw-r--r--src/analysis/disass/disassembler.c421
-rw-r--r--src/analysis/disass/fetch.c49
-rw-r--r--src/analysis/disass/fetch.h4
-rw-r--r--src/analysis/disass/instructions.c312
-rw-r--r--src/analysis/disass/instructions.h68
-rw-r--r--src/analysis/disass/limit.c355
-rw-r--r--src/analysis/disass/limit.h9
-rw-r--r--src/analysis/disass/links.c54
-rw-r--r--src/analysis/disass/links.h15
-rw-r--r--src/analysis/disass/routines.c89
-rw-r--r--src/analysis/disass/routines.h12
14 files changed, 704 insertions, 725 deletions
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);