From ffc49de3b424d3daf08b5fdeefd4a3ede6defd02 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 11 Oct 2014 20:50:03 +0000
Subject: Improved the disassembling process using memory ranges.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@411 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                   |  21 ++
 src/analysis/disass/fetch.c | 547 +++++++++++++++++++++++---------------------
 src/arch/instruction.c      |  20 ++
 src/arch/instruction.h      |   3 +
 src/format/elf/symbols.c    |   2 +-
 src/format/executable.c     |  59 +++++
 src/format/executable.h     |   5 +-
 src/glibext/gbinportion.c   |  55 ++++-
 src/glibext/gbinportion.h   |  12 +-
 9 files changed, 462 insertions(+), 262 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6af7fa3..a75ba6b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+14-10-11  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/fetch.c:
+	Improve the disassembling process using memory ranges.
+
+	* src/arch/instruction.c:
+	* src/arch/instruction.h:
+	Provide a way to merge two lists of instructions.
+
+	* src/format/elf/symbols.c:
+	Remove the arbitrary length of ELF symbols.
+
+	* src/format/executable.c:
+	* src/format/executable.h:
+	Compute ranges of executable binary areas.
+
+	* src/glibext/gbinportion.c:
+	* src/glibext/gbinportion.h:
+	Combine a memory range with each binary portion. Add a design pattern to
+	visit portions.
+
 14-10-08  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac:
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index eee2eb6..f10178a 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -24,18 +24,33 @@
 #include "fetch.h"
 
 
-#include "../../arch/artificial.h"
+#include <assert.h>
 
 
+#include "../../arch/raw.h"
+#include "../../arch/instruction.h"
 
 
-#include "../../arch/raw.h"
-#include "../../arch/instruction-int.h"
 
+/* 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);
 
@@ -44,6 +59,241 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *, const vmpa2t *,
 
 
 
+/******************************************************************************
+*                                                                             *
+*  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   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static mem_area *compute_memory_areas(const 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         */
+    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]));
+
+    }
+
+    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_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
+
+    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));
+
+            /* 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);
+
+                }
+
+                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;
+
+}
 
 
 /******************************************************************************
@@ -159,7 +409,7 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp
     {
         instr = g_arch_processor_disassemble(proc, NULL, bin_data, &pos, end);
 
-        if (!G_IS_RAW_INSTRUCTION(instr)) printf("GOT %p\n", instr);
+        //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,
@@ -187,12 +437,6 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp
 }
 
 
-
-
-
-
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : binary    = représentation de binaire chargé.                *
@@ -209,277 +453,66 @@ static GArchInstruction *load_code_binary(const GLoadedBinary *binary, const vmp
 
 GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar, bstatus_id_t id)
 {
-
     GArchInstruction *result;               /* Instruction désassemblées   */
