From 4dd8356e19b9e58990b2f3e0c4110aa2fe9642d1 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 8 Dec 2012 16:46:49 +0000
Subject: Cut instructions flow into blocks (to be continued).

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@297 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                           |  49 +++++
 configure.ac                        |   1 +
 plugins/androhelpers/androhelpers.c |   7 +-
 plugins/androhelpers/try_n_catch.c  |  48 ++---
 plugins/androhelpers/try_n_catch.h  |   2 +-
 src/analysis/Makefile.am            |   5 +-
 src/analysis/block-int.h            |  58 ++++++
 src/analysis/block.c                | 155 ++++++++++++++
 src/analysis/block.h                |  92 +++++++++
 src/analysis/blocks/Makefile.am     |  19 ++
 src/analysis/blocks/flow.c          | 364 +++++++++++++++++++++++++++++++++
 src/analysis/blocks/flow.h          |  60 ++++++
 src/analysis/blocks/virtual.c       | 244 ++++++++++++++++++++++
 src/analysis/blocks/virtual.h       |  63 ++++++
 src/analysis/decomp/decompiler.c    |   2 +-
 src/analysis/decomp/il.c            |  12 +-
 src/analysis/disass/Makefile.am     |   1 +
 src/analysis/disass/disassembler.c  |  13 ++
 src/analysis/disass/macro.c         | 397 ++++++++++++++++++++++++++++++++++++
 src/analysis/disass/macro.h         |  38 ++++
 src/analysis/routine.h              |   1 +
 src/arch/instruction.c              |   5 +
 src/plugins/plugin-def.h            |   3 +-
 23 files changed, 1604 insertions(+), 35 deletions(-)
 create mode 100644 src/analysis/block-int.h
 create mode 100644 src/analysis/block.c
 create mode 100644 src/analysis/block.h
 create mode 100755 src/analysis/blocks/Makefile.am
 create mode 100644 src/analysis/blocks/flow.c
 create mode 100644 src/analysis/blocks/flow.h
 create mode 100644 src/analysis/blocks/virtual.c
 create mode 100644 src/analysis/blocks/virtual.h
 create mode 100644 src/analysis/disass/macro.c
 create mode 100644 src/analysis/disass/macro.h

diff --git a/ChangeLog b/ChangeLog
index eea5de7..95b54c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,52 @@
+12-12-08  Cyrille Bagard <nocbos@gmail.com>
+
+	* configure.ac:
+	Add the new Makfile from the 'src/analysis/blocks' directory to
+	AC_CONFIG_FILES.
+
+	* plugins/androhelpers/androhelpers.c:
+	* plugins/androhelpers/try_n_catch.c:
+	* plugins/androhelpers/try_n_catch.h:
+	Link exception as soon as possible.
+
+	* src/analysis/block.c:
+	* src/analysis/block.h:
+	* src/analysis/block-int.h:
+	* src/analysis/blocks/flow.c:
+	* src/analysis/blocks/flow.h:
+	* src/analysis/blocks/Makefile.am:
+	* src/analysis/blocks/virtual.c:
+	* src/analysis/blocks/virtual.h:
+	New entries: cut instructions flow into blocks (to be continued).
+
+	* src/analysis/decomp/decompiler.c:
+	* src/analysis/decomp/il.c:
+	Remove debug output.
+
+	* src/analysis/disass/disassembler.c:
+	Add a new phase of disassembling.
+
+	* src/analysis/disass/macro.c:
+	* src/analysis/disass/macro.h:
+	New entries: cut instructions flow into blocks (to be continued).
+
+	* src/analysis/disass/Makefile.am:
+	Add the macro.[ch] files to libanalysisdisass_la_SOURCES.
+
+	* src/analysis/Makefile.am:
+	Add the block*[ch] files to libanalysis_la_SOURCES,
+	blocks/libanalysisblocks.la file to libanalysis_la_LIBADD
+	and blocks to SUBDIRS.
+
+	* src/analysis/routine.h:
+	Include the 'block.h' header for later use.
+
+	* src/arch/instruction.c:
+	Initialize the access list of registers for instructions without operand.
+
+	* src/plugins/plugin-def.h:
+	Add the PGA_BINARY_GROUPED action for plugins.
+
 12-12-05  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/common/extstr.c:
