From e505ea74b63394100f47233295f0a1835ffb99c2 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 14 Oct 2018 15:54:04 +0200
Subject: Refined measures of elapsed time.

---
 plugins/devdbg/speed.c        | 187 ++++++++++++++++++++++++++++++++++++------
 plugins/devdbg/speed.h        |   3 +
 plugins/pychrysalide/plugin.c |  10 +++
 src/format/format.c           |   8 ++
 src/plugins/pglist.h          |   3 +
 src/plugins/plugin-def.h      |  20 ++++-
 src/plugins/plugin-int.h      |   4 +
 src/plugins/plugin.c          |  33 ++++++++
 src/plugins/plugin.h          |   3 +
 9 files changed, 243 insertions(+), 28 deletions(-)

diff --git a/plugins/devdbg/speed.c b/plugins/devdbg/speed.c
index f9fccfe..935fbd9 100644
--- a/plugins/devdbg/speed.c
+++ b/plugins/devdbg/speed.c
@@ -24,39 +24,46 @@
 #include "speed.h"
 
 
+#include <assert.h>
 #include <malloc.h>
-#include <time.h>
+#include <string.h>
 #include <sys/time.h>
-#include <sys/resource.h>
 
 
+#include <i18n.h>
+
+
+#include <common/extstr.h>
 #include <plugins/plugin-def.h>
 
 
 
 DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("Speed Measure", "Tracks to time spent for disassembling code", "0.1.0",
+                                PGA_FORMAT_ANALYSIS_STARTED,PGA_FORMAT_ANALYSIS_ENDED,
+                                PGA_FORMAT_POST_ANALYSIS_STARTED, PGA_FORMAT_POST_ANALYSIS_ENDED,
                                 PGA_DISASSEMBLY_STARTED, PGA_DISASSEMBLY_ENDED);
 
 
 /* Mémorisation des résultats de chronométrages */
 typedef struct _speed_measure
 {
-    clock_t points[2];                      /* Points de mesure successifs */
     unsigned long usages[2];                /* Taux d'utilisation du CPU   */
 
 } speed_measure;
 
 
+/* Affiche une mesure de temps écoulé. */
+static void show_elapsed_time(const GPluginModule *, const char *, const speed_measure *);
+
+
 
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : plugin  = greffon à manipuler.                               *
-*                action  = type d'action attendue.                            *
-*                binary  = binaire dont le contenu est en cours de traitement.*
-*                status  = barre de statut à tenir informée.                  *
-*                context = contexte de désassemblage.                         *
+*                title   = désignation humaine de la mesure menée.            *
+*                measure = mesure de temps écoulé.                            *
 *                                                                             *
-*  Description : Exécute une action pendant un désassemblage de binaire.      *
+*  Description : Affiche une mesure de temps écoulé.                          *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -64,23 +71,158 @@ typedef struct _speed_measure
 *                                                                             *
 ******************************************************************************/
 