-
-
-    GBinFormat *format;                     /* Format du fichier binaire   */
-
-
-
-    vmpa2t *last;                           /* Dernière bordure rencontrée */
-
-
-
-    GBinSymbol **symbols;                   /* Symboles à représenter      */
-    size_t sym_count;                       /* Qté de symboles présents    */
-
-
+    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          */
-
-
-    const mrange_t *range;                  /* Couverture d'un symbole     */
-    const vmpa2t *border;                   /* Nouvelle bordure rencontrée */
-    off_t length;                           /* Taille d'une partie traitée */
-
-
-    GArchInstruction *instr;                /* Instruction à insérer       */
-
-
-
-    GArchInstruction *joint;                /* Jointure entre deux lots    */
-
-
-
-    off_t max_length;                       /* Taille des données à lire   */
-
-
-
-
-    result = NULL;
-
-
-
-    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
-
-    last = make_vmpa(0, VMPA_NO_VIRTUAL);
-
-    symbols = g_binary_format_get_symbols(format, &sym_count);
-
-
-    //sym_count = 0;
-
-
-    for (i = 0; i < sym_count; i++)
-    {
-
-
-
-
-        range = g_binary_symbol_get_range(symbols[i]);
-
-        border = get_mrange_addr(range);
-        length = get_mrange_length(range);
-
-
-
-
-        switch (g_binary_symbol_get_target_type(symbols[i]))
-        {
-            case STP_DATA:
-                instr = g_binary_symbol_get_instruction(symbols[i]);
-                g_object_ref(G_OBJECT(instr));
-                break;
-
-            case STP_ROUTINE:
-                instr = load_code_binary(binary, border,
-                                         get_phy_addr(border) + length,
-                                         statusbar, id);
-                break;
-
-             default:
-                 printf("BADDD !\n");
-                 exit(0);
-                 break;
-
-        }
-
-        /* Traiter la diff */
-
-        if (0 && cmp_vmpa_by_phy(last, border) < 0)
-        {
-            joint = load_raw_binary(binary, last,
-                                    get_phy_addr(last) + compute_vmpa_diff(border, last),
-                                    statusbar, id);
-
-            ainstr_list_merge(&result, &joint);
-
-        }
-
-        /* Ajout des instructions déjà établies */
-
-        ainstr_list_merge(&result, &instr);
-
-        /* Marquage de la nouvelle dernière bordure */
-
-        copy_vmpa(last, border);
-
-        advance_vmpa(last, length);
-
-    }
-
-    /* Raccord final ? */
-
-    g_loaded_binary_get_data(binary, &max_length);
-
-    if (get_phy_addr(last) < max_length)
-    {
-        joint = load_raw_binary(binary, last, max_length, statusbar, id);
-        ainstr_list_merge(&result, &joint);
-    }
-
-
-
-
-    printf("COUNT :: %zu\n", sym_count);
-
-    //exit(0);
-
-
-    return result;
-
-
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#ifdef DEBUG
-#   include "../../arch/artificial.h"
-#endif
-
-
-
-/******************************************************************************
-*                                                                             *
-*  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   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GArchInstruction *disassemble_binary_parts(const GLoadedBinary *binary, GBinPart **parts, size_t count, 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     */
-    size_t i;                               /* Boucle de parcours #1       */
-    off_t sum;                              /* Somme de toutes les tailles */
-    off_t done;                             /* Quantité déjà traitée       */
-#ifdef DEBUG
-    unsigned int valid;                     /* Instructions traduites      */
-    unsigned int db;                        /* Instructions non décodées   */
-#endif
-    off_t pos;                              /* Début d'une zone binaire    */
-    off_t len;                              /* Taille de cette même zone   */
-    vmpa_t base;                            /* Adresse de la zone binaire  */
-    off_t start;                            /* Conservation du pt de départ*/
-    GProcContext *context;                  /* Contexte pour le décodage   */
-    vmpa_t addr;                            /* Adresse d'une instruction   */
-    GArchInstruction *instr;                /* Instruction décodée         */
+    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      */
 
     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);
-
-    /* Préparation du suivi de la progression */
+    format = g_loaded_binary_get_format(binary);
+    g_loaded_binary_get_data(binary, &length);
 
-    sum = 0;
+    areas = compute_memory_areas(format, length, &count);
 
     for (i = 0; i < count; i++)
     {
-        g_binary_part_get_values(parts[i], NULL, &len, NULL);
-        if (len > bin_length) continue;
-        sum += len;
-    }
-
-    done = 0;
+        iter = &areas[i];
 
-    for (i = 0; i < count; i++)
-    {
-        g_binary_part_get_values(parts[i], &pos, &len, &base);
+        start = get_mrange_addr(&iter->range);
+        end = get_phy_addr(start) + get_mrange_length(&iter->range);
 
-        if (len > bin_length) continue;
+        assert(get_mrange_length(&iter->range) > 0);
 
-        context = g_arch_processor_get_context(proc);
+        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;
 
-        /* Décodage des instructions */
+                case STP_ROUTINE:
+                    instr = load_code_binary(binary, start, end, statusbar, id);
+                    break;
 
-#ifdef DEBUG
-        valid = 0;
-        db = 0;
-#endif
+                default:
+                    assert(false);
+                    break;
 
-        start = pos;
-        len += start;
+            }
 
-        while (pos < len)
+        else
         {
-            addr = base + (pos - start);
-
-            instr = g_arch_processor_decode_instruction(proc, context, bin_data,
-                                                        &pos, len, addr, format);
-            g_arch_instruction_add_to_list(&result, instr);
-
-#ifdef DEBUG
-            if (G_IS_DB_INSTRUCTION(instr) && !g_db_instruction_is_skipped(G_DB_INSTRUCTION(instr)))
-                db++;
+            if (iter->exec)
+                instr = load_code_binary(binary, start, end, statusbar, id);
             else
-                valid++;
-#endif
-
-            if (pos < len)
-                gtk_extended_status_bar_update_activity(statusbar, id, (done + pos - start) * 1.0 / sum);
+                instr = load_raw_binary(binary, start, end, statusbar, id);
 
         }
 
-        if (context != NULL)
-            g_object_unref(context);
-
-#ifdef DEBUG
-        g_binary_part_set_checkup(parts[i], valid, db);
-#endif
-
-        done += (len - start);
-        gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum);
+        g_arch_instruction_merge_lists(&result, &instr);
 
     }
 
