From 57d7eff57c20e75aaa4ccd34f1d9d733e12bb232 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 30 Dec 2014 08:25:05 +0000
Subject: Tracked each binary area during the disassembling process and tried
 to follow the execution flow.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@445 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                       |   38 ++
 src/analysis/disass/Makefile.am |    1 +
 src/analysis/disass/area.c      | 1289 +++++++++++++++++++++++++++++++++++++++
 src/analysis/disass/area.h      |   96 +++
 src/analysis/disass/fetch.c     |  552 ++---------------
 src/arch/arm/context.c          |   44 ++
 src/arch/arm/processor.c        |   28 +
 src/arch/arm/v7/link.c          |    7 +
 src/arch/context-int.h          |    6 +
 src/arch/context.c              |   26 +-
 src/arch/context.h              |    4 +-
 src/arch/vmpa.c                 |   31 +
 src/arch/vmpa.h                 |    3 +
 src/gtkext/gtkextstatusbar.h    |   13 +
 14 files changed, 1647 insertions(+), 491 deletions(-)
 create mode 100644 src/analysis/disass/area.c
 create mode 100644 src/analysis/disass/area.h

diff --git a/ChangeLog b/ChangeLog
index 9f1a780..37e210a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,41 @@
+14-12-30  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/area.c:
+	* src/analysis/disass/area.h:
+	New entries: track each binary area during the disassembling process
+	and try to follow the execution flow.
+
+	* src/analysis/disass/fetch.c:
+	Clean and update the code.
+
+	* src/analysis/disass/Makefile.am:
+	Add the 'area.[ch]' files to libanalysisdisass_la_SOURCES.
+
+	* src/arch/arm/context.c:
+	Handle entry points for the disassembling process.
+
+	* src/arch/arm/processor.c:
+	Provide a context for the ARM processor.
+
+	* src/arch/arm/v7/link.c:
+	Add debug code.
+
+	* src/arch/context.c:
+	Handle entry points for the disassembling process.
+
+	* src/arch/context.h:
+	Typo.
+
+	* src/arch/context-int.h:
+	Handle entry points for the disassembling process.
+
+	* src/arch/vmpa.c:
+	* src/arch/vmpa.h:
+	Allow to check if a range contains another range.
+
+	* src/gtkext/gtkextstatusbar.h:
+	Prepare some new extensions.
+
 14-12-25  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/fetch.c:
diff --git a/src/analysis/disass/Makefile.am b/src/analysis/disass/Makefile.am
index 65ed9c9..54b0fa5 100644
--- a/src/analysis/disass/Makefile.am
+++ b/src/analysis/disass/Makefile.am
@@ -2,6 +2,7 @@
 noinst_LTLIBRARIES = libanalysisdisass.la
 
 libanalysisdisass_la_SOURCES =			\
