From 6b1a70c16f83a926f7b1f1fb2af5d6a2e017737b Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 26 Nov 2015 23:30:01 +0000
Subject: Used several threads without lock to disassemble binary code.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@610 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                          |   30 +
 src/analysis/disass/area.c         | 1085 +++++++++++++++++++++++++++++++++++-
 src/analysis/disass/area.h         |   43 ++
 src/analysis/disass/disassembler.c |   11 +-
 src/analysis/disass/fetch.c        |  429 ++++++++++++--
 src/analysis/disass/fetch.h        |    3 +-
 src/arch/archbase.h                |   25 +
 src/arch/arm/context-int.h         |    1 +
 src/arch/arm/context.c             |   18 +-
 src/arch/arm/v7/context.c          |   10 +-
 src/arch/context-int.h             |   12 +-
 src/arch/context.c                 |   69 ++-
 src/arch/context.h                 |    2 +-
 src/common/bits.c                  |   68 +++
 src/common/bits.h                  |    9 +
 src/format/elf/elf.c               |    6 +
 src/format/symbol.h                |    4 +
 17 files changed, 1741 insertions(+), 84 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2e13b93..308e126 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+15-11-27  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/area.c:
+	* src/analysis/disass/area.h:
+	* src/analysis/disass/disassembler.c:
+	* src/analysis/disass/fetch.c:
+	* src/analysis/disass/fetch.h:
+	Use several threads without lock to disassemble binary code.
+
+	* src/arch/archbase.h:
+	Provide memory data sizes from byte sizes with MDS_FROM_BYTES.
+
+	* src/arch/arm/context.c:
+	* src/arch/arm/context-int.h:
+	* src/arch/arm/v7/context.c:
+	* src/arch/context.c:
+	* src/arch/context.h:
+	* src/arch/context-int.h:
+	Protect data access using locks.
+
+	* src/common/bits.c:
+	* src/common/bits.h:
+	Add bits to bit fields in an atomic way.
+
+	* src/format/elf/elf.c:
+	Do not load inner sections as portions.
+
+	* src/format/symbol.h:
+	Define the HAS_DATA_INSTR macro to filter symbols.
+
 15-11-26  Cyrille Bagard <nocbos@gmail.com>
 
 	* plugins/pychrysa/analysis/content.c:
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 1d841be..355b716 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -27,6 +27,1087 @@
 #include <assert.h>
 
 