+    free(areas);
+
     return result;
 
 }
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 402b0f5..8312bf6 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -829,6 +829,26 @@ void g_arch_instruction_add_to_list(GArchInstruction **list, GArchInstruction *i
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : list1 = première liste à traiter.                            *
+*                list2 = seconde liste à traiter.                             *
+*                                                                             *
+*  Description : Fusionne deux listes d'instructions.                         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_arch_instruction_merge_lists(GArchInstruction **list1, GArchInstruction **list2)
+{
+    ainstr_list_merge(list1, list2);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : list = liste d'instructions à consulter.                     *
 *              : iter = position actuelle dans la liste.                      *
 *                                                                             *
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 4fe0569..eadac8b 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -168,6 +168,9 @@ GArchInstruction *g_arch_instruction_find_last(const GArchInstruction *);
 /* Ajoute une instruction à un ensemble existant. */
 void g_arch_instruction_add_to_list(GArchInstruction **, GArchInstruction *);
 
+/* Fusionne deux listes d'instructions. */
+void g_arch_instruction_merge_lists(GArchInstruction **, GArchInstruction **);
+
 /* Fournit l'élement suivant un autre pour un parcours. */
 GArchInstruction *g_arch_instruction_get_prev_iter(const GArchInstruction *, const GArchInstruction *);
 
diff --git a/src/format/elf/symbols.c b/src/format/elf/symbols.c
index 84bf9b7..15c3a6b 100644
--- a/src/format/elf/symbols.c
+++ b/src/format/elf/symbols.c
@@ -1321,7 +1321,7 @@ static bool load_elf_internal_symbols(GElfFormat *format)
             init_vmpa(&addr, ELF_SYM(format, sym, st_value), VMPA_NO_VIRTUAL);
 
 
-            init_mrange(&range, &addr, 4/*ELF_SYM(format, sym, st_size) FIXME !!! */);
+            init_mrange(&range, &addr, ELF_SYM(format, sym, st_size));
 
 
             /* Première ébauche de nom */
diff --git a/src/format/executable.c b/src/format/executable.c
index 6b39ac8..ea1b398 100644
--- a/src/format/executable.c
+++ b/src/format/executable.c
@@ -28,6 +28,9 @@
 #include "format.h"
 
 
+#include <malloc.h>
+
+
 
 /* Initialise la classe des formats d'exécutables génériques. */
 static void g_executable_format_class_init(GExeFormatClass *);
@@ -162,6 +165,62 @@ GBinPortion *g_exe_format_get_portions(GExeFormat *format)
 *  Paramètres  : format = informations chargées à consulter.                  *
 *                count  = quantité de zones listées. [OUT]                    *
 *                                                                             *
+*  Description : Fournit les espaces mémoires des portions exécutables.       *
+*                                                                             *
+*  Retour      : Liste de zones binaires exécutables à libérer après usage.   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+mrange_t *g_exe_format_get_x_ranges(GExeFormat *format, size_t *count)
+{
+    mrange_t *result;                       /* Liste à retourner           */
+
+    typedef struct _x_ranges
+    {
+        mrange_t *list;
+        size_t length;
+
+    } x_ranges;
+
+    x_ranges tmp;                           /* Sauvegarde de la liste      */
+
+    bool visit_for_x(GBinPortion *portion, x_ranges *ranges)
+    {
+        const mrange_t *range;
+
+        if (g_binary_portion_get_rights(portion) & PAC_EXEC)
+        {
+            range = g_binary_portion_get_range(portion);
+
+            ranges->list = (mrange_t *)realloc(ranges->list, ++ranges->length * sizeof(mrange_t));
+            copy_mrange(&ranges->list[ranges->length - 1], range);
+
+        }
+
+        return true;
+
+    }
+
+    tmp.list = NULL;
+    tmp.length = 0;
+
+    g_binary_portion_visit(g_exe_format_get_portions(format), (visit_portion_fc)visit_for_x, &tmp);
+
+    result = tmp.list;
+    *count = tmp.length;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                count  = quantité de zones listées. [OUT]                    *
+*                                                                             *
 *  Description : Fournit les références aux zones binaires à analyser.        *
 *                                                                             *
 *  Retour      : Zones binaires à analyser.                                   *
diff --git a/src/format/executable.h b/src/format/executable.h
index b43a9f5..10bff42 100644
--- a/src/format/executable.h
+++ b/src/format/executable.h
@@ -78,8 +78,11 @@ vmpa_t g_exe_format_get_entry_point(const GExeFormat *);
 /* Décrit les différentes portions qui composent le binaire. */
 GBinPortion *g_exe_format_get_portions(GExeFormat *);
 
+/* Fournit les espaces mémoires des portions exécutables. */
+mrange_t *g_exe_format_get_x_ranges(GExeFormat *format, size_t *count);
+
 /* Fournit les références aux zones binaires à analyser. */
-GBinPart **g_exe_format_get_parts(const GExeFormat *, size_t *);
+GBinPart **g_exe_format_get_parts(const GExeFormat *, size_t *) __attribute__ ((deprecated));
 
 /* Fournit la position correspondant à une adresse virtuelle. */
 bool g_exe_format_translate_address_into_offset(const GExeFormat *, vmpa_t, off_t *);
diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c
index 76926ca..94a04cc 100644
--- a/src/glibext/gbinportion.c
+++ b/src/glibext/gbinportion.c
@@ -50,6 +50,7 @@ struct _GBinPortion
 
     char *desc;                             /* Désignation humaine         */
 
+    mrange_t range;                         /* Emplacement dans le code    */
     vmpa2t addr;                            /* Emplacement dans le code    */
     off_t size;                             /* Taille de la partie         */
 
@@ -265,7 +266,7 @@ const char *g_binary_portion_get_desc(const GBinPortion *portion)
 *                addr    = emplacement de la section à conserver.             *
 *                size    = taille de la section à conserver.                  *
 *                                                                             *
-*  Description : Définit les valeurs utiles d'une partie de code.             *
+*  Description : Définit les valeurs utiles d'une partie de code binaire.     *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -273,11 +274,32 @@ const char *g_binary_portion_get_desc(const GBinPortion *portion)
 *                                                                             *
 ******************************************************************************/
 
-void g_binary_portion_set_values(GBinPortion *portion, const vmpa2t *addr, off_t size)
+void g_binary_portion_set_values(GBinPortion *portion, const vmpa2t *addr, phys_t size)
 {
     copy_vmpa(&portion->addr, addr);
     portion->size = size;
 
+    init_mrange(&portion->range, addr, size);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : portion = description de partie à mettre à jour.             *
+*                                                                             *
+*  Description : Fournit l'emplacement d'une partie de code binaire.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const mrange_t *g_binary_portion_get_range(const GBinPortion *portion)
+{
+    return &portion->range;
+
 }
 
 
@@ -376,6 +398,35 @@ static bool g_binary_portion_compute_sub_area(GBinPortion *portion, GBinPortion
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : portion = première portion amorçant la visite.               *
+*                visitor = fonction à appeler à chaque étape de la descente.  *
+*                data    = adresse pointant vers des données de l'utilisateur.*
+*                                                                             *
+*  Description : Parcours un ensemble de portions binaires.                   *
+*                                                                             *
+*  Retour      : true si la visite a été jusqu'à son terme, false sinon.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_binary_portion_visit(GBinPortion *portion, visit_portion_fc visitor, void *data)
+{
+    bool result;                            /* Etat à retourner            */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = visitor(portion, data);
+
+    for (i = 0; i < portion->sub_count && result; i++)
+        result = g_binary_portion_visit(portion->sub_portions[i], visitor, data);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : portion = description de partie à mettre à jour.             *
 *                x       = abscisse du point de recherche.                    *
 *                y       = ordonnée du point de recherche.                    *
diff --git a/src/glibext/gbinportion.h b/src/glibext/gbinportion.h
index fb32496..ac6b4fd 100644
--- a/src/glibext/gbinportion.h
+++ b/src/glibext/gbinportion.h
@@ -72,6 +72,10 @@ typedef enum _PortionAccessRights
 } PortionAccessRights;
 
 
+/* Fonction appelée à chaque visite de portion.*/
+typedef bool (* visit_portion_fc) (GBinPortion *, void *);
+
+
 /* Indique le type défini par la GLib pour les blocs de données. */
 GType g_binary_portion_get_type(void);
 
@@ -85,7 +89,10 @@ void g_binary_portion_set_desc(GBinPortion *, const char *);
 const char *g_binary_portion_get_desc(const GBinPortion *);
 
 /* Définit les valeurs utiles d'une partie de code. */
-void g_binary_portion_set_values(GBinPortion *, const vmpa2t *, off_t);
+void g_binary_portion_set_values(GBinPortion *, const vmpa2t *, phys_t);
+
+/* Fournit l'emplacement d'une partie de code binaire. */
+const mrange_t *g_binary_portion_get_range(const GBinPortion *);
 
 /* Définit les droits associés à une partie de code. */
 void g_binary_portion_set_rights(GBinPortion *, PortionAccessRights);
@@ -96,6 +103,9 @@ PortionAccessRights g_binary_portion_get_rights(const GBinPortion *);
 /* Procède à l'inclusion d'une portion dans une autre. */
 void g_binary_portion_include(GBinPortion *, GBinPortion *);
 
+/* Parcours un ensemble de portions binaires. */
+bool g_binary_portion_visit(GBinPortion *, visit_portion_fc, void *);
+
 /* Recherche la portion présente à un point donné. */
 GBinPortion *g_binary_portion_find_at_pos(GBinPortion *, gint, GdkRectangle *);
 
-- 
cgit v0.11.2-87-g4458