From c9391d0a1d42a05c72fd1c909a00774561ac9f81 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 4 Apr 2015 17:35:53 +0000
Subject: Detected loops in disassembled instructions once again.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@502 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                          | 12 +++++
 src/analysis/disass/disassembler.c |  9 +++-
 src/analysis/disass/loop.c         | 91 ++++++++++++++++++++++++--------------
 src/analysis/disass/loop.h         |  3 +-
 src/analysis/disass/rank.c         | 63 ++++++++++++++++++++++++++
 5 files changed, 142 insertions(+), 36 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0845512..e961e22 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 15-04-04  Cyrille Bagard <nocbos@gmail.com>
 
+	* src/analysis/disass/disassembler.c:
+	Extend the disassembling process.
+
+	* src/analysis/disass/loop.c:
+	* src/analysis/disass/loop.h:
+	Detect loops in disassembled instructions once again.
+
+	* src/analysis/disass/rank.c:
+	Add debug code to display assigned ranks.
+
+15-04-04  Cyrille Bagard <nocbos@gmail.com>
+
 	* src/analysis/block.c:
 	* src/analysis/block.h:
 	* src/analysis/block-int.h:
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index 50c71da..1227e84 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -323,12 +323,19 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta
 
 
 
+    /* Troisième  étape */
 
+    id = gtk_extended_status_bar_push(statusbar, _("Detecting loops..."), true);
 
+    detect_loops_in_code(proc, routines, routines_count, statusbar, id);
 
+    gtk_extended_status_bar_remove(statusbar, id);
 
+    ///
 
-    /* Troisième  étape */
+
+
+    /* Quatrième étape */
 
     id = gtk_extended_status_bar_push(statusbar, _("Establishing links..."), true);
 
diff --git a/src/analysis/disass/loop.c b/src/analysis/disass/loop.c
index 0a06748..0cb346b 100644
--- a/src/analysis/disass/loop.c
+++ b/src/analysis/disass/loop.c
@@ -30,14 +30,10 @@
 
 
 
-#include "../../arch/instruction.h"
-
-
-
 /* Suivi du flot d'exécution */
 typedef struct _exec_flow
 {
-    vmpa_t *steps;                          /* Jalons dans l'exécution     */
+    vmpa2t *steps;                          /* Jalons dans l'exécution     */
     size_t count;                           /* Quantité de ces points      */
 
 } exec_flow;
@@ -53,13 +49,13 @@ static exec_flow *dup_exec_flow(const exec_flow *);
 static void delete_exec_flow(exec_flow *);
 
 /* Recherche si le chemin d'exécution a déjà mené à une adresse. */
-static bool is_new_exec_flow(const exec_flow *, vmpa_t);
+static bool is_new_exec_flow(const exec_flow *, const vmpa2t *);
 
 /* Ajoute une adresse jalon dans un flot d'exécution. */
-static void add_step_into_exec_flow(exec_flow *, vmpa_t);
+static void add_step_into_exec_flow(exec_flow *, const vmpa2t *);
 
 /* Suit un flot d'exécution à la recherche de boucles. */
-static void track_loops_in_code(GArchInstruction *, vmpa_t, vmpa_t, exec_flow *);
+static void track_loops_in_code(const GArchProcessor *, const mrange_t *, const vmpa2t *, exec_flow *);
 
 
 
@@ -104,8 +100,8 @@ static exec_flow *dup_exec_flow(const exec_flow *src)
 
     result = (exec_flow *)calloc(1, sizeof(exec_flow));
 
-    result->steps = (vmpa_t *)malloc(src->count * sizeof(vmpa_t));
-    memcpy(result->steps, src->steps, src->count * sizeof(vmpa_t));
+    result->steps = (vmpa2t *)malloc(src->count * sizeof(vmpa2t));
+    memcpy(result->steps, src->steps, src->count * sizeof(vmpa2t));
 
     result->count = src->count;
 