-G_MODULE_EXPORT void process_binary_disassembly(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context)
+static void show_elapsed_time(const GPluginModule *plugin, const char *title, const speed_measure *measure)
+{
+    char *tmp;                              /* Construction temporaire     */
+    double seconds;                         /* Secondes écoulées           */
+    unsigned long minutes;                  /* Minutes écoulées            */
+    unsigned long hours;                    /* Heures écoulées             */
+    char *msg;                              /* Message à faire passer      */
+
+    tmp = NULL;
+
+    seconds = (double)(measure->usages[1] - measure->usages[0]) / 1000000;
+
+    if (seconds > 60)
+    {
+        minutes = seconds / 60;
+        seconds -= minutes * 60;
+    }
+    else
+        minutes = 0;
+
+    if (minutes > 60)
+    {
+        hours = minutes / 60;
+        minutes %= 60;
+    }
+    else
+        hours = 0;
+
+    msg = strdup(title);
+
+    if (hours > 0)
+    {
+        asprintf(&tmp, " %lu", hours);
+        msg = stradd(msg, tmp);
+        free(tmp);
+
+        msg = stradd(msg, _("h"));
+
+    }
+
+    if (minutes > 0)
+    {
+        asprintf(&tmp, " %lu", minutes);
+        msg = stradd(msg, tmp);
+        free(tmp);
+
+        msg = stradd(msg, _("m"));
+
+    }
+
+    if (seconds > 0.01)
+    {
+        asprintf(&tmp, " %.2f", seconds);
+        msg = stradd(msg, tmp);
+        free(tmp);
+
+        msg = stradd(msg, _("s"));
+
+    }
+
+    if (tmp != NULL)
+        g_plugin_module_log_simple_message(plugin, LMT_INFO, msg);
+
+    free(msg);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                action = type d'action attendue.                             *
+*                format = format de binaire à manipuler pendant l'opération.  *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Procède à une opération liée à l'analyse d'un format.        *
+*                                                                             *
+*  Retour      : Bilan de l'exécution du traitement.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT bool handle_binary_format_analysis(const GPluginModule *plugin, PluginAction action, GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status)
 {
     speed_measure *measure;                 /* Suivi des progressions      */
+    struct timeval point;                   /* Point de mesure courant     */
 
-    void take_measure(clock_t *point, unsigned long *usage)
+    switch (action)
     {
-        struct rusage rusage;                /* Notification des usages     */
+        case PGA_FORMAT_ANALYSIS_STARTED:
+        case PGA_FORMAT_POST_ANALYSIS_STARTED:
+
+            measure = (speed_measure *)calloc(1, sizeof(speed_measure));
+            g_object_set_data(G_OBJECT(format), "speed_measure", measure);
+
+            gettimeofday(&point, NULL);
+            measure->usages[0] = point.tv_sec * 1000000 + point.tv_usec;
+
+            break;
+
+        case PGA_FORMAT_ANALYSIS_ENDED:
+        case PGA_FORMAT_POST_ANALYSIS_ENDED:
 
-        *point = clock();
+            measure = (speed_measure *)g_object_get_data(G_OBJECT(format), "speed_measure");
 
-        getrusage(RUSAGE_THREAD, &rusage);
+            gettimeofday(&point, NULL);
+            measure->usages[1] = point.tv_sec * 1000000 + point.tv_usec;
 
-        *usage = rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec;
-        *usage += rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec;
+            if (action == PGA_FORMAT_ANALYSIS_ENDED)
+                show_elapsed_time(plugin, _("Whole elapsed time for format analysis:"), measure);
+            else
+                show_elapsed_time(plugin, _("Whole elapsed time for format post-analysis:"), measure);
+
+            g_object_set_data(G_OBJECT(format), "speed_measure", NULL);
+            free(measure);
+
+            break;
+
+        default:
+            assert(false);
+            break;
 
     }
 
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin  = greffon à manipuler.                               *
+*                action  = type d'action attendue.                            *
+*                binary  = binaire dont le contenu est en cours de traitement.*
+*                status  = barre de statut à tenir informée.                  *
+*                context = contexte de désassemblage.                         *
+*                                                                             *
+*  Description : Exécute une action pendant un désassemblage de binaire.      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT void process_binary_disassembly(const GPluginModule *plugin, PluginAction action, GLoadedBinary *binary, GtkStatusStack *status, GProcContext *context)
+{
+    speed_measure *measure;                 /* Suivi des progressions      */
+    struct timeval point;                   /* Point de mesure courant     */
+
     switch (action)
     {
         case PGA_DISASSEMBLY_STARTED:
@@ -88,23 +230,19 @@ G_MODULE_EXPORT void process_binary_disassembly(const GPluginModule *plugin, Plu
             measure = (speed_measure *)calloc(1, sizeof(speed_measure));
             g_object_set_data(G_OBJECT(binary), "speed_measure", measure);
 
-            take_measure(&measure->points[0], &measure->usages[0]);
+            gettimeofday(&point, NULL);
+            measure->usages[0] = point.tv_sec * 1000000 + point.tv_usec;
 
             break;
 
-
         case PGA_DISASSEMBLY_ENDED:
 
             measure = (speed_measure *)g_object_get_data(G_OBJECT(binary), "speed_measure");
 
-            take_measure(&measure->points[1], &measure->usages[1]);
-
-#define SHOW_SPEED(pg, sm, title, p0, p1) \
-            g_plugin_module_log_variadic_message(pg, LMT_INFO, title ": %.2g (%.2g)",                           \
-                                                 (double)(sm->points[p1] - sm->points[p0]) / CLOCKS_PER_SEC,    \
-                                                 (sm->usages[p1] - sm->usages[p0]) / 1000000.0);
+            gettimeofday(&point, NULL);
+            measure->usages[1] = point.tv_sec * 1000000 + point.tv_usec;
 
-            SHOW_SPEED(plugin, measure, "Whole elapsed time for disassembly", 0, 1);
+            show_elapsed_time(plugin, _("Whole elapsed time for disassembly:"), measure);
 
             g_object_set_data(G_OBJECT(binary), "speed_measure", NULL);
             free(measure);
@@ -112,6 +250,7 @@ G_MODULE_EXPORT void process_binary_disassembly(const GPluginModule *plugin, Plu
             break;
 
         default:
+            assert(false);
             break;
 
     }
diff --git a/plugins/devdbg/speed.h b/plugins/devdbg/speed.h
index 4367570..e99d81c 100644
--- a/plugins/devdbg/speed.h
+++ b/plugins/devdbg/speed.h
@@ -30,6 +30,9 @@
 
 
 
+/* Procède à une opération liée à l'analyse d'un format. */
+G_MODULE_EXPORT bool handle_binary_format_analysis(const GPluginModule *, PluginAction, GBinFormat *, wgroup_id_t, GtkStatusStack *);
+
 /* Exécute une action pendant un désassemblage de binaire. */
 G_MODULE_EXPORT void process_binary_disassembly(const GPluginModule *, PluginAction , GLoadedBinary *, GtkStatusStack *, GProcContext *);
 
diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c
index eb6d00d..e57ffaf 100644
--- a/plugins/pychrysalide/plugin.c
+++ b/plugins/pychrysalide/plugin.c
@@ -747,11 +747,21 @@ static bool py_plugin_module_define_constants(PyTypeObject *obj_type)
     result = true;
 
     result &= PyDict_AddIntMacro(obj_type, PGA_BASIC_NONE);
+
     result &= PyDict_AddIntMacro(obj_type, PGA_PLUGIN_INIT);
     result &= PyDict_AddIntMacro(obj_type, PGA_PLUGIN_EXIT);
+
     result &= PyDict_AddIntMacro(obj_type, PGA_CONTENT_EXPLORER);
     result &= PyDict_AddIntMacro(obj_type, PGA_CONTENT_RESOLVER);
+    result &= PyDict_AddIntMacro(obj_type, PGA_CONTENT_ANALYZED);
+
+    result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_ANALYSIS_STARTED);
+    result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_PRELOAD);
     result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_LOADER_LAST);
+    result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_ANALYSIS_ENDED);
+    result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_POST_ANALYSIS_STARTED);
+    result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_POST_ANALYSIS_ENDED);
+
     result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_STARTED);
     result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_RAW);
     result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_HOOKED_LINK);