diff --git a/configure.ac b/configure.ac
index 89c11a1..0b2b421 100644
--- a/configure.ac
+++ b/configure.ac
@@ -253,6 +253,7 @@ AC_CONFIG_FILES([Makefile
                  src/Makefile
                  src/analysis/Makefile
                  src/analysis/binaries/Makefile
+                 src/analysis/blocks/Makefile
                  src/analysis/decomp/Makefile
                  src/analysis/disass/Makefile
                  src/analysis/types/Makefile
diff --git a/plugins/androhelpers/androhelpers.c b/plugins/androhelpers/androhelpers.c
index 95714fd..f7360f8 100644
--- a/plugins/androhelpers/androhelpers.c
+++ b/plugins/androhelpers/androhelpers.c
@@ -67,7 +67,7 @@ PluginAction get_plugin_action(const GPluginModule *plugin)
 {
     PluginAction result;                    /* Combinaison à retourner     */
 
-    result = PGA_BINARY_DISASSEMBLED | PGA_BINARY_PRINTED;
+    result = PGA_BINARY_DISASSEMBLED | PGA_BINARY_LINKED | PGA_BINARY_PRINTED;
 
     return result;
 
@@ -97,8 +97,11 @@ bool execute_action_on_binary(GPluginModule *plugin, GLoadedBinary *binary, Plug
     if (action == PGA_BINARY_DISASSEMBLED)
         result &= replace_parameters(binary);
 
+    else if (action == PGA_BINARY_LINKED)
+        result &= process_exception_handlers(binary, true);
+
     else if (action == PGA_BINARY_PRINTED)
-        result &= process_exception_handlers(binary);
+        result &= process_exception_handlers(binary, false);
 
     return result;
 
diff --git a/plugins/androhelpers/try_n_catch.c b/plugins/androhelpers/try_n_catch.c
index 27c7959..d2ab4a9 100644
--- a/plugins/androhelpers/try_n_catch.c
+++ b/plugins/androhelpers/try_n_catch.c
@@ -58,7 +58,7 @@ static void mark_exception_handlers(const GLoadedBinary *, uleb128_t, caught_exc
 static caught_exception **build_all_destinations_list(const GLoadedBinary *, const GBinRoutine *, const encoded_catch_handler_list *, size_t **);
 
 /* Recherche et met en avant tous les gestionnaires d'exception. */
-static void look_for_exception_handlers(const GLoadedBinary *, const GDexFormat *, GDexMethod *);
+static void look_for_exception_handlers(const GLoadedBinary *, const GDexFormat *, GDexMethod *, bool);
 
 
 
@@ -127,7 +127,7 @@ static void attach_caught_code(const GLoadedBinary *binary, const GBinRoutine *r
     first = g_arch_instruction_find_by_address(instrs, start, true);
     next = g_arch_instruction_find_by_address(instrs, end, true);
 
-    if (start == NULL || next == NULL)
+    if (first == NULL || next == NULL)
         return;
 
     /* Si des détachements sont nécessaires... */
@@ -312,6 +312,7 @@ static caught_exception **build_all_destinations_list(const GLoadedBinary *binar
 *  Paramètres  : binary = représentation binaire à traiter.                   *
 *                format = format du binaire Dex.                              *
 *                method = méthode à analyser.                                 *
+*                link   = édition de liens ou impression de commentaires ?    *
 *                                                                             *
 *  Description : Recherche et met en avant tous les gestionnaires d'exception.*
 *                                                                             *
@@ -321,7 +322,7 @@ static caught_exception **build_all_destinations_list(const GLoadedBinary *binar
 *                                                                             *
 ******************************************************************************/
 
-static void look_for_exception_handlers(const GLoadedBinary *binary, const GDexFormat *format, GDexMethod *method)
+static void look_for_exception_handlers(const GLoadedBinary *binary, const GDexFormat *format, GDexMethod *method, bool link)
 {
     const code_item *body;                  /* Description du corps        */
     GBinRoutine *routine;                   /* Abstraction globale         */
@@ -343,29 +344,29 @@ static void look_for_exception_handlers(const GLoadedBinary *binary, const GDexF
     hlist = body->handlers;
     handlers = build_all_destinations_list(binary, routine, hlist, &count);
 
-    /* Pour chaque zone couverte... */
-
-    for (i = 0; i < body->tries_size; i++)
-    {
-        try = &body->tries[i];
-
-        if (!check_covered_area(try, routine))
-            continue;
+    if (link)
+        /* Pour chaque zone couverte... */
+        for (i = 0; i < body->tries_size; i++)
+        {
+            try = &body->tries[i];
 
-        for (index = 0; index < hlist->size; index++)
-            if (try->handler_off == hlist->list[index].offset)
-                break;
+            if (!check_covered_area(try, routine))
+                continue;
 
-        if (index == hlist->size)
-            continue;
+            for (index = 0; index < hlist->size; index++)
+                if (try->handler_off == hlist->list[index].offset)
+                    break;
 
-        attach_caught_code(binary, routine, try, handlers[index], count[index]);
+            if (index == hlist->size)
+                continue;
 
-    }
+            attach_caught_code(binary, routine, try, handlers[index], count[index]);
 
-    /* Ajout des précisions */
+        }
 
-    mark_exception_handlers(binary, hlist->size, handlers, count);
+    else
+        /* Ajout des précisions */
+        mark_exception_handlers(binary, hlist->size, handlers, count);
 
     /* Libération de la mémoire utilisée */
 
@@ -388,6 +389,7 @@ static void look_for_exception_handlers(const GLoadedBinary *binary, const GDexF
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : binary = représentation binaire à traiter.                   *
+*                link   = édition de liens ou impression de commentaires ?    *
 *                                                                             *
 *  Description : Traite tous les gestionnaires d'exception trouvés.           *
 *                                                                             *
@@ -397,7 +399,7 @@ static void look_for_exception_handlers(const GLoadedBinary *binary, const GDexF
 *                                                                             *
 ******************************************************************************/
 
-bool process_exception_handlers(GLoadedBinary *binary)
+bool process_exception_handlers(GLoadedBinary *binary, bool link)
 {
     GDexFormat *format;                     /* Format du binaire chargé    */
     size_t cls_count;                       /* Nombre de classes trouvées  */
@@ -421,14 +423,14 @@ bool process_exception_handlers(GLoadedBinary *binary)
         for (j = 0; j < meth_count; j++)
         {
             method = g_dex_class_get_method(class, false, j);
-            look_for_exception_handlers(binary, format, method);
+            look_for_exception_handlers(binary, format, method, link);
         }
 
         meth_count = g_dex_class_count_methods(class, true);
         for (j = 0; j < meth_count; j++)
         {
             method = g_dex_class_get_method(class, true, j);
-            look_for_exception_handlers(binary, format, method);
+            look_for_exception_handlers(binary, format, method, link);
         }
 
     }
diff --git a/plugins/androhelpers/try_n_catch.h b/plugins/androhelpers/try_n_catch.h
index 5ac4ad5..31a9e5e 100644
--- a/plugins/androhelpers/try_n_catch.h
+++ b/plugins/androhelpers/try_n_catch.h
@@ -30,7 +30,7 @@
 
 
 /* Traite tous les gestionnaires d'exception trouvés. */
-bool process_exception_handlers(GLoadedBinary *);
+bool process_exception_handlers(GLoadedBinary *, bool);
 
 
 
diff --git a/src/analysis/Makefile.am b/src/analysis/Makefile.am
index f58ddca..6409943 100755
--- a/src/analysis/Makefile.am
+++ b/src/analysis/Makefile.am
@@ -3,6 +3,8 @@ noinst_LTLIBRARIES  = libanalysis.la
 
 libanalysis_la_SOURCES =				\
 	binary.h binary.c					\
+	block-int.h							\
+	block.h block.c						\
 	roptions.h roptions.c				\
 	routine.h routine.c					\
 	type-int.h							\
@@ -11,6 +13,7 @@ libanalysis_la_SOURCES =				\
 
 libanalysis_la_LIBADD =					\
 	binaries/libanalysisbinaries.la		\
+	blocks/libanalysisblocks.la			\
 	decomp/libanalysisdecomp.la			\
 	disass/libanalysisdisass.la			\
 	types/libanalysistypes.la
@@ -24,4 +27,4 @@ AM_CPPFLAGS =
 
 AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
 
-SUBDIRS = binaries decomp disass types
+SUBDIRS = binaries blocks decomp disass types
diff --git a/src/analysis/block-int.h b/src/analysis/block-int.h
new file mode 100644
index 0000000..f89fa3c
--- /dev/null
+++ b/src/analysis/block-int.h
@@ -0,0 +1,58 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * block-int.h - prototypes pour la définition interne des blocs d'instructions
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_BLOCK_INT_H
+#define _ANALYSIS_BLOCK_INT_H
+
+
+#include "block.h"
+
+
+
+/* Fournit les différents accès aux registres. */
+typedef const reg_access * (* list_regs_accesses_fc) (const GInstrBlock *, size_t *);
+
+
+
+/* Description d'un bloc d'instructions (instance) */
+struct _GInstrBlock
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    list_regs_accesses_fc list_regs;        /* Liste des accès registres   */
+
+};
+
+/* Description d'un bloc d'instructions (classe) */
+struct _GInstrBlockClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+};
+
+
+
+
+
+
+#endif  /* _ANALYSIS_BLOCK_INT_H */
diff --git a/src/analysis/block.c b/src/analysis/block.c
new file mode 100644
index 0000000..58b1fee
--- /dev/null
+++ b/src/analysis/block.c
@@ -0,0 +1,155 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * block.c - encadrement des instructions par blocs
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "block.h"
+
+
+#include "block-int.h"
+
+
+
+/* Initialise la classe des blocs d'instructions. */
+static void g_instr_block_class_init(GInstrBlockClass *);
+
+/* Initialise un bloc d'instructions. */
+static void g_instr_block_init(GInstrBlock *);
+
+/* Supprime toutes les références externes. */
+static void g_instr_block_dispose(GInstrBlock *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_instr_block_finalize(GInstrBlock *);
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = premier opérande à consulter.                            *
+*                b = second opérande à consulter.                             *
+*                                                                             *
+*  Description : Compare un accès registre avec un autre.                     *
+*                                                                             *
+*  Retour      : Bilan de la comparaison.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int compare_reg_accesses(const reg_access *a, const reg_access *b)
+{
+    return g_arch_register_compare(a->reg, b->reg);
+
+}
+
+
+
+
+
+
+/* Indique le type défini pour un bloc d'instructions. */
+G_DEFINE_TYPE(GInstrBlock, g_instr_block, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des blocs d'instructions.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_instr_block_class_init(GInstrBlockClass *class)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(class);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_instr_block_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_instr_block_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise un bloc d'instructions.                           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_instr_block_init(GInstrBlock *block)
+{
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_instr_block_dispose(GInstrBlock *block)
+{
+    G_OBJECT_CLASS(g_instr_block_parent_class)->dispose(G_OBJECT(block));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_instr_block_finalize(GInstrBlock *block)
+{
+    G_OBJECT_CLASS(g_instr_block_parent_class)->finalize(G_OBJECT(block));
+
+}
diff --git a/src/analysis/block.h b/src/analysis/block.h
new file mode 100644
index 0000000..2a7fb90
--- /dev/null
+++ b/src/analysis/block.h
@@ -0,0 +1,92 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * block.h - prototypes pour l'encadrement des instructions par blocs
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_BLOCK_H
+#define _ANALYSIS_BLOCK_H
+
+
+#include <glib.h>
+#include <glib-object.h>
+
+
+#include "../arch/register.h"
+
+
+
+
+
+
+
+
+/* Note sur le premier accès */
+typedef enum _RegAccessType
+{
+    RAT_NONE    = (0 << 0),                 /* Registre non rencontré      */
+    RAT_READ    = (1 << 0),                 /* Lecture                     */
+    RAT_WRITE   = (1 << 1)                  /* Ecriture                    */
+
+} RegAccessType;
+
+/* Description minimale des accès à un registre */
+typedef struct _reg_access
+{
+    GArchRegister *reg;                     /* Register concerné           */
+
+    RegAccessType first_access;             /* Type du premier accès       */
+    vmpa_t last_write;                      /* Dernière écriture           */
+
+} reg_access;
+
+
+/* Compare un accès registre avec un autre. */
+int compare_reg_accesses(const reg_access *, const reg_access *);
+
+
+
+
+#define G_TYPE_INSTR_BLOCK               g_instr_block_get_type()
+#define G_INSTR_BLOCK(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_instr_block_get_type(), GInstrBlock))
+#define G_IS_INSTR_BLOCK(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_instr_block_get_type()))
+#define G_INSTR_BLOCK_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_INSTR_BLOCK, GInstrBlockClass))
+#define G_IS_INSTR_BLOCK_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_INSTR_BLOCK))
+#define G_INSTR_BLOCK_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_INSTR_BLOCK, GInstrBlockClass))
+
+
+/* Description d'un bloc d'instructions (instance) */
+typedef struct _GInstrBlock GInstrBlock;
+
+/* Description d'un bloc d'instructions (classe) */
+typedef struct _GInstrBlockClass GInstrBlockClass;
+
+
+/* Indique le type défini pour un bloc d'instructions. */
+GType g_instr_block_get_type(void);
+
+
+
+
+
+
+
+
+#endif  /* _ANALYSIS_BLOCK_H */
diff --git a/src/analysis/blocks/Makefile.am b/src/analysis/blocks/Makefile.am
new file mode 100755
index 0000000..7a9e371
--- /dev/null
+++ b/src/analysis/blocks/Makefile.am
@@ -0,0 +1,19 @@
+
+noinst_LTLIBRARIES  = libanalysisblocks.la
+
+libanalysisblocks_la_SOURCES =			\
+	flow.h flow.c						\
+	virtual.h virtual.c
+
+libanalysisblocks_la_LIBADD =	
+
+libanalysisblocks_la_LDFLAGS = 
+
+
+INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+
+AM_CPPFLAGS = 
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+
+SUBDIRS = 
diff --git a/src/analysis/blocks/flow.c b/src/analysis/blocks/flow.c
new file mode 100644
index 0000000..62856dd
--- /dev/null
+++ b/src/analysis/blocks/flow.c
@@ -0,0 +1,364 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * flow.c - encadrement des instructions par blocs d'exécution
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "flow.h"
+
+
+#include <malloc.h>
+
+
+#include "../block-int.h"
+
+
+
+/* Description d'un bloc d'exécution d'instructions (instance) */
+struct _GFlowBlock
+{
+    GInstrBlock parent;                     /* A laisser en premier        */
+
+    GArchInstruction *instrs;               /* Liste complète d'instruct°  */
+    GArchInstruction *first;                /* Première instruction        */
+    GArchInstruction *last;                 /* Dernière instruction        */
+
+    reg_access *accesses;                   /* Commodités d'accès #1       */
+    size_t count;                           /* Commodités d'accès #2       */
+
+};
+
+/* Description d'un bloc d'exécution d'instructions (classe) */
+struct _GFlowBlockClass
+{
+    GInstrBlockClass parent;                /* A laisser en premier        */
+
+};
+
+
+/* Initialise la classe des blocs d'instructions. */
+static void g_flow_block_class_init(GFlowBlockClass *);
+
+/* Initialise un bloc d'instructions. */
+static void g_flow_block_init(GFlowBlock *);
+
+/* Supprime toutes les références externes. */
+static void g_flow_block_dispose(GFlowBlock *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_flow_block_finalize(GFlowBlock *);
+
+/* Prend note de l'usage d'un registre, au besoin. */
+static void g_flow_block_memorize_access(GFlowBlock *, GArchRegister *, RegAccessType, vmpa_t);
+
+/* Note les différents accès aux registres. */
+static void g_flow_block_compute_regs_access(GFlowBlock *);
+
+/* Fournit les différents accès aux registres. */
+static const reg_access *g_flow_block_list_regs_accesses(const GFlowBlock *, size_t *);
+
+
+
+/* Indique le type défini pour un bloc d'exécution d'instructions. */
+G_DEFINE_TYPE(GFlowBlock, g_flow_block, G_TYPE_INSTR_BLOCK);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des blocs d'instructions.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_flow_block_class_init(GFlowBlockClass *class)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(class);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_flow_block_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_flow_block_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise un bloc d'instructions.                           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_flow_block_init(GFlowBlock *block)
+{
+    GInstrBlock *parent;                    /* Instance parente            */
+
+    parent = G_INSTR_BLOCK(block);
+
+    parent->list_regs = (list_regs_accesses_fc)g_flow_block_list_regs_accesses;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_flow_block_dispose(GFlowBlock *block)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    g_object_unref(G_OBJECT(block->instrs));
+    g_object_unref(G_OBJECT(block->first));
+    g_object_unref(G_OBJECT(block->last));
+
+    for (i = 0; i < block->count; i++)
+        g_object_unref(G_OBJECT(block->accesses[i].reg));
+
+    G_OBJECT_CLASS(g_flow_block_parent_class)->dispose(G_OBJECT(block));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_flow_block_finalize(GFlowBlock *block)
+{
+    if (block->accesses != NULL)
+        free(block->accesses);
+
+    G_OBJECT_CLASS(g_flow_block_parent_class)->finalize(G_OBJECT(block));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instrs = liste de toutes les instructions.                   *
+*                first  = première instruction du bloc.                       *
+*                last   = dernière instruction du bloc.                       *
+*                                                                             *
+*  Description : Crée un bloc d'exécution d'instructions.                     *
+*                                                                             *
+*  Retour      : Adresse de la structure mise en place.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GInstrBlock *g_flow_block_new(GArchInstruction *instrs, GArchInstruction *first, GArchInstruction *last)
+{
+    GFlowBlock *result;                     /* Structure à retourner       */
+
+    vmpa_t addr;                            /* Adresse de la destination   */
+
+
+    result = g_object_new(G_TYPE_FLOW_BLOCK, NULL);
+
+
+
+    g_arch_instruction_get_location(first, NULL, NULL, &addr);
+    printf(" ! new block @ 0x%llx - ", addr);
+
+    g_arch_instruction_get_location(last, NULL, NULL, &addr);
+    printf("0x%llx\n", addr);
+
+
+
+
+    result->instrs = instrs;
+    result->first = first;
+    result->last = last;
+
+    g_object_ref(G_OBJECT(result->instrs));
+    g_object_ref(G_OBJECT(result->first));
+    g_object_ref(G_OBJECT(result->last));
+
+    g_flow_block_compute_regs_access(result);
+
+    return G_INSTR_BLOCK(result);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = bloc d'instructions à mettre à jour.                 *
+*                reg   = registre visé par l'opération.                       *
+*                type  = type d'accès à l'opérande.                           *
+*                addr  = adresse de l'instruction associée.                   *
+*                                                                             *
+*  Description : Prend note de l'usage d'un registre, au besoin.              *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_flow_block_memorize_access(GFlowBlock *block, GArchRegister *reg, RegAccessType type, vmpa_t addr)
+{
+    reg_access **accesses;                  /* Commodités d'accès #1       */
+    size_t *count;                          /* Commodités d'accès #2       */
+    reg_access *access;                     /* Accès à manipuler           */
+    bool need_sort;                         /* Insertion donc tri à faire  */
+
+    accesses = &block->accesses;
+    count = &block->count;
+
+    /* Recherche de l'élément à mettre à jour */
+
+    access = bsearch((reg_access []) { { .reg = reg } }, *accesses, *count, sizeof(reg_access),
+                     (__compar_fn_t)compare_reg_accesses);
+
+    if (access == NULL)
+    {
+        *accesses = (reg_access *)realloc(*accesses, ++(*count) * sizeof(reg_access));
+        access = &(*accesses)[*count - 1];
+
+        g_object_ref(G_OBJECT(reg));
+
+        access->reg = reg;
+        access->first_access = RAT_NONE;
+        access->last_write = VMPA_MAX;
+
+        need_sort = true;
+
+    }
+    else need_sort = false;
+
+    /* Mise à jour */
+
+    if (access->first_access == RAT_NONE)
+        access->first_access = type;
+
+    if (type == RAT_WRITE)
+        access->last_write = addr;
+
+    /* Remise en conditions éventuelle */
+
+    if (need_sort)
+        qsort(*accesses, *count, sizeof(reg_access), (__compar_fn_t)compare_reg_accesses);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = bloc d'instructions à parcourir.                     *
+*                                                                             *
+*  Description : Note les différents accès aux registres.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_flow_block_compute_regs_access(GFlowBlock *block)
+{
+    GArchInstruction *iter;                 /* Boucle de parcours #1       */
+    vmpa_t max;                             /* Adresse de fin              */
+    vmpa_t addr;                            /* Adresse d'instruction       */
+    GArchRegister **rregs;                  /* Liste des registres lus     */
+    size_t rcount;                          /* Nombre de registres lus     */
+    GArchRegister **wregs;                  /* Liste des registres écrits  */
+    size_t wcount;                          /* Nombre de registres écrits  */
+    size_t i;                               /* Boucle de parcours #2       */
+
+    g_arch_instruction_get_location(block->last, NULL, NULL, &max);
+    max++;
+
+    for (iter = block->first;
+         iter != NULL;
+         iter = g_arch_instruction_get_next_iter(block->instrs, iter, max))
+    {
+        g_arch_instruction_get_location(iter, NULL, NULL, &addr);
+
+        g_arch_instruction_get_rw_registers(iter, &rregs, &rcount, &wregs, &wcount);
+
+        for (i = 0; i < rcount; i++)
+        {
+            g_flow_block_memorize_access(block, rregs[i], RAT_READ, addr);
+            g_object_unref(G_OBJECT(rregs[i]));
+        }
+
+        for (i = 0; i < wcount; i++)
+        {
+            g_flow_block_memorize_access(block, wregs[i], RAT_WRITE, addr);
+            g_object_unref(G_OBJECT(wregs[i]));
+        }
+
+        if (rregs != NULL) free(rregs);
+        if (wregs != NULL) free(wregs);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = bloc d'instructions à consulter.                     *
+*                count = nombre de registres consignés. [OUT]                 *
+*                                                                             *
+*  Description : Fournit les différents accès aux registres.                  *
+*                                                                             *
+*  Retour      : Liste des accès aux registres.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const reg_access *g_flow_block_list_regs_accesses(const GFlowBlock *block, size_t *count)
+{
+    *count = block->count;
+
+    return block->accesses;
+
+}
diff --git a/src/analysis/blocks/flow.h b/src/analysis/blocks/flow.h
new file mode 100644
index 0000000..cc2eb66
--- /dev/null
+++ b/src/analysis/blocks/flow.h
@@ -0,0 +1,60 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * flow.h - prototypes pour l'encadrement des instructions par blocs d'exécution
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_BLOCKS_FLOW_H
+#define _ANALYSIS_BLOCKS_FLOW_H
+
+
+#include <glib.h>
+#include <glib-object.h>
+
+
+#include "../block.h"
+#include "../../arch/instruction.h"
+
+
+
+#define G_TYPE_FLOW_BLOCK               g_flow_block_get_type()
+#define G_FLOW_BLOCK(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_flow_block_get_type(), GFlowBlock))
+#define G_IS_FLOW_BLOCK(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_flow_block_get_type()))
+#define G_FLOW_BLOCK_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_FLOW_BLOCK, GFlowBlockClass))
+#define G_IS_FLOW_BLOCK_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_FLOW_BLOCK))
+#define G_FLOW_BLOCK_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_FLOW_BLOCK, GFlowBlockClass))
+
+
+/* Description d'un bloc d'exécution d'instructions (instance) */
+typedef struct _GFlowBlock GFlowBlock;
+
+/* Description d'un bloc d'exécution d'instructions (classe) */
+typedef struct _GFlowBlockClass GFlowBlockClass;
+
+
+/* Indique le type défini pour un bloc d'exécution d'instructions. */
+GType g_flow_block_get_type(void);
+
+/* Crée un bloc d'exécution d'instructions. */
+GInstrBlock *g_flow_block_new(GArchInstruction *, GArchInstruction *, GArchInstruction *);
+
+
+
+#endif  /* _ANALYSIS_BLOCKS_FLOW_H */
diff --git a/src/analysis/blocks/virtual.c b/src/analysis/blocks/virtual.c
new file mode 100644
index 0000000..113e333
--- /dev/null
+++ b/src/analysis/blocks/virtual.c
@@ -0,0 +1,244 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * virtual.c - encadrement des instructions par blocs virtuels
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "virtual.h"
+
+
+#include <malloc.h>
+
+
+#include "../block-int.h"
+
+
+
+/* Description d'un bloc d'exécution d'instructions (instance) */
+struct _GVirtualBlock
+{
+    GInstrBlock parent;                     /* A laisser en premier        */
+
+    GArchInstruction *instrs;               /* Liste complète d'instruct°  */
+    GArchInstruction *first;                /* Première instruction        */
+    GArchInstruction *last;                 /* Dernière instruction        */
+
+    reg_access *accesses;                   /* Commodités d'accès #1       */
+    size_t count;                           /* Commodités d'accès #2       */
+
+
+    GInstrBlock **children;                 /* Sous-blocs intégrés         */
+    size_t children_count;                  /* Nombre de ces sous-blocs    */
+
+};
+
+/* Description d'un bloc d'exécution d'instructions (classe) */
+struct _GVirtualBlockClass
+{
+    GInstrBlockClass parent;                /* A laisser en premier        */
+
+};
+
+
+/* Initialise la classe des blocs d'instructions. */
+static void g_virtual_block_class_init(GVirtualBlockClass *);
+
+/* Initialise un bloc d'instructions. */
+static void g_virtual_block_init(GVirtualBlock *);
+
+/* Supprime toutes les références externes. */
+static void g_virtual_block_dispose(GVirtualBlock *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_virtual_block_finalize(GVirtualBlock *);
+
+/* Fournit les différents accès aux registres. */
+static const reg_access *g_virtual_block_list_regs_accesses(const GVirtualBlock *, size_t *);
+
+
+
+/* Indique le type défini pour un bloc virtuel d'instructions. */
+G_DEFINE_TYPE(GVirtualBlock, g_virtual_block, G_TYPE_INSTR_BLOCK);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des blocs d'instructions.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_virtual_block_class_init(GVirtualBlockClass *class)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(class);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_virtual_block_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_virtual_block_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = instance à initialiser.                              *
+*                                                                             *
+*  Description : Initialise un bloc d'instructions.                           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_virtual_block_init(GVirtualBlock *block)
+{
+    GInstrBlock *parent;                    /* Instance parente            */
+
+    parent = G_INSTR_BLOCK(block);
+
+    parent->list_regs = (list_regs_accesses_fc)g_virtual_block_list_regs_accesses;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_virtual_block_dispose(GVirtualBlock *block)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < block->children_count; i++)
+        g_object_unref(G_OBJECT(block->children[i]));
+
+    G_OBJECT_CLASS(g_virtual_block_parent_class)->dispose(G_OBJECT(block));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = instance d'objet GLib à traiter.                     *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_virtual_block_finalize(GVirtualBlock *block)
+{
+    if (block->accesses != NULL)
+        free(block->accesses);
+
+    if (block->children != NULL)
+        free(block->children);
+
+    G_OBJECT_CLASS(g_virtual_block_parent_class)->finalize(G_OBJECT(block));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Crée un bloc virtuel d'instructions.                         *
+*                                                                             *
+*  Retour      : Adresse de la structure mise en place.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GInstrBlock *g_virtual_block_new(void)
+{
+    GVirtualBlock *result;                     /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_VIRTUAL_BLOCK, NULL);
+
+    return G_INSTR_BLOCK(result);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = bloc d'instructions à consulter.                     *
+*                count = nombre de registres consignés. [OUT]                 *
+*                                                                             *
+*  Description : Fournit les différents accès aux registres.                  *
+*                                                                             *
+*  Retour      : Liste des accès aux registres.                               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static const reg_access *g_virtual_block_list_regs_accesses(const GVirtualBlock *block, size_t *count)
+{
+    *count = 0;
+
+    return NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : block = bloc d'instructions à compléter.                     *
+*                child = sous-bloc à insérer.                                 *
+*                                                                             *
+*  Description : Ajoute un bloc au groupe courant.                            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_virtual_block_add_child(GVirtualBlock *block, GInstrBlock *child)
+{
+    block->children = (GInstrBlock **)realloc(block->children,
+                                              ++block->children_count * sizeof(GInstrBlock *));
+
+    block->children[block->children_count - 1] = child;
+
+    g_object_ref(G_OBJECT(child));
+
+}
diff --git a/src/analysis/blocks/virtual.h b/src/analysis/blocks/virtual.h
new file mode 100644
index 0000000..f1f559f
--- /dev/null
+++ b/src/analysis/blocks/virtual.h
@@ -0,0 +1,63 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * virtual.h - prototypes pour l'encadrement des instructions par blocs virtuels
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_BLOCKS_VIRTUAL_H
+#define _ANALYSIS_BLOCKS_VIRTUAL_H
+
+
+#include <glib.h>
+#include <glib-object.h>
+
+
+#include "../block.h"
+#include "../../arch/instruction.h"
+
+
+
+#define G_TYPE_VIRTUAL_BLOCK               g_virtual_block_get_type()
+#define G_VIRTUAL_BLOCK(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_virtual_block_get_type(), GVirtualBlock))
+#define G_IS_VIRTUAL_BLOCK(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_virtual_block_get_type()))
+#define G_VIRTUAL_BLOCK_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_VIRTUAL_BLOCK, GVirtualBlockClass))
+#define G_IS_VIRTUAL_BLOCK_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_VIRTUAL_BLOCK))
+#define G_VIRTUAL_BLOCK_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_VIRTUAL_BLOCK, GVirtualBlockClass))
+
+
+/* Description d'un bloc virtuel d'instructions (instance) */
+typedef struct _GVirtualBlock GVirtualBlock;
+
+/* Description d'un bloc virtuel d'instructions (classe) */
+typedef struct _GVirtualBlockClass GVirtualBlockClass;
+
+
+/* Indique le type défini pour un bloc virtuel d'instructions. */
+GType g_virtual_block_get_type(void);
+
+/* Crée un bloc virtuel d'instructions. */
+GInstrBlock *g_virtual_block_new(void);
+
+/* Ajoute un bloc au groupe courant. */
+void g_virtual_block_add_child(GVirtualBlock *, GInstrBlock *);
+
+
+
+#endif  /* _ANALYSIS_BLOCKS_VIRTUAL_H */
diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c
index 91a9163..1ac177a 100644
--- a/src/analysis/decomp/decompiler.c
+++ b/src/analysis/decomp/decompiler.c
@@ -167,7 +167,7 @@ static void prepare_all_routines_for_decomp(const GLoadedBinary *binary, const c
         max = g_binary_routine_get_address(routines[i])
             + g_binary_routine_get_size(routines[i]);
 
-        printf("##### DECOMPILE '%s' #####\n", g_binary_routine_to_string(routines[i]));
+        //printf("##### DECOMPILE '%s' #####\n", g_binary_routine_to_string(routines[i]));
 
         dinstrs = build_decompiled_block(instrs,
                                          g_binary_routine_get_address(routines[i]),
diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c
index d9b9588..693b8cb 100644
--- a/src/analysis/decomp/il.c
+++ b/src/analysis/decomp/il.c
@@ -253,7 +253,7 @@ GDecInstruction *build_decompiled_block(GArchInstruction *instrs, vmpa_t start,
 
     result = NULL;
 
-    printf("[+] processing 0x%08llx -> 0x%08llx... stop @ 0x%08llx\n", start, end, stop);
+    //printf("[+] processing 0x%08llx -> 0x%08llx... stop @ 0x%08llx\n", start, end, stop);
 
     for (iter = g_arch_instruction_find_by_address(instrs, start, true);
          iter != NULL;
@@ -266,7 +266,7 @@ GDecInstruction *build_decompiled_block(GArchInstruction *instrs, vmpa_t start,
         pite = g_arch_instruction_decompile(iter, ctx);
 
         g_arch_instruction_get_location(iter, NULL, NULL, &addr);
-        printf(" --- decomp %p @ 0x%08llx\n", pite, addr);
+        //printf(" --- decomp %p @ 0x%08llx\n", pite, addr);
 
         /* On n'approfondit que les chemins qui se séparent */
         if (!g_arch_instruction_has_destinations(iter))
@@ -340,11 +340,11 @@ GDecInstruction *build_decompiled_block(GArchInstruction *instrs, vmpa_t start,
             false_dinstr = build_decompiled_block(instrs, false_branch.jumps[0],
                                                   end, next_addr, context);
 
-
+            /*
             printf("{branch : %p (0x%08llx) | %p (0x%08llx)\n",
                    true_dinstr, true_branch.jumps[0],
                    false_dinstr, false_branch.jumps[0]);
-
+            */
             g_ite_instruction_set_branches(G_ITE_INSTRUCTION(pite), true_dinstr, false_dinstr);
 
             if (next_addr == end) break;
@@ -364,7 +364,7 @@ GDecInstruction *build_decompiled_block(GArchInstruction *instrs, vmpa_t start,
 
     first = g_dec_context_get_decomp_instrs(ctx);
 
-    printf(" ... context instr : %p\n", first);
+    //printf(" ... context instr : %p\n", first);
 
     for (dinstr = first;
          dinstr != NULL;
@@ -375,7 +375,7 @@ GDecInstruction *build_decompiled_block(GArchInstruction *instrs, vmpa_t start,
 
     }
 
-    printf(" ... return %p\n", result);
+    //printf(" ... return %p\n", result);
 
     return result;
 
diff --git a/src/analysis/disass/Makefile.am b/src/analysis/disass/Makefile.am
index ce27d15..854c726 100644
--- a/src/analysis/disass/Makefile.am
+++ b/src/analysis/disass/Makefile.am
@@ -6,6 +6,7 @@ libanalysisdisass_la_SOURCES =			\
 	fetch.h fetch.c						\
 	limit.h limit.c						\
 	links.h links.c						\
+	macro.h macro.c						\
 	output.h output.c
 
 libanalysisdisass_la_LDFLAGS = 
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index 6d0bd61..ee56043 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -35,6 +35,7 @@
 #include "fetch.h"
 #include "limit.h"
 #include "links.h"
+#include "macro.h"
 #include "output.h"
 #include "../../decomp/lang/asm.h"
 #include "../../format/format.h"
@@ -267,6 +268,18 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta
 
     /* Quatrième étape */
 
+    id = gtk_extended_status_bar_push(statusbar, _("Grouping routines instructions..."), true);
+
+    qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare);
+
+    group_routines_instructions(*disass->instrs, routines, routines_count, statusbar, id);
+
+    gtk_extended_status_bar_remove(statusbar, id);
+
+    run_plugins_on_binary(disass->binary, PGA_BINARY_GROUPED);
+
+    /* Cinquième étape */
+
     id = gtk_extended_status_bar_push(statusbar, _("Printing disassembled code..."), true);
 
     qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_compare);
diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c
new file mode 100644
index 0000000..fc5d8dc
--- /dev/null
+++ b/src/analysis/disass/macro.c
@@ -0,0 +1,397 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * macro.c - vue macroscopique des liens entre blocs d'instructions
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "macro.h"
+
+
+#include <string.h>
+
+
+#include "../blocks/flow.h"
+#include "../blocks/virtual.h"
+
+
+
+/* Indications sur une branche */
+typedef struct _branch_info
+{
+    vmpa_t *jumps;                          /* Jalons de la branche        */
+    size_t count;                           /* Quantité de ces jalons      */
+
+} branch_info;
+
+
+/* Indique si une adresse est retenue comme point de passage. */
+static bool is_addr_in_branch(const branch_info *, const vmpa_t *, bool);
+
+/* Identifie les différents points de passage d'une branche. */
+static void find_next_jumps(GArchInstruction *, vmpa_t, vmpa_t, branch_info *);
+
+/* Retrouve le point de ralliement entre deux branches. */
+static vmpa_t compute_first_common_addr(branch_info *, branch_info *);
+
+/* Procède à la définition de bloc regroupant des instructions. */
+static GInstrBlock *build_instruction_block(GArchInstruction *, vmpa_t, vmpa_t, vmpa_t);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : info = informations à consulter.                             *
+*                addr = adresse à rechercher.                                 *
+*                fast = autorise une recherche rapide.                        *
+*                                                                             *
+*  Description : Indique si une adresse est retenue comme point de passage.   *
+*                                                                             *
+*  Retour      : true si le jalon est déjà dans la liste, false sinon.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool fast)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+    void *ptr;                              /* Résultat des recherches     */
+
+    result = false;
+
+    if (!fast)
+        for (i = 0; i < info->count && !result; i++)
+            result = (info->jumps[i] == *addr);
+
+    else
+    {
+        ptr = bsearch(addr, info->jumps, info->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
+        result = (ptr != NULL);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instrs = ensemble des instructions d'assemblage.             *
+*                start  = adresse de début du bloc.                           *
+*                end    = adresse de fin du bloc (exclusive).                 *
+*                count  = nombre de sauts détectés. [OUT]                     *
+*                                                                             *
+*  Description : Identifie les différents points de passage d'une branche.    *
+*                                                                             *
+*  Retour      : Jalons dans le flot d'exécution.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end, branch_info *info)
+{
+    GArchInstruction *iter;                 /* Boucle de parcours #1       */
+    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 #2       */
+    vmpa_t addr;                            /* Adresse de la destination   */
+
+    /* On évite de boucler... */
+    if (is_addr_in_branch(info, &start, false))
+        return;
+
+    info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t));
+    info->jumps[info->count - 1] = start;
+
+    /* On suit le flot jusqu'à la prochaine bifurcation */
+    for (iter = g_arch_instruction_find_by_address(instrs, start, true);
+         iter != NULL;
+         iter = g_arch_instruction_get_next_iter(instrs, iter, end))
+    {
+        if (g_arch_instruction_is_return(iter))
+        {
+            iter = NULL;
+            break;
+        }
+
+        if (!g_arch_instruction_has_destinations(iter))
+            continue;
+
+        dcount = g_arch_instruction_get_destinations(iter, &dests, &types);
+
+        for (i = 0; i < dcount; i++)
+            switch (types[i])
+            {
+                case ILT_EXEC_FLOW:
+                case ILT_JUMP:
+                case ILT_JUMP_IF_TRUE:
+                case ILT_JUMP_IF_FALSE:
+                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
+                    find_next_jumps(instrs, addr, end, info);
+                    break;
+
+                default:
+                    break;
+
+            }
+
+        break;
+
+    }
+
+    /* Si on termine... */
+    if (iter != NULL && !is_addr_in_branch(info, &end, false))
+    {
+        info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t));
+        info->jumps[info->count - 1] = end;
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = premier ensemble de jalons à parcourir.                  *
+*                b = second ensemble de jalons à parcourir.                   *
+*                                                                             *
+*  Description : Retrouve le point de ralliement entre deux branches.         *
+*                                                                             *
+*  Retour      : Adresse commune à deux branches.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static vmpa_t compute_first_common_addr(branch_info *a, branch_info *b)
+{
+    vmpa_t result;                          /* Adresse trouvée à retourner */
+    size_t i;                               /* Boucle de parcours          */
+
+    /* Valeur conceptuellement impossible à renvoyer */
+    result = VMPA_MAX;
+
+    //qsort(a->jumps, a->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
+    //qsort(b->jumps, b->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa);
+
+    for (i = 0; i < a->count && result == VMPA_MAX; i++)
+        if (is_addr_in_branch(b, &a->jumps[i], false))
+            result = a->jumps[i];
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instrs = ensemble des instructions d'assemblage.             *
+*                start  = adresse de début du bloc.                           *
+*                end    = adresse de fin du bloc (exclusive).                 *
+*                stop   = adresse d'arrêt en cas de saut ou VMPA_MAX.         *
+*                                                                             *
+*  Description : Procède à la définition de bloc regroupant des instructions. *
+*                                                                             *
+*  Retour      : Bloc créé et enregistré, ou NULL si erreur.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t start, vmpa_t end, vmpa_t stop)
+{
+    GInstrBlock *result;                    /* Regroupement à retourner    */
+    GArchInstruction *first;                /* Première instruction        */
+    GArchInstruction *last;                 /* Dernière instruction        */
+    GArchInstruction *iter;                 /* Boucle de parcours          */
+    vmpa_t addr;                            /* Adresse de la destination   */
+    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          */
+    GInstrBlock *block;                     /* Nouveau bloc mis en place   */
+    branch_info true_branch;                /* Branche 'condition vraie'   */
+    branch_info false_branch;               /* Branche 'condition fausse'  */
+    vmpa_t next_addr;                       /* Prochaine instruction visée */
+
+    result = NULL;
+
+    first = NULL;
+    last = NULL;
+
+    printf("[+] blocking 0x%08llx -> 0x%08llx... stop @ 0x%08llx\n", start, end, stop);
+
+    for (iter = g_arch_instruction_find_by_address(instrs, start, true);
+         iter != NULL;
+         )
+    {
+        g_arch_instruction_get_location(iter, NULL, NULL, &addr);
+        if (addr == stop) break;
+
+        if (first == NULL)
+            first = iter;
+
+        last = iter;
+
+        /* On s'arrêter si l'instruction est déjà décompilée */
+        if (g_object_get_data(G_OBJECT(iter), "decomp_done") != NULL) break;
+        g_object_set_data(G_OBJECT(iter), "decomp_done", iter);
+
+        /* On n'approfondit que les chemins qui se séparent */
+        if (!g_arch_instruction_has_destinations(iter))
+        {
+            iter = g_arch_instruction_get_next_iter(instrs, iter, end);
+            continue;
+        }
+
+        /* Adaptations en fonction du type de bifurcation */
+
+        dcount = g_arch_instruction_get_destinations(iter, &dests, &types);
+
+        next_addr = 0;
+        memset(&true_branch, 0, sizeof(branch_info));
+        memset(&false_branch, 0, sizeof(branch_info));
+
+        for (i = 0; i < dcount; i++)
+            switch (types[i])
+            {
+                case ILT_EXEC_FLOW:
+                case ILT_JUMP:
+
+                    if (result == NULL)
+                        result = g_virtual_block_new();
+
+                    block = g_flow_block_new(instrs, first, iter);
+                    g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
+                    first = NULL;
+
+                    g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr);
+
+                    break;
+
+                case ILT_JUMP_IF_TRUE:
+                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
+                    find_next_jumps(instrs, addr, end, &true_branch);
+                    break;
+
+                case ILT_JUMP_IF_FALSE:
+                    g_arch_instruction_get_location(dests[i], NULL, NULL, &addr);
+                    find_next_jumps(instrs, addr, end, &false_branch);
+                    break;
+
+                default:
+                    next_addr = VMPA_MAX;
+                    break;
+
+            }
+
+        if (next_addr == VMPA_MAX)
+        {
+            iter = g_arch_instruction_get_next_iter(instrs, iter, end);
+            continue;
+        }
+
+        else if (true_branch.count > 0 || false_branch.count > 0)
+        {
+            next_addr = compute_first_common_addr(&true_branch, &false_branch);
+            next_addr = MIN(next_addr, end);
+
+            if (result == NULL)
+                result = g_virtual_block_new();
+
+            block = g_flow_block_new(instrs, first, iter);
+            g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
+            first = NULL;
+
+            block = build_instruction_block(instrs, true_branch.jumps[0], end, next_addr);
+            g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
+
+            block = build_instruction_block(instrs, false_branch.jumps[0], end, next_addr);
+            g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
+
+            free(true_branch.jumps);
+            free(false_branch.jumps);
+
+            if (next_addr == end) break;
+
+        }
+
+        /* Détermination du prochain point de chute */
+        iter = g_arch_instruction_find_by_address(instrs, next_addr, true);
+
+    }
+
+    if (first != NULL && last != NULL)
+    {
+        block = g_flow_block_new(instrs, first, last);
+
+        if (result == NULL)
+            result = block;
+        else
+            g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list      = ensemble d'instructions à relier.                *
+*                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.  *
+*                                                                             *
+*  Description : Regroupe les instructions par blocs.                         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void group_routines_instructions(GArchInstruction *list, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, guint id)
+{
+    size_t i;                               /* Boucle de parcours          */
+    vmpa_t start;                           /* Adresse de départ           */
+    vmpa_t end;                             /* Adresse de fin              */
+    GInstrBlock *block;                     /* Regroupement d'instructions */
+
+    for (i = 0; i < count; i++)
+    {
+        start = g_binary_routine_get_address(routines[i]);
+        end = start + g_binary_routine_get_size(routines[i]);
+
+
+        printf("==== %s ====\n", g_binary_routine_to_string(routines[i]));
+
+
+        block = build_instruction_block(list, start, end, VMPA_MAX);
+
+        gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);
+
+    }
+
+}
diff --git a/src/analysis/disass/macro.h b/src/analysis/disass/macro.h
new file mode 100644
index 0000000..64df785
--- /dev/null
+++ b/src/analysis/disass/macro.h
@@ -0,0 +1,38 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * macro.h - prototypes pour la vue macroscopique des liens entre blocs d'instructions
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_DISASS_MACRO_H
+#define _ANALYSIS_DISASS_MACRO_H
+
+
+#include "../routine.h"
+#include "../../gtkext/gtkextstatusbar.h"
+
+
+
+/* Regroupe les instructions par blocs. */
+void group_routines_instructions(GArchInstruction *, GBinRoutine **, size_t, GtkExtStatusBar *, guint);
+
+
+
+#endif  /* _ANALYSIS_DISASS_MACRO_H */
diff --git a/src/analysis/routine.h b/src/analysis/routine.h
index a13c460..de28f38 100644
--- a/src/analysis/routine.h
+++ b/src/analysis/routine.h
@@ -30,6 +30,7 @@
 #include <sys/types.h>
 
 
+#include "block.h"
 #include "variable.h"
 #include "../arch/instruction.h"
 #include "../decomp/instruction.h"
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index aa90e70..a45e8fa 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -284,6 +284,11 @@ void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchReg
 {
     size_t i;                               /* Boucle de parcours          */
 
+    *rregs = NULL;
+    *rcount = 0;
+    *wregs = NULL;
+    *wcount = 0;
+
     instr->get_rw_regs(instr, rregs, rcount, wregs, wcount);
 
     for (i = 0; i < *rcount; i++)
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index 602b296..9dbe53c 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -52,7 +52,8 @@ typedef enum _PluginAction
     PGA_BINARY_DISASSEMBLED = (1 << 2),     /* Désassemblage fini          */
     PGA_BINARY_LINKED       = (1 << 3),     /* Liaison en place            */
     PGA_BINARY_BOUNDED      = (1 << 4),     /* Limites de routines définies*/
-    PGA_BINARY_PRINTED      = (1 << 5),     /* Instructions imprimées      */
+    PGA_BINARY_GROUPED      = (1 << 5),     /* Instructions regroupées     */
+    PGA_BINARY_PRINTED      = (1 << 6),     /* Instructions imprimées      */
 
     PGA_DISASS_PROCESS      = (1 << 6),     /* Traitement niveau assembleur*/
     PGA_CODE_PROCESS        = (1 << 7),     /* Traitement du code existant */
-- 
cgit v0.11.2-87-g4458