@@ -128,7 +124,8 @@ static exec_flow *dup_exec_flow(const exec_flow *src)
 
 static void delete_exec_flow(exec_flow *flow)
 {
-    free(flow->steps);
+    if (flow->steps != NULL)
+        free(flow->steps);
 
     free(flow);
 
@@ -148,12 +145,12 @@ static void delete_exec_flow(exec_flow *flow)
 *                                                                             *
 ******************************************************************************/
 
-static bool is_new_exec_flow(const exec_flow *flow, vmpa_t addr)
+static bool is_new_exec_flow(const exec_flow *flow, const vmpa2t *addr)
 {
     void *ret;                              /* Conclusion d'une recherche  */
 
-    ret = bsearch(&addr, flow->steps, flow->count,
-                  sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
+    ret = bsearch(addr, flow->steps, flow->count,
+                  sizeof(vmpa2t), (__compar_fn_t)cmp_vmpa);
 
     return (ret == NULL);
 
@@ -173,19 +170,19 @@ static bool is_new_exec_flow(const exec_flow *flow, vmpa_t addr)
 *                                                                             *
 ******************************************************************************/
 
-static void add_step_into_exec_flow(exec_flow *flow, vmpa_t addr)
+static void add_step_into_exec_flow(exec_flow *flow, const vmpa2t *addr)
 {
-    flow->steps = (vmpa_t *)realloc(flow->steps, ++flow->count * sizeof(vmpa_t));
-    flow->steps[flow->count - 1] = addr;
+    flow->steps = (vmpa2t *)realloc(flow->steps, ++flow->count * sizeof(vmpa2t));
+    copy_vmpa(&flow->steps[flow->count - 1], addr);
 
-    qsort(flow->steps, flow->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
+    qsort(flow->steps, flow->count, sizeof(vmpa2t), (__compar_fn_t)cmp_vmpa);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : list  = ensemble d'instructions à parcourir.                 *
+*  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.          *
@@ -198,28 +195,40 @@ static void add_step_into_exec_flow(exec_flow *flow, vmpa_t addr)
 *                                                                             *
 ******************************************************************************/
 
-static void track_loops_in_code(GArchInstruction *list, vmpa_t start, vmpa_t end, exec_flow *flow)
+static void track_loops_in_code(const GArchProcessor *proc, const mrange_t *range, const vmpa2t *start, exec_flow *flow)
 {
     bool exit_track;                        /* Détermine la fin du parcours*/
     GArchInstruction *iter;                 /* Boucle de parcours          */
+    const mrange_t *irange;                 /* Emplacement d'instruction   */
     GArchInstruction **dests;               /* Instr. visée par une autre  */
     InstructionLinkType *types;             /* Type de lien entre lignes   */
     size_t dcount;                          /* Nombre de liens de dest.    */
     size_t i;                               /* Boucle de parcours          */
-    vmpa_t addr;                            /* Prochaine adresse de saut   */
+    const vmpa2t *addr;                     /* Prochaine adresse de saut   */
     exec_flow *next_flow;                   /* Suite de l'exécution        */
 
     add_step_into_exec_flow(flow, start);
 
     exit_track = false;
 
-    for (iter = g_arch_instruction_find_by_address(list, start, true);
+    for (iter = g_arch_processor_find_instr_by_address(proc, start);
          iter != NULL && !exit_track;
-         iter = g_arch_instruction_get_next_iter(list, iter, end))
+         iter = g_arch_instruction_get_next_iter(iter /* FIXME : list*/, iter, ~0))
     {
+        /* L'instruction sort-elle des clous ? */
+
+        irange = g_arch_instruction_get_range(iter);
+
+        if (!mrange_contains_mrange(range, irange))
+            break;
+
+        /* Fin de parcours ? */
+
         if (g_arch_instruction_is_return(iter))
             break;
 
+        /* Analyse des destinations */
+
         dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL);
         if (dcount == 0) continue;
 
@@ -233,18 +242,31 @@ static void track_loops_in_code(GArchInstruction *list, vmpa_t start, vmpa_t end
                     exit_track = true;
                     break;
 
-                case ILT_CALL:
                 case ILT_CATCH_EXCEPTION:
+
+                    irange = g_arch_instruction_get_range(dests[i]);
+                    addr = get_mrange_addr(irange);
+
+                    next_flow = create_exec_flow();
+                    track_loops_in_code(proc, range, addr, next_flow);
+                    delete_exec_flow(next_flow);
+
                     break;
 
-                default:
+                case ILT_EXEC_FLOW:
+                case ILT_JUMP:
+                case ILT_CASE_JUMP:
+                case ILT_JUMP_IF_TRUE:
+                case ILT_JUMP_IF_FALSE:
+
                     /**
                      * On se lance dans d'autres suivis qui vont parcourir le reste des
                      * instructions, donc on peut arrêter le parcours courant ici.
                      */
                     exit_track = true;
 
-                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
+                    irange = g_arch_instruction_get_range(dests[i]);
+                    addr = get_mrange_addr(irange);
 
                     if (!is_new_exec_flow(flow, addr))
                         types[i] = ILT_LOOP;
@@ -252,12 +274,15 @@ static void track_loops_in_code(GArchInstruction *list, vmpa_t start, vmpa_t end
                     else
                     {
                         next_flow = dup_exec_flow(flow);
-                        track_loops_in_code(list, addr, end, next_flow);
+                        track_loops_in_code(proc, range, addr, next_flow);
                         delete_exec_flow(next_flow);
                     }
 
                     break;
 
+                default:
+                    break;
+
             }
 
     }
@@ -267,7 +292,7 @@ static void track_loops_in_code(GArchInstruction *list, vmpa_t start, vmpa_t end
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : list      = ensemble d'instructions à relier.                *
+*  Paramètres  : proc      = ensemble d'instructions à relier.                *
 *                routines  = prototypes existants à insérer.                  *
 *                count     = quantité de ces prototypes.                      *
 *                statusbar = barre de statut avec progression à mettre à jour.*
@@ -281,20 +306,18 @@ static void track_loops_in_code(GArchInstruction *list, vmpa_t start, vmpa_t end
 *                                                                             *
 ******************************************************************************/
 
-void detect_loops_in_code(GArchInstruction *list, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
+void detect_loops_in_code(const GArchProcessor *proc, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
 {
     size_t i;                               /* Boucle de parcours          */
-    vmpa_t start;                           /* Adresse de départ           */
-    vmpa_t end;                             /* Adresse de fin              */
+    const mrange_t *range;                  /* Couverture d'une routine    */
     exec_flow *flow;                        /* Flot d'exécution à suivre   */
 
     for (i = 0; i < count; i++)
     {
-        start = g_binary_routine_get_address(routines[i]);
-        end = start + g_binary_routine_get_size(routines[i]);
+        range = g_binary_routine_get_range(routines[i]);
 
         flow = create_exec_flow();
-        track_loops_in_code(list, start, end, flow);
+        track_loops_in_code(proc, range, get_mrange_addr(range), flow);
         delete_exec_flow(flow);
 
         gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);
diff --git a/src/analysis/disass/loop.h b/src/analysis/disass/loop.h
index 7c8d7b3..f4b05cf 100644
--- a/src/analysis/disass/loop.h
+++ b/src/analysis/disass/loop.h
@@ -26,12 +26,13 @@
 
 
 #include "../routine.h"
+#include "../../arch/processor.h"
 #include "../../gtkext/gtkextstatusbar.h"
 
 
 
 /* Détecte les boucles dans du code machine. */
-void detect_loops_in_code(GArchInstruction *, GBinRoutine **, size_t, GtkExtStatusBar *, bstatus_id_t);
+void detect_loops_in_code(const GArchProcessor *, GBinRoutine **, size_t, GtkExtStatusBar *, bstatus_id_t);
 
 
 
diff --git a/src/analysis/disass/rank.c b/src/analysis/disass/rank.c
index 94494d5..758e15d 100644
--- a/src/analysis/disass/rank.c
+++ b/src/analysis/disass/rank.c
@@ -202,6 +202,69 @@ void rank_routines_blocks(GBinRoutine **routines, size_t count, GtkExtStatusBar
 
         g_instr_block_visit(main_block, (instr_block_visitor_cb)rank_flow_block, main_block);
 
+
+
+        printf("===== BLOCK(S) xXXx ======\n");
+
+
+        bool visit_ranked_block(GInstrBlock *blk, BlockVisitOrder order, int *indent)
+        {
+            int i;
+
+            switch (order)
+            {
+                case BVO_IN:
+                case BVO_PENDING:
+
+                    for (i = 0; i < *indent; i++)
+                        printf("   ");
+
+                    printf("%p '%s'", blk, G_OBJECT_TYPE_NAME(blk));
+
+                    if (G_IS_FLOW_BLOCK(blk))
+                    {
+                        vmpa2t start;
+                        vmpa2t end;
+
+                        g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blk), &start, &end);
+
+                        printf("  0x%08x -> 0x%08x (rank = %u)",
+                               (unsigned int)start.virtual,
+                               (unsigned int)end.virtual,
+                               g_flow_block_get_rank(G_FLOW_BLOCK(blk)));
+
+                    }
+
+                    printf("\n");
+
+                    if (order == BVO_IN) (*indent)++;
+                    break;
+
+                case BVO_OUT:
+                    (*indent)--;
+                    break;
+
+            }
+
+            return true;
+
+        }
+
+        g_instr_block_visit(main_block, (instr_block_visitor_cb)visit_ranked_block, (int []){ 0 });
+
+        printf("\n");
+
+
+
+
+
+
+
+
+
+
+
+
     }
 
 }
-- 
cgit v0.11.2-87-g4458