From fe3ac685849b69d87ad536e80d6f31d08c593eac Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 7 Oct 2015 21:18:39 +0000
Subject: Introduced code coverages to reduce search time.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@588 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                  |  8 ++++++
 src/analysis/disass/loop.c | 26 +++++++++++-------
 src/arch/processor-int.h   |  4 +--
 src/arch/processor.c       | 66 ++++++++++++++++++++++++++--------------------
 src/arch/processor.h       | 10 +++++++
 5 files changed, 74 insertions(+), 40 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b98dfce..9f66771 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+15-10-07  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/loop.c:
+	* src/arch/processor.c:
+	* src/arch/processor.h:
+	* src/arch/processor-int.h:
+	Introduce code coverages to reduce search time.
+
 15-10-06  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/arch/processor.c:
diff --git a/src/analysis/disass/loop.c b/src/analysis/disass/loop.c
index 30265c9..5f97981 100644
--- a/src/analysis/disass/loop.c
+++ b/src/analysis/disass/loop.c
@@ -34,16 +34,17 @@
 
 
 /* Suit un flot d'exécution à la recherche de boucles. */
-static void track_loops_in_code(const GArchProcessor *, const mrange_t *, const vmpa2t *, memfield_t *);
+static void track_loops_in_code(const GArchProcessor *, const instr_coverage *, const mrange_t *, const vmpa2t *, memfield_t *);
 
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : proc  = ensemble d'instructions à parcourir.                 *
-*                start = adresse du début de l'analyse.                       *
-*                end   = adresse de fin de la routine traitée.                *
-*                flow  = ensemble des jalons de l'exécution du code.          *
+*  Paramètres  : proc     = ensemble d'instructions à parcourir.              *
+*                coverage = zone de couverture où rechercher des instructions.*
+*                range    = zone de couverture de la routine analysée.        *
+*                start    = adresse du début de l'analyse.                    *
+*                flow     = ensemble des jalons de l'exécution du code.       *
 *                                                                             *
 *  Description : Suit un flot d'exécution à la recherche de boucles.          *
 *                                                                             *