+	area.h area.c						\
 	disassembler.h disassembler.c		\
 	fetch.h fetch.c						\
 	limit.h limit.c						\
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
new file mode 100644
index 0000000..9d8dcf5
--- /dev/null
+++ b/src/analysis/disass/area.c
@@ -0,0 +1,1289 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * area.c - définition et manipulation des aires à désassembler
+ *
+ * Copyright (C) 2014 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  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 "area.h"
+
+
+#include <assert.h>
+
+
+
+#if 0
+
+
+/* Zone mémoire bien bornée */
+struct _mem_area
+{
+    mrange_t range;                         /* Couverture de la zone       */
+
+    unsigned long *processed;               /* Octets traités dans la zone */
+
+    bool has_sym;                           /* Représentation via symbole ?*/
+
+    union
+    {
+        bool exec;                          /* Zone exécutable ?           */
+        GBinSymbol *symbol;                 /* Symbole associé à la zone   */
+    };
+
+};
+
+
+#endif
+
+
+
+/* Initialise une aire de données à partir d'une adresse donnée. */
+static void init_mem_area_from_addr(mem_area *, const vmpa2t *, phys_t);
+
+/* Initialise une aire de données à partir d'un espace donné. */
+static void init_mem_area_from_range(mem_area *, const mrange_t *);
+
+/* Copie certaines propriétés d'une aire à une autre. */
+static void copy_mem_area_properties(mem_area *, const mem_area *);
+
+/* Libère d'une aire de données les ressources allouées. */
+static void fini_mem_area(mem_area *);
+
+/* Indique si une zone donnée est intégralement vierge ou non. */
+static bool is_range_blank_in_mem_area(mem_area *, phys_t, phys_t, GArchInstruction *);
+
+/* Marque une série d'octets comme ayant été traités. */
+static bool mark_range_in_mem_area_as_processed(mem_area *, phys_t, phys_t, GArchInstruction *);
+
+
+
+
+
+/* Procède au désassemblage d'un contenu binaire non exécutable. */
+static void load_data_from_mem_area(mem_area *, mem_area *, size_t, const GLoadedBinary *, GProcContext *, const vmpa2t *, status_info *);
+
+/* S'assure qu'une aire contient toutes ses instructions. */
+static void fill_mem_area(mem_area *, mem_area *, size_t, const GLoadedBinary *, GProcContext *, status_info *);
+
+
+
+/* Rassemble les instructions conservées dans une zone donnée. */
+static GArchInstruction *get_instructions_from_mem_area(const mem_area *);
+
+
+
+
+///////////////////////////////
+
+
+
+/* Manipule la cartographie des octets traités d'une zone. */
+typedef bool (* visit_bytes_map_fc) (mem_area *, phys_t, phys_t, GArchInstruction *);
+
+
+
+
+
+/* Manipule la cartographie des octets d'aires de données. */
+static bool handle_bytes_map_in_mem_area(mem_area *, size_t, const mrange_t *, GArchInstruction *, visit_bytes_map_fc);
+
+/* Indique si une zone donnée est intégralement vierge ou non. */
+static bool is_range_blank_in_mem_areas(mem_area *, size_t, const mrange_t *);
+
+/* Marque une série d'octets comme ayant été traités. */
+static bool mark_range_in_mem_areas_as_processed(mem_area *, size_t, GArchInstruction *);
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area = aire représentant à contenu à initialiser.            *
+*                addr = adresse de départ de l'espace à mettre en place.      *
+*                len  = longueur de l'espace à créer.                         *
+*                                                                             *
+*  Description : Initialise une aire de données à partir d'une adresse donnée.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void init_mem_area_from_addr(mem_area *area, const vmpa2t *addr, phys_t len)
+{
+    size_t requested;                       /* Nombre de mots à allouer    */
+
+    init_mrange(&area->range, addr, len);
+
+    requested = len / sizeof(unsigned long);
+    if (len % sizeof(unsigned long) != 0) requested++;
+
+    area->processed = (unsigned long *)calloc(requested, sizeof(unsigned long));
+    area->instructions = (GArchInstruction **)calloc(len, sizeof(GArchInstruction *));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : dest = aire délimitée représentant des données.              *
+*                src  = aire délimitée contenant les informations à copier.   *
+*                                                                             *
+*  Description : Copie certaines propriétés d'une aire à une autre.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void copy_mem_area_properties(mem_area *dest, const mem_area *src)
+{
+    dest->has_sym = src->has_sym;
+
+    if (src->has_sym)
+        dest->symbol = src->symbol;
+    else
+        dest->exec = src->exec;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area  = aire représentant à contenu à initialiser.           *
+*                range = espace limitant à associer à l'aire de données.      *
+*                                                                             *
+*  Description : Initialise une aire de données à partir d'un espace donné.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void init_mem_area_from_range(mem_area *area, const mrange_t *range)
+{
+    phys_t len;                             /* Taille de la zone courante  */
+    size_t requested;                       /* Nombre de mots à allouer    */
+
+    copy_mrange(&area->range, range);
+
+    len = get_mrange_length(range);
+
+    requested = len / sizeof(unsigned long);
+    if (len % sizeof(unsigned long) != 0) requested++;
+
+    area->processed = (unsigned long *)calloc(requested, sizeof(unsigned long));
+    area->instructions = (GArchInstruction **)calloc(len, sizeof(GArchInstruction *));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area = aire représentant à contenu à nettoyer en mémoire.    *
+*                                                                             *
+*  Description : Libère d'une aire de données les ressources allouées.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void fini_mem_area(mem_area *area)
+{
+    free(area->processed);
+
+    if (area->has_sym)
+        g_object_unref(area->symbol);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area  = aire représentant à contenu à parcourir.             *
+*                start = début de la zone à manipuler.                        *
+*                len   = taille de cette même aire de données.                *
+*                instr = instruction à mémoriser pour la suite.               *
+*                                                                             *
+*  Description : Indique si une zone donnée est intégralement vierge ou non.  *
+*                                                                             *
+*  Retour      : true si l'aire visée n'a jamais été traitée, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool is_range_blank_in_mem_area(mem_area *area, phys_t start, phys_t len, GArchInstruction *instr)
+{
+    bool result;                            /* Bilan à renvoyer            */
+	phys_t max;								/* Point d'arrêt de la boucle  */
+    phys_t i;                               /* Boucle de parcours          */
+    size_t index;                           /* Cellule de tableau visée    */
+    unsigned int remaining;                 /* Nombre de bits restants     */
+
+	max = start + len;
+
+    assert(max <= get_mrange_length(&area->range));
+
+    result = true;
+
+    for (i = start; i < max && result; i++)
+    {
+        index = i / (sizeof(unsigned long) * 8);
+        remaining = i % (sizeof(unsigned long) * 8);
+
+        result &= ((area->processed[index] & (1ul << remaining)) == 0);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area  = aire représentant à contenu à parcourir.             *
+*                start = début de la zone à manipuler.                        *
+*                len   = taille de cette même aire de données.                *
+*                instr = instruction à mémoriser pour la suite.               *
+*                                                                             *
+*  Description : Marque une série d'octets comme ayant été traités.           *
+*                                                                             *
+*  Retour      : true.                                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool mark_range_in_mem_area_as_processed(mem_area *area, phys_t start, phys_t len, GArchInstruction *instr)
+{
+	phys_t max;								/* Point d'arrêt de la boucle  */
+    phys_t i;                               /* Boucle de parcours          */
+    size_t index;                           /* Cellule de tableau visée    */
+    unsigned int remaining;                 /* Nombre de bits restants     */
+
+	max = start + len;
+
+    assert(max <= get_mrange_length(&area->range));
+
+    for (i = start; i < max; i++)
+    {
+        index = i / (sizeof(unsigned long) * 8);
+        remaining = i % (sizeof(unsigned long) * 8);
+
+        area->processed[index] |= (1ul << remaining);
+
+    }
+
+    area->instructions[start] = instr;
+
+    return true;
+
+}
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area   = aire représentant à contenu à parcourir.            *
+*                list   = liste de zones délimitant des contenus à traiter.   *
+*                count  = nombre de zones à disposition.                      *
+*                binary = représentation de binaire chargé.                   *
+*                ctx    = contexte offert en soutien à un désassemblage.      *
+*                start  = démarrage de l'exécution au sein de la zone.        *
+*                info   = indications quant à la progression à afficher.      *
+*                                                                             *
+*  Description : Procède au désassemblage d'un contenu binaire exécutable.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void load_code_from_mem_area(mem_area *area, mem_area *list, size_t count, const GLoadedBinary *binary, GProcContext *ctx, const vmpa2t *start, status_info *info)
+{
+
+
+    GBinFormat *format;                     /* Format du fichier binaire   */
+    GArchProcessor *proc;                   /* Architecture du binaire     */
+    off_t bin_length;                       /* Taille des données à lire   */
+    bin_t *bin_data;                        /* Données binaires à lire     */
+
+    phys_t diff;                            /* Volume de données traité    */
+    phys_t alen;                            /* Taille de l'aire utilisée   */
+
+    phys_t i;                               /* Boucle de parcours          */
+
+
+    vmpa2t pos;                             /* Boucle de parcours          */
+    vmpa2t prev;                            /* Boucle de parcours          */
+
+    GArchInstruction *instr;                /* Instruction décodée         */
+
+
+
+    mrange_t range;                             /* Couverture de l'instruction */
+
+
+
+    /* On cherche à obtenir l'assurance que le traitement n'a jamais été fait */
+
+    init_mrange(&range, start, 1);
+    if (!is_range_blank_in_mem_areas(list, count, &range)) printf("CODE OK!!\n");;
+    if (!is_range_blank_in_mem_areas(list, count, &range)) return;
+
+    /* Récupération des informations de base */
+
+    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+    proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
+    bin_data = g_loaded_binary_get_data(binary, &bin_length);
+
+    diff = compute_vmpa_diff(get_mrange_addr(&area->range), start);
+    alen = get_mrange_length(&area->range);
+
+    /**
+     * On copie la position courante à partir de l'aire plutôt que du
+     * point de départ car cette première est potentiellement plus complète.
+     */
+
+    copy_vmpa(&pos, get_mrange_addr(&area->range));
+    advance_vmpa(&pos, diff);
+
+	printf(" [%p] CODE start @ %u (len=%u)\n", area, (unsigned int)diff, (unsigned int)alen);
+
+    for (i = diff; i < alen; i += diff)
+    {
+        //il y a eu un point d'entrée... -> STOP
+
+        /* Décodage d'une nouvelle instruction */
+
+        copy_vmpa(&prev, &pos);
+
+        instr = g_arch_processor_disassemble(proc, ctx, bin_data, &pos, bin_length);
+
+		//printf(" @ 0x%08x -> %p\n", (uint32_t)get_virt_addr(&prev), instr);
+
+        if (instr == NULL) break;
+
+
+
+
+        /* Enregistrement des positions et adresses */
+
+        diff = compute_vmpa_diff(&prev, &pos);
+
+        init_mrange(&range, &prev, diff);
+
+        g_arch_instruction_set_range(instr, &range);
+
+        /* Eventuel renvoi vers d'autres adresses */
+
+        g_arch_instruction_call_hook(instr, IPH_LINK, ctx, format);
+
+        /* Progression dans les traitements */
+
+        mark_range_in_mem_areas_as_processed(list, count, instr);
+
+        //done += (new_phy - old_phy);
+        //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
+
+
+
+
+
+
+
+
+    }
+
+
+    printf("\n");
+
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area   = aire représentant à contenu à parcourir.            *
+*                list   = liste de zones délimitant des contenus à traiter.   *
+*                count  = nombre de zones à disposition.                      *
+*                binary = représentation de binaire chargé.                   *
+*                ctx    = contexte offert en soutien à un désassemblage.      *
+*                start  = démarrage de l'exécution au sein de la zone.        *
+*                info   = indications quant à la progression à afficher.      *
+*                                                                             *
+*  Description : Procède au désassemblage d'un contenu binaire non exécutable.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void load_data_from_mem_area(mem_area *area, mem_area *list, size_t count, const GLoadedBinary *binary, GProcContext *ctx, const vmpa2t *start, status_info *info)
+{
+    GBinFormat *format;                     /* Format du fichier binaire   */
+    GArchProcessor *proc;                   /* Architecture du binaire     */
+	SourceEndian endianness;				/* Boutisme de cette machine   */
+    off_t bin_length;                       /* Taille des données à lire   */
+    bin_t *bin_data;                        /* Données binaires à lire     */
+    phys_t diff;                            /* Volume de données traité    */
+    phys_t alen;                            /* Taille de l'aire utilisée   */
+    phys_t i;                               /* Boucle de parcours          */
+    vmpa2t pos;                             /* Boucle de parcours          */
+    vmpa2t prev;                            /* Boucle de parcours          */
+    GArchInstruction *instr;                /* Instruction décodée         */
+    mrange_t range;                         /* Couverture de l'instruction */
+
+    /* On cherche à obtenir l'assurance que le traitement n'a jamais été fait */
+
+    init_mrange(&range, start, 1);
+    if (!is_range_blank_in_mem_areas(list, count, &range)) printf("DATA OK!!\n");;
+    if (!is_range_blank_in_mem_areas(list, count, &range)) return;
+
+    /* Récupération des informations de base */
+
+    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+    proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
+	endianness = g_arch_processor_get_endianness(proc);
+    bin_data = g_loaded_binary_get_data(binary, &bin_length);
+
+    diff = compute_vmpa_diff(get_mrange_addr(&area->range), start);
+    alen = get_mrange_length(&area->range);
+
+    /**
+     * On copie la position courante à partir de l'aire plutôt que du
+     * point de départ car cette première est potentiellement plus complète.
+     */
+
+    copy_vmpa(&pos, get_mrange_addr(&area->range));
+    advance_vmpa(&pos, diff);
+
+	printf(" [%p] DATA start @ 0x%08x -> %u (len=%u)\n",
+		   area, (unsigned int)get_phy_addr(&pos), (unsigned int)diff, (unsigned int)alen);
+
+    for (i = diff; i < alen; i += diff)
+    {
+        /* Décodage d'une nouvelle instruction, sur mesure */
+
+        copy_vmpa(&prev, &pos);
+
+		instr = NULL;
+
+		if (instr == NULL && (i + 4) <= alen)
+		{
+			init_mrange(&range, &pos, 4);
+
+			if (is_range_blank_in_mem_areas(list, count, &range))
+				instr = g_raw_instruction_new_array(bin_data, MDS_32_BITS, 1, &pos, bin_length, endianness);
+
+		}
+
+		if (instr == NULL && (i + 2) <= alen)
+		{
+			copy_vmpa(&pos, &prev);
+			init_mrange(&range, &pos, 2);
+
+			if (is_range_blank_in_mem_areas(list, count, &range))
+				instr = g_raw_instruction_new_array(bin_data, MDS_16_BITS, 1, &pos, bin_length, endianness);
+
+		}
+
+		if (instr == NULL/* && (i + 1) <= alen*/)
+		{
+			copy_vmpa(&pos, &prev);
+			init_mrange(&range, &pos, 1);
+
+			if (is_range_blank_in_mem_areas(list, count, &range))
+				instr = g_raw_instruction_new_array(bin_data, MDS_8_BITS, 1, &pos, bin_length, endianness);
+			else
+			{
+				printf("      break !!  0x%08x\n",
+					   (unsigned int)get_phy_addr(&pos));
+				assert(0);
+				break;
+			}
+
+		}
+
+		assert(instr != NULL);
+
+        /* Enregistrement des positions et adresses */
+
+        diff = compute_vmpa_diff(&prev, &pos);
+
+		printf("   decomp @ 0x%08x  -> ++ %u\n",
+			   (unsigned int)get_phy_addr(&pos), (unsigned int)diff);
+
+        init_mrange(&range, &prev, diff);
+
+        g_arch_instruction_set_range(instr, &range);
+
+        /* Progression dans les traitements */
+
+        mark_range_in_mem_areas_as_processed(list, count, instr);
+
+		assert(!is_range_blank_in_mem_areas(list, count, &range));
+
+        //done += (new_phy - old_phy);
+        //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area   = aire représentant à contenu à parcourir.            *
+*                list   = liste de zones délimitant des contenus à traiter.   *
+*                count  = nombre de zones à disposition.                      *
+*                binary = représentation de binaire chargé.                   *
+*                ctx    = contexte offert en soutien à un désassemblage.      *
+*                info   = indications quant à la progression à afficher.      *
+*                                                                             *
+*  Description : S'assure qu'une aire contient toutes ses instructions.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void fill_mem_area(mem_area *area, mem_area *list, size_t count, const GLoadedBinary *binary, GProcContext *ctx, status_info *info)
+{
+	phys_t len;								/* Taille de la zone à remplir */
+    phys_t i;                               /* Boucle de parcours          */
+	vmpa2t start;							/* Adresse de départ de combles*/
+
+
+	printf(" === FILLING | 0x%08x (%u)...\n",
+		   (unsigned int)get_phy_addr(get_mrange_addr(&area->range)),
+		   (unsigned int)get_phy_addr(get_mrange_addr(&area->range)));
+
+
+	/* Les symboles se doivent d'être indépendants ! */
+	if (area->has_sym) return;
+
+    len = get_mrange_length(&area->range);
+
+    for (i = 0; i < len; i++)
+    {
+		if (is_range_blank_in_mem_area(area, i, 1, NULL))
+		{
+			copy_vmpa(&start, get_mrange_addr(&area->range));
+			advance_vmpa(&start, i);
+
+			if (area->exec)
+				load_code_from_mem_area(area, list, count, binary, ctx, &start, info);
+
+			if (is_range_blank_in_mem_area(area, i, 1, NULL))
+				load_data_from_mem_area(area, list, count, binary, ctx, &start, info);
+
+		}
+
+		if (is_range_blank_in_mem_area(area, i, 1, NULL))
+			printf(" [%p] error with %u\n", area, (unsigned int)i);
+
+        assert(!is_range_blank_in_mem_area(area, i, 1, NULL));
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area = aire représentant à contenu à parcourir.              *
+*                                                                             *
+*  Description : Rassemble les instructions conservées dans une zone donnée.  *
+*                                                                             *
+*  Retour      : Liste d'instructions prêtes à emploi.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GArchInstruction *get_instructions_from_mem_area(const mem_area *area)
+{
+    GArchInstruction *result;               /* Liste d'instr. à renvoyer   */
+	phys_t len;								/* Nombre d'instructions au max*/
+	phys_t i;								/* Boucle de parcours		   */
+    GArchInstruction *instr;                /* Instruction décodée         */
+
+    result = NULL;
+
+	if (area->has_sym)
+		switch (g_binary_symbol_get_target_type(area->symbol))
+		{
+		    case STP_DATA:
+				result = g_binary_symbol_get_instruction(area->symbol);
+				g_object_ref(G_OBJECT(result));
+				break;
+
+		    case STP_ROUTINE:
+				assert(false);
+				//instr = load_code_binary(binary, start, end, statusbar, id);
+				// + fill
+				break;
+
+		    default:
+				assert(false);
+				break;
+
+		}
+
+	else
+	{
+		len = get_mrange_length(&area->range);
+
+		for (i = 0; i < len; i++)
+		{
+			instr = area->instructions[i];
+
+			if (instr != NULL)
+			{
+				g_object_ref(G_OBJECT(instr));
+				g_arch_instruction_add_to_list(&result, instr);
+			}
+
+		}
+
+	}
+
+	return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format     = format d'un exécutable à consulter.             *
+*                bin_length = quantité d'octets à traiter au total.           *
+*                count      = nombre de zones mises en place. [OUT]           *
+*                                                                             *
+*  Description : Détermine une liste de zones contigües à traiter.            *
+*                                                                             *
+*  Retour      : Liste de zones mémoire à libérer après usage.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+mem_area *compute_memory_areas(GExeFormat *format, phys_t bin_length, size_t *count)
+{
+    mem_area *result;                       /* Liste à renvoyer            */
+    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */
+    size_t exe_count;                       /* Nombre de ces zones         */
+    GBinSymbol **symbols;                   /* Symboles à représenter      */
+    size_t sym_count;                       /* Qté de symboles présents    */
+    vmpa2t *last;                           /* Dernière bordure rencontrée */
+    size_t i;                               /* Boucle de parcours #1       */
+    vmpa2t *border;                         /* Nouvelle bordure rencontrée */
+    mem_area *area;                         /* Zone avec valeurs à éditer  */
+    vmpa2t tmp;                             /* Stockage temporaire         */
+
+
+    GBinPortion **portions;                 /* Morceaux d'encadrement      */
+    size_t portions_count;                  /* Taille de cette liste       */
+    const vmpa2t *portion_start;            /* Point de départ de portion  */
+
+    size_t j;                               /* Boucle de parcours #2       */
+    const mrange_t *range;                  /* Couverture d'un symbole     */
+    const vmpa2t *start;                    /* Point de départ du symbole  */
+    phys_t length;                          /* Taille de ce même symbole   */
+    bool included;                          /* Inclusion dans une zone ?   */
+    mem_area orig;                          /* Copie de la zone réduite    */
+    phys_t old_length;                      /* Taille de zone originelle   */
+    phys_t new_length;                      /* Nouvelle taille déterminée  */
+    size_t next;                            /* Indice de zone suivante     */
+
+    result = NULL;
+    *count = 0;
+
+    /**
+     * Le parcours n'est valide que si les listes, symboles et zones exécutables,
+     * sont triées !
+     */
+
+    exe_ranges = g_exe_format_get_x_ranges(format, &exe_count);
+
+    symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count);
+
+
+
+
+
+
+    for (i = 0; i < exe_count; i++)
+    {
+		printf(" (init) AREA %zu :: 0x%08x + %u\n",
+			   i,
+			   (unsigned int)get_phy_addr(get_mrange_addr(&exe_ranges[i])),
+			   (unsigned int)get_mrange_length(&exe_ranges[i]));
+
+	}
+
+
+	printf("----------------\n");
+
+
+
+    /* Première étape : on comble les trous ! */
+
+    last = make_vmpa(0, VMPA_NO_VIRTUAL);
+
+    for (i = 0; i < exe_count; i++)
+    {
+        border = get_mrange_addr(&exe_ranges[i]);
+
+        /* Zone tampon à constituer */
+
+        if (cmp_vmpa_by_phy(last, border) < 0)
+        {
+            result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+            area = &result[*count - 1];
+
+            init_mem_area_from_addr(area, last, compute_vmpa_diff(last, border));
+            area->has_sym = false;
+            area->exec = false;
+
+        }
+
+        /* Insertion d'une zone exécutable déjà définie */
+
+        result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+        area = &result[*count - 1];
+
+        init_mem_area_from_range(area, &exe_ranges[i]);
+        area->has_sym = false;
+        area->exec = true;
+
+        /* Avancée du curseur */
+
+        copy_vmpa(last, border);
+
+        advance_vmpa(last, get_mrange_length(&exe_ranges[i]));
+
+    }
+
+    delete_vmpa(last);
+
+    /* Extension finale complémentaire ? */
+
+    area = &result[*count - 1];
+
+    copy_vmpa(&tmp, get_mrange_addr(&area->range));
+    advance_vmpa(&tmp, get_mrange_length(&area->range));
+
+    if (get_phy_addr(&tmp) < bin_length)
+    {
+        result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+        area = &result[*count - 1];
+
+        init_mem_area_from_addr(area, &tmp, bin_length - get_phy_addr(&tmp));
+        area->has_sym = false;
+        area->exec = false;
+
+    }
+
+    /* Seconde étape : on s'assure du découpage autour des portions pour respecter l'alignement */
+
+
+
+    for (i = 0; i < *count; i++)
+    {
+		printf(" (fini) AREA %zu :: 0x%08x + %u\n",
+			   i,
+			   (unsigned int)get_phy_addr(get_mrange_addr(&result[i].range)),
+			   (unsigned int)get_mrange_length(&result[i].range));
+
+	}
+
+    printf("--------------------\n");
+
+    portions = g_exe_format_get_portions_at_level(format, -1, &portions_count);
+
+
+    for (i = 1; i < portions_count; i++)
+    {
+        portion_start = get_mrange_addr(g_binary_portion_get_range(portions[i]));
+
+        for (j = 0; j < *count; j++)
+        {
+            area = &result[j];
+
+            if (!mrange_contains_addr(&area->range, portion_start))
+                continue;
+
+            /* Si le déccoupage actuel ne correspond pas au besoin des portions... */
+            if (cmp_vmpa(get_mrange_addr(&area->range), portion_start) != 0)
+            {
+                fini_mem_area(&result[j]);
+
+                result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+                memmove(&result[j + 2], &result[j + 1], (*count - j - 2) * sizeof(mem_area));
+
+                copy_mem_area_properties(&result[j + 1], &result[j]);
+
+                /* Première moitié */
+
+                area = &result[j];
+
+                copy_vmpa(&tmp, get_mrange_addr(&area->range));
+                length = get_mrange_length(&area->range);
+
+                init_mem_area_from_addr(area, &tmp, compute_vmpa_diff(&tmp, portion_start));
+
+                /* Seconde moitié */
+
+                length -= get_mrange_length(&area->range);
+
+                area = &result[j + 1];
+
+                init_mem_area_from_addr(area, portion_start, length);
+
+            }
+
+            j = *count;
+
+        }
+
+    }
+
+
+
+
+
+
+    for (i = 0; i < *count; i++)
+    {
+		printf(" (sect) AREA %zu :: 0x%08x + %u\n",
+			   i,
+			   (unsigned int)get_phy_addr(get_mrange_addr(&result[i].range)),
+			   (unsigned int)get_mrange_length(&result[i].range));
+
+	}
+
+
+	//exit(0);
+
+
+
+    /* Troisième étape : on insère les symboles existants */
+
+    j = 0;
+
+#define SKIP_EMPTY_SYMBOLS                                  \
+    for (; j < sym_count; j++)                              \
+    {                                                       \
+        range = g_binary_symbol_get_range(symbols[j]);      \
+                                                            \
+        length = get_mrange_length(range);                  \
+        if (length > 0) break;                              \
+                                                            \
+    }                                                       \
+
+    SKIP_EMPTY_SYMBOLS
+
+    for (i = 0; i < *count && j < sym_count; i++)
+    {
+        range = g_binary_symbol_get_range(symbols[j]);
+
+        start = get_mrange_addr(range);
+        length = get_mrange_length(range);
+
+        /* Si un découpage s'impose... */
+
+        if (mrange_contains_addr(&result[i].range, start))
+        {
+            copy_vmpa(&tmp, start);
+            advance_vmpa(&tmp, length);
+
+            included = mrange_contains_addr(&result[i].range, &tmp);
+
+            memcpy(&orig, &result[i], sizeof(mem_area));
+
+            fini_mem_area(&orig);
+
+            /* Réduction de la zone de départ */
+
+            copy_vmpa(&tmp, get_mrange_addr(&result[i].range));
+            old_length = get_mrange_length(&result[i].range);
+
+            new_length = compute_vmpa_diff(get_mrange_addr(&result[i].range), start);
+
+            if (new_length == 0)
+            {
+                memmove(&result[i], &result[i + 1], (*count - i - 1) * sizeof(mem_area));
+
+                (*count)--;
+                next = i;
+
+            }
+            else
+            {
+                init_mem_area_from_addr(&result[i], &tmp, new_length);
+                next = i + 1;
+            }
+
+            /* Insertion de la zone du symbole */
+
+            result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+            memmove(&result[next + 1], &result[next], (*count - next - 1) * sizeof(mem_area));
+
+            area = &result[next];
+
+            init_mem_area_from_range(area, range);
+
+            area->has_sym = true;
+            area->symbol = symbols[j];
+
+            /* Jointure finale... */
+
+            if (included)
+            {
+                /* Simple extension pour rattraper la fin originelle */
+
+                if ((old_length - new_length - length) > 0)
+                {
+                    result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
+
+                    memmove(&result[next + 2], &result[next + 1], (*count - next - 2) * sizeof(mem_area));
+
+                    area = &result[next + 1];
+
+                    copy_vmpa(&tmp, start);
+                    advance_vmpa(&tmp, length);
+
+                    init_mem_area_from_addr(area, &tmp, old_length - new_length - length);
+
+                    copy_mem_area_properties(area, &orig);
+
+                }
+
+                i = next;
+
+            }
+            else
+            {
+                /* Suppression des éventuelles zones totalement recouvertes */
+
+
+
+                /* Réduction de la zone d'arrivée */
+
+
+            }
+
+
+
+
+
+            j++;
+
+            SKIP_EMPTY_SYMBOLS
+
+        }
+
+    }
+
+
+
+    //free
+
+    //exit(0);
+
+    return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list  = listes de zones utable à consulter.                  *
+*                count = nombre de zones mises en place.                      *
+*                addr  = adresse à retrouver dans les aires présentes.        *
+*                                                                             *
+*  Description : Détermine une liste de zones contigües à traiter.            *
+*                                                                             *
+*  Retour      : Liste de zones mémoire à libérer après usage.                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+mem_area *find_memory_area_by_addr(mem_area *list, size_t count, const vmpa2t *addr)
+{
+    mem_area *result;                       /* Trouvaille à retourner      */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = NULL;
+
+    for (i = 0; i < count && result == NULL; i++)
+        if (mrange_contains_addr(&list[i].range, addr))
+            result = &list[i];
+
+    return result;
+
+}
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list    = liste de zones délimitant des contenus à traiter.  *
+*                count   = nombre de zones à disposition.                     *
+*                range   = aire des octets à manipuler.                       *
+*                visitor = fonction opérationnelle finale à appeler.          *
+*                                                                             *
+*  Description : Manipule la cartographie des octets d'aires de données.      *
+*                                                                             *
+*  Retour      : valeur retournée par le visiteur, voire false si erreur.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool handle_bytes_map_in_mem_area(mem_area *list, size_t count, const mrange_t *range, GArchInstruction *instr, visit_bytes_map_fc visitor)
+{
+    bool result;                            /* Bilan à retourner           */
+    mem_area *area;                         /* Aire à traiter trouvée      */
+    phys_t offset;                          /* Point de départ dans l'aire */
+    phys_t remaining;                       /* Quantité restant à traiter  */
+    phys_t processed;                       /* Quantité traitée            */
+    vmpa2t start;                           /* Point de départ suivant     */
+
+    result = false;
+
+    area = find_memory_area_by_addr(list, count, get_mrange_addr(range));
+    if (area == NULL) printf("NOT FOUND!\n");
+    if (area == NULL) return false;
+
+    offset = compute_vmpa_diff(get_mrange_addr(&area->range), get_mrange_addr(range));
+    remaining = get_mrange_length(range);
+
+    /* Traitement intégral dans la zone trouvée */
+
+    if ((offset + remaining) <= get_mrange_length(&area->range))
+        result = visitor(area, offset, remaining, instr);
+
+    else
+    {
+		assert(0);
+
+        /* Traitement de la fin de la première aire */
+
+        processed = get_mrange_length(&area->range) - offset;
+
+        result = visitor(area, offset, processed, instr);
+
+        /* Traitement des zones adjacentes suivantes */
+
+        copy_vmpa(&start, get_mrange_addr(range));
+
+        for (remaining -= processed; remaining > 0 && result; remaining -= processed)
+        {
+            advance_vmpa(&start, processed);
+
+            area = find_memory_area_by_addr(list, count, &start);
+            if (area == NULL)
+            {
+                result = false;
+                break;
+            }
+
+            processed = get_mrange_length(&area->range);
+            if (remaining < processed) processed = remaining;
+
+            result = visitor(area, 0, processed, instr);
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list  = liste de zones délimitant des contenus à traiter.    *
+*                count = nombre de zones à disposition.                       *
+*                range = aire des octets à manipuler.                         *
+*                                                                             *
+*  Description : Indique si une zone donnée est intégralement vierge ou non.  *
+*                                                                             *
+*  Retour      : true si l'aire visée n'a jamais été traitée, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool is_range_blank_in_mem_areas(mem_area *list, size_t count, const mrange_t *range)
+{
+    return handle_bytes_map_in_mem_area(list, count,
+                                        range, NULL,
+                                        is_range_blank_in_mem_area);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list  = liste de zones délimitant des contenus à traiter.    *
+*                count = nombre de zones à disposition.                       *
+*                instr = instruction désassemblée à conserver en mémoire.     *
+*                                                                             *
+*  Description : Marque une série d'octets comme ayant été traités.           *
+*                                                                             *
+*  Retour      : true.                                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool mark_range_in_mem_areas_as_processed(mem_area *list, size_t count, GArchInstruction *instr)
+{
+    return handle_bytes_map_in_mem_area(list, count,
+                                        g_arch_instruction_get_range(instr), instr,
+                                        mark_range_in_mem_area_as_processed);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : list   = liste de zones délimitant des contenus à traiter.   *
+*                count  = nombre de zones à disposition.                      *
+*                binary = représentation de binaire chargé.                   *
+*                ctx    = contexte offert en soutien à un désassemblage.      *
+*                info   = indications quant à la progression à afficher.      *
+*                                                                             *
+*  Description : S'assure que l'ensemble des aires est entièrement décodé.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void ensure_all_mem_areas_are_filled(mem_area *list, size_t count, const GLoadedBinary *binary, GProcContext *ctx, status_info *info)
+{
+	size_t i;								/* Boucle de parcours		   */
+
+	for (i = 0; i < count; i++)
+		fill_mem_area(&list[i], list, count, binary, ctx, info);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : areas = série d'aires représentant à contenu à parcourir.    *
+*                count = nombre de ces zones présentes.                       *
+*                                                                             *
+*  Description : Rassemble les instructions conservées dans des zones données.*
+*                                                                             *
+*  Retour      : Liste d'instructions prêtes à emploi.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GArchInstruction *collect_instructions_from_mem_areas(mem_area *list, size_t count)
+{
+    GArchInstruction *result;               /* Liste d'instr. à renvoyer   */
+	size_t i;								/* Boucle de parcours		   */
+    GArchInstruction *instr;                /* Instruction(s) à insérer    */
+
+	result = NULL;
+
+	for (i = 0; i < count; i++)
+	{
+		instr = get_instructions_from_mem_area(&list[i]);
+        g_arch_instruction_merge_lists(&result, &instr);
+	}
+
+	return result;
+
+}
diff --git a/src/analysis/disass/area.h b/src/analysis/disass/area.h
new file mode 100644
index 0000000..58539ca
--- /dev/null
+++ b/src/analysis/disass/area.h
@@ -0,0 +1,96 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * area.h - prototypes pour la définition et la manipulation des aires à désassembler
+ *
+ * Copyright (C) 2014 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  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_AREA_H
+#define _ANALYSIS_DISASS_AREA_H
+
+
+#include "../binary.h"
+#include "../../format/executable.h"
+#include "../../gtkext/gtkextstatusbar.h"
+
+
+//////
+#include "../../arch/raw.h"
+#include "../../arch/instruction.h"
+
+
+
+/* Zone mémoire bien bornée */
+typedef struct _mem_area
+{
+    mrange_t range;                         /* Couverture de la zone       */
+
+    unsigned long *processed;               /* Octets traités dans la zone */
+    GArchInstruction **instructions;        /* Instructions en place       */
+
+    bool has_sym;                           /* Représentation via symbole ?*/
+
+    union
+    {
+        bool exec;                          /* Zone exécutable ?           */
+        GBinSymbol *symbol;                 /* Symbole associé à la zone   */
+    };
+
+} mem_area;
+
+
+
+
+/* Zone mémoire bien bornée */
+//typedef struct _mem_area mem_area;
+
+
+
+
+/* Procède au désassemblage d'un contenu binaire exécutable. */
+void load_code_from_mem_area(mem_area *, mem_area *, size_t, const GLoadedBinary *, GProcContext *, const vmpa2t *, status_info *);
+
+
+
+/* Détermine une liste de zones contigües à traiter. */
+mem_area *compute_memory_areas(GExeFormat *, phys_t, size_t *);
+
+
+
+
+
+
+
+
+
+/* Détermine une liste de zones contigües à traiter. */
+mem_area *find_memory_area_by_addr(mem_area *, size_t, const vmpa2t *);
+
+
+
+
+/* S'assure que l'ensemble des aires est entièrement décodé. */
+void ensure_all_mem_areas_are_filled(mem_area *, size_t, const GLoadedBinary *, GProcContext *, status_info *);
+
+/* Rassemble les instructions conservées dans des zones données. */
+GArchInstruction *collect_instructions_from_mem_areas(mem_area *, size_t);
+
+
+
+#endif  /* _ANALYSIS_DISASS_AREA_H */
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index 1fd5550..8bddaa1 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -24,429 +24,96 @@
 #include "fetch.h"
 
 
-#include <assert.h>
+#include "area.h"
 
 
-#include "../../arch/raw.h"
-#include "../../arch/instruction.h"
 
 
+/* Suit un flot d'exécution pour désassembler du code. */
+static void follow_execution_flow(const GLoadedBinary *, GProcContext *, mem_area *, size_t, status_info *, virt_t);
 
-/* Zone mémoire bien bornée */
-typedef struct _mem_area
-{
-    mrange_t range;                         /* Couverture de la zone       */
-
-    bool has_sym;                           /* Représentation via symbole ?*/
-
-    union
-    {
-        bool exec;                          /* Zone exécutable ?           */
-        GBinSymbol *symbol;                 /* Symbole associé à la zone   */
-    };
 
-} mem_area;
 
 
-/* Détermine une liste de zones contigües à traiter. */
-static mem_area *compute_memory_areas(const GExeFormat *, phys_t, size_t *);
 
-/* Procède au désassemblage basique d'un contenu binaire. */
-static GArchInstruction *load_raw_binary(const GLoadedBinary *, const vmpa2t *, off_t, GtkExtStatusBar *, bstatus_id_t);
 
-/* Procède au désassemblage d'un contenu binaire exécutable. */
-static GArchInstruction *load_code_binary(const GLoadedBinary *, const vmpa2t *, off_t, GtkExtStatusBar *, bstatus_id_t);
 
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format     = format d'un exécutable à consulter.             *
-*                bin_length = quantité d'octets à traiter au total.           *
-*                count      = nombre de zones mises en place. [OUT]           *
+*  Paramètres  : binary = représentation de binaire chargé.                   *
+*                ctx    = contexte offert en soutien à un désassemblage.      *
+*                areas  = liste de zones contenant des données à traiter.     *
+*                count  = nombre de ces aires à disposition.                  *
+*                info   = informations liées à l'affichage de la progression. *
+*                virt   = adresse d'un point de départ d'un traitement.       *
 *                                                                             *
-*  Description : Détermine une liste de zones contigües à traiter.            *
+*  Description : Suit un flot d'exécution pour désassembler du code.          *
 *                                                                             *
-*  Retour      : Liste de zones mémoire à libérer après usage.                *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static mem_area *compute_memory_areas(const GExeFormat *format, phys_t bin_length, size_t *count)
+static void follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx, mem_area *areas, size_t count, status_info *info, virt_t virt)
 {
-    mem_area *result;                       /* Liste à renvoyer            */
-    mrange_t *exe_ranges;                   /* Liste de zones exécutables  */
-    size_t exe_count;                       /* Nombre de ces zones         */
-    GBinSymbol **symbols;                   /* Symboles à représenter      */
-    size_t sym_count;                       /* Qté de symboles présents    */
-    vmpa2t *last;                           /* Dernière bordure rencontrée */
-    size_t i;                               /* Boucle de parcours #1       */
-    vmpa2t *border;                         /* Nouvelle bordure rencontrée */
-    mem_area *area;                         /* Zone avec valeurs à éditer  */
-    vmpa2t tmp;                             /* Stockage temporaire         */
-    size_t j;                               /* Boucle de parcours #2       */
-    const mrange_t *range;                  /* Couverture d'un symbole     */
-    const vmpa2t *start;                    /* Point de départ du symbole  */
-    phys_t length;                          /* Taille de ce même symbole   */
-    bool included;                          /* Inclusion dans une zone ?   */
-    mem_area orig;                          /* Copie de la zone réduite    */
-    phys_t old_length;                      /* Taille de zone originelle   */
-    phys_t new_length;                      /* Nouvelle taille déterminée  */
-    size_t next;                            /* Indice de zone suivante     */
-
-    result = NULL;
-    *count = 0;
-
-    /**
-     * Le parcours n'est valide que si les listes, symboles et zones exécutables,
-     * sont triées !
-     */
-
-    exe_ranges = g_exe_format_get_x_ranges(format, &exe_count);
-
-    symbols = g_binary_format_get_symbols(G_BIN_FORMAT(format), &sym_count);
-
-    /* Première étape : on comble les trous ! */
-
-    last = make_vmpa(0, VMPA_NO_VIRTUAL);
-
-    for (i = 0; i < exe_count; i++)
-    {
-        border = get_mrange_addr(&exe_ranges[i]);
-
-        /* Zone tampon à constituer */
-
-        if (cmp_vmpa_by_phy(last, border) < 0)
-        {
-            result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
-
-            area = &result[*count - 1];
-
-            init_mrange(&area->range, last, compute_vmpa_diff(last, border));
-            area->has_sym = false;
-            area->exec = false;
-
-        }
-
-        /* Insertion d'une zone exécutable déjà définie */
-
-        result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
 
-        area = &result[*count - 1];
 
-        copy_mrange(&area->range, &exe_ranges[i]);
-        area->has_sym = false;
-        area->exec = true;
 
-        /* Avancée du curseur */
 
-        copy_vmpa(last, border);
 
-        advance_vmpa(last, get_mrange_length(&exe_ranges[i]));
+    vmpa2t addr;                            /* Conversion en pleine adresse*/
 
-    }
-
-    delete_vmpa(last);
-
-    /* Extension finale complémentaire ? */
-
-    area = &result[*count - 1];
-
-    copy_vmpa(&tmp, get_mrange_addr(&area->range));
-    advance_vmpa(&tmp, get_mrange_length(&area->range));
-
-    if (get_phy_addr(&tmp) < bin_length)
-    {
-        result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
 
-        area = &result[*count - 1];
+    mem_area *area;                         /* Zone de désassemblage       */
 
-        init_mrange(&area->range, &tmp, bin_length - get_phy_addr(&tmp));
-        area->has_sym = false;
-        area->exec = false;
 
-    }
 
-    /* Seconde étape : on insère les symboles existants */
 
-    j = 0;
 
-#define SKIP_EMPTY_SYMBOLS                                  \
-    for (; j < sym_count; j++)                              \
-    {                                                       \
-        range = g_binary_symbol_get_range(symbols[j]);      \
-                                                            \
-        length = get_mrange_length(range);                  \
-        if (length > 0) break;                              \
-                                                            \
-    }                                                       \
 
-    SKIP_EMPTY_SYMBOLS
+    g_proc_context_push_drop_point(ctx, virt);
 
-    for (i = 0; i < *count && j < sym_count; i++)
+    while (g_proc_context_has_drop_points(ctx))
     {
-        range = g_binary_symbol_get_range(symbols[j]);
-
-        start = get_mrange_addr(range);
-        length = get_mrange_length(range);
-
-        /* Si un découpage s'impose... */
-
-        if (mrange_contains_addr(&result[i].range, start))
-        {
-            copy_vmpa(&tmp, start);
-            advance_vmpa(&tmp, length);
-
-            included = mrange_contains_addr(&result[i].range, &tmp);
-
-            memcpy(&orig, &result[i], sizeof(mem_area));
-
-            /* Réduction de la zone de départ */
-
-            copy_vmpa(&tmp, get_mrange_addr(&result[i].range));
-            old_length = get_mrange_length(&result[i].range);
-
-            new_length = compute_vmpa_diff(get_mrange_addr(&result[i].range), start);
-
-            if (new_length == 0)
-            {
-                memmove(&result[i], &result[i + 1], (*count - i - 1) * sizeof(mem_area));
-
-                (*count)--;
-                next = i;
-
-            }
-            else
-            {
-                init_mrange(&result[i].range, &tmp, new_length);
-                next = i + 1;
-            }
-
-            /* Insertion de la zone du symbole */
-
-            result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
-
-            memmove(&result[next + 1], &result[next], (*count - next - 1) * sizeof(mem_area));
-
-            area = &result[next];
-
-            copy_mrange(&area->range, range);
-
-            area->has_sym = true;
-            area->symbol = symbols[j];
-
-            /* Jointure finale... */
-
-            if (included)
-            {
-                /* Simple extension pour rattraper la fin originelle */
-
-                if ((old_length - new_length - length) > 0)
-                {
-                    result = (mem_area *)realloc(result, ++(*count) * sizeof(mem_area));
-
-                    memmove(&result[next + 2], &result[next + 1], (*count - next - 2) * sizeof(mem_area));
-
-                    area = &result[next + 1];
-
-                    copy_vmpa(&tmp, start);
-                    advance_vmpa(&tmp, length);
-
-                    memcpy(area, &orig, sizeof(mem_area));
-
-                    init_mrange(&area->range, &tmp, old_length - new_length - length);
-
-                }
+        virt = g_proc_context_pop_drop_point(ctx);
+        init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
 
-                i = next;
 
-            }
-            else
-            {
-                /* Suppression des éventuelles zones totalement recouvertes */
+        area = find_memory_area_by_addr(areas, count, &addr);
 
+        /*
+        printf("found area = %p\n", area);
 
+        printf("      ... 0x%08x - 0x%08x + %u\n",
+               area->range.addr.physical,
+               area->range.addr.virtual,
+               area->range.length);
+        */
 
-                /* Réduction de la zone d'arrivée */
 
+        load_code_from_mem_area(area, areas, count, binary, ctx, &addr, info);
 
-            }
 
 
-
-
-
-            j++;
-
-            SKIP_EMPTY_SYMBOLS
-
-        }
+        //exit(0);
 
     }
 
-
-
-    //free
-
-    //exit(0);
-
-    return result;
-
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : binary    = représentation de binaire chargé.                *
-*                parts     = parties binaires à désassembler.                 *
-*                count     = nombre de parties à traiter.                     *
-*                statusbar = barre de statut avec progression à mettre à jour.*
-*                id        = identifiant du message affiché à l'utilisateur.  *
-*                                                                             *
-*  Description : Procède au désassemblage basique d'un contenu binaire.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
 
-static GArchInstruction *load_raw_binary(const GLoadedBinary *binary, const vmpa2t *base, off_t end, GtkExtStatusBar *statusbar, bstatus_id_t id)
-{
-    GArchInstruction *result;               /* Liste d'instr. à renvoyer   */
-    GBinFormat *format;                     /* Format du fichier binaire   */
-    GArchProcessor *proc;                   /* Architecture du binaire     */
-    off_t bin_length;                       /* Taille des données à lire   */
-    bin_t *bin_data;                        /* Données binaires à lire     */
-    vmpa2t pos;                             /* Boucle de parcours          */
-    vmpa2t prev;                            /* Boucle de parcours          */
-    off_t old_phy;                          /* Ancienne position physique  */
-    GArchInstruction *instr;                /* Instruction décodée         */
-    off_t new_phy;                          /* Nouvelle position physique  */
-    mrange_t range;                         /* Couverture de l'instruction */
 
-    result = NULL;
 
-    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
-    proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
-    bin_data = g_loaded_binary_get_data(binary, &bin_length);
 
-    copy_vmpa(&pos, base);
-    copy_vmpa(&prev, base);
 
-    old_phy = get_phy_addr(&prev);
 
-    while (old_phy < end)
-    {
-        instr = g_raw_instruction_new_array(bin_data, MDS_32_BITS, 1, &pos, end,
-                                            g_arch_processor_get_endianness(proc));
-        if (instr == NULL) printf(" Break !!!\n");
-        if (instr == NULL) break;
 
-        new_phy = get_phy_addr(&pos);
-        init_mrange(&range, &prev, new_phy - old_phy);
 
-        g_arch_instruction_set_range(instr, &range);
 
-        g_arch_instruction_add_to_list(&result, instr);
-
-        copy_vmpa(&prev, &pos);
-        old_phy = get_phy_addr(&prev);
-
-        //done += (new_phy - old_phy);
-        //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : binary    = représentation de binaire chargé.                *
-*                parts     = parties binaires à désassembler.                 *
-*                count     = nombre de parties à traiter.                     *
-*                statusbar = barre de statut avec progression à mettre à jour.*
-*                id        = identifiant du message affiché à l'utilisateur.  *
-*                                                                             *
-*  Description : Procède au désassemblage d'un contenu binaire exécutable.    *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmpa2t *base, off_t end, GtkExtStatusBar *statusbar, bstatus_id_t id)
-{
-    GArchInstruction *result;               /* Liste d'instr. à renvoyer   */
-    GBinFormat *format;                     /* Format du fichier binaire   */
-    GArchProcessor *proc;                   /* Architecture du binaire     */
-    off_t bin_length;                       /* Taille des données à lire   */
-    bin_t *bin_data;                        /* Données binaires à lire     */
-    vmpa2t pos;                             /* Boucle de parcours          */
-    vmpa2t prev;                            /* Boucle de parcours          */
-    off_t old_phy;                          /* Ancienne position physique  */
-    GArchInstruction *instr;                /* Instruction décodée         */
-    off_t new_phy;                          /* Nouvelle position physique  */
-    mrange_t range;                         /* Couverture de l'instruction */
-
-    result = NULL;
-
-    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
-    proc = get_arch_processor_from_format(G_EXE_FORMAT(format));
-    bin_data = g_loaded_binary_get_data(binary, &bin_length);
-
-    copy_vmpa(&pos, base);
-    copy_vmpa(&prev, base);
-
-    old_phy = get_phy_addr(&prev);
-
-    while (old_phy < end)
-    {
-        instr = g_arch_processor_disassemble(proc, NULL, bin_data, &pos, end);
-
-        //if (!G_IS_RAW_INSTRUCTION(instr)) printf("GOT %p\n", instr);
-
-        if (instr == NULL)
-        instr = g_raw_instruction_new_array(bin_data, MDS_32_BITS, 1, &pos, end,
-                                            g_arch_processor_get_endianness(proc));
-        if (instr == NULL) printf(" Break !!!\n");
-        if (instr == NULL) break;
-
-        new_phy = get_phy_addr(&pos);
-        init_mrange(&range, &prev, new_phy - old_phy);
-
-        g_arch_instruction_set_range(instr, &range);
-
-        g_arch_instruction_add_to_list(&result, instr);
-
-        copy_vmpa(&prev, &pos);
-        old_phy = get_phy_addr(&prev);
-
-        //done += (new_phy - old_phy);
-        //gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
-
-
-
-
-
-        g_arch_instruction_call_hook(instr, IPH_LINK, NULL, format);
-
-
-        g_arch_instruction_call_hook(instr, IPH_POST, NULL, format);
-
-
-
-
-    }
-
-    return result;
-
-}
 
 
 
@@ -467,83 +134,34 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp
 *                                                                             *
 ******************************************************************************/
 
-static GArchInstruction *follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx, mem_area *areas, size_t count, GtkExtStatusBar *statusbar, bstatus_id_t id)
+GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id)
 {
-    GBinFormat *format;                     /* Format du fichier binaire   */
-
-    virt_t addr;
-
-
-
-    mem_area *area;                         /* Zone de désassemblage       */
-
-
-    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
-
-    /* Insertion du point de départ */
-
-    addr = g_binary_format_get_entry_point(format);
-
-    g_proc_context_push_drop_point(ctx, addr);
-
-    /* Suivi de l'exécution autant que possible */
-
-    while (g_proc_context_has_drop_points(ctx))
-    {
-        //virt = g_proc_context_pop_drop_point(ctx);
-
-
-        area = NULL;
-
-
-
-
-    }
-
-
-
-
-    // ctx.add(entry_point)
-
-    // while (ctx.has_pending_addresses)
-
-    //      virt = ctx.pop
-    //      find mem_area for virt
-
-    //      if area.limit < virt then continue
-
-
+    GArchInstruction *result;               /* Instruction désassemblées   */
 
+    GBinFormat *format;                     /* Format du fichier binaire   */
+    GArchProcessor *proc;                   /* Architecture du binaire     */
 
+    GProcContext *ctx;                      /* Contexte de désassemblage   */
 
-}
+    status_info *info;
 
+    off_t length;                           /* Taille des données à lire   */
+    mem_area *areas;                        /* Zone de productions         */
+    size_t count;                           /* Nombre de ces zones         */
 
 
+    virt_t virt;                            /* Point d'accroche virtuelle  */
 
+    GBinSymbol **symbols;                   /* Symboles à représenter      */
+    size_t sym_count;                       /* Qté de symboles présents    */
 
+    size_t i;                               /* Boucle de parcours          */
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : binary    = représentation de binaire chargé.                *
-*                statusbar = barre de statut avec progression à mettre à jour.*
-*                id        = identifiant du message affiché à l'utilisateur.  *
-*                                                                             *
-*  Description : Procède au désassemblage basique d'un contenu binaire.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
 
-GArchInstruction *disassemble_binary_content_new(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id)
-{
 
-    GBinFormat *format;                     /* Format du fichier binaire   */
-    GArchProcessor *proc;                   /* Architecture du binaire     */
+    const mrange_t *range;                  /* Couverture d'un symbole     */
+    const vmpa2t *addr;                     /* Point de départ du symbole  */
 
-    GProcContext *ctx;                      /* Contexte de désassemblage   */
 
 
 
@@ -553,88 +171,46 @@ GArchInstruction *disassemble_binary_content_new(const GLoadedBinary *binary, Gt
 
     ctx = g_arch_processor_get_context(proc);
 
+    info = NULL;
 
 
-}
-
+    /* Définition à la découpe des parties à traiter */
 
+    g_loaded_binary_get_data(binary, &length);
+    areas = compute_memory_areas(G_EXE_FORMAT(format), length, &count);
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : binary    = représentation de binaire chargé.                *
-*                statusbar = barre de statut avec progression à mettre à jour.*
-*                id        = identifiant du message affiché à l'utilisateur.  *
-*                                                                             *
-*  Description : Procède au désassemblage basique d'un contenu binaire.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+    /* Insertion du point de départ */
 
-GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id)
-{
-    GArchInstruction *result;               /* Instruction désassemblées   */
-    GExeFormat *format;                     /* Format du fichier binaire   */
-    off_t length;                           /* Taille des données à lire   */
-    mem_area *areas;                        /* Zone de productions         */
-    size_t count;                           /* Nombre de ces zones         */
-    size_t i;                               /* Boucle de parcours          */
-    mem_area *iter;                         /* Zone parcourue              */
-    GArchInstruction *instr;                /* Instruction(s) à insérer    */
-    const vmpa2t *start;                    /* Début d'une zone traitée    */
-    phys_t end;                             /* Fin d'une zone traitée      */
+    virt = g_binary_format_get_entry_point(format);
 
-    result = NULL;
+    follow_execution_flow(binary, ctx, areas, count, info, virt);
 
-    format = g_loaded_binary_get_format(binary);
-    g_loaded_binary_get_data(binary, &length);
+    /* Symboles exécutables présents et passés à travers les mailles */
 
-    areas = compute_memory_areas(format, length, &count);
+    symbols = g_binary_format_get_symbols(format, &sym_count);
 
-    for (i = 0; i < count; i++)
+    for (i = 0; i < sym_count; i++)
     {
-        iter = &areas[i];
-
-        start = get_mrange_addr(&iter->range);
-        end = get_phy_addr(start) + get_mrange_length(&iter->range);
+        if (g_binary_symbol_get_target_type(symbols[i]) != STP_FUNCTION)
+            continue;
 
-        assert(get_mrange_length(&iter->range) > 0);
+        range = g_binary_symbol_get_range(symbols[i]);
+        addr = get_mrange_addr(range);
+        virt = get_virt_addr(addr);
 
-        if (iter->has_sym)
-            switch (g_binary_symbol_get_target_type(iter->symbol))
-            {
-                case STP_DATA:
-                    instr = g_binary_symbol_get_instruction(iter->symbol);
-                    g_object_ref(G_OBJECT(instr));
-                    break;
+        follow_execution_flow(binary, ctx, areas, count, info, virt);
 
-                case STP_ROUTINE:
-                    instr = load_code_binary(binary, start, end, statusbar, id);
-                    break;
-
-                default:
-                    assert(false);
-                    break;
+    }
 
-            }
 
-        else
-        {
-            if (iter->exec)
-                instr = load_code_binary(binary, start, end, statusbar, id);
-            else
-                instr = load_raw_binary(binary, start, end, statusbar, id);
+	ensure_all_mem_areas_are_filled(areas, count, binary, ctx, info);
 
-        }
 
-        g_arch_instruction_merge_lists(&result, &instr);
 
-    }
+	result = collect_instructions_from_mem_areas(areas, count);
 
-    free(areas);
+	/* free */
 
-    return result;
+	return result;
 
 }
diff --git a/src/arch/arm/context.c b/src/arch/arm/context.c
index c86b190..7f41b92 100644
--- a/src/arch/arm/context.c
+++ b/src/arch/arm/context.c
@@ -60,6 +60,9 @@ static void g_arm_context_dispose(GArmContext *);
 /* Procède à la libération totale de la mémoire. */
 static void g_arm_context_finalize(GArmContext *);
 
+/* Ajoute une adresse virtuelle comme point de départ de code. */
+static void g_arm_context_push_drop_point(GArmContext *, virt_t );
+
 
 
 /* ------------------------- CONTEXTE POUR LA DECOMPILATION ------------------------- */
@@ -124,12 +127,17 @@ G_DEFINE_TYPE(GArmContext, g_arm_context, G_TYPE_PROC_CONTEXT);
 static void g_arm_context_class_init(GArmContextClass *klass)
 {
     GObjectClass *object;                   /* Autre version de la classe  */
+    GProcContextClass *proc;                /* Version parente de la classe*/
 
     object = G_OBJECT_CLASS(klass);
 
     object->dispose = (GObjectFinalizeFunc/* ! */)g_arm_context_dispose;
     object->finalize = (GObjectFinalizeFunc)g_arm_context_finalize;
 
+	proc = G_PROC_CONTEXT_CLASS(klass);
+
+	proc->push_point = (push_drop_point_fc)g_arm_context_push_drop_point;
+
 }
 
 
@@ -212,6 +220,42 @@ GArmContext *g_arm_context_new(void)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx  = contexte de désassemblage à compléter.                *
+*                addr = adresse d'un nouveau point de départ à traiter.       *
+*                                                                             *
+*  Description : Ajoute une adresse virtuelle comme point de départ de code.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_arm_context_push_drop_point(GArmContext *ctx, virt_t addr)
+{
+
+
+	printf("PUSH !!\n");
+
+
+
+	if (addr & 0x1)
+	{
+		addr -= 0x1;
+
+
+	}
+	else ;
+
+	// ARM / Thumb
+
+	G_PROC_CONTEXT_CLASS(g_arm_context_parent_class)->push_point(G_PROC_CONTEXT(ctx), addr);
+
+}
+
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                           CONTEXTE POUR LA DECOMPILATION                           */
diff --git a/src/arch/arm/processor.c b/src/arch/arm/processor.c
index 2c676be..cf993c0 100644
--- a/src/arch/arm/processor.c
+++ b/src/arch/arm/processor.c
@@ -24,6 +24,7 @@
 #include "processor.h"
 
 
+#include "context.h"
 #include "processor-int.h"
 
 
@@ -40,6 +41,9 @@ static void g_arm_processor_dispose(GArmProcessor *);
 /* Procède à la libération totale de la mémoire. */
 static void g_arm_processor_finalize(GArmProcessor *);
 
+/* Fournit un contexte pour l'exécution du processeur ARM. */
+static GArmContext *g_arm_processor_get_context(const GArmProcessor *);
+
 
 
 /* Indique le type défini par la GLib pour le processeur ARM. */
@@ -84,6 +88,11 @@ static void g_arm_processor_class_init(GArmProcessorClass *klass)
 
 static void g_arm_processor_init(GArmProcessor *proc)
 {
+    GArchProcessor *parent;                 /* Instance parente            */
+
+    parent = G_ARCH_PROCESSOR(proc);
+
+    parent->get_ctx = (get_processor_context_fc)g_arm_processor_get_context;
 
 }
 
@@ -124,3 +133,22 @@ static void g_arm_processor_finalize(GArmProcessor *proc)
     G_OBJECT_CLASS(g_arm_processor_parent_class)->finalize(G_OBJECT(proc));
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : proc = architecture, spectatrice ici.                        *
+*                                                                             *
+*  Description : Fournit un contexte pour l'exécution du processeur Arm.      *
+*                                                                             *
+*  Retour      : Contexte mis en place.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GArmContext *g_arm_processor_get_context(const GArmProcessor *proc)
+{
+    return g_arm_context_new();
+
+}
diff --git a/src/arch/arm/v7/link.c b/src/arch/arm/v7/link.c
index 278b8d0..e7a1b40 100644
--- a/src/arch/arm/v7/link.c
+++ b/src/arch/arm/v7/link.c
@@ -67,6 +67,9 @@ void handle_links_with_thumb_instruction_bl(GArchInstruction *instr, GProcContex
     if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset))
         g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset);
 
+
+    printf("[@ 0x%08x] Add 0x%08x to %p\n", (uint32_t)get_virt_addr(get_mrange_addr(range)), (uint32_t)(pc + offset), context);
+
 }
 
 
@@ -110,4 +113,8 @@ void handle_links_with_thumb_instruction_blx(GArchInstruction *instr, GProcConte
     if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset))
         g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset);
 
+
+    printf("[@ 0x%08x] Add 0x%08x to %p\n", (uint32_t)get_virt_addr(get_mrange_addr(range)), (uint32_t)(pc + offset), context);
+
+
 }
diff --git a/src/arch/context-int.h b/src/arch/context-int.h
index 3a65f79..b181202 100644
--- a/src/arch/context-int.h
+++ b/src/arch/context-int.h
@@ -29,6 +29,10 @@
 
 
 
+/* Ajoute une adresse virtuelle comme point de départ de code. */
+typedef void (* push_drop_point_fc) (GProcContext *, virt_t);
+
+
 /* Définition d'un contexte pour processeur (instance) */
 struct _GProcContext
 {
@@ -45,6 +49,8 @@ struct _GProcContextClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
+	push_drop_point_fc push_point;			/* Inclusion de points de chute*/
+
 };
 
 
diff --git a/src/arch/context.c b/src/arch/context.c
index 46c4dd1..794030a 100644
--- a/src/arch/context.c
+++ b/src/arch/context.c
@@ -39,6 +39,9 @@ static void g_proc_context_class_init(GProcContextClass *);
 /* Initialise une instance de contexte de processeur. */
 static void g_proc_context_init(GProcContext *);
 
+/* Ajoute une adresse virtuelle comme point de départ de code. */
+static void _g_proc_context_push_drop_point(GProcContext *, virt_t);
+
 
 
 /* Indique le type définit par la GLib pour le contexte de processeur. */
@@ -60,6 +63,7 @@ G_DEFINE_TYPE(GProcContext, g_proc_context, G_TYPE_OBJECT);
 
 static void g_proc_context_class_init(GProcContextClass *klass)
 {
+	klass->push_point = (push_drop_point_fc)_g_proc_context_push_drop_point;
 
 }
 
@@ -97,7 +101,7 @@ static void g_proc_context_init(GProcContext *ctx)
 *                                                                             *
 ******************************************************************************/
 
-void g_proc_context_push_drop_point(GProcContext *ctx, virt_t addr)
+static void _g_proc_context_push_drop_point(GProcContext *ctx, virt_t addr)
 {
     ctx->drop_points = (virt_t *)realloc(ctx->drop_points, ++ctx->dp_count * sizeof(virt_t));
 
@@ -108,6 +112,26 @@ void g_proc_context_push_drop_point(GProcContext *ctx, virt_t addr)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : ctx  = contexte de désassemblage à compléter.                *
+*                addr = adresse d'un nouveau point de départ à traiter.       *
+*                                                                             *
+*  Description : Ajoute une adresse virtuelle comme point de départ de code.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_proc_context_push_drop_point(GProcContext *ctx, virt_t addr)
+{
+	return G_PROC_CONTEXT_GET_CLASS(ctx)->push_point(ctx, addr);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : ctx = contexte de désassemblage à consulter.                 *
 *                                                                             *
 *  Description : Indique si des points de départ restent à traiter ou non.    *
diff --git a/src/arch/context.h b/src/arch/context.h
index 9bb7cd3..97b23b6 100644
--- a/src/arch/context.h
+++ b/src/arch/context.h
@@ -36,9 +36,9 @@
 #define G_TYPE_PROC_CONTEXT              g_proc_context_get_type()
 #define G_PROC_CONTEXT(obj)              (G_TYPE_CHECK_INSTANCE_CAST((obj), g_proc_context_get_type(), GProcContext))
 #define G_IS_PROC_CONTEXT(obj)           (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_proc_context_get_type()))
-#define G_PROC_CONTEXT_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PROC_CONTEXT, GGProcContextClass))
+#define G_PROC_CONTEXT_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PROC_CONTEXT, GProcContextClass))
 #define G_IS_PROC_CONTEXT_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PROC_CONTEXT))
-#define G_PROC_CONTEXT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PROC_CONTEXT, GGProcContextClass))
+#define G_PROC_CONTEXT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PROC_CONTEXT, GProcContextClass))
 
 
 /* Définition d'un contexte pour processeur (instance) */
diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c
index 024161c..7d57909 100644
--- a/src/arch/vmpa.c
+++ b/src/arch/vmpa.c
@@ -626,6 +626,37 @@ int cmp_mrange(const mrange_t *a, const mrange_t *b)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : range = zone mémoire à consulter.                            *
+*                sub   = éventuelle sous-région à valider.                    *
+*                                                                             *
+*  Description : Indique si une zone en contient une autre ou non.            *
+*                                                                             *
+*  Retour      : Bilan de la consultation.                                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool mrange_contains_mrange(const mrange_t *range, const mrange_t *sub)
+{
+    bool result;                            /* Bilan à retourner           */
+    phys_t start;                           /* Point de départ             */
+
+    result = mrange_contains_addr(range, get_mrange_addr(sub));
+
+    if (result)
+    {
+        start = compute_vmpa_diff(get_mrange_addr(range), get_mrange_addr(sub));
+        result = (start + get_mrange_length(sub) <= get_mrange_length(range));
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : range = zone mémoire à consulter.                            *
 *                addr  = localisation mémoire à analyser.                     *
 *                                                                             *
 *  Description : Indique si une localisation est incluse dans une zone ou non.*
diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h
index f0a8faf..96e8a56 100644
--- a/src/arch/vmpa.h
+++ b/src/arch/vmpa.h
@@ -153,6 +153,9 @@ void copy_mrange(mrange_t *, const mrange_t *);
 /* Compare deux couvertures mémoire selon leurs propriétés. */
 int cmp_mrange(const mrange_t *, const mrange_t *);
 
+/* Indique si une zone en contient une autre ou non. */
+bool mrange_contains_mrange(const mrange_t *, const mrange_t *);
+
 /* Indique si une localisation est incluse dans une zone ou non. */
 bool mrange_contains_addr(const mrange_t *, const vmpa2t *);
 
diff --git a/src/gtkext/gtkextstatusbar.h b/src/gtkext/gtkextstatusbar.h
index fba0823..779a177 100644
--- a/src/gtkext/gtkextstatusbar.h
+++ b/src/gtkext/gtkextstatusbar.h
@@ -30,6 +30,19 @@
 
 
 
+typedef struct _status_info
+{
+
+
+    void *a;
+
+    //GtkExtStatusBar *statusbar, bstatus_id_t id
+
+} status_info;
+
+
+
+
 #define GTK_TYPE_EXT_STATUS_BAR            (gtk_extended_status_bar_get_type())
 #define GTK_EXT_STATUS_BAR(obj)            (G_TYPE_CHECK_INSTANCE_CAST(obj, gtk_extended_status_bar_get_type (), GtkExtStatusBar))
 #define GTK_IS_EXT_STATUS_BAR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE(obj, gtk_extended_status_bar_get_type()))
-- 
cgit v0.11.2-87-g4458