From f21c18a6933036bd4cfec25446ac363c63997c13 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 16 Apr 2015 21:51:10 +0000
Subject: Fixed some bugs in the basic blocks building.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@512 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                   |  6 ++++
 src/analysis/disass/loop.c  | 14 ++++++++
 src/analysis/disass/macro.c | 88 +++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 106 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 05c70ad..6830213 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+15-04-16  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/loop.c:
+	* src/analysis/disass/macro.c:
+	Fix some bugs in the basic blocks building.
+
 15-04-12  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/glibext/gbufferline.c:
diff --git a/src/analysis/disass/loop.c b/src/analysis/disass/loop.c
index 44fa6d5..9a99bc4 100644
--- a/src/analysis/disass/loop.c
+++ b/src/analysis/disass/loop.c
@@ -227,6 +227,20 @@ static void track_loops_in_code(const GArchProcessor *proc, const mrange_t *rang
         if (g_arch_instruction_is_return(iter))
             break;
 
+        /**
+         * Afin de détecter les boucles le plus en aval possible,
+         * on marque toutes les arrivées potentielles de boucles comme jalons.
+         * Ainsi la détection se réalise sur l'ultime saut qui boucle effectivement.
+         */
+        if (g_arch_instruction_has_sources(iter))
+        {
+            addr = get_mrange_addr(irange);
+
+            if (is_new_exec_flow(flow, addr))
+                add_step_into_exec_flow(flow, addr);
+
+        }
+
         /* Analyse des destinations */
 
         dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL);
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c
index 75032fa..96a3b25 100644
--- a/src/analysis/disass/macro.c
+++ b/src/analysis/disass/macro.c
@@ -877,7 +877,7 @@ static bool compute_first_common_addr_in_group(const branch_group *group, vmpa2t
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-
+#include "../../arch/instruction-int.h"
 static GInstrBlock *build_instruction_block_simple(GArchInstruction *instrs, code_coverage *coverage, GArchInstruction **first, GArchInstruction *cur)
 {
     GInstrBlock *result;                    /* Regroupement à retourner    */
@@ -979,6 +979,59 @@ static GInstrBlock *build_instruction_blocks_ite(GArchInstruction *instrs, code_
     GInstrBlock *block;                     /* Nouveau bloc mis en place   */
 
     has_common = compute_first_common_addr(true_branch, false_branch, next);
+
+
+    if (!has_common)
+    {
+        code_coverage *_sub_coverage;        /* Couverture pour les suivants*/
+
+
+        result = g_virtual_block_new();
+
+
+        /* Branche 'true' */
+
+        _sub_coverage = dup_code_coverage(coverage, get_entry_to_branch(true_branch));
+
+        block = build_instruction_blocks(instrs, _sub_coverage);
+
+        delete_code_coverage(_sub_coverage);
+
+        printf("===> !TRUE_BRANCH = %p\n", block);
+
+        if (block != NULL)
+            g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
+
+        /* Branche 'false' */
+
+        _sub_coverage = dup_code_coverage(coverage, get_entry_to_branch(false_branch));
+
+        block = build_instruction_blocks(instrs, _sub_coverage);
+
+        delete_code_coverage(_sub_coverage);
+
+        printf("===> !FALSE_BRANCH = %p\n", block);
+
+        if (block != NULL)
+            g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
+
+        /* Conclusion */
+
+        if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(result)) == 0)
+        {
+            g_object_unref(G_OBJECT(result));
+            result = NULL;
+        }
+
+        return result;
+
+
+
+
+    }
+
+    assert(has_common);
+
     if (!has_common) printf("   === nothing in common\n");
     if (!has_common) return NULL;
 
@@ -1153,7 +1206,7 @@ static GInstrBlock *build_instruction_blocks(GArchInstruction *instrs, code_cove
 
         if (code_coverage_stop_here(coverage, addr)) break;
 
-        /* On s'arrêter si l'instruction est déjà décompilée */
+        /* On s'arrête si l'instruction est déjà décompilée */
         if (is_range_processed_in_coverage(coverage, range)) break;
 
         if (first == NULL)
@@ -1161,6 +1214,13 @@ static GInstrBlock *build_instruction_blocks(GArchInstruction *instrs, code_cove
 
         last = iter;
 
+        /**
+         * On s'arrête également en fin de procédure.
+         * L'expérience montre qu'il peut y avoir plusieurs fins dans une routine,
+         * et donc des fins en milieu de couverture de cette même routine.
+         */
+        if (g_arch_instruction_is_return(iter)) break;
+
         /* On n'approfondit que les chemins qui se séparent */
         if (!g_arch_instruction_has_destinations(iter))
         {
@@ -1211,6 +1271,30 @@ static GInstrBlock *build_instruction_blocks(GArchInstruction *instrs, code_cove
 
                     break;
 
+                case ILT_LOOP:
+                    /**
+                     * Lorsque l'on désassemble un flot d'instructions et que l'on rencontre
+                     * une amorce de boucle, il y a deux cas de figure :
+                     *
+                     *    - soit il s'agit d'un ancien JUMP, et la reprise du désassemblage
+                     *      se fera à partir de l'adresse ciblée.
+                     *
+                     *    - soit il s'agit d'un branchement conditionnel dont une des branches
+                     *      conduit à un rebouclage. Le désassemblage s'arrête alors pour la
+                     *      partie en boucle car il n'y a plus d'adresse commune pour la suite.
+                     *
+                     * Il reste donc à forcer une coupure dans le cas suivant :
+                     *
+                     *       ...
+                     *       jmp xxxx
+                     *    loc:
+                     *       ...
+                     *
+                     * Il suffit de ne pas initialiser 'next_addr' et de laisser la main à d'éventuelles
+                     * autres destinations voisines.
+                     */
+                     break;
+
                 case ILT_CASE_JUMP:
                     branch = extend_branch_group(&cases_branches);
                     break;
-- 
cgit v0.11.2-87-g4458