@@ -53,7 +54,7 @@ static void track_loops_in_code(const GArchProcessor *, const mrange_t *, const
 *                                                                             *
 ******************************************************************************/
 
-static void track_loops_in_code(const GArchProcessor *proc, const mrange_t *range, const vmpa2t *start, memfield_t *flow)
+static void track_loops_in_code(const GArchProcessor *proc, const instr_coverage *coverage, const mrange_t *range, const vmpa2t *start, memfield_t *flow)
 {
     bool exit_track;                        /* Détermine la fin du parcours*/
     GArchInstruction *iter;                 /* Boucle de parcours          */
@@ -69,7 +70,7 @@ static void track_loops_in_code(const GArchProcessor *proc, const mrange_t *rang
 
     exit_track = false;
 
-    for (iter = g_arch_processor_find_instr_by_address(proc, start);
+    for (iter = g_arch_processor_find_covered_instr_by_address(proc, coverage, start);
          iter != NULL && !exit_track;
          iter = g_arch_instruction_get_next_iter(iter /* FIXME : list*/, iter, ~0))
     {
@@ -120,7 +121,7 @@ static void track_loops_in_code(const GArchProcessor *proc, const mrange_t *rang
                     addr = get_mrange_addr(irange);
 
                     next_flow = create_mem_field_from(flow);
-                    track_loops_in_code(proc, range, addr, next_flow);
+                    track_loops_in_code(proc, coverage, range, addr, next_flow);
                     delete_mem_field(next_flow);
 
                     break;
@@ -150,7 +151,7 @@ static void track_loops_in_code(const GArchProcessor *proc, const mrange_t *rang
                     else
                     {
                         next_flow = dup_mem_field(flow);
-                        track_loops_in_code(proc, range, addr, next_flow);
+                        track_loops_in_code(proc, coverage, range, addr, next_flow);
                         delete_mem_field(next_flow);
                     }
 
@@ -186,14 +187,19 @@ void detect_loops_in_code(const GArchProcessor *proc, GBinRoutine **routines, si
 {
     size_t i;                               /* Boucle de parcours          */
     const mrange_t *range;                  /* Couverture d'une routine    */
+    const vmpa2t *start;                    /* Adresse de départ           */
+    const instr_coverage *coverage;         /* Instructions couvertes      */
     memfield_t *flow;                       /* Flot d'exécution à suivre   */
 
     for (i = 0; i < count; i++)
     {
         range = g_binary_routine_get_range(routines[i]);
+        start = get_mrange_addr(range);
+
+        coverage = g_arch_processor_find_coverage_by_address(proc, start);
 
         flow = create_mem_field(range);
-        track_loops_in_code(proc, range, get_mrange_addr(range), flow);
+        track_loops_in_code(proc, coverage, range, start, flow);
         delete_mem_field(flow);
 
         gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);
diff --git a/src/arch/processor-int.h b/src/arch/processor-int.h
index fcd7a52..19076a2 100644
--- a/src/arch/processor-int.h
+++ b/src/arch/processor-int.h
@@ -63,14 +63,14 @@ typedef GArchInstruction * (* disass_instr_fc) (const GArchProcessor *, GProcCon
 
 
 /* Couverture d'un groupe d'instructions */
-typedef struct _instr_coverage
+struct _instr_coverage
 {
     mrange_t range;                         /* Couverture du groupement    */
 
     size_t start;                           /* Indice de départ            */
     size_t count;                           /* Quantité d'inclusions       */
 
-} instr_coverage;
+};
 
 
 
diff --git a/src/arch/processor.c b/src/arch/processor.c
index c70d586..6b60c8c 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -72,9 +72,6 @@ static void g_arch_processor_add_new_coverage(GArchProcessor *, GArchInstruction
 /* Termine la définition d'un nouveau groupe d'instructions. */
 static void g_arch_processor_finish_last_coverage(GArchProcessor *, GArchInstruction *, size_t);
 
-/* Recherche un groupe d'instruction d'après son adresse. */
-static bool g_arch_processor_find_coverage_by_address(const GArchProcessor *, const vmpa2t *, size_t *, size_t *);
-
 
 
 
@@ -399,20 +396,18 @@ static void g_arch_processor_finish_last_coverage(GArchProcessor *proc, GArchIns
 *                                                                             *
 *  Paramètres  : proc  = processeur recensant diverses instructions.          *
 *                addr  = position en mémoire ou physique à chercher.          *
-*                start = indice de départ du groupe concerné trouvé. [OUT]    *
-*                end   = indice de fin du groupe d'instructions visées. [OUT] *
 *                                                                             *
 *  Description : Recherche un groupe d'instruction d'après son adresse.       *
 *                                                                             *
-*  Retour      : Bilan de la recherche menée.                                 *
+*  Retour      : Couverture trouvée ou NULL si aucune.                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool g_arch_processor_find_coverage_by_address(const GArchProcessor *proc, const vmpa2t *addr, size_t *start, size_t *count)
+const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProcessor *proc, const vmpa2t *addr)
 {
-    bool result;                            /* Bilan à retourner           */
+    instr_coverage *result;                 /* Trouvaille à retourner      */
     void *ptr;                              /* Résultat des recherches     */
 
     int search_for_coverage_by_addr(const vmpa2t *a, const instr_coverage *c)
@@ -428,14 +423,7 @@ static bool g_arch_processor_find_coverage_by_address(const GArchProcessor *proc
     ptr = bsearch(addr, proc->coverages, proc->cov_count,
                   sizeof(instr_coverage), (__compar_fn_t)search_for_coverage_by_addr);
 
-    if (ptr != NULL)
-    {
-        result = true;
-        *start = ((instr_coverage *)ptr)->start;
-        *count = ((instr_coverage *)ptr)->count;
-    }
-    else
-        result = false;
+    result = ((instr_coverage *)ptr);
 
     return result;
 
@@ -543,8 +531,37 @@ GArchInstruction *g_arch_processor_get_disassembled_instructions(const GArchProc
 GArchInstruction *g_arch_processor_find_instr_by_address(const GArchProcessor *proc, const vmpa2t *addr)
 {
     GArchInstruction *result;               /* Trouvaille à retourner      */
-    size_t cov_start;                       /* Début d'un groupe ciblé     */
-    size_t cov_count;                       /* Nombre d'éléments à tester  */
+    const instr_coverage *coverage;         /* Couverture fine à fouiller  */
+
+    coverage = g_arch_processor_find_coverage_by_address(proc, addr);
+
+    if (coverage != NULL)
+        result = g_arch_processor_find_covered_instr_by_address(proc, coverage, addr);
+    else
+        result = NULL;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc     = processeur recensant diverses instructions.       *
+*                coverage = zone de couverture fine à fouiller.               *
+*                addr     = position en mémoire ou physique à chercher.       *
+*                                                                             *
+*  Description : Recherche rapidement une instruction d'après son adresse.    *
+*                                                                             *
+*  Retour      : Instruction trouvée à l'adresse donnée, NULL si aucune.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GArchInstruction *g_arch_processor_find_covered_instr_by_address(const GArchProcessor *proc, const instr_coverage *coverage, const vmpa2t *addr)
+{
+    GArchInstruction *result;               /* Trouvaille à retourner      */
     void *ptr;                              /* Résultat des recherches     */
 
     int search_for_instr_by_addr(const vmpa2t *a, const GArchInstruction **b)
@@ -557,17 +574,10 @@ GArchInstruction *g_arch_processor_find_instr_by_address(const GArchProcessor *p
 
     }
 
+    ptr = bsearch(addr, &proc->instructions[coverage->start], coverage->count,
+                  sizeof(GArchInstruction *), (__compar_fn_t)search_for_instr_by_addr);
 
-    if (g_arch_processor_find_coverage_by_address(proc, addr, &cov_start, &cov_count))
-    {
-        ptr = bsearch(addr, &proc->instructions[cov_start], cov_count,
-                      sizeof(GArchInstruction *), (__compar_fn_t)search_for_instr_by_addr);
-
-        result = (ptr != NULL ? *((GArchInstruction **)ptr) : NULL);
-
-    }
-    else
-        result = NULL;
+    result = (ptr != NULL ? *((GArchInstruction **)ptr) : NULL);
 
     return result;
 
diff --git a/src/arch/processor.h b/src/arch/processor.h
index f7d474a..45b9012 100644
--- a/src/arch/processor.h
+++ b/src/arch/processor.h
@@ -81,15 +81,25 @@ GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *, GProcCont
 /* ------------------ MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES ------------------ */
 
 
+/* Couverture d'un groupe d'instructions */
+typedef struct _instr_coverage  instr_coverage;
+
+
 /* Note les instructions désassemblées avec une architecture. */
 void g_arch_processor_set_disassembled_instructions(GArchProcessor *, GArchInstruction *);
 
 /* Fournit les instructions désassemblées pour une architecture. */
 GArchInstruction *g_arch_processor_get_disassembled_instructions(const GArchProcessor *);
 
+/* Recherche un groupe d'instruction d'après son adresse. */
+const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProcessor *, const vmpa2t *);
+
 /* Recherche une instruction d'après son adresse. */
 GArchInstruction *g_arch_processor_find_instr_by_address(const GArchProcessor *, const vmpa2t *);
 
+/* Recherche rapidement une instruction d'après son adresse. */
+GArchInstruction *g_arch_processor_find_covered_instr_by_address(const GArchProcessor *, const instr_coverage *, const vmpa2t *);
+
 /* Fournit l'instruction qui en précède une autre. */
 GArchInstruction *g_arch_processor_get_prev_instr(const GArchProcessor *, const GArchInstruction *);
 
-- 
cgit v0.11.2-87-g4458