diff --git a/src/format/format.c b/src/format/format.c
index ac6b215..de57e4c 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -326,10 +326,14 @@ bool g_binary_format_analyze(GBinFormat *format, wgroup_id_t gid, GtkStatusStack
     bool result;                            /* Bilan à retourner           */
     GBinFormatClass *class;                 /* Classe de l'instance        */
 
+    handle_binary_format_analysis(PGA_FORMAT_ANALYSIS_STARTED, format, gid, status);
+
     class = G_BIN_FORMAT_GET_CLASS(format);
 
     result = class->analyze(format, gid, status);
 
+    handle_binary_format_analysis(PGA_FORMAT_ANALYSIS_ENDED, format, gid, status);
+
     return result;
 
 }
@@ -470,11 +474,15 @@ void g_binary_format_complete_analysis(GBinFormat *format, wgroup_id_t gid, GtkS
 {
     GBinFormatClass *class;                 /* Classe de l'instance        */
 
+    handle_binary_format_analysis(PGA_FORMAT_POST_ANALYSIS_STARTED, format, gid, status);
+
     class = G_BIN_FORMAT_GET_CLASS(format);
 
     if (class->complete != NULL)
         class->complete(format, gid, status);
 
+    handle_binary_format_analysis(PGA_FORMAT_POST_ANALYSIS_ENDED, format, gid, status);
+
 }
 
 
diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h
index 7cc4416..5fc2867 100644
--- a/src/plugins/pglist.h
+++ b/src/plugins/pglist.h
@@ -98,6 +98,9 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
 
 /* DPS_FORMAT */
 
+#define handle_binary_format_analysis(a, f, g, s) \
+    process_all_plugins_for(a, g_plugin_module_handle_binary_format_analysis, f, g, s)
+
 #define handle_binary_format(a, f, s) \
     process_all_plugins_for(a, g_plugin_module_handle_binary_format, f, s)
 
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index 643b6e2..f404b14 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -130,11 +130,23 @@ typedef enum _PluginAction
      * DPC_BINARY_PROCESSING | DPS_FORMAT
      */
 
-    /* Accompagnement du chargement (fin) */
-    PGA_FORMAT_LOADER_LAST = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(0),
+    /* Début de l'analyse d'un format */
+    PGA_FORMAT_ANALYSIS_STARTED      = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(0),
 
-    /* Accompagnement du chargement (fin) */
-    PGA_FORMAT_PRELOAD     = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(1),
+    /* Accompagnement du chargement */
+    PGA_FORMAT_PRELOAD               = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(1),
+
+    /* Accompagnement du chargement */
+    PGA_FORMAT_LOADER_LAST           = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(2),
+
+    /* Fin de l'analyse d'un format */
+    PGA_FORMAT_ANALYSIS_ENDED        = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(3),
+
+    /* Début de la vague finale d'analyse d'un format */
+    PGA_FORMAT_POST_ANALYSIS_STARTED = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(4),
+
+    /* Début de la vague finale d'analyse d'un format */
+    PGA_FORMAT_POST_ANALYSIS_ENDED   = DPC_BINARY_PROCESSING | DPS_FORMAT | DEFINE_PLUGIN_ACTION(5),
 
     /**
      * DPC_BINARY_PROCESSING | DPS_DISASSEMBLY
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index d04d9ab..0ab4f56 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -53,6 +53,9 @@ typedef void (* pg_handle_content_fc) (const GPluginModule *, PluginAction, GBin
 /* Procède à une opération liée à un contenu chargé. */
 typedef void (* pg_handle_loaded_fc) (const GPluginModule *, PluginAction, GLoadedContent *, wgroup_id_t, GtkStatusStack *);
 
+/* Assure l'interprétation d'un format en différé. */
+typedef bool (* pg_handle_format_analysis_fc) (const GPluginModule *, PluginAction, GBinFormat *, wgroup_id_t, GtkStatusStack *);
+
 /* Procède à une opération liée au format de fichier uniquement. */
 typedef bool (* pg_handle_format_fc) (const GPluginModule *, PluginAction, GBinFormat *, GtkStatusStack *);
 
@@ -124,6 +127,7 @@ struct _GPluginModule
 
     pg_handle_content_fc handle_content;    /* Explorations ou résolutions */
     pg_handle_loaded_fc handle_loaded;      /* Traitement de contenu chargé*/
+    pg_handle_format_analysis_fc handle_fmt_analysis; /* Analyse de format */
     pg_handle_format_fc handle_format;      /* Manipulation du format      */
     pg_preload_format_fc preload_format;    /* Préchargement d'un format   */
 
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 40f44ce..b63b263 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -334,6 +334,16 @@ GPluginModule *g_plugin_module_new(const gchar *filename)
 
                         switch (action)
                         {
+                            case PGA_FORMAT_ANALYSIS_STARTED:
+                            case PGA_FORMAT_ANALYSIS_ENDED:
+                            case PGA_FORMAT_POST_ANALYSIS_STARTED:
+                            case PGA_FORMAT_POST_ANALYSIS_ENDED:
+                                if (!load_plugin_symbol(result->module,
+                                                        "handle_binary_format_analysis",
+                                                        &result->handle_fmt_analysis))
+                                    goto bad_plugin;
+                                break;
+
                             case PGA_FORMAT_LOADER_LAST:
                                 if (!load_plugin_symbol(result->module,
                                                         "handle_binary_format", &result->handle_format))
@@ -781,6 +791,29 @@ void g_plugin_module_handle_loaded_content(const GPluginModule *plugin, PluginAc
 *  Paramètres  : plugin = greffon à manipuler.                                *
 *                action = type d'action attendue.                             *
 *                format = format de binaire à manipuler pendant l'opération.  *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Procède à une opération liée à l'analyse d'un format.        *
+*                                                                             *
+*  Retour      : Bilan de l'exécution du traitement.                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_plugin_module_handle_binary_format_analysis(const GPluginModule *plugin, PluginAction action, GBinFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+    return plugin->handle_fmt_analysis(plugin, action, format, gid, status);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                action = type d'action attendue.                             *
+*                format = format de binaire à manipuler pendant l'opération.  *
 *                status = barre de statut à tenir informée.                   *
 *                                                                             *
 *  Description : Procède à une opération liée au format de fichier uniquement.*
diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h
index a73cc6f..718531a 100644
--- a/src/plugins/plugin.h
+++ b/src/plugins/plugin.h
@@ -97,6 +97,9 @@ void g_plugin_module_handle_binary_content(const GPluginModule *, PluginAction,
 /* Procède à une opération liée à un contenu chargé. */
 void g_plugin_module_handle_loaded_content(const GPluginModule *, PluginAction, GLoadedContent *, wgroup_id_t, GtkStatusStack *);
 
+/* Procède à une opération liée à l'analyse d'un format. */
+bool g_plugin_module_handle_binary_format_analysis(const GPluginModule *, PluginAction, GBinFormat *, wgroup_id_t, GtkStatusStack *);
+
 /* Procède à une opération liée au format de fichier uniquement. */
 bool g_plugin_module_handle_binary_format(const GPluginModule *, PluginAction, GBinFormat *, GtkStatusStack *);
 
-- 
cgit v0.11.2-87-g4458