From 9dad150aedfae6423f1166665d47674df51014d2 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 12 Jan 2016 22:31:50 +0100
Subject: Used all available CPUs to compute routines limits.

---
 ChangeLog                          |  12 ++
 src/analysis/disass/disassembler.c |   2 +-
 src/analysis/disass/fetch.c        |   1 -
 src/analysis/disass/limit.c        | 292 ++++++++++++++++++++++++++++++++++---
 src/analysis/disass/limit.h        |   6 +-
 5 files changed, 291 insertions(+), 22 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 61dd761..44486bc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+16-01-12  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/disassembler.c:
+	Update code.
+
+	* src/analysis/disass/fetch.c:
+	Typo.
+
+	* src/analysis/disass/limit.c:
+	* src/analysis/disass/limit.h:
+	Use all available CPUs to compute routines limits.
+
 16-01-10  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/limit.c:
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index c563b2e..272529c 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -341,7 +341,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta
 
     //qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare);
 
-    limit_all_routines(disass->format, proc, routines, routines_count, statusbar, id);
+    limit_all_routines(disass->format, proc, routines, routines_count, gid, id);
 
     gtk_extended_status_bar_remove(statusbar, id);
 
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index 29d8923..e9098eb 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -522,7 +522,6 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, wgroup
      * Première phase de désassemblage : suivi des chemins tracés.
      */
 
-
     g_work_queue_set_extra_wait_callback(queue, gid,
                                          (wait_for_incoming_works_cb)check_if_extra_wait_is_needed,
                                          template.ctx);
diff --git a/src/analysis/disass/limit.c b/src/analysis/disass/limit.c
index dd99643..4fd931d 100644
--- a/src/analysis/disass/limit.c
+++ b/src/analysis/disass/limit.c
@@ -27,10 +27,206 @@
 #include <malloc.h>
 
 