+#include <i18n.h>
+
+
+#include "../../analysis/contents/restricted.h"
+#include "../../common/bits.h"
+#include "../../gui/panels/log.h"
+
+
+
+
+/* Zone mémoire bien bornée */
+typedef struct _mem_area_v2
+{
+    GBinFormat *format;                     /* Format du fichier binaire   */
+    GBinContent *content;                   /* Données binaires à lire     */
+    GArchProcessor *proc;                   /* Architecture du binaire     */
+    SourceEndian endianness;                /* Boutisme de cette machine   */
+
+    mrange_t range;                         /* Couverture de la zone       */
+
+    phys_t packing_size;                    /* Granularité des découpages  */
+
+    bitfield_t *processed;                  /* Octets traités dans la zone */
+    GArchInstruction **instructions;        /* Instructions en place       */
+
+
+
+
+    bool is_exec;                           /* Zone exécutable ?           */
+
+} mem_area_v2;
+
+
+
+/* Initialise une aire de données à partir d'une adresse donnée. */
+static void init_mem_area_from_addr_v2(mem_area_v2 *, const vmpa2t *, phys_t, const GLoadedBinary *);
+
+/* Libère d'une aire de données les ressources allouées. */
+static void fini_mem_area_v2(mem_area_v2 *);
+
+/* Indique si une zone donnée est intégralement vierge ou non. */
+static bool is_range_blank_in_mem_area_v2(mem_area_v2 *, phys_t, phys_t);
+
+/* Marque une série d'octets comme ayant été traités. */
+static bool mark_range_in_mem_area_as_processed_v2(mem_area_v2 *, GArchInstruction *, bool);
+
+
+
+
+/* Procède au désassemblage d'un contenu binaire non exécutable. */
+static void load_data_from_mem_area_v2(mem_area_v2 *, GProcContext *, const vmpa2t *, status_blob_info *);
+
+/* S'assure qu'une aire contient toutes ses instructions. */
+static void fill_mem_area_v2(mem_area_v2 *, mem_area_v2 *, size_t, GProcContext *, status_blob_info *);
+
+/* Rassemble les instructions conservées dans une zone donnée. */
+static GArchInstruction *get_instructions_from_mem_area_v2(const mem_area_v2 *);
+
+
+
+
+
+
+/* S'assure de la présence d'un début de routine à un point. */
+static void update_address_as_routine(GBinFormat *, const vmpa2t *);
+
+
+/**
+ * Content :: à passer en restricted.
+
+ * Les sections croisées : pas de sens de les traiter ici, car au final une instruction sera à cheval
+ * sur deux sections différentes -> incohérence au niveau de l'éditeur.
+ * => régler le périmètres de segments règle donc tous les soucis.
+
+ */
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  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.                       *
+*                binary = binaire analysé content quantités d'informations.   *
+*                                                                             *
+*  Description : Initialise une aire de données à partir d'une adresse donnée.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void init_mem_area_from_addr_v2(mem_area_v2 *area, const vmpa2t *addr, phys_t len, const GLoadedBinary *binary)
+{
+    GBinContent *content;                   /* Données binaires à lire     */
+
+    assert(len > 0);
+
+    area->format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+
+    content = g_binary_format_get_content(area->format);
+
+    area->proc = g_loaded_binary_get_processor(binary);
+    area->endianness = g_arch_processor_get_endianness(area->proc);
+
+    init_mrange(&area->range, addr, len);
+
+    area->content = g_restricted_content_new(content, &area->range);
+
+    area->packing_size = 2; /* FIXME */
+
+    area->processed = create_bit_field(len, false);
+    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_v2(mem_area_v2 *area)
+{
+    phys_t len;                             /* Etendue du parcours total   */
+    phys_t i;                               /* Boucle de parcours          */
+
+    //g_object_unref(area->format);   /* FIXME */
+    g_object_unref(area->content);
+    //g_object_unref(area->proc);   /* FIXME */
+
+    delete_bit_field(area->processed);
+
+    len = get_mrange_length(&area->range);
+
+    for (i = 0; i < len; i++)
+        if (area->instructions[i] != NULL)
+            g_object_unref(G_OBJECT(area->instructions[i]));
+
+    free(area->instructions);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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.                *
+*                                                                             *
+*  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_v2(mem_area_v2 *area, phys_t start, phys_t len)
+{
+    bool result;                            /* Résultat à renvoyer         */
+
+    if ((start + len) >= get_mrange_length(&area->range))
+        result = false;
+
+    else
+        result = !test_in_bit_field(area->processed, start, len);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area  = aire représentant à contenu à parcourir.             *
+*                instr = instruction à mémoriser pour la suite.               *
+*                force = impose l'enregistrement de l'instruction.            *
+*                                                                             *
+*  Description : Marque une série d'octets comme ayant été traités.           *
+*                                                                             *
+*  Retour      : true si l'enregistrement a bien été réalisé, false sinon.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool mark_range_in_mem_area_as_processed_v2(mem_area_v2 *area, GArchInstruction *instr, bool force)
+{
+    bool result;                            /* Bilan d'action à renvoyer   */
+    const vmpa2t *start;                    /* Adresse de départ de la zone*/
+    const mrange_t *range;                  /* Emplacement d'instruction   */
+    const vmpa2t *addr;                     /* Début de la zone à traiter  */
+    phys_t len;                             /* Taille de l'aire visée      */
+    phys_t offset;                          /* Décallage de départ         */
+
+    start = get_mrange_addr(&area->range);
+
+    range = g_arch_instruction_get_range(instr);
+    addr = get_mrange_addr(range);
+    len = get_mrange_length(range);
+
+    offset = compute_vmpa_diff(start, addr);
+
+    result = set_atomic_in_bit_field(area->processed, offset, len);
+
+    /* Si l'instruction était bien la première à s'inscrire... */
+
+    result |= force;
+
+    if (result)
+        area->instructions[offset] = instr;
+
+    return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area   = aire représentant à contenu à parcourir.            *
+*                list   = liste de zones délimitant des contenus à traiter.   *
+*                count  = nombre de zones à disposition.                      *
+*                index  = indice de l'aire à considérer pendant l'opération.  *
+*                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_v2(mem_area_v2 *area, mem_area_v2 *list, size_t count, GProcContext *ctx, const vmpa2t *start, status_blob_info *info)
+{
+
+
+
+    GBinFormat *format;                     /* Format du fichier binaire   */
+    GArchProcessor *proc;                   /* Architecture du binaire     */
+    GBinContent *content;                   /* 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 */
+
+
+    bool done;                              /* Enregistrement effectué ?   */
+
+
+    vmpa2t sym_addr;                        /* Adresse de nouveau symbole  */
+    bool has_new_sym;                       /* Statut d'un dépilement      */
+
+    GBinSymbol *symbol;                     /* Symbole créé en parallèle   */
+
+
+
+
+
+    /* Récupération des informations de base */
+
+    format = area->format;
+    proc = area->proc;
+    content = area->content;
+
+    diff = compute_vmpa_diff(get_mrange_addr(&area->range), start);
+    alen = get_mrange_length(&area->range);
+
+    copy_vmpa(&pos, start);
+
+    /* Traitement de la zone */
+
+    printf("=== processing @ 0x%08x\n", (unsigned int)start->virtual);
+
+    for (i = diff; i < alen; i += diff)
+    {
+        /**
+         * On réalise un premier test informel (car non atomique) peu coûteux
+         * avant de se lancer dans un désassemblage d'instruction potentiellement
+         * inutile.
+         */
+
+        printf(" (%u) blank ? %d\n", (unsigned int)i, is_range_blank_in_mem_area_v2(area, i, 1));
+        printf("   +1 blank ? %d\n", is_range_blank_in_mem_area_v2(area, i + 1, 1));
+
+        if (!is_range_blank_in_mem_area_v2(area, i, 1))
+            break;
+
+        /* Décodage d'une nouvelle instruction */
+
+        copy_vmpa(&prev, &pos);
+
+        instr = g_arch_processor_disassemble(proc, ctx, content, &pos);
+        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);
+
+        /* Progression dans les traitements */
+
+        done = mark_range_in_mem_area_as_processed_v2(area, instr, false);
+
+        if (!done)
+        {
+            g_object_unref(G_OBJECT(instr));
+            break;
+        }
+
+        inc_progessive_status(info, diff);
+
+        assert(!is_range_blank_in_mem_area_v2(area, i, diff));
+
+        /* Enregistrement d'un éventuel début de routine */
+
+        if (g_arch_instruction_get_flags(instr) & AIF_ROUTINE_START)
+            update_address_as_routine(format, &prev);
+
+        /* Eventuel renvoi vers d'autres adresses */
+
+        g_arch_instruction_call_hook(instr, IPH_FETCH, proc, ctx, format);
+
+        /* Insertion des symboles découverts en parallèle */
+
+        for (has_new_sym = g_proc_context_pop_new_symbol_at(ctx, &sym_addr);
+             has_new_sym;
+             has_new_sym = g_proc_context_pop_new_symbol_at(ctx, &sym_addr))
+        {
+            has_new_sym = g_binary_format_find_symbol_at(format, &sym_addr, &symbol);
+            assert(has_new_sym);
+
+            insert_extra_symbol_into_mem_areas_v2(list, count, symbol);
+
+        }
+
+        /* Rupture du flot d'exécution ? */
+        if (g_arch_instruction_get_flags(instr) & AIF_RETURN_POINT)
+            break;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : area   = aire représentant à contenu à parcourir.            *
+*                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_v2(mem_area_v2 *area, GProcContext *ctx, const vmpa2t *start, status_blob_info *info)
+{
+    GBinContent *content;                   /* Données binaires à lire     */
+    SourceEndian endianness;                /* Boutisme de cette machine   */
+    phys_t diff;                            /* Volume de données traité    */
+    phys_t alen;                            /* Taille de l'aire utilisée   */
+    vmpa2t pos;                             /* Boucle de parcours          */
+    phys_t i;                               /* Boucle de parcours          */
+    vmpa2t prev;                            /* Boucle de parcours          */
+    GArchInstruction *instr;                /* Instruction décodée         */
+    mrange_t range;                         /* Couverture de l'instruction */
+    bool done;                              /* Enregistrement effectué ?   */
+
+    /* Récupération des informations de base */
+
+    content = area->content;
+    endianness = area->endianness;
+
+    diff = compute_vmpa_diff(get_mrange_addr(&area->range), start);
+    alen = get_mrange_length(&area->range);
+
+    copy_vmpa(&pos, start);
+
+    /* Traitement de la zone */
+
+    for (i = diff; i < alen; i += diff)
+    {
+        /* On cherche à obtenir l'assurance que le traitement n'a jamais été fait */
+
+        if (!is_range_blank_in_mem_area_v2(area, i, 1))
+            break;
+
+        instr = NULL;
+
+        copy_vmpa(&prev, &pos);
+
+        /* Décodage d'une nouvelle instruction, sur mesure puis minimale */
+
+        if (get_virt_addr(&pos) % area->packing_size == 0
+            && is_range_blank_in_mem_area_v2(area, i, area->packing_size))
+        {
+            diff = area->packing_size;
+
+            instr = g_raw_instruction_new_array(content, MDS_FROM_BYTES(diff), 1, &pos, endianness);
+
+            if (instr == NULL)
+                copy_vmpa(&pos, &prev);
+
+        }
+
+        if (instr == NULL)
+        {
+            diff = 1;
+
+            instr = g_raw_instruction_new_array(content, MDS_8_BITS, 1, &pos, endianness);
+
+        }
+
+        /* On rencontre ici un morceau déjà traité. */
+
+        if (instr == NULL) break;
+
+        /* Enregistrement des positions et adresses */
+
+        assert(diff == compute_vmpa_diff(&prev, &pos));
+
+        init_mrange(&range, &prev, diff);
+
+        g_arch_instruction_set_range(instr, &range);
+
+        /* Progression dans les traitements */
+
+        done = mark_range_in_mem_area_as_processed_v2(area, instr, false);
+
+        if (!done)
+        {
+            g_object_unref(G_OBJECT(instr));
+            break;
+        }
+
+        inc_progessive_status(info, diff);
+
+        assert(!is_range_blank_in_mem_area_v2(area, i, diff));
+
+        /* On laisse une chance au code pour se reprendre... */
+
+        if (area->is_exec) break;
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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_v2(mem_area_v2 *area, mem_area_v2 *list, size_t count, GProcContext *ctx, status_blob_info *info)
+{
+    const vmpa2t *addr;                     /* Début de la zone à traiter  */
+    phys_t len;                             /* Taille de la zone à remplir */
+    phys_t i;                               /* Boucle de parcours          */
+    vmpa2t start;                           /* Adresse de départ de combles*/
+
+    addr = get_mrange_addr(&area->range);
+    len = get_mrange_length(&area->range);
+
+    for (i = 0; i < len; i++)
+    {
+        if (is_range_blank_in_mem_area_v2(area, i, 1))
+        {
+            copy_vmpa(&start, addr);
+            advance_vmpa(&start, i);
+
+            if (area->is_exec && get_virt_addr(&start) % area->packing_size == 0)
+                load_code_from_mem_area_v2(area, list, count, ctx, &start, info);
+
+            if (is_range_blank_in_mem_area_v2(area, i, 1))
+                load_data_from_mem_area_v2(area, ctx, &start, info);
+
+        }
+
+        assert(!is_range_blank_in_mem_area_v2(area, i, 1));
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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_v2(const mem_area_v2 *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;
+
+    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  : 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      : Indice de la zone trouvée, ou nombre d'aires en cas d'échec. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+mem_area_v2 *find_memory_area_by_addr_v2(mem_area_v2 *list, size_t count, const vmpa2t *addr)
+{
+    mem_area_v2 *result;                       /* Elément trouvé à renvoyer   */
+
+    int find_mem_area(const vmpa2t *addr, const mem_area_v2 *area)
+    {
+        int status;                         /* Bilan à retourner           */
+
+        if (mrange_contains_addr(&area->range, addr))
+            status = 0;
+
+        else
+            status = cmp_vmpa(addr, get_mrange_addr(&area->range));
+
+        return status;
+
+    }
+
+    result = bsearch(addr, list, count, sizeof(mem_area_v2), (__compar_fn_t)find_mem_area);
+
+    return result;
+
+}
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : binary     = binaire analysé contenant quantités d'infos.    *
+*                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_v2 *compute_memory_areas_v2(const GLoadedBinary *binary, phys_t bin_length, size_t *count)
+{
+    mem_area_v2 *result;                       /* Liste à renvoyer            */
+    GExeFormat *format;                     /* Format de fichier associé   */
+    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 */
+    bool status;                            /* Bilan d'une conversion      */
+    size_t i;                               /* Boucle de parcours #1       */
+    const vmpa2t *border;                   /* Nouvelle bordure rencontrée */
+    mem_area_v2 *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       */
+    SymbolType type;                        /* Nature d'un symbole         */
+    const mrange_t *range;                  /* Couverture d'un symbole     */
+    phys_t length;                          /* Taille de ce même symbole   */
+    phys_t new_length;                      /* Nouvelle taille déterminée  */
+
+    result = NULL;
+    *count = 0;
+
+    /**
+     * Le parcours n'est valide que si les zones exécutables sont triées !
+     */
+
+    format = g_loaded_binary_get_format(binary);
+
+    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 ! */
+
+    status = g_exe_format_translate_offset_into_vmpa(format, 0, &last);
+    assert(status);
+
+    for (i = 0; i < exe_count; i++)
+    {
+        border = get_mrange_addr(&exe_ranges[i]);
+
+        /* Zone tampon à constituer */
+
+        if (cmp_vmpa(&last, border) < 0)
+        {
+            result = (mem_area_v2 *)realloc(result, ++(*count) * sizeof(mem_area_v2));
+
+            area = &result[*count - 1];
+
+            init_mem_area_from_addr_v2(area, &last, compute_vmpa_diff(&last, border), binary);
+            area->is_exec = false;
+
+        }
+
+        /* Insertion d'une zone exécutable déjà définie */
+
+        result = (mem_area_v2 *)realloc(result, ++(*count) * sizeof(mem_area_v2));
+
+        area = &result[*count - 1];
+
+        init_mem_area_from_addr_v2(area, get_mrange_addr(&exe_ranges[i]),
+                                   get_mrange_length(&exe_ranges[i]), binary);
+        area->is_exec = true;
+
+        /* Avancée du curseur */
+
+        compute_mrange_end_addr(&exe_ranges[i], &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_v2 *)realloc(result, ++(*count) * sizeof(mem_area_v2));
+
+        area = &result[*count - 1];
+
+        init_mem_area_from_addr_v2(area, &tmp, bin_length - get_phy_addr(&tmp), binary);
+        area->is_exec = false;
+
+    }
+
+
+
+
+
+
+
+
+    for (i = 0; i < *count; i++)
+    {
+        printf(" (init) AREA %zu :: 0x%x / 0x%x + 0x%x\n",
+               i,
+               (unsigned int)get_phy_addr(get_mrange_addr(&result[i].range)),
+               (unsigned int)get_virt_addr(get_mrange_addr(&result[i].range)),
+               (unsigned int)get_mrange_length(&result[i].range));
+
+    }
+
+    printf("--------------------\n");
+
+
+
+
+
+
+
+
+    /* Seconde étape : on s'assure du découpage autour des portions pour respecter l'alignement */
+
+    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]));
+
+        printf(" [portion % 3zu] addr = 0x%x / 0x%x\n",
+               i,
+               (unsigned int)get_phy_addr(portion_start),
+               (unsigned int)get_virt_addr(portion_start));
+
+        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_v2(&result[j]);
+
+                result = (mem_area_v2 *)realloc(result, ++(*count) * sizeof(mem_area_v2));
+
+                memmove(&result[j + 2], &result[j + 1], (*count - j - 2) * sizeof(mem_area_v2));
+
+                status = result[j].is_exec;
+
+                /* Première moitié */
+
+                area = &result[j];
+
+                copy_vmpa(&tmp, get_mrange_addr(&area->range));
+                length = get_mrange_length(&area->range);
+
+                new_length = compute_vmpa_diff(&tmp, portion_start);
+
+                init_mem_area_from_addr_v2(area, &tmp, new_length, binary);
+                area->is_exec = status;
+
+                /* Seconde moitié */
+
+                length -= get_mrange_length(&area->range);
+
+                area = &result[j + 1];
+
+                init_mem_area_from_addr_v2(area, portion_start, length, binary);
+                area->is_exec = status;
+
+            }
+
+            j = *count;
+
+        }
+
+    }
+
+
+
+
+
+
+
+
+    for (i = 0; i < *count; i++)
+    {
+        printf(" (fini) AREA %zu :: 0x%x / 0x%x + 0x%x\n",
+               i,
+               (unsigned int)get_phy_addr(get_mrange_addr(&result[i].range)),
+               (unsigned int)get_virt_addr(get_mrange_addr(&result[i].range)),
+               (unsigned int)get_mrange_length(&result[i].range));
+
+    }
+
+    printf("--------------------\n");
+
+
+
+
+
+
+
+
+    /* Troisième étape : on insère les symboles existants */
+
+    for (i = 0; i < sym_count; i++)
+    {
+        type = g_binary_symbol_get_target_type(symbols[i]);
+
+        /**
+         * On ne garde que les symboles renvoyant directement une ou
+         * plusieurs instructions, c'est à dire les symboles valides
+         * pour un appel à g_binary_symbol_get_instruction().
+         *
+         * Les instructions des autres symboles sont obtenues et mises
+         * en place durant la procédure de désassemblage.
+         */
+
+        if (type == STP_ROUTINE || type == STP_ENTRY_POINT || type == STP_CODE_LABEL)
+            continue;
+
+        range = g_binary_symbol_get_range(symbols[i]);
+
+        length = get_mrange_length(range);
+
+        if (length == 0)
+            continue;
+
+        insert_extra_symbol_into_mem_areas_v2(result, *count, symbols[i]);
+
+    }
+
+    /* Nettoyage final */
+
+    if (portions != NULL)
+        free(portions);
+
+    if (exe_ranges != NULL)
+        free(exe_ranges);
+
+    /// FIXME g_object_unref(G_OBJECT(format));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : areas  = liste de zones délimitant des contenus à traiter.   *
+*                count  = nombre de zones à disposition.                      *
+*                symbol = élément nouveau à venir insérer dans les zones.     *
+*                                                                             *
+*  Description : Insère un symbole dans un découpage en aires.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void insert_extra_symbol_into_mem_areas_v2(mem_area_v2 *areas, size_t count, const GBinSymbol *symbol)
+{
+    SymbolType type;                        /* Type de symbole             */
+    GArchInstruction *list;                 /* Ensemble à insérer          */
+    GArchInstruction *iter;                 /* Boucle de parcours          */
+    const mrange_t *range;                  /* Emplacement d'instruction   */
+    const vmpa2t *addr;                     /* Départ de cet emplacement   */
+    mem_area_v2 *area;                         /* Zone d'accueil désignée     */
+    VMPA_BUFFER(loc);                       /* Description d'un emplacement*/
+    phys_t start;                           /* Point de départ             */
+
+    type = g_binary_symbol_get_target_type(symbol);
+
+    if (!HAS_DATA_INSTR(type))
+        return;
+
+    list = g_binary_symbol_get_instruction(symbol);
+
+    for (iter = list; iter != NULL; iter = g_arch_instruction_get_next_iter(list, iter, ~0))
+    {
+        range = g_arch_instruction_get_range(iter);
+        addr = get_mrange_addr(range);
+
+        /* Une aire d'accueil existe-t-elle ? */
+
+        area = find_memory_area_by_addr_v2(areas, count, addr);
+
+        if (area == NULL)
+        {
+            vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL);
+
+            log_variadic_message(LMT_WARNING, _("No place found for symbol located at %s."), loc);
+            continue;
+
+        }
+
+        /* L'instruction est-elle accueillie dans son intégralité ? */
+
+        start = compute_vmpa_diff(get_mrange_addr(&area->range), addr);
+
+        if (start + get_mrange_length(range) > get_mrange_length(&area->range))
+        {
+            vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL);
+
+            log_variadic_message(LMT_WARNING, _("The symbol located at %s is too big for one place only."), loc);
+            continue;
+
+        }
+
+        /* Inscription d'une instruction de symbole (sans retour arrière possible :/ ) */
+
+        mark_range_in_mem_area_as_processed_v2(area, iter, true);
+
+        g_object_ref(G_OBJECT(iter));
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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_v2 *list, size_t count, GProcContext *ctx, status_blob_info *info)
+{
+    size_t i;                               /* Boucle de parcours          */
+
+    for (i = 0; i < count; i++)
+        fill_mem_area_v2(&list[i], list, count, 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_v2(const mem_area_v2 *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_v2(&list[i]);
+        g_arch_instruction_merge_lists(&result, &instr);
+    }
+
+    return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+//////////////////////////////////::://////////////////////////////////////////////////////////////////////
+
+
+
 
 /* Zone mémoire bien bornée */
 typedef struct _mem_area
@@ -72,7 +1153,7 @@ static bool mark_range_in_mem_area_as_processed(mem_area *, phys_t, phys_t, GArc
 
 
 /* S'assure de la présence d'un début de routine à un point. */
-static void update_address_as_routine(GBinFormat *, const vmpa2t *);
+//static void update_address_as_routine(GBinFormat *, const vmpa2t *);
 
 
 
@@ -1468,8 +2549,6 @@ static bool insert_extra_symbol_into_mem_areas(mem_area **list, size_t *count, G
 
         memmove(&(*list)[index + 1], &(*list)[index], (*count - index - 1) * sizeof(mem_area));
 
-        /* Aire raccourcie */
-
         copy_vmpa(&area_pos, get_mrange_addr(&area_range));
         new_length = get_mrange_length(&area_range) - get_mrange_length(sym_range);
 
diff --git a/src/analysis/disass/area.h b/src/analysis/disass/area.h
index 35a3533..aa26da0 100644
--- a/src/analysis/disass/area.h
+++ b/src/analysis/disass/area.h
@@ -25,10 +25,52 @@
 #define _ANALYSIS_DISASS_AREA_H
 
 
+#include "../binary.h"
+#include "../../arch/instruction.h"
+#include "../../gtkext/gtkextstatusbar.h"
+
+
+
+
+/* Zone mémoire bien bornée */
+typedef struct _mem_area_v2 mem_area_v2;
+
+
+
+
+
+/* Procède au désassemblage d'un contenu binaire exécutable. */
+void load_code_from_mem_area_v2(mem_area_v2 *, mem_area_v2 *, size_t, GProcContext *, const vmpa2t *, status_blob_info *);
+
+
+
+
+/* Détermine une liste de zones contigües à traiter. */
+mem_area_v2 *find_memory_area_by_addr_v2(mem_area_v2 *, size_t, const vmpa2t *);
+
+
+
+/* Détermine une liste de zones contigües à traiter. */
+mem_area_v2 *compute_memory_areas_v2(const GLoadedBinary *, phys_t, size_t *);
+
+/* Insère un symbole dans un découpage en aires. */
+void insert_extra_symbol_into_mem_areas_v2(mem_area_v2 *, size_t, const GBinSymbol *);
+
+/* S'assure que l'ensemble des aires est entièrement décodé. */
+void ensure_all_mem_areas_are_filled(mem_area_v2 *, size_t, GProcContext *, status_blob_info *);
+
+/* Rassemble les instructions conservées dans des zones données. */
+GArchInstruction *collect_instructions_from_mem_areas_v2(const mem_area_v2 *, size_t);
+
+
+
+
+
 #include <stdbool.h>
 
 
 
+
 #include "../binary.h"
 #include "../../format/executable.h"
 #include "../../gtkext/gtkextstatusbar.h"
@@ -48,6 +90,7 @@ typedef struct _mem_area mem_area;
 
 
 
+
 /* Procède au désassemblage d'un contenu binaire exécutable. */
 bool load_code_from_mem_area(mem_area **, size_t *, size_t *, const GLoadedBinary *, GProcContext *, const vmpa2t *, status_blob_info *);
 
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index ce49aca..ce2e6ff 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -190,6 +190,8 @@ static GDelayedDisassembly *g_delayed_disassembly_new(GLoadedBinary *binary, GAr
 
 static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtStatusBar *statusbar)
 {
+    wgroup_id_t gid;                        /* Identifiant pour les tâches */
+
     //GBinFormat *format;                     /* Format du fichier binaire   */
     GArchProcessor *proc;                   /* Architecture du binaire     */
 
@@ -208,6 +210,13 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta
     //GArchProcessor *proc;                   /* Architecture du binaire     */
 
 
+
+    gid = g_work_queue_define_work_group(get_work_queue());
+
+
+
+
+
     //format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
     proc = g_loaded_binary_get_processor(disass->binary);
 
@@ -225,7 +234,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta
 
 
 
-    *disass->instrs = disassemble_binary_content(disass->binary, statusbar);
+    *disass->instrs = disassemble_binary_content(disass->binary, gid, statusbar);
 
 
     g_arch_processor_set_disassembled_instructions(proc, *disass->instrs);
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index 67a6f3b..bfc0598 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -31,18 +31,331 @@
 
 
 #include "area.h"
+#include "../../glibext/delayed-int.h"
+
+
+
+
+
+
+
+
+/* ------------------------- RECUPERATIONS EN TOILE DE FOND ------------------------- */
+/* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */
+
+
+#define G_TYPE_DELAYED_FETCHING               g_delayed_fetching_get_type()
+#define G_DELAYED_FETCHING(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_fetching_get_type(), GDelayedFetching))
+#define G_IS_DELAYED_FETCHING(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_fetching_get_type()))
+#define G_DELAYED_FETCHING_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_FETCHING, GDelayedFetchingClass))
+#define G_IS_DELAYED_FETCHING_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_FETCHING))
+#define G_DELAYED_FETCHING_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_FETCHING, GDelayedFetchingClass))
+
+
+/* Ensembles binaires à désassembler (instance) */
+typedef struct _GDelayedFetching
+{
+    GDelayedWork parent;                    /* A laisser en premier        */
+
+    wgroup_id_t gid;                        /* Groupe de travail parallèle */
+
+    GExeFormat *format;                     /* Format du fichier binaire   */
+
+    GProcContext *ctx;                      /* Contexte de désassemblage   */
+    mem_area_v2 *areas;                        /* Zone de productions         */
+    size_t count;                           /* Nombre de ces zones         */
+    status_blob_info *info;                 /* Informations de progression */
+
+    virt_t virt;                            /* Adresse de départ dépilée   */
+
+} GDelayedFetching;
+
+/* Ensembles binaires à désassembler (classe) */
+typedef struct _GDelayedFetchingClass
+{
+    GDelayedWorkClass parent;               /* A laisser en premier        */
+
+} GDelayedFetchingClass;
+
+
+/* Indique le type défini pour les tâches de récupération différée. */
+GType g_delayed_fetching_get_type(void);
+
+/* Initialise la classe des tâches de désassemblage différé. */
+static void g_delayed_fetching_class_init(GDelayedFetchingClass *);
+
+/* Initialise une tâche de désassemblage différé. */
+static void g_delayed_fetching_init(GDelayedFetching *);
+
+/* Supprime toutes les références externes. */
+static void g_delayed_fetching_dispose(GDelayedFetching *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_delayed_fetching_finalize(GDelayedFetching *);
+
+/* Crée une tâche de récupération d'instructions différée. */
+static GDelayedFetching *g_delayed_fetching_new(const GDelayedFetching *, virt_t);
+
+/* Assure la récupération d'instructions en différé. */
+static void g_delayed_fetching_process(GDelayedFetching *, GtkExtStatusBar *);
+
+
+
+
+
+
+
+
+
+
+/* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */
+/* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */
+
 
 
 
 /* Suit un flot d'exécution pour désassembler du code. */
 static void follow_execution_flow(const GLoadedBinary *, GProcContext *, mem_area **, size_t *, status_blob_info *);
 
-/* S'assure que l'ensemble des aires est entièrement décodé. */
-static void ensure_all_mem_areas_are_filled(mem_area **, size_t *, const GLoadedBinary *, GProcContext *, status_blob_info *);
 
 
 
 
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           RECUPERATIONS EN TOILE DE FOND                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+
+
+
+
+
+
+/* Indique le type défini pour les tâches de récupération différée. */
+G_DEFINE_TYPE(GDelayedFetching, g_delayed_fetching, G_TYPE_DELAYED_WORK);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : klass = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des tâches de récupération différée.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_delayed_fetching_class_init(GDelayedFetchingClass *klass)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+    GDelayedWorkClass *work;                /* Version en classe parente   */
+
+    object = G_OBJECT_CLASS(klass);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_fetching_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_delayed_fetching_finalize;
+
+    work = G_DELAYED_WORK_CLASS(klass);
+
+    work->run = (run_task_fc)g_delayed_fetching_process;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : fetching = instance à initialiser.                           *
+*                                                                             *
+*  Description : Initialise une tâche de récupération différée.               *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_delayed_fetching_init(GDelayedFetching *fetching)
+{
+
+
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : fetching = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_delayed_fetching_dispose(GDelayedFetching *fetching)
+{
+    g_object_unref(G_OBJECT(fetching->format));
+
+    g_object_unref(G_OBJECT(fetching->ctx));
+
+    G_OBJECT_CLASS(g_delayed_fetching_parent_class)->dispose(G_OBJECT(fetching));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : fetching = instance d'objet GLib à traiter.                  *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_delayed_fetching_finalize(GDelayedFetching *fetching)
+{
+    G_OBJECT_CLASS(g_delayed_fetching_parent_class)->finalize(G_OBJECT(fetching));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : template = modèle dont les informations sont à copier.       *
+*                virt     = point départ dépilé et personnalisant l'instance. *
+*                                                                             *
+*  Description : Crée une tâche de récupération d'instructions différée.      *
+*                                                                             *
+*  Retour      : Tâche créée.                                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static GDelayedFetching *g_delayed_fetching_new(const GDelayedFetching *template, virt_t virt)
+{
+    GDelayedFetching *result;            /* Tâche à retourner           */
+
+    result = g_object_new(G_TYPE_DELAYED_FETCHING, NULL);
+
+    result->gid = template->gid;
+
+    result->format = template->format;
+    g_object_ref(G_OBJECT(result->format));
+
+    result->ctx = template->ctx;
+    g_object_ref(G_OBJECT(result->ctx));
+
+    result->areas = template->areas;
+    result->count = template->count;
+    result->info = template->info;
+
+    result->virt = virt;
+
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : fetching  = récupération à mener.                            *
+*                statusbar = barre de statut à tenir informée.                *
+*                                                                             *
+*  Description : Assure la récupération d'instructions en différé.            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_delayed_fetching_process(GDelayedFetching *fetching, GtkExtStatusBar *statusbar)
+{
+    vmpa2t addr;                            /* Conversion en pleine adresse*/
+    mem_area_v2 *area;                         /* Zone trouvée à traiter      */
+
+    if (!g_exe_format_translate_address_into_vmpa(fetching->format, fetching->virt, &addr))
+        init_vmpa(&addr, VMPA_NO_PHYSICAL, fetching->virt);
+
+    area = find_memory_area_by_addr_v2(fetching->areas, fetching->count, &addr);
+
+    if (area != NULL)
+        load_code_from_mem_area_v2(area, fetching->areas, fetching->count,
+                                   fetching->ctx, &addr, fetching->info);
+
+}
+
+
+
+
+
+
+
+
+
+
+/* Poursuit l'analyse à partir des points d'entrée découverts. */
+static void follow_execution_flow_v2(GProcContext *, const GDelayedFetching *);
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : ctx      = contexte de désass. avec une nouvelle entrée.     *
+*                template = modèle dont les informations sont à copier.       *
+*                                                                             *
+*  Description : Poursuit l'analyse à partir des points d'entrée découverts.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void follow_execution_flow_v2(GProcContext *ctx, const GDelayedFetching *template)
+{
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    virt_t virt;                            /* Adresse de départ dépilée   */
+    GDelayedFetching *fetching;             /* Récupération à mener        */
+
+    queue = get_work_queue();
+
+    while (g_proc_context_pop_drop_point(ctx, &virt))
+    {
+        fetching = g_delayed_fetching_new(template, virt);
+
+        /**
+         * Pas très élégant : l'identifiant du groupe de travail ne sert qu'ici ;
+         * il n'est donc aucune utilité dans la tâche elle-même.
+         *
+         * Cependant, les paramètres d'appel étant limités, il faudrait créer
+         * une structure intermediare pour communiquer l'identifiant, ce qui
+         * est tout aussi moche.
+         */
+
+        g_work_queue_schedule_work(queue, G_DELAYED_WORK(fetching), template->gid);
+
+    }
+
+}
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : binary = représentation de binaire chargé.                   *
@@ -68,7 +381,7 @@ static void follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx
 
     while (g_proc_context_has_drop_points(ctx))
     {
-        virt = g_proc_context_pop_drop_point(ctx);
+        g_proc_context_pop_drop_point(ctx, &virt);
 
         format = g_loaded_binary_get_format(binary);
 
@@ -96,38 +409,13 @@ static void follow_execution_flow(const GLoadedBinary *binary, GProcContext *ctx
 
 }
 
-
-/******************************************************************************
-*                                                                             *
-*  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   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void ensure_all_mem_areas_are_filled(mem_area **list, size_t *count, const GLoadedBinary *binary, GProcContext *ctx, status_blob_info *info)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < *count; i++)
-        fill_mem_area(list, count, &i, binary, ctx, info);
-
-}
-
+static GDelayedFetching template;              /* Patron des tâches à venir   */
 
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : binary    = représentation de binaire chargé.                *
+*                gid       = identifiant du groupe de travail à utiliser.     *
 *                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.       *
 *                                                                             *
@@ -137,75 +425,96 @@ static void ensure_all_mem_areas_are_filled(mem_area **list, size_t *count, cons
 *                                                                             *
 ******************************************************************************/
 
-GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExtStatusBar *statusbar)
+GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, wgroup_id_t gid, GtkExtStatusBar *statusbar)
 {
     GArchInstruction *result;               /* Instruction désassemblées   */
+    //GDelayedFetching template;              /* Patron des tâches à venir   */
     GBinFormat *format;                     /* Format du fichier binaire   */
     GArchProcessor *proc;                   /* Architecture du binaire     */
-    GProcContext *ctx;                      /* Contexte de désassemblage   */
     GBinContent *content;                   /* Contenu binaire à manipuler */
     phys_t length;                          /* Taille des données à lire   */
-    mem_area *areas;                        /* Zone de productions         */
-    size_t count;                           /* Nombre de ces zones         */
-    status_blob_info *info;                 /* Informations de progression */
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
     double done;                            /* Portion de travail accompli */
 
-    format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
-    proc = g_loaded_binary_get_processor(binary);
 
-    ctx = g_arch_processor_get_context(proc);
-    g_binary_format_setup_disassembling_context(format, ctx);
 
-    /* Définition à la découpe des parties à traiter */
+
+
+
+
+
+    /* Constitution du modèle de référence */
+
+    template.gid = gid;
+
+    template.format = g_loaded_binary_get_format(binary);
+    format = G_BIN_FORMAT(template.format);
+
+    proc = g_loaded_binary_get_processor(binary);
+    template.ctx = g_arch_processor_get_context(proc);
+    g_object_unref(G_OBJECT(proc));
 
     content = g_binary_format_get_content(format);
     length = g_binary_content_compute_size(content);
+    g_object_unref(G_OBJECT(content));
 
-    areas = compute_memory_areas(G_EXE_FORMAT(format), length, &count);
+    template.areas = compute_memory_areas_v2(binary, length, &template.count);
+
+    /* Amorce des traitements */
+
+    g_signal_connect(template.ctx, "drop-point-pushed", G_CALLBACK(follow_execution_flow_v2), &template);
+
+    queue = get_work_queue();
 
     /**
      * Première phase de désassemblage : suivi des chemins tracés.
      */
 
-    info = init_progessive_status(statusbar,
-                                  _("Disassembling following the execution flow..."),
-                                  0, length);
+    template.info = init_progessive_status(statusbar,
+                                           _("Disassembling following the execution flow..."),
+                                           0, length);
+    
+    g_binary_format_setup_disassembling_context(format, template.ctx);
+
+    g_work_queue_wait_for_completion(queue, gid);
 
-    follow_execution_flow(binary, ctx, &areas, &count, info);
+    printf("===================== DONE !\n");
 
-    done = get_current_progessive_status(info);
+    done = get_current_progessive_status(template.info);
 
-    fini_progessive_status(info);
+    fini_progessive_status(template.info);
 
     /**
      * Seconde phase : on comble les trous laissés.
      */
 
-    info = init_progessive_status(statusbar,
-                                  _("Disassembling the remaining instructions..."),
-                                  done, length);
+    template.info = init_progessive_status(statusbar,
+                                           _("Disassembling the remaining instructions..."),
+                                           done, length);
 
-    ensure_all_mem_areas_are_filled(&areas, &count, binary, ctx, info);
+    ensure_all_mem_areas_are_filled(template.areas, template.count, template.ctx, template.info);
 
-    fini_progessive_status(info);
+    fini_progessive_status(template.info);
 
     /**
      * Troisième et dernière phase : récolte des fruits.
      */
 
-    info = init_progessive_status(statusbar,
-                                  _("Collecting disassembled instructions..."),
-                                  0, length);
+    template.info = init_progessive_status(statusbar,
+                                           _("Collecting disassembled instructions..."),
+                                           0, length);
 
-    result = collect_instructions_from_mem_areas(areas, count);
+    result = collect_instructions_from_mem_areas_v2(template.areas, template.count);
 
-    fini_progessive_status(info);
+    fini_progessive_status(template.info);
 
-    /* free */
+    /* Libérations finales */
 
-    g_object_unref(G_OBJECT(content));
+    //g_object_unref(G_OBJECT(template.format));
 
-    g_object_unref(G_OBJECT(proc));
+    g_object_unref(G_OBJECT(template.ctx));
+
+    /* TODO / del(areas); */
 
     return result;
 
diff --git a/src/analysis/disass/fetch.h b/src/analysis/disass/fetch.h
index 0270f78..37dac80 100644
--- a/src/analysis/disass/fetch.h
+++ b/src/analysis/disass/fetch.h
@@ -26,12 +26,13 @@
 
 
 #include "../binary.h"
+#include "../../glibext/delayed.h"
 #include "../../gtkext/gtkextstatusbar.h"
 
 
 
 /* Procède au désassemblage basique d'un contenu binaire. */
-GArchInstruction *disassemble_binary_content(const GLoadedBinary *, GtkExtStatusBar *);
+GArchInstruction *disassemble_binary_content(const GLoadedBinary *, wgroup_id_t, GtkExtStatusBar *);
 
 
 
diff --git a/src/arch/archbase.h b/src/arch/archbase.h
index 24cfd77..fc6fe4d 100644
--- a/src/arch/archbase.h
+++ b/src/arch/archbase.h
@@ -74,6 +74,31 @@ typedef enum _MemoryDataSize
 #define MDS_IS_SIGNED(mds) (mds & 0x80)
 
 
+#define MDS_FROM_BYTES(sz)                          \
+    ({                                              \
+        MemoryDataSize __result;                    \
+        switch (sz)                                 \
+        {                                           \
+             case 1:                                \
+                 __result = MDS_8_BITS_UNSIGNED;    \
+                 break;                             \
+             case 2:                                \
+                 __result = MDS_16_BITS_UNSIGNED;   \
+                 break;                             \
+             case 4:                                \
+                 __result = MDS_32_BITS_UNSIGNED;   \
+                 break;                             \
+             case 8:                                \
+                 __result = MDS_64_BITS_UNSIGNED;   \
+                 break;                             \
+             default:                               \
+                 __result = MDS_UNDEFINED;          \
+                 break;                             \
+        }                                           \
+        __result;                                   \
+    })
+
+
 #define MDS_4_BITS  MDS_4_BITS_UNSIGNED
 #define MDS_8_BITS  MDS_8_BITS_UNSIGNED
 #define MDS_16_BITS MDS_16_BITS_UNSIGNED
diff --git a/src/arch/arm/context-int.h b/src/arch/arm/context-int.h
index 51ed6d0..fbd3a6f 100644
--- a/src/arch/arm/context-int.h
+++ b/src/arch/arm/context-int.h
@@ -50,6 +50,7 @@ struct _GArmContext
 
     disass_arm_area *areas;                 /* Désassemblage découpé       */
     size_t acount;                          /* Nombre de zones définies    */
+    GMutex areas_access;                    /* Accès aux découpes de zones */
 
 };
 
diff --git a/src/arch/arm/context.c b/src/arch/arm/context.c
index b54de42..d805e8c 100644
--- a/src/arch/arm/context.c
+++ b/src/arch/arm/context.c
@@ -139,6 +139,7 @@ static void g_arm_context_class_init(GArmContextClass *klass)
 
 static void g_arm_context_init(GArmContext *ctx)
 {
+    g_mutex_init(&ctx->areas_access);
 
 }
 
@@ -157,6 +158,8 @@ static void g_arm_context_init(GArmContext *ctx)
 
 static void g_arm_context_dispose(GArmContext *ctx)
 {
+    g_mutex_clear(&ctx->areas_access);
+
     G_OBJECT_CLASS(g_arm_context_parent_class)->dispose(G_OBJECT(ctx));
 
 }
@@ -263,11 +266,11 @@ void _g_arm_context_define_encoding(GArmContext *ctx, virt_t addr, unsigned int
 {
     size_t selected;                        /* Zone associée à une adresse */
 
-    /* TODO : pose de verroux ? */
+    g_mutex_lock(&ctx->areas_access);
 
     selected = find_disass_arm_area(ctx->areas, addr, 0, ctx->acount - 1);
 
-    assert(ctx->areas[selected].start != addr || ctx->areas[selected].marker == marker);
+    //assert(ctx->areas[selected].start != addr || ctx->areas[selected].marker == marker);
 
     /* S'agit-il d'une redéfinition ? */
     if (ctx->areas[selected].start == addr)
@@ -290,6 +293,8 @@ void _g_arm_context_define_encoding(GArmContext *ctx, virt_t addr, unsigned int
 
     }
 
+    g_mutex_unlock(&ctx->areas_access);
+
 }
 
 
@@ -308,13 +313,18 @@ void _g_arm_context_define_encoding(GArmContext *ctx, virt_t addr, unsigned int
 
 unsigned int _g_arm_context_find_encoding(GArmContext *ctx, virt_t addr)
 {
+    unsigned int result;                    /* Identifiant à retourner     */
     size_t selected;                        /* Zone associée à une adresse */
 
-    /* TODO : pose de verroux ? */
+    g_mutex_lock(&ctx->areas_access);
 
     selected = find_disass_arm_area(ctx->areas, addr, 0, ctx->acount - 1);
 
-    return ctx->areas[selected].marker;
+    result = ctx->areas[selected].marker;
+
+    g_mutex_unlock(&ctx->areas_access);
+
+    return result;
 
 }
 
diff --git a/src/arch/arm/v7/context.c b/src/arch/arm/v7/context.c
index 885ce70..030457e 100644
--- a/src/arch/arm/v7/context.c
+++ b/src/arch/arm/v7/context.c
@@ -245,7 +245,15 @@ void g_armv7_context_push_drop_point_ext(GArmV7Context *ctx, virt_t addr, ArmV7I
 
     g_armv7_context_define_encoding(ctx, addr, marker);
 
-	G_PROC_CONTEXT_CLASS(g_armv7_context_parent_class)->push_point(G_PROC_CONTEXT(ctx), addr);
+    /**
+     * Il faut impérativement passer pour l'interface publique afin :
+     *  - de poser le verrou associé.
+     *  - de déclencher l'émission du signal lié.
+     *
+     * Pas d'appel via G_PROC_CONTEXT_CLASS(g_armv7_context_parent_class)->push_point() donc.
+     */
+
+    g_proc_context_push_drop_point(G_PROC_CONTEXT(ctx), addr);
 
 }
 
diff --git a/src/arch/context-int.h b/src/arch/context-int.h
index 64465a2..086a8ec 100644
--- a/src/arch/context-int.h
+++ b/src/arch/context-int.h
@@ -29,6 +29,10 @@
 
 
 
+/* Granularité des allocations */
+#define DP_ALLOC_BLOCK 10
+
+
 /* Ajoute une adresse virtuelle comme point de départ de code. */
 typedef void (* push_drop_point_fc) (GProcContext *, virt_t);
 
@@ -39,7 +43,9 @@ struct _GProcContext
     GObject parent;                         /* A laisser en premier        */
 
     virt_t *drop_points;                    /* Liste de points de départ   */
-    size_t dp_count;                        /* Taille de cette liste       */
+    size_t dp_allocated;                    /* Taille de liste allouée     */
+    size_t dp_count;                        /* Quantité utile de la liste  */
+    GMutex dp_access;                       /* Accès à la liste FIFO       */
 
     vmpa2t *extra_symbols;                  /* Adresses de symboles        */
     size_t esyms_count;                     /* Nombres de nouveautés       */
@@ -54,6 +60,10 @@ struct _GProcContextClass
 
 	push_drop_point_fc push_point;			/* Inclusion de points de chute*/
 
+    /* Signaux */
+
+    void (* drop_point_pushed) (GProcContext *);
+
 };
 
 
diff --git a/src/arch/context.c b/src/arch/context.c
index 5427e4a..968a6ea 100644
--- a/src/arch/context.c
+++ b/src/arch/context.c
@@ -65,6 +65,14 @@ static void g_proc_context_class_init(GProcContextClass *klass)
 {
 	klass->push_point = (push_drop_point_fc)_g_proc_context_push_drop_point;
 
+    g_signal_new("drop-point-pushed",
+                 G_TYPE_PROC_CONTEXT,
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GProcContextClass, drop_point_pushed),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+
 }
 
 
@@ -83,7 +91,9 @@ static void g_proc_context_class_init(GProcContextClass *klass)
 static void g_proc_context_init(GProcContext *ctx)
 {
     ctx->drop_points = NULL;
+    ctx->dp_allocated = 0;
     ctx->dp_count = 0;
+    g_mutex_init(&ctx->dp_access);
 
     ctx->extra_symbols = NULL;
     ctx->esyms_count = 0;
@@ -106,9 +116,15 @@ static void g_proc_context_init(GProcContext *ctx)
 
 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));
+    if (ctx->dp_count >= ctx->dp_allocated)
+    {
+        ctx->dp_allocated += DP_ALLOC_BLOCK;
+
+        ctx->drop_points = (virt_t *)realloc(ctx->drop_points, ctx->dp_allocated * sizeof(virt_t));
+
+    }
 
-    ctx->drop_points[ctx->dp_count - 1] = addr;
+    ctx->drop_points[ctx->dp_count++] = addr;
 
 }
 
@@ -128,7 +144,13 @@ static void _g_proc_context_push_drop_point(GProcContext *ctx, virt_t addr)
 
 void g_proc_context_push_drop_point(GProcContext *ctx, virt_t addr)
 {
-	return G_PROC_CONTEXT_GET_CLASS(ctx)->push_point(ctx, addr);
+    g_mutex_lock(&ctx->dp_access);
+
+    G_PROC_CONTEXT_GET_CLASS(ctx)->push_point(ctx, addr);
+
+    g_mutex_unlock(&ctx->dp_access);
+
+    g_signal_emit_by_name(ctx, "drop-point-pushed");
 
 }
 
@@ -147,7 +169,15 @@ void g_proc_context_push_drop_point(GProcContext *ctx, virt_t addr)
 
 bool g_proc_context_has_drop_points(const GProcContext *ctx)
 {
-    return ctx->dp_count > 0;
+    bool result;                            /* Etat à retourner            */
+
+    g_mutex_lock(&ctx->dp_access);
+
+    result = (ctx->dp_count > 0);
+
+    g_mutex_unlock(&ctx->dp_access);
+
+    return result;
 
 }
 
@@ -172,9 +202,13 @@ bool g_proc_context_has_addr_as_drop_points(const GProcContext *ctx, virt_t addr
 
     result = false;
 
+    g_mutex_lock(&ctx->dp_access);
+
     for (i = 0; i < ctx->dp_count && !result; i++)
         result = (ctx->drop_points[i] == addr);
 
+    g_mutex_unlock(&ctx->dp_access);
+
     return result;
 
 }
@@ -183,27 +217,38 @@ bool g_proc_context_has_addr_as_drop_points(const GProcContext *ctx, virt_t addr
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : ctx  = contexte de désassemblage à compléter.                *
+*                virt = adresse d'un point de départ de code à traiter.       *
 *                                                                             *
 *  Description : Fournit une adresse virtuelle comme point de départ de code. *
 *                                                                             *
-*  Retour      : Adresse d'un point de départ de code à traiter.              *
+*  Retour      : true si une adresse a pu être dépilée, false sinon.          *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-virt_t g_proc_context_pop_drop_point(GProcContext *ctx)
+bool g_proc_context_pop_drop_point(GProcContext *ctx, virt_t *virt)
 {
-    virt_t result;                          /* Adresse à retourner         */
+    bool result;                            /* Bilan d'accès à retourner   */
 
-    assert(ctx->dp_count > 0);
+    g_mutex_lock(&ctx->dp_access);
 
-    result = ctx->drop_points[0];
+    if (ctx->dp_count > 0)
+    {
+        result = true;
+
+        *virt = ctx->drop_points[0];
+
+        if (ctx->dp_count > 1)
+            memmove(&ctx->drop_points[0], &ctx->drop_points[1], (ctx->dp_count - 1) * sizeof(virt_t));
 
-    if (ctx->dp_count > 1)
-        memmove(&ctx->drop_points[0], &ctx->drop_points[1], (ctx->dp_count - 1) * sizeof(virt_t));
+        ctx->dp_count--;
+
+    }
+    else
+        result = false;
 
-    ctx->drop_points = (virt_t *)realloc(ctx->drop_points, --ctx->dp_count * sizeof(virt_t));
+    g_mutex_unlock(&ctx->dp_access);
 
     return result;
 
diff --git a/src/arch/context.h b/src/arch/context.h
index 390d9f9..973b7ae 100644
--- a/src/arch/context.h
+++ b/src/arch/context.h
@@ -61,7 +61,7 @@ bool g_proc_context_has_drop_points(const GProcContext *);
 bool g_proc_context_has_addr_as_drop_points(const GProcContext *, virt_t);
 
 /* Fournit une adresse virtuelle comme point de départ de code. */
-virt_t g_proc_context_pop_drop_point(GProcContext *);
+bool g_proc_context_pop_drop_point(GProcContext *, virt_t *);
 
 /* Empile une adresse de nouveau symbole à prendre en compte. */
 void g_proc_context_push_new_symbol_at(GProcContext *, const vmpa2t *);
diff --git a/src/common/bits.c b/src/common/bits.c
index d451100..b08dcb4 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -25,6 +25,7 @@
 
 
 #include <assert.h>
+#include <glib.h>
 #include <malloc.h>
 #include <string.h>
 
@@ -41,6 +42,7 @@ struct _bitfield_t
 
     void *tail;                             /* Limite du tableau de bits   */
 
+    GMutex mutex;                           /* Garantie d'atomicité        */
     unsigned long bits[0];                  /* Mémoire d'accès associée    */
 
 };
@@ -94,6 +96,8 @@ static bitfield_t *_create_bit_field(size_t length, bool state, size_t extra)
 
     result->tail = ((char *)result) + base;
 
+    g_mutex_init(&result->mutex);
+
     if (state)
         set_all_in_bit_field(result);
     else
@@ -177,6 +181,8 @@ bitfield_t *create_bit_field_from(const bitfield_t *field)
 
 void delete_bit_field(bitfield_t *field)
 {
+    g_mutex_clear(&field->mutex);
+
     free(field);
 
 }
@@ -330,6 +336,68 @@ void set_in_bit_field(bitfield_t *field, size_t first, size_t count)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : field = champ de bits à modifier.                            *
+*                first = indice du premier bit à traiter.                     *
+*                count = nombre de bits à marquer.                            *
+*                                                                             *
+*  Description : Bascule à 1 de façon atomique une partie d'un champ de bits. *
+*                                                                             *
+*  Retour      : true si la zone traitée était entièrement vierge.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool set_atomic_in_bit_field(bitfield_t *field, size_t first, size_t count)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t start;                           /* Mot de départ               */
+    size_t end;                             /* Mot d'arrivée               */
+    size_t remaining;                       /* Nombre de bits restants     */
+    unsigned long oldval;                   /* Ancienne valeur présente    */
+    unsigned long mask;                     /* Nouvelle valeur à insérer   */
+
+    start = first / (sizeof(unsigned long) * 8);
+    end = (first + count - 1) / (sizeof(unsigned long) * 8);
+
+#if 0 //sizeof(gsize) != sizeof(unsigned long)
+#   warning "Can not perform atomic operations on bit fields!"
+#else
+    if (start == end)
+    {
+        remaining = first % (sizeof(unsigned long) * 8);
+
+        assert(count > 0);
+
+        mask = (1 << count) - 1;
+        mask <<= remaining;
+
+        oldval = g_atomic_pointer_or(&field->bits[start], mask);
+
+        result = ((oldval & mask) == 0);
+
+    }
+    else
+#endif
+    {
+        g_mutex_lock(&field->mutex);
+
+        result = !test_in_bit_field(field, first, count);
+
+        if (result)
+            set_in_bit_field(field, first, count);
+
+        g_mutex_unlock(&field->mutex);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : dest = champ de bits à modifier.                             *
 *                src  = champ de bits à utiliser pour l'opération.            *
 *                                                                             *
diff --git a/src/common/bits.h b/src/common/bits.h
index 0e8ef65..074aac4 100644
--- a/src/common/bits.h
+++ b/src/common/bits.h
@@ -60,6 +60,9 @@ void set_all_in_bit_field(bitfield_t *);
 /* Bascule à 1 une partie d'un champ de bits. */
 void set_in_bit_field(bitfield_t *, size_t, size_t);
 
+/* Bascule à 1 de façon atomique une partie d'un champ de bits. */
+bool set_atomic_in_bit_field(bitfield_t *, size_t, size_t);
+
 /* Réalise une opération ET logique entre deux champs de bits. */
 void and_bit_field(bitfield_t *, const bitfield_t *);
 
@@ -74,6 +77,7 @@ bool is_bit_field_equal_to(const bitfield_t *, const bitfield_t *);
 
 
 
+
 unsigned long gfw(const bitfield_t *);
 
 
@@ -104,4 +108,9 @@ bool test_in_mem_field(memfield_t *, const vmpa2t *);
 
 
 
+#define set_atomic_in_mem_field(f, range) false
+
+
+
+
 #endif  /* _COMMON_BITS_H */
diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c
index ea520b9..3dc5d64 100644
--- a/src/format/elf/elf.c
+++ b/src/format/elf/elf.c
@@ -432,6 +432,12 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GBinPortion *
 
         sh_flags = ELF_SHDR(format, section, sh_flags);
 
+        printf("[section % 2hu] 0x%08x -> %x -> %d\n", i, sh_flags,
+               sh_flags & SHF_ALLOC, (sh_flags & SHF_ALLOC) == 0);
+
+        if ((sh_flags & SHF_ALLOC) == 0)
+            continue;
+
         if (sh_flags & SHF_EXECINSTR) background = BPC_CODE;
         else if (sh_flags & SHF_WRITE) background = BPC_DATA;
         else background = BPC_DATA_RO;
diff --git a/src/format/symbol.h b/src/format/symbol.h
index 1368691..6f38020 100644
--- a/src/format/symbol.h
+++ b/src/format/symbol.h
@@ -51,6 +51,10 @@ typedef enum _SymbolType
 } SymbolType;
 
 
+#define HAS_DATA_INSTR(type) (type == STP_DATA || type == STP_RO_STRING)
+
+
+
 #define G_TYPE_BIN_SYMBOL               g_binary_symbol_get_type()
 #define G_BIN_SYMBOL(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_binary_symbol_get_type(), GBinSymbol))
 #define G_IS_BIN_SYMBOL(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_binary_symbol_get_type()))
-- 
cgit v0.11.2-87-g4458