summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog49
-rw-r--r--Makefile.am2
-rwxr-xr-xsrc/analysis/Makefile.am1
-rw-r--r--src/analysis/binary.c562
-rw-r--r--src/analysis/delayed.c714
-rw-r--r--src/analysis/delayed.h97
-rw-r--r--src/analysis/line-int.h1
-rw-r--r--src/analysis/line.c39
-rw-r--r--src/analysis/line.h6
-rw-r--r--src/glibext/delayed-int.h41
-rw-r--r--src/glibext/delayed.c319
-rw-r--r--src/glibext/delayed.h12
-rw-r--r--src/gtkext/gtkbinview-int.h4
-rw-r--r--src/gtkext/gtkbinview.c8
-rw-r--r--src/gtkext/gtkblockview.c326
-rw-r--r--src/gtkext/gtkgraphview.c80
-rw-r--r--src/main.c4
-rw-r--r--src/plugins/pglist.c2
-rw-r--r--src/project.c95
-rw-r--r--src/project.h2
-rw-r--r--src/shell.c4
21 files changed, 1389 insertions, 979 deletions
diff --git a/ChangeLog b/ChangeLog
index a0e9573..b2fb0ed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,52 @@
+09-09-20 Cyrille Bagard <nocbos@gmail.com>
+
+ * Makefile.am:
+ Fix compilation order.
+
+ * src/analysis/binary.c:
+ Process the disassembly here and use the new queue to push works.
+
+ * src/analysis/delayed.c:
+ * src/analysis/delayed.h:
+ Deleted entries. Their content is merged with src/analysis/binary.c.
+
+ * src/analysis/line.c:
+ * src/analysis/line.h:
+ Add functions to retrieve the last line of a list and the length of a line.
+
+ * src/analysis/line-int.h:
+ Define the lines_list_last() macro.
+
+ * src/analysis/Makefile.am:
+ Remove the delayed.[ch] files from libanalysis_la_SOURCES.
+
+ * src/glibext/delayed.c:
+ * src/glibext/delayed.h:
+ * src/glibext/delayed-int.h:
+ Improved heavyly the work queue: it is now more generic and creates thread pools.
+
+ * src/gtkext/gtkbinview.c:
+ * src/gtkext/gtkbinview-int.h:
+ Create a signal called "lines-set".
+
+ * src/gtkext/gtkblockview.c:
+ * src/gtkext/gtkgraphview.c:
+ Use threads to build the views. The caller has now to carefully wait
+ the end of the building.
+
+ * src/main.c:
+ Init the generic work queue instead of the disassembly one.
+
+ * src/plugins/pglist.c:
+ Disable plugins again.
+
+ * src/project.c:
+ * src/project.h:
+ Update code for building view and fix the concurrency between the threads.
+
+ * src/shell.c:
+ Keep the standard output clean.
+
09-09-19 Cyrille Bagard <nocbos@gmail.com>
* configure.ac:
diff --git a/Makefile.am b/Makefile.am
index b0caf58..a28f09b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
EXTRA_DIST = config.rpath config.rpath config.rpath ChangeLog
-SUBDIRS = pixmaps plugins src
+SUBDIRS = pixmaps src plugins
ACLOCAL_AMFLAGS = -I m4
diff --git a/src/analysis/Makefile.am b/src/analysis/Makefile.am
index d7c694b..7dca420 100755
--- a/src/analysis/Makefile.am
+++ b/src/analysis/Makefile.am
@@ -3,7 +3,6 @@ noinst_LTLIBRARIES = libanalysis.la
libanalysis_la_SOURCES = \
binary.h binary.c \
- delayed.h delayed.c \
exporter-int.h \
exporter.h exporter.c \
line-int.h \
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index c991125..4fe8f06 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -35,13 +35,12 @@
#include <sys/types.h>
-#include "delayed.h"
#include "line_code.h" /* TODO : supprimer ? */
#include "line_comment.h" /* TODO : supprimer ? */
#include "line_prologue.h"
#include "prototype.h"
#include "../common/extstr.h"
-#include "../glibext/delayed.h"
+#include "../glibext/delayed-int.h"
#include "../format/format.h"
#include "../panels/log.h"
#include "../plugins/pglist.h"
@@ -58,6 +57,71 @@
+/* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */
+
+
+#define G_TYPE_DELAYED_DISASSEMBLY g_delayed_disassembly_get_type()
+#define G_DELAYED_DISASSEMBLY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_disassembly_get_type(), GDelayedDisassembly))
+#define G_IS_DELAYED_DISASSEMBLY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_disassembly_get_type()))
+#define G_DELAYED_DISASSEMBLY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_DISASSEMBLY, GDelayedDisassemblyClass))
+#define G_IS_DELAYED_DISASSEMBLY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_DISASSEMBLY))
+#define G_DELAYED_DISASSEMBLY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_DISASSEMBLY, GDelayedDisassemblyClass))
+
+
+/* Ensembles binaires à désassembler (instance) */
+typedef struct _GDelayedDisassembly
+{
+ GDelayedWork parent; /* A laisser en premier */
+
+ GOpenidaBinary *binary; /* Destinataire final */
+
+ GBinPart **parts; /* Parties binaires à traiter */
+ size_t count; /* Nombre de ces parties */
+
+ GRenderingLine *lines; /* Lignes de rendu résultantes */
+
+} GDelayedDisassembly;
+
+/* Ensembles binaires à désassembler (classe) */
+typedef struct _GDelayedDisassemblyClass
+{
+ GDelayedWorkClass parent; /* A laisser en premier */
+
+} GDelayedDisassemblyClass;
+
+
+/* Indique le type défini pour les tâches de désassemblage différé. */
+static GType g_delayed_disassembly_get_type(void);
+
+/* Initialise la classe des tâches de désassemblage différé. */
+static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *);
+
+/* Initialise une tâche de désassemblage différé. */
+static void g_delayed_disassembly_init(GDelayedDisassembly *);
+
+/* Crée une tâche de désassemblage différé. */
+static GDelayedDisassembly *g_delayed_disassembly_new(GOpenidaBinary *, GBinPart **, size_t);
+
+/* Assure le désassemblage en différé. */
+static void g_delayed_disassembly_process(GDelayedDisassembly *, GtkExtStatusBar *);
+
+/* Procède au désassemblage basique d'un contenu binaire. */
+static GRenderingLine *disassemble_binary_parts(GDelayedDisassembly *, GBinRoutine **, size_t, GtkExtStatusBar *, guint);
+
+/* Etablit les liens entres les différentes lignes de code. */
+static void establish_links_between_lines(GRenderingLine *, GBinRoutine **, size_t, GtkExtStatusBar *, guint);
+
+/* S'assure que toutes les routines ont une taille définie. */
+static void limit_all_routines(GRenderingLine *, GBinRoutine **, size_t, GtkExtStatusBar *, guint);
+
+/* Cherche l'adresse de fin d'une routine. */
+static vmpa_t find_best_ending_address_for_routine(GRenderingLine *, size_t, const vmpa_t *, const off_t *, size_t);
+
+
+
+
+
+
/* Description de fichier binaire (instance) */
struct _GOpenidaBinary
@@ -102,7 +166,470 @@ bin_t *map_binary_file(const char *, off_t *);
GRenderingLine *build_binary_prologue(const char *, const uint8_t *, off_t);
/* Acquitte la fin d'un désasemblage différé et complet. */
-void ack_completed_disassembly(GDisassManager *, GOpenidaBinary *, GRenderingLine *, GOpenidaBinary *);
+void ack_completed_disassembly(GDelayedDisassembly *, GOpenidaBinary *);
+
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DESASSEMBLAGE DE BINAIRE DIFFERE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour les tâches de désassemblage différé. */
+G_DEFINE_TYPE(GDelayedDisassembly, g_delayed_disassembly, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des tâches de désassemblage différé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : disass = instance à initialiser. *
+* *
+* Description : Initialise une tâche de désassemblage différé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_disassembly_init(GDelayedDisassembly *disass)
+{
+ G_DELAYED_WORK(disass)->run = (run_task_fc)g_delayed_disassembly_process;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : binary = binaire chargé en attente des résultats. *
+* parts = parties binaires à désassembler. *
+* count = nombre de parties à traiter. *
+* *
+* Description : Crée une tâche de désassemblage différé. *
+* *
+* Retour : Tâche créée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GDelayedDisassembly *g_delayed_disassembly_new(GOpenidaBinary *binary, GBinPart **parts, size_t count)
+{
+ GDelayedDisassembly *result; /* Tâche à retourner */
+
+ result = g_object_new(G_TYPE_DELAYED_DISASSEMBLY, NULL);
+
+ result->binary = binary;
+
+ result->parts = parts;
+ result->count = count;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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(GDelayedDisassembly *disass, GtkExtStatusBar *statusbar)
+{
+ GBinRoutine **routines; /* Liste des routines trouvées */
+ size_t routines_count; /* Nombre de ces routines */
+ guint id; /* Identifiant de statut */
+
+ routines = g_binary_format_get_routines(G_BIN_FORMAT(disass->binary->format), &routines_count);
+ qsort(routines, routines_count, sizeof(GBinRoutine *), g_binary_routine_rcompare);
+
+ /* Première étape */
+
+ id = gtk_extended_status_bar_push(statusbar, _("Disassembling..."), true);
+
+ disass->lines = disassemble_binary_parts(disass, routines, routines_count, statusbar, id);
+
+ gtk_extended_status_bar_remove(statusbar, id);
+
+ /* Seconde étape */
+
+ id = gtk_extended_status_bar_push(statusbar, _("Establishing links..."), true);
+
+ establish_links_between_lines(disass->lines, routines, routines_count, statusbar, id);
+
+ gtk_extended_status_bar_remove(statusbar, id);
+
+ /* Troisième étape */
+
+ id = gtk_extended_status_bar_push(statusbar, _("Finding remaining limits..."), true);
+
+ limit_all_routines(disass->lines, routines, routines_count, statusbar, id);
+
+ gtk_extended_status_bar_remove(statusbar, id);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : disass = tâche à l'origine du traitement. *
+* routines = prototypes existants à insérer. *
+* count = quantité de ces prototypes. *
+* statusbar = barre de statut avec progression à mettre à jour.*
+* id = identifiant du message affiché à l'utilisateur. *
+* *
+* Description : Procède au désassemblage basique d'un contenu binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GRenderingLine *disassemble_binary_parts(GDelayedDisassembly *disass, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, guint id)
+{
+ GRenderingLine *result; /* Ligne de rendu à retourner */
+ GArchProcessor *proc; /* Architecture du binaire */
+ GRenderingOptions *options; /* Options de désassemblage */
+ bin_t *bin_data; /* Données binaires à lire */
+ size_t i; /* Boucle de parcours #1 */
+ off_t sum; /* Somme de toutes les tailles */
+ off_t done; /* Quantité déjà traitée */
+ off_t pos; /* Début d'une zone binaire */
+ off_t len; /* Taille de cette même zone */
+ vmpa_t base; /* Adresse de la zone binaire */
+ off_t start; /* Conservation du pt de départ*/
+ vmpa_t addr; /* Adresse d'une instruction */
+ GArchInstruction *instr; /* Instruction décodée */
+ GRenderingLine *line; /* Nouvelle ligne de rendu */
+ size_t k; /* Boucle de parcours #2 */
+ uint64_t routine_offset; /* Point de départ de routine */
+ char *routine_desc; /* Prototype d'une routine */
+
+ result = NULL;
+
+ proc = get_arch_processor_from_format(g_openida_binary_get_format(disass->binary));
+ options = g_openida_binary_get_options(disass->binary);
+ bin_data = g_openida_binary_get_data(disass->binary, NULL);
+
+ /* Préparation du suivi de la progression */
+
+ sum = 0;
+
+ for (i = 0; i < disass->count; i++)
+ {
+ g_binary_part_get_values(disass->parts[i], NULL, &len, NULL);
+ sum += len;
+ }
+
+ done = 0;
+
+ for (i = 0; i < disass->count; i++)
+ {
+ g_binary_part_get_values(disass->parts[i], &pos, &len, &base);
+
+ /* Décodage des instructions */
+
+ start = pos;
+ pos = 0;
+
+ while (pos < len)
+ {
+ addr = base + pos;
+
+ instr = g_arch_processor_decode_instruction(proc, &bin_data[start],
+ &pos, len, start, addr);
+
+ line = g_code_line_new(addr, instr, options);
+ g_rendering_line_add_to_lines(&result, line);
+
+ if (pos < len)
+ gtk_extended_status_bar_update_activity(statusbar, id, (done + pos) * 1.0 / sum);
+
+ }
+
+ done += len;
+ gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
+
+ /* Ajout des prototypes de fonctions */
+
+ for (k = 0; k < count; k++)
+ {
+ routine_offset = g_binary_routine_get_address(routines[k]);
+
+ if (!(base <= routine_offset && routine_offset < (base + len))) continue;
+
+ routine_desc = g_binary_routine_to_string(routines[k]);
+
+ line = g_comment_line_new(routine_offset, routine_desc, options);
+ g_rendering_line_insert_into_lines(&result, line, true);
+
+ free(routine_desc);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : lines = lignes de rendu à relier. *
+* routines = prototypes existants à insérer. *
+* count = quantité de ces prototypes. *
+* 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 : - *
+* *
+******************************************************************************/
+
+static void establish_links_between_lines(GRenderingLine *lines, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, guint id)
+{
+ size_t i; /* Boucle de parcours */
+ vmpa_t start; /* Adresse de départ */
+ vmpa_t end; /* Adresse de fin */
+ GRenderingLine *iter; /* Boucle de parcours */
+ GArchInstruction *instr; /* Instruction à ausculter */
+ vmpa_t addr; /* Adresse référencée */
+ InstructionLinkType type; /* Type de référence */
+ GRenderingLine *target; /* Ligne visée par la référence*/
+
+ for (i = 0; i < count; i++)
+ {
+ start = g_binary_routine_get_address(routines[i]);
+ end = start + g_binary_routine_get_size(routines[i]);
+
+ for (iter = g_rendering_line_find_by_address(lines, NULL, start);
+ iter != NULL;
+ iter = g_rendering_line_get_next_iter(lines, iter, NULL))
+ {
+ /* Si on sort de la zone... */
+ if (get_rendering_line_address(iter) >= end) break;
+
+ /* On ne traite que du code ici ! */
+ if (!G_IS_CODE_LINE(iter)) continue;
+
+ instr = g_code_line_get_instruction(G_CODE_LINE(iter));
+ type = g_arch_instruction_get_link(instr, &addr);
+
+ switch (type)
+ {
+ case ILT_NONE:
+ break;
+
+ case ILT_JUMP:
+
+ target = g_rendering_line_find_by_address(lines, NULL, addr);
+
+ if (target != NULL)
+ g_rendering_line_link_with(iter, target, type);
+
+ break;
+
+ case ILT_JUMP_IF_FALSE:
+ break;
+
+ case ILT_JUMP_IF_TRUE:
+
+ target = g_rendering_line_find_by_address(lines, NULL, addr);
+
+ if (target != NULL)
+ {
+ g_rendering_line_link_with(iter, target, type);
+
+ target = g_rendering_line_get_next_iter(lines, iter, NULL);
+ if (target != NULL)
+ g_rendering_line_link_with(iter, target, ILT_JUMP_IF_FALSE);
+
+ }
+
+ break;
+
+ case ILT_CALL:
+
+ target = g_rendering_line_find_by_address(lines, NULL, addr);
+
+ if (target != NULL)
+ g_rendering_line_link_with(iter, target, type);
+
+ break;
+
+ }
+
+ }
+
+ gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : lines = lignes de rendu à parcourir. *
+* routines = prototypes existants à insérer. *
+* count = quantité de ces prototypes. *
+* statusbar = barre de statut avec progression à mettre à jour.*
+* id = identifiant du message affiché à l'utilisateur. *
+* *
+* Description : S'assure que toutes les routines ont une taille définie. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void limit_all_routines(GRenderingLine *lines, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, guint id)
+{
+ size_t i; /* Boucle de parcours */
+ vmpa_t *starts; /* Adresses de départ */
+ off_t *lengths; /* Tailles des routines */
+ GRenderingLine *line; /* Ligne de départ / d'arrivée */
+ vmpa_t start; /* Adresse de début de routine */
+ vmpa_t last; /* Meilleur dernière adresse */
+ GArchInstruction *instr; /* Instruction à ausculter */
+ off_t length; /* Taille du code */
+
+ if (count == 0) return;
+
+ starts = (vmpa_t *)calloc(count, sizeof(vmpa_t));
+ lengths = (off_t *)calloc(count, sizeof(off_t));
+
+ for (i = 0; i < count; i++)
+ {
+ starts[i] = g_binary_routine_get_address(routines[i]);
+ lengths[i] = g_binary_routine_get_size(routines[i]);
+
+ gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / (count * 2));
+
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ if (lengths[i] > 0) continue;
+
+ start = g_binary_routine_get_address(routines[i]);
+ line = g_rendering_line_find_by_address(lines, NULL, start);
+
+ last = find_best_ending_address_for_routine(line, i, starts, lengths, count);
+
+ line = g_rendering_line_find_by_address(lines, NULL, last);
+ line = g_rendering_line_loop_for_code(line, NULL);
+
+ instr = g_code_line_get_instruction(G_CODE_LINE(line));
+ g_arch_instruction_get_location(instr, NULL, &length, NULL);
+
+ lengths[i] = last - start + length;
+ g_binary_routine_set_size(routines[i], lengths[i]);
+
+ gtk_extended_status_bar_update_activity(statusbar, id, (i + 1 + count) * 1.0 / (count * 2));
+
+ }
+
+ free(starts);
+ free(lengths);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : line = ligne de départ du parcours. *
+* index = indice de la routine traitée dans la liste. *
+* starts = adresse de départ des autres routines. *
+* lengths = taille des différentes routines, valides ou nulles.*
+* count = quantité de routines présentes. *
+* *
+* Description : Cherche l'adresse de fin d'une routine. *
+* *
+* Retour : Plus grande adresse de dernière instruction de routine. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static vmpa_t find_best_ending_address_for_routine(GRenderingLine *line, size_t index, const vmpa_t *starts, const off_t *lengths, size_t count)
+{
+ vmpa_t result; /* Haute adresse à remonter */
+ GRenderingLine *iter; /* Boucle de parcours #1 */
+ vmpa_t candidate; /* Candidat potentiel */
+ size_t i; /* Boucle de parcours #2 */
+ GArchInstruction *instr; /* Instruction à ausculter */
+
+ result = starts[index];
+
+ for (iter = line; iter != NULL; iter = g_rendering_line_get_next_iter(line, iter, NULL))
+ {
+ if (!G_IS_CODE_LINE(iter)) continue;
+
+ candidate = get_rendering_line_address(iter);
+
+ /* Regarde si on n'empiète pas sur une autre routine */
+
+ for (i = 0; i < count; i++)
+ {
+ if (i == index) continue;
+
+ if (starts[i] <= candidate && candidate < (starts[i] + lengths[i]))
+ break;
+
+ }
+
+ if (i != count) break;
+ else result = candidate;
+
+ /* Retour de fonction ? */
+
+ instr = g_code_line_get_instruction(G_CODE_LINE(iter));
+ if (g_arch_instruction_is_return(instr)) break;
+
+ }
+
+ return result;
+
+}
+
+
+
+
@@ -313,22 +840,22 @@ bool g_openida_binary_save(const GOpenidaBinary *binary, xmlDocPtr xdoc, xmlXPat
void g_openida_binary_analyse(GOpenidaBinary *binary)
{
- GDisassManager *manager; /* Gestionnaire de différés */
+ GWorkQueue *queue; /* Gestionnaire de différés */
GBinPart **parts; /* Parties d'élément binaire */
size_t parts_count; /* Nombre de ces parties */
GDelayedDisassembly *disass; /* Désassemblage à mener */
- manager = get_disassembly_manager();
+ queue = get_work_queue();
parts = g_exe_format_get_parts(binary->format, &parts_count);
qsort(parts, parts_count, sizeof(GBinPart *), g_binary_part_compare);
disass = g_delayed_disassembly_new(binary, parts, parts_count);
- g_signal_connect(manager, "disassembly-completed",
+ g_signal_connect(disass, "work-completed",
G_CALLBACK(ack_completed_disassembly), binary);
- g_delayed_queue_schedule_work(G_WORK_QUEUE(manager), G_DELAYED_WORK(disass));
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(disass));
}
@@ -591,10 +1118,8 @@ GRenderingLine *build_binary_prologue(const char *filename, const uint8_t *data,
/******************************************************************************
* *
-* Paramètres : manager = gestionnaire des traitements en parallèle. *
-* binary = binaire dont le contenu est à analyser. *
-* lines = lignes de rendu produites par le désasemblage. *
-* user = élément binaire à l'origine du traitement. *
+* Paramètres : disass = travail de désassemblage mené à bien. *
+* binary = représentation de binaire à l'origine de l'opérat°. *
* *
* Description : Acquitte la fin d'un désasemblage différé et complet. *
* *
@@ -604,25 +1129,22 @@ GRenderingLine *build_binary_prologue(const char *filename, const uint8_t *data,
* *
******************************************************************************/
-void ack_completed_disassembly(GDisassManager *manager, GOpenidaBinary *binary, GRenderingLine *lines, GOpenidaBinary *user)
+void ack_completed_disassembly(GDelayedDisassembly *disass, GOpenidaBinary *binary)
{
GRenderingLine *line; /* "Première" ligne de rendu */
GPluginModule **pglist; /* Liste de greffons */
size_t pgcount; /* Taille de cette liste */
size_t i; /* Boucle de parcours */
- /* Si ce n'est pas pour nous... */
- if (binary != user) return;
+ binary->lines = disass->lines;
- binary->lines = lines;
-
- line = g_rendering_line_find_by_address(lines, NULL,
+ line = g_rendering_line_find_by_address(disass->lines, NULL,
g_exe_format_get_entry_point(binary->format));
if (line != NULL) g_rendering_line_add_flag(line, RLF_ENTRY_POINT);
@@ -641,12 +1163,6 @@ void ack_completed_disassembly(GDisassManager *manager, GOpenidaBinary *binary,
/* On réintègre le flot premier */
- gdk_threads_enter();
-
g_signal_emit_by_name(binary, "disassembly-done");
- gdk_flush ();
-
- gdk_threads_leave();
-
}
diff --git a/src/analysis/delayed.c b/src/analysis/delayed.c
deleted file mode 100644
index 0d02d39..0000000
--- a/src/analysis/delayed.c
+++ /dev/null
@@ -1,714 +0,0 @@
-
-/* OpenIDA - Outil d'analyse de fichiers binaires
- * delayed.c - gestion des actions d'analyse différées
- *
- * Copyright (C) 2009 Cyrille Bagard
- *
- * This file is part of OpenIDA.
- *
- * 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 "delayed.h"
-
-
-#include "line_code.h"
-#include "line_comment.h"
-#include "../common/dllist.h"
-#include "../format/format.h"
-#include "../glibext/delayed-int.h"
-#include "../gtkext/gtkextstatusbar.h"
-#include "../gtkext/iodamarshal.h"
-
-
-
-#ifndef _
-# define _(str) (str)
-#endif
-
-
-
-
-/* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */
-
-
-/* Ensembles binaires à désassembler (instance) */
-struct _GDelayedDisassembly
-{
- GDelayedWork parent; /* A laisser en premier */
-
- GOpenidaBinary *binary; /* Destinataire final */
-
- GBinPart **parts; /* Parties binaires à traiter */
- size_t count; /* Nombre de ces parties */
-
-};
-
-/* Ensembles binaires à désassembler (classe) */
-struct _GDelayedDisassemblyClass
-{
- GDelayedWorkClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des tâches de désassemblage différé. */
-static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *);
-
-/* Initialise une tâche de désassemblage différé. */
-static void g_delayed_disassembly_init(GDelayedDisassembly *);
-
-
-
-/* ------------------------- GESTION DES ANALYSES DIFFEREES ------------------------- */
-
-
-/* Gestionnaire des analyses différées (instance) */
-struct _GDisassManager
-{
- GWorkQueue parent; /* A laisser en premier */
-
- GtkExtStatusBar *statusbar; /* Barre de statut principale */
-
-};
-
-/* Gestionnaire des analyses différées (classe) */
-struct _GDisassManagerClass
-{
- GWorkQueueClass parent; /* A laisser en premier */
-
- /* Signaux */
-
- void (* disassembly_completed) (GDisassManager *, GOpenidaBinary *, GRenderingLine *);
-
-};
-
-
-/* Initialise la classe des gestionnaires d'analyses différées. */
-static void g_disassembly_manager_class_init(GDisassManagerClass *);
-
-/* Initialise un gestionnaire d'analyses différées. */
-static void g_disassembly_manager_init(GDisassManager *);
-
-/* Crée un gestionnaire d'analyses différées. */
-static GDisassManager *g_disassembly_manager_new(GObject *);
-
-/* Assure le désassemblage en différé. */
-static void process_disassemblies(GDisassManager *, GDelayedDisassembly *);
-
-/* Procède au désassemblage basique d'un contenu binaire. */
-static GRenderingLine *disassemble_binary_parts(GDelayedDisassembly *, GBinRoutine **, size_t, GtkExtStatusBar *, guint);
-
-/* Etablit les liens entres les différentes lignes de code. */
-static void establish_links_between_lines(GRenderingLine *, GBinRoutine **, size_t, GtkExtStatusBar *, guint);
-
-/* S'assure que toutes les routines ont une taille définie. */
-static void limit_all_routines(GRenderingLine *, GBinRoutine **, size_t, GtkExtStatusBar *, guint);
-
-/* Cherche l'adresse de fin d'une routine. */
-static vmpa_t find_best_ending_address_for_routine(GRenderingLine *, size_t, const vmpa_t *, const off_t *, size_t);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* DESASSEMBLAGE DE BINAIRE DIFFERE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour les tâches de désassemblage différé. */
-G_DEFINE_TYPE(GDelayedDisassembly, g_delayed_disassembly, G_TYPE_DELAYED_WORK);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des tâches de désassemblage différé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *klass)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : disass = instance à initialiser. *
-* *
-* Description : Initialise une tâche de désassemblage différé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_delayed_disassembly_init(GDelayedDisassembly *disass)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : binary = binaire chargé en attente des résultats. *
-* parts = parties binaires à désassembler. *
-* count = nombre de parties à traiter. *
-* *
-* Description : Crée une tâche de désassemblage différé. *
-* *
-* Retour : Tâche créée. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GDelayedDisassembly *g_delayed_disassembly_new(GOpenidaBinary *binary, GBinPart **parts, size_t count)
-{
- GDelayedDisassembly *result; /* Tâche à retourner */
-
- result = g_object_new(G_TYPE_DELAYED_DISASSEMBLY, NULL);
-
- result->binary = binary;
-
- result->parts = parts;
- result->count = count;
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION DES ANALYSES DIFFEREES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Indique le type défini pour le gestionnaire des analyses différées. */
-G_DEFINE_TYPE(GDisassManager, g_disassembly_manager, G_TYPE_WORK_QUEUE);
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe des gestionnaires d'analyses différées. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_disassembly_manager_class_init(GDisassManagerClass *klass)
-{
- g_signal_new("disassembly-completed",
- G_TYPE_DISASS_MANAGER,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GDisassManagerClass, disassembly_completed),
- NULL, NULL,
- g_cclosure_user_marshal_VOID__OBJECT_OBJECT,
- G_TYPE_NONE, 2, G_TYPE_OPENIDA_BINARY, G_TYPE_RENDERING_LINE);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : manager = instance à initialiser. *
-* *
-* Description : Initialise un gestionnaire d'analyses différées. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_disassembly_manager_init(GDisassManager *manager)
-{
- GWorkQueue *parent; /* Instance parente */
-
- parent = G_WORK_QUEUE(manager);
-
- parent->process = (process_work_fc)process_disassemblies;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ref = espace de référencements global. *
-* *
-* Description : Crée un gestionnaire d'analyses différées. *
-* *
-* Retour : Gestionnaire mis en place ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GDisassManager *g_disassembly_manager_new(GObject *ref)
-{
- GDisassManager *result; /* Adresse à retourner */
-
- result = g_object_new(G_TYPE_DISASS_MANAGER, NULL);
-
- result->statusbar = g_object_get_data(ref, "statusbar");
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : manager = gestionnaire des actions à mener. *
-* disass = analyse à mener. *
-* *
-* Description : Assure le désassemblage en différé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void process_disassemblies(GDisassManager *manager, GDelayedDisassembly *disass)
-{
- GBinRoutine **routines; /* Liste des routines trouvées */
- size_t routines_count; /* Nombre de ces routines */
- guint id; /* Identifiant de statut */
- GRenderingLine *lines; /* Nouvelles lignes de rendu */
-
- routines = g_binary_format_get_routines(G_BIN_FORMAT(g_openida_binary_get_format(disass->binary)), &routines_count);
- qsort(routines, routines_count, sizeof(GBinRoutine *), g_binary_routine_rcompare);
-
- /* Première étape */
-
- id = gtk_extended_status_bar_push(manager->statusbar, _("Disassembling..."), true);
-
- lines = disassemble_binary_parts(disass, routines, routines_count, manager->statusbar, id);
-
- gtk_extended_status_bar_remove(manager->statusbar, id);
-
- /* Seconde étape */
-
- id = gtk_extended_status_bar_push(manager->statusbar, _("Establishing links..."), true);
-
- establish_links_between_lines(lines, routines, routines_count, manager->statusbar, id);
-
- gtk_extended_status_bar_remove(manager->statusbar, id);
-
- /* Troisième étape */
-
- id = gtk_extended_status_bar_push(manager->statusbar, _("Finding remaining limits..."), true);
-
- limit_all_routines(lines, routines, routines_count, manager->statusbar, id);
-
- gtk_extended_status_bar_remove(manager->statusbar, id);
-
- /* Fin */
-
- g_signal_emit_by_name(manager, "disassembly-completed", disass->binary, lines);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : disass = tâche à l'origine du traitement. *
-* routines = prototypes existants à insérer. *
-* count = quantité de ces prototypes. *
-* statusbar = barre de statut avec progression à mettre à jour.*
-* id = identifiant du message affiché à l'utilisateur. *
-* *
-* Description : Procède au désassemblage basique d'un contenu binaire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GRenderingLine *disassemble_binary_parts(GDelayedDisassembly *disass, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, guint id)
-{
- GRenderingLine *result; /* Ligne de rendu à retourner */
- GArchProcessor *proc; /* Architecture du binaire */
- GRenderingOptions *options; /* Options de désassemblage */
- bin_t *bin_data; /* Données binaires à lire */
- size_t i; /* Boucle de parcours #1 */
- off_t sum; /* Somme de toutes les tailles */
- off_t done; /* Quantité déjà traitée */
- off_t pos; /* Début d'une zone binaire */
- off_t len; /* Taille de cette même zone */
- vmpa_t base; /* Adresse de la zone binaire */
- off_t start; /* Conservation du pt de départ*/
- vmpa_t addr; /* Adresse d'une instruction */
- GArchInstruction *instr; /* Instruction décodée */
- GRenderingLine *line; /* Nouvelle ligne de rendu */
- size_t k; /* Boucle de parcours #2 */
- uint64_t routine_offset; /* Point de départ de routine */
- char *routine_desc; /* Prototype d'une routine */
-
- result = NULL;
-
- proc = get_arch_processor_from_format(g_openida_binary_get_format(disass->binary));
- options = g_openida_binary_get_options(disass->binary);
- bin_data = g_openida_binary_get_data(disass->binary, NULL);
-
- /* Préparation du suivi de la progression */
-
- sum = 0;
-
- for (i = 0; i < disass->count; i++)
- {
- g_binary_part_get_values(disass->parts[i], NULL, &len, NULL);
- sum += len;
- }
-
- done = 0;
-
- for (i = 0; i < disass->count; i++)
- {
- g_binary_part_get_values(disass->parts[i], &pos, &len, &base);
-
- /* Décodage des instructions */
-
- start = pos;
- pos = 0;
-
- while (pos < len)
- {
- addr = base + pos;
-
- instr = g_arch_processor_decode_instruction(proc, &bin_data[start],
- &pos, len, start, addr);
-
- line = g_code_line_new(addr, instr, options);
- g_rendering_line_add_to_lines(&result, line);
-
- if (pos < len)
- gtk_extended_status_bar_update_activity(statusbar, id, (done + pos) * 1.0 / sum);
-
- }
-
- done += len;
- gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
-
- /* Ajout des prototypes de fonctions */
-
- for (k = 0; k < count; k++)
- {
- routine_offset = g_binary_routine_get_address(routines[k]);
-
- if (!(base <= routine_offset && routine_offset < (base + len))) continue;
-
- routine_desc = g_binary_routine_to_string(routines[k]);
-
- line = g_comment_line_new(routine_offset, routine_desc, options);
- g_rendering_line_insert_into_lines(&result, line, true);
-
- free(routine_desc);
-
- }
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : lines = lignes de rendu à relier. *
-* routines = prototypes existants à insérer. *
-* count = quantité de ces prototypes. *
-* 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 : - *
-* *
-******************************************************************************/
-
-static void establish_links_between_lines(GRenderingLine *lines, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, guint id)
-{
- size_t i; /* Boucle de parcours */
- vmpa_t start; /* Adresse de départ */
- vmpa_t end; /* Adresse de fin */
- GRenderingLine *iter; /* Boucle de parcours */
- GArchInstruction *instr; /* Instruction à ausculter */
- vmpa_t addr; /* Adresse référencée */
- InstructionLinkType type; /* Type de référence */
- GRenderingLine *target; /* Ligne visée par la référence*/
-
- for (i = 0; i < count; i++)
- {
- start = g_binary_routine_get_address(routines[i]);
- end = start + g_binary_routine_get_size(routines[i]);
-
- for (iter = g_rendering_line_find_by_address(lines, NULL, start);
- iter != NULL;
- iter = g_rendering_line_get_next_iter(lines, iter, NULL))
- {
- /* Si on sort de la zone... */
- if (get_rendering_line_address(iter) >= end) break;
-
- /* On ne traite que du code ici ! */
- if (!G_IS_CODE_LINE(iter)) continue;
-
- instr = g_code_line_get_instruction(G_CODE_LINE(iter));
- type = g_arch_instruction_get_link(instr, &addr);
-
- switch (type)
- {
- case ILT_NONE:
- break;
-
- case ILT_JUMP:
-
- target = g_rendering_line_find_by_address(lines, NULL, addr);
-
- if (target != NULL)
- g_rendering_line_link_with(iter, target, type);
-
- break;
-
- case ILT_JUMP_IF_FALSE:
- break;
-
- case ILT_JUMP_IF_TRUE:
-
- target = g_rendering_line_find_by_address(lines, NULL, addr);
-
- if (target != NULL)
- {
- g_rendering_line_link_with(iter, target, type);
-
- target = g_rendering_line_get_next_iter(lines, iter, NULL);
- if (target != NULL)
- g_rendering_line_link_with(iter, target, ILT_JUMP_IF_FALSE);
-
- }
-
- break;
-
- case ILT_CALL:
-
- target = g_rendering_line_find_by_address(lines, NULL, addr);
-
- if (target != NULL)
- g_rendering_line_link_with(iter, target, type);
-
- break;
-
- }
-
- }
-
- gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : lines = lignes de rendu à parcourir. *
-* routines = prototypes existants à insérer. *
-* count = quantité de ces prototypes. *
-* statusbar = barre de statut avec progression à mettre à jour.*
-* id = identifiant du message affiché à l'utilisateur. *
-* *
-* Description : S'assure que toutes les routines ont une taille définie. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void limit_all_routines(GRenderingLine *lines, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, guint id)
-{
- size_t i; /* Boucle de parcours */
- vmpa_t *starts; /* Adresses de départ */
- off_t *lengths; /* Tailles des routines */
- GRenderingLine *line; /* Ligne de départ / d'arrivée */
- vmpa_t start; /* Adresse de début de routine */
- vmpa_t last; /* Meilleur dernière adresse */
- GArchInstruction *instr; /* Instruction à ausculter */
- off_t length; /* Taille du code */
-
- if (count == 0) return;
-
- starts = (vmpa_t *)calloc(count, sizeof(vmpa_t));
- lengths = (off_t *)calloc(count, sizeof(off_t));
-
- for (i = 0; i < count; i++)
- {
- starts[i] = g_binary_routine_get_address(routines[i]);
- lengths[i] = g_binary_routine_get_size(routines[i]);
-
- gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / (count * 2));
-
- }
-
- for (i = 0; i < count; i++)
- {
- if (lengths[i] > 0) continue;
-
- start = g_binary_routine_get_address(routines[i]);
- line = g_rendering_line_find_by_address(lines, NULL, start);
-
- last = find_best_ending_address_for_routine(line, i, starts, lengths, count);
-
- line = g_rendering_line_find_by_address(lines, NULL, last);
- line = g_rendering_line_loop_for_code(line, NULL);
-
- instr = g_code_line_get_instruction(G_CODE_LINE(line));
- g_arch_instruction_get_location(instr, NULL, &length, NULL);
-
- lengths[i] = last - start + length;
- g_binary_routine_set_size(routines[i], lengths[i]);
-
- gtk_extended_status_bar_update_activity(statusbar, id, (i + 1 + count) * 1.0 / (count * 2));
-
- }
-
- free(starts);
- free(lengths);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : line = ligne de départ du parcours. *
-* index = indice de la routine traitée dans la liste. *
-* starts = adresse de départ des autres routines. *
-* lengths = taille des différentes routines, valides ou nulles.*
-* count = quantité de routines présentes. *
-* *
-* Description : Cherche l'adresse de fin d'une routine. *
-* *
-* Retour : Plus grande adresse de dernière instruction de routine. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static vmpa_t find_best_ending_address_for_routine(GRenderingLine *line, size_t index, const vmpa_t *starts, const off_t *lengths, size_t count)
-{
- vmpa_t result; /* Haute adresse à remonter */
- GRenderingLine *iter; /* Boucle de parcours #1 */
- vmpa_t candidate; /* Candidat potentiel */
- size_t i; /* Boucle de parcours #2 */
- GArchInstruction *instr; /* Instruction à ausculter */
-
- result = starts[index];
-
- for (iter = line; iter != NULL; iter = g_rendering_line_get_next_iter(line, iter, NULL))
- {
- if (!G_IS_CODE_LINE(iter)) continue;
-
- candidate = get_rendering_line_address(iter);
-
- /* Regarde si on n'empiète pas sur une autre routine */
-
- for (i = 0; i < count; i++)
- {
- if (i == index) continue;
-
- if (starts[i] <= candidate && candidate < (starts[i] + lengths[i]))
- break;
-
- }
-
- if (i != count) break;
- else result = candidate;
-
- /* Retour de fonction ? */
-
- instr = g_code_line_get_instruction(G_CODE_LINE(iter));
- if (g_arch_instruction_is_return(instr)) break;
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : manager = nouveau gestionnaire à mémoriser ou NULL. *
-* *
-* Description : Fournit le gestionnaire d'analyse en différé courant. *
-* *
-* Retour : Gestionnaire d'analyse en différé courant. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GDisassManager *_get_disassembly_manager(GDisassManager *manager)
-{
- static GDisassManager *result = NULL; /* Singleton à retourner */
-
- if (manager != NULL)
- result = manager;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : ref = espace de référencements global. *
-* *
-* Description : Procède au chargement du gestionnaire d'analyse différées. *
-* *
-* Retour : true pour indiquer un chargement réussi, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool init_disassembly_manager(GObject *ref)
-{
- GDisassManager *manager; /* Singleton à mettre en place */
-
- manager = g_disassembly_manager_new(ref);
-
- if (manager != NULL)
- _get_disassembly_manager(manager);
-
- return (manager != NULL);
-
-}
diff --git a/src/analysis/delayed.h b/src/analysis/delayed.h
deleted file mode 100644
index c543f0b..0000000
--- a/src/analysis/delayed.h
+++ /dev/null
@@ -1,97 +0,0 @@
-
-/* OpenIDA - Outil d'analyse de fichiers binaires
- * delayed.h - prototypes pour la gestion des actions d'analyse différées
- *
- * Copyright (C) 2009 Cyrille Bagard
- *
- * This file is part of OpenIDA.
- *
- * 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_DELAYED_H
-#define _ANALYSIS_DELAYED_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-#include "binary.h"
-
-
-#include "../format/exe_format.h" /* TODO : Voir pour n'include que GBinPart */
-
-
-
-/* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */
-
-
-#define G_TYPE_DELAYED_DISASSEMBLY g_delayed_disassembly_get_type()
-#define G_DELAYED_DISASSEMBLY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_disassembly_get_type(), GDelayedDisassembly))
-#define G_IS_DELAYED_DISASSEMBLY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_disassembly_get_type()))
-#define G_DELAYED_DISASSEMBLY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_DISASSEMBLY, GDelayedDisassemblyClass))
-#define G_IS_DELAYED_DISASSEMBLY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_DISASSEMBLY))
-#define G_DELAYED_DISASSEMBLY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_DISASSEMBLY, GDelayedDisassemblyClass))
-
-
-/* Ensembles binaires à désassembler (instance) */
-typedef struct _GDelayedDisassembly GDelayedDisassembly;
-
-/* Ensembles binaires à désassembler (classe) */
-typedef struct _GDelayedDisassemblyClass GDelayedDisassemblyClass;
-
-
-
-/* Indique le type défini pour les tâches de désassemblage différé. */
-GType g_delayed_disassembly_get_type(void);
-
-/* Crée une tâche de désassemblage différé. */
-GDelayedDisassembly *g_delayed_disassembly_new(GOpenidaBinary *, GBinPart **, size_t);
-
-
-
-/* ------------------------- GESTION DES ANALYSES DIFFEREES ------------------------- */
-
-
-#define G_TYPE_DISASS_MANAGER g_disassembly_manager_get_type()
-#define G_DISASS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_disassembly_manager_get_type(), GDisassManager))
-#define G_IS_DISASS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_disassembly_manager_get_type()))
-#define G_DISASS_MANAGER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_disassembly_manager_get_type(), GDisassManagerIface))
-#define G_DISASS_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DISASS_MANAGER, GDisassManagerClass))
-
-
-/* Gestionnaire des analyses différées (instance) */
-typedef struct _GDisassManager GDisassManager;
-
-/* Gestionnaire des analyses différées (classe) */
-typedef struct _GDisassManagerClass GDisassManagerClass;
-
-
-#define get_disassembly_manager() _get_disassembly_manager(NULL)
-
-
-/* Indique le type défini pour le gestionnaire des analyses différées. */
-GType g_disassembly_manager_get_type(void);
-
-/* Fournit le gestionnaire d'analyse en différé courant. */
-GDisassManager *_get_disassembly_manager(GDisassManager *);
-
-/* Procède au chargement du gestionnaire d'analyse différées. */
-bool init_disassembly_manager(GObject *);
-
-
-
-#endif /* _ANALYSIS_DELAYED_H */
diff --git a/src/analysis/line-int.h b/src/analysis/line-int.h
index bc7d848..a78d8b2 100644
--- a/src/analysis/line-int.h
+++ b/src/analysis/line-int.h
@@ -55,6 +55,7 @@ struct _GRenderingLine
};
+#define lines_list_last(head) dl_list_last(head, GRenderingLine, link)
#define lines_list_next_iter(iter, head) dl_list_next_iter(iter, head, GRenderingLine, link)
#define lines_list_add_tail(new, head) dl_list_add_tail(new, head, GRenderingLine, link)
#define lines_list_splice_before(pos, head1, head2) dl_list_splice_before(pos, head1, head2, GRenderingLine, link)
diff --git a/src/analysis/line.c b/src/analysis/line.c
index a810b1f..507597c 100644
--- a/src/analysis/line.c
+++ b/src/analysis/line.c
@@ -131,6 +131,25 @@ vmpa_t get_rendering_line_address(const GRenderingLine *line)
* *
* Paramètres : line = ligne dont les informations sont à consulter. *
* *
+* Description : Fournit la longueur du code représenté par une ligne. *
+* *
+* Retour : Taille du code représenté (0 si aucun). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+off_t get_rendering_line_length(const GRenderingLine *line)
+{
+ return line->length;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : line = ligne dont les informations sont à consulter. *
+* *
* Description : Fournit le type d'une ligne. *
* *
* Retour : Type de la ligne fournie. *
@@ -443,6 +462,26 @@ GRenderingLine *g_rendering_line_get_next_iter(GRenderingLine *lines, const GRen
/******************************************************************************
* *
+* Paramètres : lines = liste de lignes de représentation à actualiser. *
+* last = dernière élément imposé du parcours ou NULL. *
+* *
+* Description : Fournit le dernier élément d'une liste de lignes. *
+* *
+* Retour : Dernier élément de la liste. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GRenderingLine *g_rendering_line_get_last_iter(GRenderingLine *lines, GRenderingLine *last)
+{
+ return (last != NULL ? last : lines_list_last(lines));
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : lines = liste de lignes à parcourir. *
* last = dernière élément imposé du parcours ou NULL. *
* addr = position en mémoire ou physique à chercher. *
diff --git a/src/analysis/line.h b/src/analysis/line.h
index 7455371..20d6234 100644
--- a/src/analysis/line.h
+++ b/src/analysis/line.h
@@ -75,6 +75,9 @@ GType g_rendering_line_get_type(void);
/* Fournit l'adresse physique ou en mémoire d'une ligne. */
vmpa_t get_rendering_line_address(const GRenderingLine *);
+/* Fournit la longueur du code représenté par une ligne. */
+off_t get_rendering_line_length(const GRenderingLine *);
+
/* Fournit le type d'une ligne. */
RenderingLineType get_rendering_line_type(const GRenderingLine *);
@@ -116,6 +119,9 @@ void g_rendering_line_insert_into_lines(GRenderingLine **, GRenderingLine *, boo
/* Fournit l'élement suivant un autre pour un parcours. */
GRenderingLine *g_rendering_line_get_next_iter(GRenderingLine *, const GRenderingLine *, const GRenderingLine *);
+/* Fournit le dernier élément d'une liste de lignes. */
+GRenderingLine *g_rendering_line_get_last_iter(GRenderingLine *, GRenderingLine *);
+
/* Recherche une ligne d'après sa position en mémoire/physique. */
GRenderingLine *g_rendering_line_find_by_address(GRenderingLine *, const GRenderingLine *, vmpa_t);
diff --git a/src/glibext/delayed-int.h b/src/glibext/delayed-int.h
index 7fb8f3a..b2e2b23 100644
--- a/src/glibext/delayed-int.h
+++ b/src/glibext/delayed-int.h
@@ -25,12 +25,17 @@
#include "../common/dllist.h"
+#include "../gtkext/gtkextstatusbar.h"
/* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */
+/* Traite un travail programmé. */
+typedef void (* run_task_fc) (GDelayedWork *, GtkExtStatusBar *);
+
+
/* Travail différé (instance) */
struct _GDelayedWork
{
@@ -38,6 +43,8 @@ struct _GDelayedWork
DL_LIST_ITEM(link); /* Lien vers les maillons */
+ run_task_fc run; /* Traitement externalisé */
+
};
/* Travail différé (classe) */
@@ -45,38 +52,12 @@ struct _GDelayedWorkClass
{
GObjectClass parent; /* A laisser en premier */
-};
-
-
-#define delayed_work_list_add_tail(new, head) dl_list_add_tail(new, head, GDelayedWork, link)
-#define delayed_work_list_del(item, head) dl_list_del(item, head, GDelayedWork, link)
-
-
-
-/* ------------------------- TRAITEMENT DE TACHES DIFFEREES ------------------------- */
-
+ /* Signaux */
-/* Effectue le traitement d'une tâche donnée. */
-typedef void (* process_work_fc) (GWorkQueue *, GDelayedWork *);
-
-
-/* Gestionnaire des travaux différés (instance) */
-struct _GWorkQueue
-{
- GObject parent; /* A laisser en premier */
-
- GDelayedWork *works; /* Tâches à mener à bien */
- GMutex *mutex; /* Verrou pour l'accès */
- GCond *cond; /* Réveil pour un traitement */
-
- GThread *thread; /* Procédure de traitement */
- process_work_fc process; /* Coeur du traitement */
+ void (* work_completed) (GDelayedWork *);
};
-/* Gestionnaire des travaux différés (classe) */
-struct _GWorkQueueClass
-{
- GObjectClass parent; /* A laisser en premier */
-};
+#define delayed_work_list_add_tail(new, head) dl_list_add_tail(new, head, GDelayedWork, link)
+#define delayed_work_list_del(item, head) dl_list_del(item, head, GDelayedWork, link)
diff --git a/src/glibext/delayed.c b/src/glibext/delayed.c
index 4388b2c..8f23538 100644
--- a/src/glibext/delayed.c
+++ b/src/glibext/delayed.c
@@ -24,6 +24,9 @@
#include "delayed.h"
+#include <malloc.h>
+
+
#include "delayed-int.h"
@@ -37,20 +40,96 @@ static void g_delayed_work_class_init(GDelayedWorkClass *);
/* Initialise une instance de travail différé. */
static void g_delayed_work_init(GDelayedWork *);
+/* Mène l'opération programmée. */
+static void g_delayed_work_process(GDelayedWork *, GtkExtStatusBar *);
+
+
+
+/* -------------------------- THREAD DE TRAITEMENTS DEDIES -------------------------- */
+
+
+#define G_TYPE_TYPED_QUEUE g_typed_queue_get_type()
+#define G_TYPED_QUEUE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_typed_queue_get_type(), GTypedQueue))
+#define G_IS_TYPED_QUEUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_typed_queue_get_type()))
+#define G_TYPED_QUEUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_TYPED_QUEUE, GTypedQueueClass))
+#define G_IS_TYPED_QUEUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_TYPED_QUEUE))
+#define G_TYPED_QUEUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_TYPED_QUEUE, GTypedQueueClass))
+
+
+/* File de traitement pour un type donné (instance) */
+typedef struct _GTypedQueue
+{
+ GObject parent; /* A laisser en premier */
+
+ GType type; /* Type de travaux menés */
+
+ GtkExtStatusBar *statusbar; /* Barre de statut principale */
+
+ GDelayedWork *works; /* Tâches à mener à bien */
+ GMutex *mutex; /* Verrou pour l'accès */
+ GCond *cond; /* Réveil pour un traitement */
+
+ GThread *thread; /* Procédure de traitement */
+
+} GTypedQueue;
+
+/* File de traitement pour un type donné (classe) */
+typedef struct _GTypedQueueClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+} GTypedQueueClass;
+
+
+/* Indique le type défini pour les travaux typés. */
+static GType g_typed_queue_get_type(void);
+
+/* Initialise la classe des travaux typés. */
+static void g_typed_queue_class_init(GTypedQueueClass *);
+
+/* Initialise une instance de gestionnaire de travaux typés. */
+static void g_typed_queue_init(GTypedQueue *);
+
+/* Crée un nouveau thread dédié à un type de travaux donné. */
+static GTypedQueue *g_typed_queue_new(GType, GtkExtStatusBar *);
+
+/* Place une nouvelle tâche en attente dans une file dédiée. */
+static void g_typed_queue_schedule(GTypedQueue *, GDelayedWork *);
+
+/* Assure le traitement en différé. */
+static void *g_typed_queue_process(GTypedQueue *);
+
/* ------------------------- TRAITEMENT DE TACHES DIFFEREES ------------------------- */
+/* Gestionnaire des travaux différés (instance) */
+struct _GWorkQueue
+{
+ GObject parent; /* A laisser en premier */
+
+ GtkExtStatusBar *statusbar; /* Barre de statut principale */
+
+ GTypedQueue **threads; /* Files de traitement */
+ size_t threads_count; /* Nombre de files internes */
+
+};
+
+/* Gestionnaire des travaux différés (classe) */
+struct _GWorkQueueClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
/* Initialise la classe des travaux différés. */
static void g_work_queue_class_init(GWorkQueueClass *);
/* Initialise une instance de gestionnaire de travaux différés. */
static void g_work_queue_init(GWorkQueue *);
-/* Assure le traitement en différé. */
-static void *g_work_queue_process(GWorkQueue *);
-
/* ---------------------------------------------------------------------------------- */
@@ -76,6 +155,13 @@ G_DEFINE_TYPE(GDelayedWork, g_delayed_work, G_TYPE_OBJECT);
static void g_delayed_work_class_init(GDelayedWorkClass *klass)
{
+ g_signal_new("work-completed",
+ G_TYPE_DELAYED_WORK,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GDelayedWorkClass, work_completed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
}
@@ -98,21 +184,43 @@ static void g_delayed_work_init(GDelayedWork *work)
}
+/******************************************************************************
+* *
+* Paramètres : work = travail à effectuer. *
+* statusbar = barre de statut à tenir informée. *
+* *
+* Description : Mène l'opération programmée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_work_process(GDelayedWork *work, GtkExtStatusBar *statusbar)
+{
+ work->run(work, statusbar);
+
+ g_signal_emit_by_name(work, "work-completed");
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
-/* TRAITEMENT DE TACHES DIFFEREES */
+/* THREAD DE TRAITEMENTS DEDIES */
/* ---------------------------------------------------------------------------------- */
-/* Indique le type défini pour le gestionnaire des travaux différés. */
-G_DEFINE_TYPE(GWorkQueue, g_work_queue, G_TYPE_OBJECT);
+/* Indique le type défini pour les travaux typés. */
+G_DEFINE_TYPE(GTypedQueue, g_typed_queue, G_TYPE_OBJECT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
-* Description : Initialise la classe des travaux différés. *
+* Description : Initialise la classe des travaux typés. *
* *
* Retour : - *
* *
@@ -120,7 +228,7 @@ G_DEFINE_TYPE(GWorkQueue, g_work_queue, G_TYPE_OBJECT);
* *
******************************************************************************/
-static void g_work_queue_class_init(GWorkQueueClass *klass)
+static void g_typed_queue_class_init(GTypedQueueClass *klass)
{
}
@@ -130,7 +238,7 @@ static void g_work_queue_class_init(GWorkQueueClass *klass)
* *
* Paramètres : queue = instance à initialiser. *
* *
-* Description : Initialise une instance de gestionnaire de travaux différés. *
+* Description : Initialise une instance de gestionnaire de travaux typés. *
* *
* Retour : - *
* *
@@ -138,23 +246,23 @@ static void g_work_queue_class_init(GWorkQueueClass *klass)
* *
******************************************************************************/
-static void g_work_queue_init(GWorkQueue *queue)
+static void g_typed_queue_init(GTypedQueue *queue)
{
GError *error; /* Bilan de création de thread */
queue->mutex = g_mutex_new();
if (queue->mutex == NULL)
- goto gwqi_error;
+ goto gtqi_error;
queue->cond = g_cond_new();
if (queue->cond == NULL)
- goto gwqi_error;
+ goto gtqi_error;
- queue->thread = g_thread_create((GThreadFunc)g_work_queue_process, queue, FALSE, &error);
+ queue->thread = g_thread_create((GThreadFunc)g_typed_queue_process, queue, FALSE, &error);
if (!queue->thread)
- goto gwqi_error;
+ goto gtqi_error;
- gwqi_error:
+ gtqi_error:
/* TODO */ return;
@@ -163,6 +271,59 @@ static void g_work_queue_init(GWorkQueue *queue)
/******************************************************************************
* *
+* Paramètres : type = type dont seront marqués tous les travaux donnés.*
+* statusbar = barre de statut à tenir informée. *
+* *
+* Description : Crée un nouveau thread dédié à un type de travaux donné. *
+* *
+* Retour : Structure associée au thread mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GTypedQueue *g_typed_queue_new(GType type, GtkExtStatusBar *statusbar)
+{
+ GTypedQueue *result; /* Traiteur à retourner */
+
+ result = g_object_new(G_TYPE_TYPED_QUEUE, NULL);
+
+ result->type = type;
+ result->statusbar = statusbar;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : queue = gestionnaire des actions à mener. *
+* work = nouvelle tâche à programmer, puis effectuer. *
+* *
+* Description : Place une nouvelle tâche en attente dans une file dédiée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_typed_queue_schedule(GTypedQueue *queue, GDelayedWork *work)
+{
+ g_mutex_lock(queue->mutex);
+
+ delayed_work_list_add_tail(work, &queue->works);
+
+ g_cond_signal(queue->cond);
+
+ g_mutex_unlock(queue->mutex);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : queue = gestionnaire des actions à mener. *
* *
* Description : Assure le traitement en différé. *
@@ -173,7 +334,7 @@ static void g_work_queue_init(GWorkQueue *queue)
* *
******************************************************************************/
-static void *g_work_queue_process(GWorkQueue *queue)
+static void *g_typed_queue_process(GTypedQueue *queue)
{
GDelayedWork *work; /* Traitement à mener */
@@ -189,7 +350,7 @@ static void *g_work_queue_process(GWorkQueue *queue)
g_mutex_unlock(queue->mutex);
- queue->process(queue, work);
+ g_delayed_work_process(work, queue->statusbar);
/* TODO : delete work */
@@ -200,10 +361,108 @@ static void *g_work_queue_process(GWorkQueue *queue)
}
+
+/* ---------------------------------------------------------------------------------- */
+/* TRAITEMENT DE TACHES DIFFEREES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour le gestionnaire des travaux différés. */
+G_DEFINE_TYPE(GWorkQueue, g_work_queue, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des travaux différés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_work_queue_class_init(GWorkQueueClass *klass)
+{
+
+}
+
+
/******************************************************************************
* *
-* Paramètres : queu = gestionnaire des actions à mener. *
-* work = nouvelle tâche à programmer, puis effectuer. *
+* Paramètres : queue = instance à initialiser. *
+* *
+* Description : Initialise une instance de gestionnaire de travaux différés. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_work_queue_init(GWorkQueue *queue)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : ref = espace de référencements global. *
+* *
+* Description : Procède au chargement du gestionnaire d'analyse différées. *
+* *
+* Retour : true pour indiquer un chargement réussi, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool init_work_queue(GObject *ref)
+{
+ GWorkQueue *queue; /* Singleton à mettre en place */
+
+ queue = g_object_new(G_TYPE_WORK_QUEUE, NULL);
+
+ queue->statusbar = g_object_get_data(ref, "statusbar");
+
+ if (queue != NULL)
+ _get_work_queue(queue);
+
+ return (queue != NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : queue = nouveau gestionnaire à mémoriser ou NULL. *
+* *
+* Description : Fournit le gestionnaire de traitements parallèles courant. *
+* *
+* Retour : Gestionnaire de traitements parallèles courant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GWorkQueue *_get_work_queue(GWorkQueue *queue)
+{
+ static GWorkQueue *result = NULL; /* Singleton à retourner */
+
+ if (queue != NULL)
+ result = queue;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : queue = gestionnaire des actions à mener. *
+* work = nouvelle tâche à programmer, puis effectuer. *
* *
* Description : Place une nouvelle tâche en attente. *
* *
@@ -213,14 +472,26 @@ static void *g_work_queue_process(GWorkQueue *queue)
* *
******************************************************************************/
-void g_delayed_queue_schedule_work(GWorkQueue *queue, GDelayedWork *work)
+void g_work_queue_schedule_work(GWorkQueue *queue, GDelayedWork *work)
{
- g_mutex_lock(queue->mutex);
+ GType target; /* Type de travail à ajouter */
+ size_t i; /* Boucle de traitement */
- delayed_work_list_add_tail(work, &queue->works);
+ target = G_TYPE_FROM_INSTANCE(work);
- g_cond_signal(queue->cond);
+ for (i = 0; i < queue->threads_count; i++)
+ if (queue->threads[i]->type == target) break;
- g_mutex_unlock(queue->mutex);
+ if (i == queue->threads_count)
+ {
+ queue->threads_count++;
+ queue->threads = (GTypedQueue **)realloc(queue->threads,
+ queue->threads_count * sizeof(GTypedQueue *));
+
+ queue->threads[i] = g_typed_queue_new(target, queue->statusbar);
+
+ }
+
+ g_typed_queue_schedule(queue->threads[i], work);
}
diff --git a/src/glibext/delayed.h b/src/glibext/delayed.h
index d1e3967..501bb7f 100644
--- a/src/glibext/delayed.h
+++ b/src/glibext/delayed.h
@@ -26,6 +26,7 @@
#include <glib-object.h>
+#include <stdbool.h>
@@ -70,11 +71,20 @@ typedef struct _GWorkQueue GWorkQueue;
typedef struct _GWorkQueueClass GWorkQueueClass;
+#define get_work_queue() _get_work_queue(NULL)
+
+
/* Indique le type défini pour le gestionnaire des travaux différés. */
GType g_work_queue_get_type(void);
+/* Procède au chargement du gestionnaire d'analyse différées. */
+bool init_work_queue(GObject *);
+
+/* Fournit le gestionnaire de traitements parallèles courant. */
+GWorkQueue *_get_work_queue(GWorkQueue *);
+
/* Place une nouvelle tâche en attente. */
-void g_delayed_queue_schedule_work(GWorkQueue *, GDelayedWork *);
+void g_work_queue_schedule_work(GWorkQueue *, GDelayedWork *);
diff --git a/src/gtkext/gtkbinview-int.h b/src/gtkext/gtkbinview-int.h
index 0e38c57..e785bab 100644
--- a/src/gtkext/gtkbinview-int.h
+++ b/src/gtkext/gtkbinview-int.h
@@ -66,6 +66,10 @@ struct _GtkBinViewClass
{
GtkFixedClass parent; /* A laisser en premier */
+ /* Signaux */
+
+ void (* lines_set) (GtkBinView *);
+
};
diff --git a/src/gtkext/gtkbinview.c b/src/gtkext/gtkbinview.c
index 696799b..147a59c 100644
--- a/src/gtkext/gtkbinview.c
+++ b/src/gtkext/gtkbinview.c
@@ -68,6 +68,14 @@ static void gtk_binview_class_init(GtkBinViewClass *class)
widget_class->realize = gtk_bin_view_realize;
widget_class->expose_event = gtk_bin_view_expose;
+ g_signal_new("lines-set",
+ GTK_TYPE_BIN_VIEW,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkBinViewClass, lines_set),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
}
diff --git a/src/gtkext/gtkblockview.c b/src/gtkext/gtkblockview.c
index 23f86ce..ac06af3 100644
--- a/src/gtkext/gtkblockview.c
+++ b/src/gtkext/gtkblockview.c
@@ -35,10 +35,63 @@
#include "support.h"
#include "../analysis/exporter.h"
#include "../common/dllist.h"
+#include "../glibext/delayed-int.h"
-#define MARGIN_SPACE 4 /* TODO : delete me ! */
+#ifndef _
+# define _(str) str
+#endif
+
+
+
+
+/* -------------------------- INSERTION DIFFEREE DE LIGNES -------------------------- */
+
+
+#define G_TYPE_DELAYED_INSERTION g_delayed_insertion_get_type()
+#define G_DELAYED_INSERTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_insertion_get_type(), GDelayedInsertion))
+#define G_IS_DELAYED_INSERTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_insertion_get_type()))
+#define G_DELAYED_INSERTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_INSERTION, GDelayedInsertionClass))
+#define G_IS_DELAYED_INSERTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_INSERTION))
+#define G_DELAYED_INSERTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_INSERTION, GDelayedInsertionClass))
+
+
+/* Ensembles binaires à désassembler (instance) */
+typedef struct _GDelayedInsertion
+{
+ GDelayedWork parent; /* A laisser en premier */
+
+ GtkBlockView *view; /* Visualisation à constituer */
+
+ size_t lengths[SAR_COUNT]; /* Différentes tailles de zone */
+
+} GDelayedInsertion;
+
+/* Ensembles binaires à désassembler (classe) */
+typedef struct _GDelayedInsertionClass
+{
+ GDelayedWorkClass parent; /* A laisser en premier */
+
+} GDelayedInsertionClass;
+
+
+/* Indique le type défini pour les tâches d'insertions différées. */
+static GType g_delayed_insertion_get_type(void);
+
+/* Initialise la classe des tâches d'insertions différées. */
+static void g_delayed_insertion_class_init(GDelayedInsertionClass *);
+
+/* Initialise une tâche d'insertions différées. */
+static void g_delayed_insertion_init(GDelayedInsertion *);
+
+/* Crée une tâche d'insertions différées. */
+static GDelayedInsertion *g_delayed_insertion_new(GtkBlockView *);
+
+/* Assure des insertion de lignes en différé. */
+static void g_delayed_insertion_process(GDelayedInsertion *, GtkExtStatusBar *);
+
+
@@ -76,6 +129,8 @@ struct _GtkBlockViewClass
+
+
static void
gtk_text_view2_set_attributes_from_style (GtkTextAttributes *values,
GtkStyle *style)
@@ -108,6 +163,8 @@ static void gtk_block_view_realize(GtkWidget *);
/* Définit les lignes du bloc de représentation. */
static void gtk_block_view_set_rendering_lines(GtkBlockView *, GRenderingLine *, GRenderingLine *);
+/* Achève la construction de la visualisation des lignes. */
+static void gtk_block_view_complete_building_content(GDelayedInsertion *, GtkBlockView *);
@@ -150,6 +207,171 @@ static void gtk_block_view_destroy(GtkObject *object);
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INSERTION DIFFEREE DE LIGNES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour les tâches d'insertions différées. */
+G_DEFINE_TYPE(GDelayedInsertion, g_delayed_insertion, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des tâches d'insertions différées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_insertion_class_init(GDelayedInsertionClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : insertion = instance à initialiser. *
+* *
+* Description : Initialise une tâche d'insertions différées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_insertion_init(GDelayedInsertion *insertion)
+{
+ G_DELAYED_WORK(insertion)->run = (run_task_fc)g_delayed_insertion_process;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = visualisation de lignes à constituer. *
+* *
+* Description : Crée une tâche d'insertions différées. *
+* *
+* Retour : Tâche créée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GDelayedInsertion *g_delayed_insertion_new(GtkBlockView *view)
+{
+ GDelayedInsertion *result; /* Tâche à retourner */
+
+ result = g_object_new(G_TYPE_DELAYED_INSERTION, NULL);
+
+ result->view = view;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : insertion = insertions de lignes à mener. *
+* statusbar = barre de statut à tenir informée. *
+* *
+* Description : Assure des insertion de lignes en différé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_delayed_insertion_process(GDelayedInsertion *insertion, GtkExtStatusBar *statusbar)
+{
+ GtkBlockView *view; /* Visualisation à constituer */
+ GRenderingLine *lines; /* Liste de lignes à intégrer */
+ GRenderingLine *last; /* Dernière ligne ou NULL */
+ vmpa_t start; /* Adresse de début de parcours*/
+ vmpa_t end; /* Adresse de fin de parcours */
+ guint id; /* Identifiant de statut */
+ GRenderingLine *iter; /* Boucle de parcours */
+ GtkTextIter pos; /* Point d'insertion */
+ GtkTextMark *mark; /* Marquage de ligne associée */
+ vmpa_t done; /* Quantité déjà parcourue */
+
+ view = insertion->view;
+
+ lines = GTK_BIN_VIEW(view)->lines;
+ last = GTK_BIN_VIEW(view)->last;
+
+ iter = g_rendering_line_loop_for_code(lines, last);
+ start = get_rendering_line_address(lines);
+
+ iter = g_rendering_line_get_last_iter(lines, last);
+ end = get_rendering_line_address(iter) + get_rendering_line_length(iter) - start;
+
+ insertion->lengths[SAR_ADDRESS] = 0;
+ insertion->lengths[SAR_CODE] = 0;
+ insertion->lengths[SAR_INSTRUCTION] = 0;
+
+ id = gtk_extended_status_bar_push(statusbar, _("Inserting lines..."), true);
+
+ for (iter = lines;
+ iter != NULL;
+ iter = g_rendering_line_get_next_iter(lines, iter, last))
+ {
+ g_signal_connect(iter, "rendering-line-flags-changed",
+ G_CALLBACK(gtk_block_view_update_margin), view);
+
+ gdk_threads_enter();
+
+ if (iter != lines)
+ {
+ gtk_text_buffer_get_end_iter(view->buffer, &pos);
+ gtk_text_buffer_insert_with_tags(view->buffer, &pos, "\n", 1, NULL);
+ }
+
+ gtk_text_buffer_get_end_iter(view->buffer, &pos);
+
+ mark = gtk_text_buffer_create_mark(view->buffer, NULL, &pos, TRUE);
+ g_object_set_data(G_OBJECT(mark), "line", iter);
+
+ g_content_exporter_add_to_gtk_buffer(G_CONTENT_EXPORTER(iter), view->rendering,
+ view->buffer, &pos, insertion->lengths);
+
+ gdk_flush ();
+ gdk_threads_leave();
+
+ done = get_rendering_line_address(iter) + get_rendering_line_length(iter) - start;
+ gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / end);
+
+ }
+
+ gtk_extended_status_bar_remove(statusbar, id);
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/* Détermine le type du composant d'affichage en block. */
G_DEFINE_TYPE(GtkBlockView, gtk_block_view, GTK_TYPE_BIN_VIEW)
@@ -571,43 +793,6 @@ static gboolean gtk_block_view_expose(GtkWidget *widget, GdkEventExpose *event)
/* Impression du désassemblage */
-
-#if 0
- gdk_window_begin_paint_region(GDK_DRAWABLE(widget->window), event->region);
-
- gdk_gc_set_clip_region(bview->gc, event->region);
-
- gdk_gc_get_values(bview->gc, &values);
-
- gdk_color_white(gtk_widget_get_colormap(widget), &white);
- gdk_gc_set_foreground(bview->gc, &white);
-
- gtk_widget_get_size_request(widget, &width, &height);
-
- gdk_draw_rectangle(GDK_DRAWABLE(widget->window), bview->gc,
- TRUE, 0, 0, width, height);
-
- gdk_gc_set_foreground(bview->gc, &values.foreground);
- /*
- y = event->area.y;
- iter = g_rendering_line_find_by_y(bview->lines, bview->last, &y);
-
- y = event->area.y - y;
-
- for ( ; iter != NULL && y < (event->area.y + event->area.height);
- iter = g_rendering_line_get_next_iter(bview->lines, iter, bview->last))
- {
- g_rendering_line_draw(iter, GDK_DRAWABLE(widget->window), bview->gc,
- MARGIN_SPACE, 2 * MARGIN_SPACE + GTK_BLOCK_VIEW(bview)->line_height,
- y, GTK_BLOCK_VIEW(bview)->line_height, GTK_BLOCK_VIEW(bview)->rendering);
-
- y += GTK_BLOCK_VIEW(bview)->line_height;
-
- }
- */
- gdk_window_end_paint(GDK_DRAWABLE(widget->window));
-#endif
-
gtk_text_layout_set_screen_width (GTK_BLOCK_VIEW(bview)->layout,
MAX (1, 1000));
@@ -730,40 +915,48 @@ void gtk_block_view_set_format(GtkBlockView *view, const exe_format *format)
static void gtk_block_view_set_rendering_lines(GtkBlockView *view, GRenderingLine *lines, GRenderingLine *last)
{
- size_t lengths[SAR_COUNT]; /* Différentes tailles de zone */
- GRenderingLine *iter; /* Boucle de parcours */
- GtkTextIter pos; /* Point d'insertion */
- GtkTextMark *mark; /* Marquage de ligne associée */
- PangoTabArray *tabs; /* Tailles de tabulation */
- GdkRectangle rect; /* Zone d'un point */
+ GWorkQueue *queue; /* Gestionnaire de différés */
+ GDelayedInsertion *insertion; /* Insertions à mener */
- lengths[SAR_ADDRESS] = 0;
- lengths[SAR_CODE] = 0;
- lengths[SAR_INSTRUCTION] = 0;
+ queue = get_work_queue();
- for (iter = GTK_BIN_VIEW(view)->lines;
- iter != NULL;
- iter = g_rendering_line_get_next_iter(GTK_BIN_VIEW(view)->lines, iter, GTK_BIN_VIEW(view)->last))
- {
- g_signal_connect(iter, "rendering-line-flags-changed",
- G_CALLBACK(gtk_block_view_update_margin), view);
+ insertion = g_delayed_insertion_new(view);
- if (iter != GTK_BIN_VIEW(view)->lines)
- {
- gtk_text_buffer_get_end_iter(view->buffer, &pos);
- gtk_text_buffer_insert_with_tags(view->buffer, &pos, "\n", 1, NULL);
- }
+ g_signal_connect(insertion, "work-completed",
+ G_CALLBACK(gtk_block_view_complete_building_content), view);
- gtk_text_buffer_get_end_iter(view->buffer, &pos);
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(insertion));
- mark = gtk_text_buffer_create_mark(view->buffer, NULL, &pos, TRUE);
- g_object_set_data(G_OBJECT(mark), "line", iter);
+}
- g_content_exporter_add_to_gtk_buffer(G_CONTENT_EXPORTER(iter), view->rendering,
- view->buffer, &pos, lengths);
- }
+/******************************************************************************
+* *
+* Paramètres : insertion = travail d'insertion effectué. *
+* view = composant GTK à mettre à jour. *
+* *
+* Description : Achève la construction de la visualisation des lignes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_block_view_complete_building_content(GDelayedInsertion *insertion, GtkBlockView *view)
+{
+ size_t lengths[SAR_COUNT]; /* Différentes tailles de zone */
+ GtkTextIter pos; /* Point d'insertion */
+ PangoTabArray *tabs; /* Tailles de tabulation */
+ GdkRectangle rect; /* Zone d'un point */
+
+ lengths[SAR_ADDRESS] = insertion->lengths[SAR_ADDRESS];
+ lengths[SAR_CODE] = insertion->lengths[SAR_CODE];
+ lengths[SAR_INSTRUCTION] = insertion->lengths[SAR_INSTRUCTION];
+ gdk_threads_enter();
+
+ gtk_text_buffer_get_end_iter(view->buffer, &pos);
gtk_text_layout_move_iter_visually(view->layout, &pos, -1);
gtk_text_layout_get_iter_location(view->layout, &pos, &rect);
@@ -808,6 +1001,11 @@ static void gtk_block_view_set_rendering_lines(GtkBlockView *view, GRenderingLin
gtk_block_view_recompute_size_request(view);
+ gdk_flush ();
+ gdk_threads_leave();
+
+ g_signal_emit_by_name(view, "lines-set");
+
}
diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c
index cc2d930..d62cc33 100644
--- a/src/gtkext/gtkgraphview.c
+++ b/src/gtkext/gtkgraphview.c
@@ -45,6 +45,10 @@ struct _GtkGraphView
GtkBinView **childs; /* Liste des sous-blocs */
size_t childs_count; /* Taille de cette liste */
+ size_t ready; /* Construction complète */
+ GMutex *mutex; /* Accès à la variable */
+ GCond *cond; /* Attente de changement */
+
GtkLinkRenderer **links; /* Liste des liens graphiques */
size_t links_count; /* Nombre de ces liens */
@@ -80,7 +84,10 @@ static void gtk_graph_view_define_main_address(GtkGraphView *, vmpa_t);
static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *, vmpa_t, gint *, gint *);
/* Définit la liste complète des éléments du futur graphique. */
-static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *, GRenderingLine *, GRenderingLine *, size_t *);
+static GtkBinView **gtk_graph_view_load_nodes(GtkGraphView *, GOpenidaBinary *, GRenderingLine *, GRenderingLine *);
+
+/* Prend note de la fin d'une construction d'une visualisation. */
+static void notify_graph_view(GtkBinView *, GtkGraphView *);
/* Détermine le type du composant d'affichage en graphique. */
@@ -132,6 +139,9 @@ static void gtk_graph_view_init(GtkGraphView *view)
binview->define_address = (define_main_address_fc)gtk_graph_view_define_main_address;
binview->get_coordinates = (get_addr_coordinates_fc)gtk_graph_view_get_address_coordinates;
+ view->mutex = g_mutex_new();
+ view->cond = g_cond_new();
+
}
@@ -255,6 +265,8 @@ static void gtk_graph_view_set_rendering_lines(GtkGraphView *view, GRenderingLin
{
gtk_graph_view_reset(view);
+ g_signal_emit_by_name(view, "lines-set");
+
}
@@ -308,7 +320,7 @@ static void gtk_graph_view_define_main_address(GtkGraphView *view, vmpa_t addr)
first = g_rendering_line_find_by_address(GTK_BIN_VIEW(view)->lines, GTK_BIN_VIEW(view)->last, start);
last = g_rendering_line_find_by_address(GTK_BIN_VIEW(view)->lines, GTK_BIN_VIEW(view)->last, end - 1);
- view->childs = gtk_graph_view_load_nodes(GTK_BIN_VIEW(view)->binary, first, last, &view->childs_count);
+ view->childs = gtk_graph_view_load_nodes(view, GTK_BIN_VIEW(view)->binary, first, last);
build_graph_view(GTK_FIXED(view), view->childs, view->childs_count);
@@ -363,10 +375,10 @@ static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *view, vmp
/******************************************************************************
* *
-* Paramètres : binary = contenu binaire à l'origine des lignes. *
+* Paramètres : view = composant d'affichage GTK à mettre à jour. *
+* binary = contenu binaire à l'origine des lignes. *
* first = première ligne à analyser. *
* last = dernière ligne à analyser. *
-* count = nombre d'éléments créés. [OUT] *
* *
* Description : Définit la liste complète des éléments du futur graphique. *
* *
@@ -376,16 +388,28 @@ static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *view, vmp
* *
******************************************************************************/
-static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *binary, GRenderingLine *first, GRenderingLine *last, size_t *count)
+static GtkBinView **gtk_graph_view_load_nodes(GtkGraphView *view, GOpenidaBinary *binary, GRenderingLine *first, GRenderingLine *last)
{
GtkBinView **result; /* Liste à retourner */
+ size_t *count; /* Nombre d'éléments créés. */
GRenderingLine *begin; /* Début d'un groupe de lignes */
GRenderingLine *end; /* Fin d'un groupe de lignes */
GRenderingLine *iter; /* Boucle de parcours */
result = NULL;
+
+ view->ready = 0;
+
+ count = &view->childs_count;
*count = 0;
+ /**
+ * Comme la fonction est appelée depuis un événement et utilise des threads et GTK,
+ * on doit lever temporairement le verrou GDK.
+ */
+ gdk_flush ();
+ gdk_threads_leave();
+
begin = NULL;
for (iter = first; iter != NULL; iter = g_rendering_line_get_next_iter(first, iter, last))
@@ -395,7 +419,8 @@ static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *binary, GRendering
result = (GtkBinView **)realloc(result, ++(*count) * sizeof(GtkBinView *));
result[*count - 1] = GTK_BIN_VIEW(gtk_block_view_new(MRD_GRAPH));
- gtk_widget_show(GTK_WIDGET(result[*count - 1]));
+
+ g_signal_connect(result[*count - 1], "lines-set", G_CALLBACK(notify_graph_view), view);
gtk_bin_view_show_border(result[*count - 1], true);
gtk_bin_view_set_rendering_lines(result[*count - 1], binary, begin, end);
@@ -412,7 +437,8 @@ static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *binary, GRendering
result = (GtkBinView **)realloc(result, ++(*count) * sizeof(GtkBinView *));
result[*count - 1] = GTK_BIN_VIEW(gtk_block_view_new(MRD_GRAPH));
- gtk_widget_show(GTK_WIDGET(result[*count - 1]));
+
+ g_signal_connect(result[*count - 1], "lines-set", G_CALLBACK(notify_graph_view), view);
gtk_bin_view_show_border(result[*count - 1], true);
gtk_bin_view_set_rendering_lines(result[*count - 1], binary, begin, end);
@@ -428,13 +454,22 @@ static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *binary, GRendering
result = (GtkBinView **)realloc(result, ++(*count) * sizeof(GtkBinView *));
result[*count - 1] = GTK_BIN_VIEW(gtk_block_view_new(MRD_GRAPH));
- gtk_widget_show(GTK_WIDGET(result[*count - 1]));
+
+ g_signal_connect(result[*count - 1], "lines-set", G_CALLBACK(notify_graph_view), view);
gtk_bin_view_show_border(result[*count - 1], true);
gtk_bin_view_set_rendering_lines(result[*count - 1], binary, begin, end);
}
+ /* Attente de la fin de construction */
+ g_mutex_lock(view->mutex);
+ while (view->ready < *count)
+ g_cond_wait(view->cond, view->mutex);
+ g_mutex_unlock(view->mutex);
+
+ gdk_threads_enter();
+
return result;
@@ -443,6 +478,35 @@ static GtkBinView **gtk_graph_view_load_nodes(GOpenidaBinary *binary, GRendering
/******************************************************************************
* *
+* Paramètres : view = composant d'affichage prêt à utilisation. *
+* parent = composant d'affichage supérieur. *
+* *
+* Description : Prend note de la fin d'une construction d'une visualisation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void notify_graph_view(GtkBinView *view, GtkGraphView *parent)
+{
+ g_mutex_lock(parent->mutex);
+
+ parent->ready++;
+
+ g_cond_signal(parent->cond);
+ g_mutex_unlock(parent->mutex);
+
+ g_signal_handlers_disconnect_by_func(view, G_CALLBACK(notify_graph_view), parent);
+
+ gtk_widget_show(GTK_WIDGET(view));
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : view = composant GTK à mettre à jour. *
* links = liens graphiques entre les blocs à intégrer. *
* count = quantité de ces liens graphiques. *
diff --git a/src/main.c b/src/main.c
index 41ea7ce..a3fa5ae 100644
--- a/src/main.c
+++ b/src/main.c
@@ -31,11 +31,11 @@
#include "editor.h"
#include "params.h"
#include "project.h"
-#include "analysis/delayed.h"
#include "analysis/exporter.h"
#include "arch/processor.h"
#include "format/format.h"
#include "format/mangling/demangler.h"
+#include "glibext/delayed.h"
#include "gtkext/support.h"
#include "plugins/pglist.h"
@@ -112,7 +112,7 @@ int main(int argc, char **argv)
editor = create_editor();
gtk_widget_show(editor);
- init_disassembly_manager(G_OBJECT(editor));
+ init_work_queue(G_OBJECT(editor));
init_all_plugins(G_OBJECT(editor));
diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c
index 6d47f57..6725fd8 100644
--- a/src/plugins/pglist.c
+++ b/src/plugins/pglist.c
@@ -77,7 +77,7 @@ bool init_all_plugins(GObject *ref)
{
_list.ref = ref;
- browse_directory_for_plugins(&_list, PACKAGE_SOURCE_DIR "/plugins");
+ browse_directory_for_plugins(&_list, PACKAGE_SOURCE_DIR "/plugins.disabled");
return true;
diff --git a/src/project.c b/src/project.c
index cf76a33..14261f3 100644
--- a/src/project.c
+++ b/src/project.c
@@ -44,6 +44,10 @@ typedef struct _loaded_binary
{
GOpenidaBinary *binary; /* Binaire en question */
+ bool lines_set; /* Construction complète */
+ GMutex *mutex; /* Accès à la variable */
+ GCond *cond; /* Attente de changement */
+
GtkWidget *views[BVW_COUNT]; /* Composants pour l'affichage */
} loaded_binary;
@@ -52,6 +56,9 @@ typedef struct _loaded_binary
/* Met en place un nouveau binaire pour un projet. */
loaded_binary *load_openida_binary(GOpenidaBinary *);
+/* Prend note de la fin d'une construction d'une visualisation. */
+static void notify_loaded_binary(GtkBinView *, loaded_binary *);
+
/* Fournit un support d'affichage donné pour un binaire chargé. */
GtkWidget *get_loaded_binary_view(const loaded_binary *, BinaryView);
@@ -68,6 +75,7 @@ struct openida_project
loaded_binary **binaries; /* Fichiers binaires associés */
size_t binaries_count; /* Nombre de ces fichiers */
+ GMutex *mutex; /* Modification de la liste */
@@ -108,8 +116,15 @@ loaded_binary *load_openida_binary(GOpenidaBinary *binary)
result->binary = binary;
+ result->mutex = g_mutex_new();
+ result->cond = g_cond_new();
+
for (i = 0; i < BVW_COUNT; i++)
{
+ /* Préparation du support */
+
+ gdk_threads_enter();
+
scrolledwindow = qck_create_scrolled_window(NULL, NULL);
switch (i)
@@ -123,15 +138,37 @@ loaded_binary *load_openida_binary(GOpenidaBinary *binary)
break;
}
+ gdk_flush ();
+ gdk_threads_leave();
+
+ result->lines_set = false;
+
+ g_signal_connect(view, "lines-set", G_CALLBACK(notify_loaded_binary), result);
+
gtk_bin_view_set_rendering_lines(GTK_BIN_VIEW(view), binary,
g_openida_binary_get_lines(binary), NULL);
+ /* Attente de la fin de construction */
+ g_mutex_lock(result->mutex);
+ while (!result->lines_set)
+ g_cond_wait(result->cond, result->mutex);
+ g_mutex_unlock(result->mutex);
+
+ g_signal_handlers_disconnect_by_func(view, G_CALLBACK(notify_loaded_binary), result);
+
+ /* Intégration finale */
+
+ gdk_threads_enter();
+
gtk_widget_show(view);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwindow), view);
result->views[i] = scrolledwindow;
+ gdk_flush ();
+ gdk_threads_leave();
+
}
return result;
@@ -139,8 +176,29 @@ loaded_binary *load_openida_binary(GOpenidaBinary *binary)
}
+/******************************************************************************
+* *
+* Paramètres : view = composant d'affichage prêt à utilisation. *
+* binary = binaire chargé et encadré. *
+* *
+* Description : Prend note de la fin d'une construction d'une visualisation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void notify_loaded_binary(GtkBinView *view, loaded_binary *binary)
+{
+ g_mutex_lock(binary->mutex);
+ binary->lines_set = true;
+ g_cond_signal(binary->cond);
+ g_mutex_unlock(binary->mutex);
+
+}
@@ -220,8 +278,16 @@ openida_project *create_empty_openida_project(GObject *ref)
result->ref = ref;
+ result->mutex = g_mutex_new();
+ if (result->mutex == NULL)
+ goto crop_error;
+
return result;
+ crop_error:
+
+ return NULL;
+
}
@@ -402,18 +468,28 @@ bool has_storing_filename(const openida_project *project)
* *
* Description : Attache un fichier donné à un projet donné. *
* *
-* Retour : - *
+* Retour : Emplacement de l'élément créé. *
* *
* Remarques : - *
* *
******************************************************************************/
-void attach_binary_to_openida_project(openida_project *project, GOpenidaBinary *binary)
+size_t attach_binary_to_openida_project(openida_project *project, GOpenidaBinary *binary)
{
+ size_t result; /* Indice à retourner */
+
+ g_mutex_lock(project->mutex);
+
project->binaries = (loaded_binary **)realloc(project->binaries,
- ++project->binaries_count * sizeof(loaded_binary *));
+ ++project->binaries_count * sizeof(loaded_binary *));
+
+ result = project->binaries_count - 1;
+
+ g_mutex_unlock(project->mutex);
- project->binaries[project->binaries_count - 1] = load_openida_binary(binary);
+ project->binaries[result] = load_openida_binary(binary);
+
+ return result;
}
@@ -679,11 +755,7 @@ void display_new_binary_of_openida_project(GOpenidaBinary *binary, openida_proje
GtkDockItem *ditem; /* Panneau avec ses infos. */
GtkBinView *binview; /* Affichage à faire défiler */
-
-
-
- attach_binary_to_openida_project(project, binary);
- index = project->binaries_count - 1;
+ index = attach_binary_to_openida_project(project, binary);
dpanel = GTK_DOCK_PANEL(g_object_get_data(project->ref, "binpanel"));
@@ -691,10 +763,13 @@ void display_new_binary_of_openida_project(GOpenidaBinary *binary, openida_proje
title = g_openida_binary_to_string(binary);
+ gdk_threads_enter();
+
ditem = gtk_dock_item_new(strrchr(title, '/') + 1, view);
gtk_dock_item_set_desc(ditem, title);
gtk_dock_panel_add_item(dpanel, ditem);
-
+ gdk_flush ();
+ gdk_threads_leave();
}
diff --git a/src/project.h b/src/project.h
index 815d922..cf4c9e2 100644
--- a/src/project.h
+++ b/src/project.h
@@ -76,7 +76,7 @@ bool has_storing_filename(const openida_project *);
/* Attache un fichier donné à un projet donné. */
-void attach_binary_to_openida_project(openida_project *, GOpenidaBinary *);
+size_t attach_binary_to_openida_project(openida_project *, GOpenidaBinary *);
/* Détache un fichier donné à un projet donné. */
void detach_binary_to_openida_project(openida_project *, GOpenidaBinary *);
diff --git a/src/shell.c b/src/shell.c
index 2d3420f..76e26bb 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -105,8 +105,8 @@ GtkWidget *build_shell_panel(GObject *ref)
vte_terminal_set_cursor_blinks(VTE_TERMINAL(term), TRUE);
-#if 0
- vte_terminal_fork_command (term, "/bin/sh", NULL, NULL, "/", 0, 0, 0);
+#if 1
+ //vte_terminal_fork_command (term, "/bin/sh", NULL, NULL, "/", 0, 0, 0);
return result;
#endif