+#include "../../glibext/delayed-int.h"
+
+
+
+/* ------------------------- CALCULS DE LIMITES DE ROUTINES ------------------------- */
+
+
+#define G_TYPE_LIMIT_COMPUTING               g_limit_computing_get_type()
+#define G_LIMIT_COMPUTING(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_limit_computing_get_type(), GLimitComputing))
+#define G_IS_LIMIT_COMPUTING(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_limit_computing_get_type()))
+#define G_LIMIT_COMPUTING_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_LIMIT_COMPUTING, GLimitComputingClass))
+#define G_IS_LIMIT_COMPUTING_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_LIMIT_COMPUTING))
+#define G_LIMIT_COMPUTING_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_LIMIT_COMPUTING, GLimitComputingClass))
+
+
+/* Fraction de routines à limiter (instance) */
+typedef struct _GLimitComputing
+{
+    GDelayedWork parent;                    /* A laisser en premier        */
+
+    const GArchProcessor *proc;             /* Processeurs avec ses instr. */
+
+    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */
+    size_t exe_count;                       /* Nombre de ces zones         */
+
+    GBinRoutine **routines;                 /* Liste de routines à traiter */
+    size_t count;                           /* Taille de cette liste       */
+    size_t begin;                           /* Point de départ du parcours */
+    size_t end;                             /* Point d'arrivée exclu       */
+
+    bstatus_id_t id;                        /* Identifiant pour messages   */
+
+} GLimitComputing;
+
+/* Fraction de routines à limiter (classe) */
+typedef struct _GLimitComputingClass
+{
+    GDelayedWorkClass parent;               /* A laisser en premier        */
+
+} GLimitComputingClass;
+
+
+/* Indique le type défini pour les tâches de calculs de limites. */
+GType g_limit_computing_get_type(void);
+
+/* Initialise la classe des tâches de calculs de limites. */
+static void g_limit_computing_class_init(GLimitComputingClass *);
+
+/* Initialise une tâche de calculs de limites. */
+static void g_limit_computing_init(GLimitComputing *);
+
+/* Supprime toutes les références externes. */
+static void g_limit_computing_dispose(GLimitComputing *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_limit_computing_finalize(GLimitComputing *);
+
+/* Crée une tâche de calculs de limites différée. */
+static GLimitComputing *g_limit_computing_new(const GArchProcessor *, mrange_t *, size_t, GBinRoutine **, size_t, size_t, size_t, bstatus_id_t);
 
 /* Recherche la zone correspond à une adresse donnée. */
 static const mrange_t *find_x_range_for_addr(const mrange_t *, size_t, const vmpa2t *);
 
+/* Assure le calcul de limites de routines en différé. */
+static void g_limit_computing_process(GLimitComputing *, GtkExtStatusBar *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           CALCULS DE LIMITES DE ROUTINES                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour les tâches de calculs de limites. */
+G_DEFINE_TYPE(GLimitComputing, g_limit_computing, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des tâches de calculs de limites.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_limit_computing_class_init(GLimitComputingClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GDelayedWorkClass *work;                /* Version en classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_limit_computing_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_limit_computing_finalize;
+
+    work = G_DELAYED_WORK_CLASS(klass);
+
+    work->run = (run_task_fc)g_limit_computing_process;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : computing = instance à initialiser.                          *
+*                                                                             *
+*  Description : Initialise une tâche de calculs de limites.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_limit_computing_init(GLimitComputing *computing)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : computing = instance d'objet GLib à traiter.                 *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_limit_computing_dispose(GLimitComputing *computing)
+{
+    G_OBJECT_CLASS(g_limit_computing_parent_class)->dispose(G_OBJECT(computing));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : computing = instance d'objet GLib à traiter.                 *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_limit_computing_finalize(GLimitComputing *computing)
+{
+    G_OBJECT_CLASS(g_limit_computing_parent_class)->finalize(G_OBJECT(computing));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc     = ensemble d'instructions désassemblées.            *
+*                routines = prototypes existants à insérer.                   *
+*                count    = quantité de ces prototypes.                       *
+*                begin    = point de départ du parcours de liste.             *
+*                end      = point d'arrivée exclu du parcours.                *
+*                id       = identifiant du message affiché à l'utilisateur.   *
+*                                                                             *
+*  Description : Crée une tâche de calculs de limites différée.               *
+*                                                                             *
+*  Retour      : Tâche créée.                                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GLimitComputing *g_limit_computing_new(const GArchProcessor *proc, mrange_t *exe_ranges, size_t exe_count, GBinRoutine **routines, size_t count, size_t begin, size_t end, bstatus_id_t id)
+{
+    GLimitComputing *result;                /* Tâche à retourner           */
+
+    result = g_object_new(G_TYPE_LIMIT_COMPUTING, NULL);
+
+    result->proc = proc;
+
+    result->exe_ranges = exe_ranges;
+    result->exe_count = exe_count;
+
+    result->routines = routines;
+    result->count = count;
+    result->begin = begin;
+    result->end = end;
+
+    result->id = id;
+
+    return result;
+
+}
 
 
 /******************************************************************************
@@ -64,14 +260,10 @@ static const mrange_t *find_x_range_for_addr(const mrange_t *ranges, size_t coun
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format    = format du binaire concerné par la procédure.     *
-*                proc      = ensemble d'instructions désassemblées.           *
-*                routines  = prototypes existants à insérer.                  *
-*                count     = quantité de ces prototypes.                      *
-*                statusbar = barre de statut avec progression à mettre à jour.*
-*                id        = identifiant du message affiché à l'utilisateur.  *
+*  Paramètres  : computing  = récupération à mener.                           *
+*                statusbar = barre de statut à tenir informée.                *
 *                                                                             *
-*  Description : S'assure que toutes les routines ont une taille définie.     *
+*  Description : Assure le calcul de limites de routines en différé.          *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -79,31 +271,30 @@ static const mrange_t *find_x_range_for_addr(const mrange_t *ranges, size_t coun
 *                                                                             *
 ******************************************************************************/
 
-void limit_all_routines(GExeFormat *format, const GArchProcessor *proc, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
+static void g_limit_computing_process(GLimitComputing *computing, GtkExtStatusBar *statusbar)
 {
-    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */
-    size_t exe_count;                       /* Nombre de ces zones         */
     size_t i;                               /* Boucle de parcours          */
+    GBinRoutine *routine;                   /* Routine en traitement       */
     const mrange_t *range;                  /* Emplacement courant         */
     vmpa2t addr;                            /* Adresse à conserver         */
     GArchInstruction *start;                /* Première instruction        */
     phys_t diff;                            /* Taille définie par déduction*/
     mrange_t new;                           /* Nouvel emplacement taillé   */
 
-    exe_ranges = g_exe_format_get_x_ranges(format, &exe_count);
-
-    for (i = 0; i < count; i++)
+    for (i = computing->begin; i < computing->end; i++)
     {
         //gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);
 
-        range = g_binary_routine_get_range(routines[i]);
+        routine = computing->routines[i];
+
+        range = g_binary_routine_get_range(routine);
         if (get_mrange_length(range) > 0) continue;
 
         copy_vmpa(&addr, get_mrange_addr(range));
 
         /* Marquage de la première instruction */
 
-        start = g_arch_processor_find_instr_by_address(proc, &addr);
+        start = g_arch_processor_find_instr_by_address(computing->proc, &addr);
 
 
         if (start == NULL) continue;
@@ -112,9 +303,9 @@ void limit_all_routines(GExeFormat *format, const GArchProcessor *proc, GBinRout
         g_arch_instruction_set_flag(start, AIF_ROUTINE_START);
 
         /* Si on peut se raccrocher à la routine suivante... */
-        if ((i + 1) < count)
+        if ((i + 1) < computing->count)
         {
-            range = g_binary_routine_get_range(routines[i + 1]);
+            range = g_binary_routine_get_range(computing->routines[i + 1]);
 
             diff = compute_vmpa_diff(&addr, get_mrange_addr(range));
 
@@ -123,7 +314,7 @@ void limit_all_routines(GExeFormat *format, const GArchProcessor *proc, GBinRout
         /* Sinon on va jusqu'à la fin de la zone ! */
         else
         {
-            range = find_x_range_for_addr(exe_ranges, exe_count, &addr);
+            range = find_x_range_for_addr(computing->exe_ranges, computing->exe_count, &addr);
             if (range == NULL) continue;
 
             diff = compute_vmpa_diff(&addr, get_mrange_addr(range));
@@ -133,10 +324,73 @@ void limit_all_routines(GExeFormat *format, const GArchProcessor *proc, GBinRout
 
         init_mrange(&new, &addr, diff);
 
-        g_binary_routine_set_range(routines[i], &new);
+        g_binary_routine_set_range(routine, &new);
 
     }
 
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                            POINT D'ENTREE ET DECOUPAGES                            */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format   = format du binaire concerné par la procédure.      *
+*                proc     = ensemble d'instructions désassemblées.            *
+*                routines = prototypes existants à insérer.                   *
+*                count    = quantité de ces prototypes.                       *
+*                gid      = identifiant du groupe de travail à utiliser.      *
+*                id       = identifiant du message affiché à l'utilisateur.   *
+*                                                                             *
+*  Description : S'assure que toutes les routines ont une taille définie.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void limit_all_routines(GExeFormat *format, const GArchProcessor *proc, GBinRoutine **routines, size_t count, wgroup_id_t gid, bstatus_id_t id)
+{
+    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */
+    size_t exe_count;                       /* Nombre de ces zones         */
+    guint runs_count;                       /* Qté d'exécutions parallèles */
+    size_t run_size;                        /* Volume réparti par exécution*/
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    guint i;                                /* Boucle de parcours          */
+    size_t begin;                           /* Début de bloc de traitement */
+    size_t end;                             /* Fin d'un bloc de traitement */
+    GLimitComputing *computing;             /* Tâche de calcul à programmer*/
+
+    exe_ranges = g_exe_format_get_x_ranges(format, &exe_count);
+
+    runs_count = g_get_num_processors();
+
+    run_size = count / runs_count;
+
+    queue = get_work_queue();
+
+    for (i = 0; i < runs_count; i++)
+    {
+        begin = i * run_size;
+
+        if ((i + 1) < runs_count)
+            end = count - begin;
+        else
+            end = begin + run_size;
+
+        computing = g_limit_computing_new(proc, exe_ranges, exe_count, routines, count, begin, end, id);
+
+        g_work_queue_schedule_work(queue, G_DELAYED_WORK(computing), gid);
+
+    }
+
+    g_work_queue_wait_for_completion(queue, gid);
+
     if (exe_ranges != NULL)
         free(exe_ranges);
 
diff --git a/src/analysis/disass/limit.h b/src/analysis/disass/limit.h
index eeffc71..2fa3303 100644
--- a/src/analysis/disass/limit.h
+++ b/src/analysis/disass/limit.h
@@ -28,12 +28,16 @@
 #include "../routine.h"
 #include "../../arch/processor.h"
 #include "../../format/executable.h"
+#include "../../glibext/delayed.h"
 #include "../../gtkext/gtkextstatusbar.h"
 
 
 
+/* -------------------------- POINT D'ENTREE ET DECOUPAGES -------------------------- */
+
+
 /* S'assure que toutes les routines ont une taille définie. */
-void limit_all_routines(GExeFormat *, const GArchProcessor *, GBinRoutine **, size_t, GtkExtStatusBar *, bstatus_id_t);
+void limit_all_routines(GExeFormat *, const GArchProcessor *, GBinRoutine **, size_t, wgroup_id_t, bstatus_id_t);
 
 
 
-- 
cgit v0.11.2-87-g4458