From 6c51b9eed427fd55ce1457834853386cc8d543cd Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 29 Jan 2018 21:56:31 +0100
Subject: Handled properly imported/exported ELF symbols, as well as all other
 symbols.

---
 ChangeLog                |   42 ++
 plugins/elf/dynamic.c    |  107 +++++
 plugins/elf/dynamic.h    |    6 +
 plugins/elf/elf_def.h    |    4 +-
 plugins/elf/format.c     |   25 ++
 plugins/elf/helper_arm.c |  195 +++++----
 plugins/elf/helper_arm.h |    4 +-
 plugins/elf/loading.c    |  453 ++++++++++++++++++--
 plugins/elf/loading.h    |   40 +-
 plugins/elf/section.c    |    7 +-
 plugins/elf/symbols.c    | 1020 ++++++++++++++++++++++++++++++++--------------
 plugins/elf/symbols.h    |   16 +-
 src/analysis/binary.c    |    4 +-
 src/common/sort.c        |   31 ++
 src/common/sort.h        |    4 +
 src/format/format-int.h  |    5 +
 src/format/format.c      |  189 ++++++++-
 src/format/format.h      |   14 +
 src/format/symiter.c     |    5 +
 19 files changed, 1716 insertions(+), 455 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2ec6dab..da7fe01 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+18-01-29  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/elf/dynamic.c:
+	* plugins/elf/dynamic.h:
+	Extract more information from the PT_DYNAMIC segment.
+
+	* plugins/elf/elf_def.h:
+	Improve the macro definitions for relocations.
+
+	* plugins/elf/format.c:
+	Insert some extra processings atfer the disassembly process.
+
+	* plugins/elf/helper_arm.c:
+	* plugins/elf/helper_arm.h:
+	Resolve relocation offsets for ARM.
+
+	* plugins/elf/loading.c:
+	* plugins/elf/loading.h:
+	Rely on threads to load more ELF information.
+
+	* plugins/elf/section.c:
+	Make all arguments optional when looking for section parameters.
+
+	* plugins/elf/symbols.c:
+	* plugins/elf/symbols.h:
+	Handle properly imported/exported ELF symbols, as well as all other symbols.
+
+	* src/analysis/binary.c:
+	Update the format symbols after disassembling.
+
+	* src/common/sort.c:
+	* src/common/sort.h:
+	Compare uint64_t integers.
+
+	* src/format/format-int.h:
+	* src/format/format.c:
+	* src/format/format.h:
+	Update code for post-processing. Create new ways to search for symbols.
+
+	* src/format/symiter.c:
+	Add a check for locked format symbol list.
+
 18-01-26  Cyrille Bagard <nocbos@gmail.com>
 
 	* plugins/elf/format.c:
diff --git a/plugins/elf/dynamic.c b/plugins/elf/dynamic.c
index ed681d1..f1d5e02 100644
--- a/plugins/elf/dynamic.c
+++ b/plugins/elf/dynamic.c
@@ -111,6 +111,35 @@ bool find_elf_dynamic_item_from_pheader(const GElfFormat *format, const elf_phdr
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : format  = informations chargées à consulter.                 *
+*                type    = sorte d'élément recherché.                         *
+*                item    = élément retrouvé dans la section. [OUT]            *
+*                                                                             *
+*  Description : Retrouve rapidement un élément dans la section dynamique.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool find_elf_dynamic_item(const GElfFormat *format, int64_t type, elf_dyn *item)
+{
+    bool result;                            /* Bilan à retourner           */
+    elf_phdr dynamic;                       /* En-tête de programme DYNAMIC*/
+
+    result = find_elf_dynamic_program_header(format, &dynamic);
+
+    if (result)
+        result = find_elf_dynamic_item_from_pheader(format, &dynamic, type, item);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : format = description de l'exécutable à consulter.            *
 *                count  = nombre d'éléments dans la liste constituée.         *
 *                                                                             *
@@ -202,3 +231,81 @@ const char **list_elf_needed_objects(const GElfFormat *format, size_t *count)
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à manipuler.            *
+*                virt   = position en mémoire de la PLT. [OUT]                *
+*                                                                             *
+*  Description : Retrouve l'adresse de la PLT en se basant sur la GOT.        *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool resolve_plt_using_got(GElfFormat *format, virt_t *virt)
+{
+    bool result;                            /* Bilan à retourner           */
+    elf_phdr dynamic;                       /* Programme à analyser        */
+    elf_dyn pltgot;                         /* Table de type DT_PLTGOT     */
+    virt_t got_virt;                        /* Adresse mémoire de la GOT   */
+    vmpa2t got_addr;                        /* Localisation complète       */
+    GBinContent *content;                   /* Contenu binaire à parcourir */
+    uint32_t raw_32;                        /* Valeur brute de 32 bits lue */
+    uint64_t raw_64;                        /* Valeur brute de 64 bits lue */
+
+    result = false;
+
+    if (!find_elf_program_by_type(format, PT_DYNAMIC, &dynamic))
+        goto rpug_exit;
+
+    if (!find_elf_dynamic_item_from_pheader(format, &dynamic, DT_PLTGOT, &pltgot))
+        goto rpug_exit;
+
+    got_virt = ELF_DYN(format, pltgot, d_un.d_ptr);
+
+    if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), got_virt, &got_addr))
+        goto rpug_exit;
+
+    content = G_BIN_FORMAT(format)->content;
+
+    /**
+     * Quelques pistes pour la connaissance des premières cellules d'une GOT :
+     *
+     *    "Lazy procedure linkage with the PLT" (mot clef : GOT+4).
+     *    http://www.iecc.com/linker/linker10.html
+     *
+     *    "How the ELF Ruined Christmas" (mot clef : GOT[1]).
+     *     https://www.usenix.org/system/files/conference/usenixsecurity15/sec15-paper-di-frederico.pdf
+     */
+
+    if (format->is_32b)
+    {
+        advance_vmpa(&got_addr, 3 * sizeof(uint32_t));
+
+        result = g_binary_content_read_u32(content, &got_addr, format->endian, &raw_32);
+
+        if (result)
+            *virt = raw_32;
+
+    }
+
+    else
+    {
+        advance_vmpa(&got_addr, 3 * sizeof(uint64_t));
+
+        result = g_binary_content_read_u64(content, &got_addr, format->endian, &raw_64);
+
+        if (result)
+            *virt = raw_64;
+
+    }
+
+ rpug_exit:
+
+    return result;
+
+}
diff --git a/plugins/elf/dynamic.h b/plugins/elf/dynamic.h
index c166712..1ca4785 100644
--- a/plugins/elf/dynamic.h
+++ b/plugins/elf/dynamic.h
@@ -36,9 +36,15 @@ bool find_elf_dynamic_program_header(const GElfFormat *, elf_phdr *);
 /* Retrouve un élément donné dans la section dynamique. */
 bool find_elf_dynamic_item_from_pheader(const GElfFormat *, const elf_phdr *, int64_t, elf_dyn *);
 
+/* Retrouve rapidement un élément dans la section dynamique. */
+bool find_elf_dynamic_item(const GElfFormat *, int64_t, elf_dyn *);
+
 /* Fournit la liste des objets partagés requis. */
 const char **list_elf_needed_objects(const GElfFormat *, size_t *);
 
+/* Retrouve l'adresse de la PLT en se basant sur la GOT. */
+bool resolve_plt_using_got(GElfFormat *, virt_t *);
+
 
 
 #endif  /* _PLUGINS_ELF_DYNAMIC_H */
diff --git a/plugins/elf/elf_def.h b/plugins/elf/elf_def.h
index 06adff7..2120afa 100644
--- a/plugins/elf/elf_def.h
+++ b/plugins/elf/elf_def.h
@@ -599,8 +599,8 @@ typedef union _elf_rel
 
 #define ELF_REL(fmt, rl, fld) (fmt->is_32b ? (rl).rel32.fld : (rl).rel64.fld)
 
-#define ELF_REL_SYM(fmt, rl) (fmt->is_32b ? ELF32_R_SYM(rl.rel32.r_info) : ELF64_R_SYM(rl.rel64.r_info))
-#define ELF_REL_TYPE(fmt, rl) (fmt->is_32b ? ELF32_R_TYPE(rl.rel32.r_info) : ELF64_R_TYPE(rl.rel64.r_info))
+#define ELF_REL_SYM(fmt, rl) (fmt->is_32b ? ELF32_R_SYM((rl).rel32.r_info) : ELF64_R_SYM((rl).rel64.r_info))
+#define ELF_REL_TYPE(fmt, rl) (fmt->is_32b ? ELF32_R_TYPE((rl).rel32.r_info) : ELF64_R_TYPE((rl).rel64.r_info))
 
 #define ELF_SIZEOF_REL(fmt) (fmt->is_32b ? sizeof(elf32_rel) : sizeof(elf64_rel))
 
diff --git a/plugins/elf/format.c b/plugins/elf/format.c
index 9e3b636..d48eef9 100644
--- a/plugins/elf/format.c
+++ b/plugins/elf/format.c
@@ -62,6 +62,9 @@ static void g_elf_format_finalize(GElfFormat *);
 /* Informe quant au boutisme utilisé. */
 static SourceEndian g_elf_format_get_endianness(const GElfFormat *);
 
+/* Réalise un traitement post-désassemblage. */
+static void g_elf_format_complete_analysis(GElfFormat *, GtkStatusStack *);
+
 /* Indique le type d'architecture visée par le format. */
 static const char *g_elf_format_get_target_machine(const GElfFormat *);
 
@@ -157,6 +160,8 @@ static void g_elf_format_class_init(GElfFormatClass *klass)
 
     fmt->get_endian = (format_get_endian_fc)g_elf_format_get_endianness;
 
+    fmt->complete = (format_complete_analysis_fc)g_elf_format_complete_analysis;
+
     exe = G_EXE_FORMAT_CLASS(klass);
 
     exe->get_machine = (get_target_machine_fc)g_elf_format_get_target_machine;
@@ -340,6 +345,26 @@ static SourceEndian g_elf_format_get_endianness(const GElfFormat *format)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : format = description de l'exécutable à manipuler.            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Réalise un traitement post-désassemblage.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_elf_format_complete_analysis(GElfFormat *format, GtkStatusStack *status)
+{
+    refresh_elf_relocations(format, status);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
 *                                                                             *
 *  Description : Indique le type d'architecture visée par le format.          *
diff --git a/plugins/elf/helper_arm.c b/plugins/elf/helper_arm.c
index a037469..4c34d78 100644
--- a/plugins/elf/helper_arm.c
+++ b/plugins/elf/helper_arm.c
@@ -24,15 +24,8 @@
 #include "helper_arm.h"
 
 
-#include <assert.h>
-
-
-#include <format/mangling/demangler.h>
-
-
 #include "elf_def_arm.h"
 #include "elf-int.h"
-#include "symbols.h"
 
 
 
@@ -70,12 +63,11 @@ const char *get_elf_program_arm_type_desc(uint32_t p_type)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à compléter.            *
-*                relxxx = section .rel.xxx trouvée (zone à traiter).          *
-*                dynsym = section .dynsym trouvée (info. dynamiques).         *
-*                dynstr = section .dynstr trouvée (chaînes de caractères).    *
+*  Paramètres  : format = description de l'exécutable à manipuler.            *
+*                range  = emplacement de la procédure de liaison.             *
+*                offset = décalage retrouvé par désassemblage... [OUT]        *
 *                                                                             *
-*  Description : Charge en mémoire la liste des symboles relogés.             *
+*  Description : Retrouve le décalage appliqué lors d'une résolution.         *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -83,87 +75,124 @@ const char *get_elf_program_arm_type_desc(uint32_t p_type)
 *                                                                             *
 ******************************************************************************/
 
-bool load_elf_arm_relocated_symbols(GElfFormat *format, const elf_shdr *relxxx, const elf_shdr *dynsym, const elf_shdr *dynstr)
+bool retrieve_arm_linkage_offset(GElfFormat *format, const mrange_t *range, uint64_t *offset)
 {
     bool result;                            /* Bilan à retourner           */
-    phys_t rel_start;                       /* Début de la zone à traiter  */
-    phys_t rel_size;                        /* Taille de cette même zone   */
-    GBinFormat *base;                       /* Autre version du format     */
-    phys_t iter;                            /* Boucle de parcours          */
-    elf_rel reloc;                          /* Infos de relocalisation     */
-    off_t index;                            /* Indice de la portion visée  */
-    elf_sym sym;                            /* Définition complète         */
-    const char *name;                       /* Nom du symbole trouvé       */
-    char *plt_name;                         /* Adaptation de l'étiquette   */
-    virt_t virt;                            /* Adresse en mémoire virtuelle*/
-    virt_t final_virt;                      /* Adresse virtuelle retenue   */
-    bool status;                            /* Bilan d'une opération       */
-    vmpa2t addr;                            /* Localisation d'une routine  */
-    GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
-    GBinSymbol *symbol;                     /* Nouveau symbole construit   */
-    mrange_t range;                         /* Couverture mémoire associée */
-
-    result = true;
-
-    get_elf_section_content(format, relxxx, &rel_start, &rel_size, NULL);
-
-    base = G_BIN_FORMAT(format);
-
-    for (iter = rel_start; iter < (rel_start + rel_size); )
+    GBinContent *content;                   /* Contenu binaire à parcourir */
+    vmpa2t pos;                             /* Tete de lecture             */
+    uint32_t raw;                           /* Valeur brute lue            */
+    uint32_t shift;                         /* Décalage arithmétique       */
+
+    /**
+     * Pour faciliter la compréhension, on peut s'appuyer sur la lecture de :
+     *
+     *    http://blog.qt.io/blog/2010/12/04/moving-code-around/
+     *
+     */
+
+    content = G_BIN_FORMAT(format)->content;
+
+    copy_vmpa(&pos, get_mrange_addr(range));
+
+    result = g_binary_content_read_u32(content, &pos, format->endian, &raw);
+    if (!result) goto ralo_exit;
+
+    /**
+     * On ne reconnaît pour l'instant que la seule combinaison suivante.
+     *
+     * Charge de compléter cette reconnaissance en fonction de nouvelles
+     * découvertes !
+     */
+
+    /**
+     * R_ARM_JUMP_SLOT :
+     *
+     *    e28fc600     add ip, pc, #0, 12
+     *    e28cca08     add ip, ip, #8, 20  ; 0x8000
+     *    e5bcf310     ldr pc, [ip, #784]! ; 0x310
+     */
+
+    if (raw == 0xe28fc600)
     {
-        result = read_elf_relocation(format, &iter, &reloc);
-        if (!result) break;
-
-        index = ELF_REL_SYM(format, reloc);
-
-        if (!get_elf_symbol_by_index(format, dynsym, index, &sym))
-            continue;
-
-        name = get_elf_symbol_name(format, dynsym, dynstr, index);
-
-        if (name == NULL)
-            name = "unknown";
-
-        asprintf(&plt_name, "%s@plt", name);
-
-        switch (ELF_REL_TYPE(format, reloc))
+        *offset = get_virt_addr(get_mrange_addr(range)) + 8;
+
+        result = g_binary_content_read_u32(content, &pos, format->endian, &raw);
+        if (!result) goto ralo_exit;
+
+        /**
+         * La seconde instruction répond à l'encodage spécifié dans :
+         *
+         *    A8.8.5 - ADD (immediate, ARM)
+         *
+         *    31 30 29 28 | 27 26 25 24 23 22 21 20 | 19 18 17 16 | 15 14 13 12 | 11 10 9 8 7 6 5 4 3 2 1 0
+         *        cond    |  0  0  1  0  1  0  0  S |      Rn     |      Rd     |           imm12
+         *
+         * On a donc :
+         *
+         *    ADD{S}{<c>}{<q>} {<Rd>,} <Rn>, #<const>
+         *
+         * Avec :
+         *
+         *    - S = 0.
+         *    - Rn = ip = r12 = 0xc
+         *    - Rd = ip = r12 = 0xc
+         *    - const = ARMExpandImm(imm12)
+         *
+         * Le fonctionnement de la macro ARMExpandImm est détaillé dans :
+         *
+         *    A5.2.4 - Modified immediate constants in ARM instructions
+         *
+         */
+
+        if ((raw & 0xfffff000) != 0xe28cc000)
         {
-            case R_ARM_JUMP_SLOT:
-
-                virt = ELF_SYM(format, sym, st_value);
-                if (virt == 0) goto lears_next;
-
-                final_virt = virt & ~0x1;
-
-                status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_virt, &addr);
-                if (!status) goto lears_next;
-
-                routine = try_to_demangle_routine(plt_name);
-                symbol = G_BIN_SYMBOL(routine);
-
-                init_mrange(&range, &addr, 0);
-                g_binary_symbol_set_range(symbol, &range);
-
-                /* Comptabilisation pour le désassemblage brut */
-                g_binary_format_register_code_point(base, virt, false);
-
-                break;
-
-            default:
-                assert(false);
-                symbol = NULL;
-                break;
+            result = false;
+            goto ralo_exit;
+        }
 
+        shift = 32 - ((raw & 0xf00) >> 8) * 2;
+
+        *offset += (raw & 0xf) << shift;
+
+        result = g_binary_content_read_u32(content, &pos, format->endian, &raw);
+        if (!result) goto ralo_exit;
+
+        /**
+         * La dernière instruction répond à l'encodage spéficié dans :
+         *
+         *    A8.8.63 - LDR (immediate, ARM)
+         *
+         *    31 30 29 28 | 27 26 25 24 23 22 21 20 | 19 18 17 16 | 15 14 13 12 | 11 10 9 8 7 6 5 4 3 2 1 0
+         *        cond    |  0  1  0  P  U  0  W  1 |      Rn     |      Rt     |           imm12
+         *
+         * On a donc :
+         *
+         *    LDR{<c>}{<q>} <Rt>, [<Rn>, #+/-<imm>]!
+         *
+         * Avec :
+         *
+         *    - P = 1 (index).
+         *    - U = 1 (add).
+         *    - W = 1 (wback).
+         *    - Rn = ip = r12 = 0xc
+         *    - Rt = pc = r15 = 0xf
+         *
+         */
+
+        if ((raw & 0xfffff000) != 0xe5bcf000)
+        {
+            result = false;
+            goto ralo_exit;
         }
 
-        if (symbol != NULL)
-            g_binary_format_add_symbol(base, symbol);
+        *offset += (raw & 0xfff);
 
-    lears_next:
+    }
 
-        free(plt_name);
+    else
+        result = false;
 
-    }
+ ralo_exit:
 
     return result;
 
diff --git a/plugins/elf/helper_arm.h b/plugins/elf/helper_arm.h
index d4be96c..07549ad 100644
--- a/plugins/elf/helper_arm.h
+++ b/plugins/elf/helper_arm.h
@@ -32,8 +32,8 @@
 /* Fournit la description humaine d'un type de segment ELF. */
 const char *get_elf_program_arm_type_desc(uint32_t);
 
-/* Charge en mémoire la liste des symboles relogés. */
-bool load_elf_arm_relocated_symbols(GElfFormat *, const elf_shdr *, const elf_shdr *, const elf_shdr *);
+/* Retrouve le décalage appliqué lors d'une résolution. */
+bool retrieve_arm_linkage_offset(GElfFormat *, const mrange_t *, uint64_t *);
 
 
 
diff --git a/plugins/elf/loading.c b/plugins/elf/loading.c
index 377eb14..5d82fcc 100644
--- a/plugins/elf/loading.c
+++ b/plugins/elf/loading.c
@@ -24,13 +24,19 @@
 #include "loading.h"
 
 
+#include <assert.h>
+#include <string.h>
+
+
 #include <i18n.h>
+#include <common/extstr.h>
+#include <common/sort.h>
 #include <core/logs.h>
+#include <core/params.h>
 #include <glibext/delayed-int.h>
 
 
 #include "elf-int.h"
-#include "section.h"
 
 
 
@@ -41,24 +47,58 @@ struct _GElfLoading
 
     GElfFormat *format;                     /* Format à faire évoluer      */
 
+    phys_t str_start;                       /* Chaînes à disposition       */
+
     union
     {
         struct
         {
-            const elf_shdr *section;        /* Section à éplucher          */
             bool use_virt;                  /* Représentatio par défaut    */
 
-            elf_shdr strtab;                /* Section .strtab trouvée     */
-            bool has_strtab;                /* Présence de cette section   */
+        };
+
+        struct
+        {
+            elf_rel *relocs_to_fill;        /* Tableau à remplir           */
+
+        };
+
+        struct
+        {
+            elf_rel *relocs;                /* Relocalisations présentes   */
+            size_t rel_count;               /* Qté de ces relocalisations  */
+
+            phys_t sym_start;               /* Début de zone des symboles  */
+            uint32_t sym_count;             /* Nombre de symboles présents */
 
         };
 
+
     };
 
-    elf_loading_cb callback;                /* Routine de traitement finale*/
-    phys_t first;                           /* Position du premier élément */
-    phys_t begin;                           /* Point de départ du parcours */
-    phys_t end;                             /* Point d'arrivée exclu       */
+    union
+    {
+        struct
+        {
+            phys_t begin;                   /* Point de départ du parcours */
+            phys_t end;                     /* Point d'arrivée exclu       */
+
+            elf_loading_cb callback_0;      /* Routine de traitement #0    */
+
+        };
+
+        struct
+        {
+            sym_iter_t *iter;               /* Symboles à parcourir        */
+
+            elf_applying_cb callback_1;     /* Routine de traitement #1    */
+
+        };
+
+    };
+
+    unsigned int kind;                      /* Type de traitements         */
+    bool status;                            /* Bilan des traitements       */
 
     activity_id_t id;                       /* Identifiant pour messages   */
 
@@ -136,6 +176,7 @@ static void g_elf_loading_class_init(GElfLoadingClass *klass)
 
 static void g_elf_loading_init(GElfLoading *loading)
 {
+    loading->status = false;
 
 }
 
@@ -180,12 +221,61 @@ static void g_elf_loading_finalize(GElfLoading *loading)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = = ensemble d'instructions désassemblées.            *
-*                section  = prototypes existants à insérer.                   *
-*                use_virt = quantité de ces prototypes.                       *
-*                first    = position du premier élément.                      *
+*  Paramètres  : format    = ensemble d'instructions désassemblées.           *
+*                str_start = début des chaînes de caractères à consulter.     *
+*                first     = position du premier élément.                     *
+*                begin     = point de départ du parcours de liste.            *
+*                end       = point d'arrivée exclu du parcours.               *
+*                id        = identifiant du message affiché à l'utilisateur.  *
+*                callback  = routine de traitements particuliers.             *
+*                                                                             *
+*  Description : Crée une tâche de chargement pour ELF différée.              *
+*                                                                             *
+*  Retour      : Tâche créée.                                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GElfLoading *g_elf_loading_new_for_symbols(GElfFormat *format, phys_t str_start, phys_t first, phys_t begin, phys_t end, activity_id_t id, elf_loading_cb callback)
+{
+    GElfLoading *result;                    /* Tâche à retourner           */
+#ifndef NDEBUG
+    bool status;                            /* Etat d'une consultation     */
+#endif
+
+    result = g_object_new(G_TYPE_ELF_LOADING, NULL);
+
+    result->format = format;
+
+    result->str_start = str_start;
+
+#ifndef NDEBUG
+    status = g_generic_config_get_value(get_main_configuration(), MPK_FORMAT_NO_NAME, &result->use_virt);
+    assert(status);
+#else
+    g_generic_config_get_value(get_main_configuration(), MPK_FORMAT_NO_NAME, &result->use_virt);
+#endif
+
+    result->begin = begin;
+    result->end = end;
+    result->callback_0 = callback;
+
+    result->kind = 0;
+
+    result->id = id;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format   = ensemble d'instructions désassemblées.            *
 *                begin    = point de départ du parcours de liste.             *
 *                end      = point d'arrivée exclu du parcours.                *
+*                relocs   = table des relocalisations à remplir.              *
 *                id       = identifiant du message affiché à l'utilisateur.   *
 *                callback = routine de traitements particuliers.              *
 *                                                                             *
@@ -197,7 +287,7 @@ static void g_elf_loading_finalize(GElfLoading *loading)
 *                                                                             *
 ******************************************************************************/
 
-GElfLoading *g_elf_loading_new(GElfFormat *format, const elf_shdr *section, bool use_virt, phys_t first, phys_t begin, phys_t end, activity_id_t id, elf_loading_cb callback)
+GElfLoading *g_elf_loading_new_for_relocations(GElfFormat *format, phys_t begin, phys_t end, elf_rel *relocs, activity_id_t id, elf_loading_cb callback)
 {
     GElfLoading *result;                    /* Tâche à retourner           */
 
@@ -205,17 +295,15 @@ GElfLoading *g_elf_loading_new(GElfFormat *format, const elf_shdr *section, bool
 
     result->format = format;
 
-    result->section = section;
-    result->use_virt = use_virt;
+    result->str_start = VMPA_NO_PHYSICAL;
 
-    result->has_strtab = find_elf_section_by_index(format,
-                                                   ELF_SHDR(format, *section, sh_link),
-                                                   &result->strtab);
+    result->relocs_to_fill = relocs;
 
-    result->callback = callback;
-    result->first = first;
     result->begin = begin;
     result->end = end;
+    result->callback_0 = callback;
+
+    result->kind = 0;
 
     result->id = id;
 
@@ -226,8 +314,55 @@ GElfLoading *g_elf_loading_new(GElfFormat *format, const elf_shdr *section, bool
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : study  = étude de routines à mener.                          *
-*                status = barre de statut à tenir informée.                   *
+*  Paramètres  : format    = ensemble d'instructions désassemblées.           *
+*                iter      = itérateur sur les symboles à parcourir.          *
+*                str_start = début de la zone contenant les descriptions.     *
+*                relocs    = table des relocalisations chargées.              *
+*                rel_count = nombre de ces éléments à interpréter.            *
+*                sym_start = localisation du début de la zone de symboles.    *
+*                sym_count = nombre de descriptions de symbole attendues.     *
+*                id        = identifiant du message affiché à l'utilisateur.  *
+*                callback  = routine de traitements particuliers.             *
+*                                                                             *
+*  Description : Crée une tâche de chargement pour ELF différée.              *
+*                                                                             *
+*  Retour      : Tâche créée.                                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GElfLoading *g_elf_loading_new_for_applying(GElfFormat *format, sym_iter_t *iter, phys_t str_start, elf_rel *relocs, size_t rel_count, phys_t sym_start, uint32_t sym_count, activity_id_t id, elf_applying_cb callback)
+{
+    GElfLoading *result;                    /* Tâche à retourner           */
+
+    result = g_object_new(G_TYPE_ELF_LOADING, NULL);
+
+    result->format = format;
+
+    result->str_start = str_start;
+
+    result->relocs = relocs;
+    result->rel_count = rel_count;
+    result->sym_start = sym_start;
+    result->sym_count = sym_count;
+
+    result->iter = iter;
+    result->callback_1 = callback;
+
+    result->kind = 1;
+
+    result->id = id;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : loading = traitements différés à mener.                      *
+*                status  = barre de statut à tenir informée.                  *
 *                                                                             *
 *  Description : Assure le chargement pour un format ELF en différé.          *
 *                                                                             *
@@ -239,22 +374,66 @@ GElfLoading *g_elf_loading_new(GElfFormat *format, const elf_shdr *section, bool
 
 static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status)
 {
+    GElfFormat *format;                     /* Format plus accessible      */
     phys_t iter;                            /* Boucle de parcours          */
     phys_t old;                             /* Sauvegarde du point d'avant */
     bool ret;                               /* Bilan d'un appel            */
+    size_t processed;                       /* Nombre de symboles traités  */
+    GBinSymbol *symbol;                     /* Symbole analysé             */
+
+    format = loading->format;
 
-    for (iter = loading->begin; iter < loading->end; )
+    switch (loading->kind)
     {
-        old = iter;
-        ret = loading->callback(loading, loading->format, &iter);
+        case 0:
 
-        if (!ret)
-        {
-            log_variadic_message(LMT_ERROR, _("Error while loading ELF data @ 0x%08x!"), old);
+            for (iter = loading->begin; iter < loading->end; )
+            {
+                old = iter;
+                ret = loading->callback_0(loading, format, &iter);
+
+                if (!ret)
+                {
+                    log_variadic_message(LMT_ERROR, _("Error while loading ELF data @ 0x%08x!"), old);
+                    break;
+                }
+
+                gtk_status_stack_update_activity_value(status, loading->id, 1);
+
+            }
+
+            loading->status = (iter == loading->end);
             break;
-        }
 
-        gtk_status_stack_update_activity_value(status, loading->id, 1);
+        case 1:
+
+            ret = true;
+
+            processed = 0;
+
+            for (symbol = get_symbol_iterator_next(loading->iter);
+                 symbol != NULL && ret;
+                 symbol = get_symbol_iterator_next(loading->iter))
+            {
+                ret = loading->callback_1(loading, format, symbol);
+
+                if (!ret)
+                {
+                    log_variadic_message(LMT_ERROR, _("Error while applying ELF relocation %zu!"), processed);
+                    break;
+                }
+
+                processed++;
+
+                gtk_status_stack_update_activity_value(status, loading->id, 1);
+
+                if (processed == loading->rel_count)
+                    break;
+
+            }
+
+            loading->status = (processed == loading->rel_count);
+            break;
 
     }
 
@@ -263,14 +442,95 @@ static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : loading    = chargement pour ELF à mener.                    *
-*                section    = prototypes existants à insérer. [OUT]           *
-*                use_virt   = quantité de ces prototypes. [OUT]               *
-*                strtab     = informations quant à la table des chaînes. [OUT]*
-*                has_strtab = validité du champ précédemment renseigné. [OUT] *
-*                first      = position du premier élément. [OUT]              *
+*  Paramètres  : loading = procédure de chargements écoulés à consulter.      *
+*                                                                             *
+*  Description : Fournit le bilan des traitements différés.                   *
+*                                                                             *
+*  Retour      : true si tout s'est bien déroulé.                             *
 *                                                                             *
-*  Description : Fournit les infos utiles au chargement de symbols internes.  *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_elf_loading_get_status(const GElfLoading *loading)
+{
+    return loading->status;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : loading = chargement pour ELF à mener.                       *
+*                name    = indice de la désignation du symbole concerné.      *
+*                virt    = adresse virtuelle du symbole en mémoire.           *
+*                prefix  = préfixe d'une désignation par défaut.              *
+*                alt     = zone de constitution d'un nom alternatif. [OUT]    *
+*                addr    = localisation compléte à associer au symbole. [OUT] *
+*                                                                             *
+*  Description : Construit la désignation adaptée à un symbole.               *
+*                                                                             *
+*  Retour      : Pointeur vers une étiquette constituée.                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_elf_loading_build_name(const GElfLoading *loading, uint32_t name, virt_t virt, const char *prefix, char *alt, vmpa2t *addr)
+{
+    const char *result;                     /* Désignation à retourner     */
+    GElfFormat *format;                     /* Format plus accessible      */
+    vmpa2t pos;                             /* Position de lecture         */
+    const GBinContent *content;             /* Contenu binaire à lire      */
+    size_t plen;                            /* Taille du préfixe           */
+
+    result = NULL;
+
+    format = loading->format;
+
+    if (g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), virt, addr))
+    {
+        init_vmpa(&pos, loading->str_start + name, VMPA_NO_VIRTUAL);
+
+        content = G_BIN_FORMAT(format)->content;
+
+        result = (const char *)g_binary_content_get_raw_access(content, &pos, 1);
+
+        if (result != NULL && result[0] == '\0')
+            result = NULL;
+
+        if (result == NULL)
+        {
+            /**
+             * Charge à l'appelant de s'assurer que la zone tampon est assez grande !
+             */
+
+            strcpy(alt, prefix);
+            plen = strlen(prefix);
+
+            if (loading->use_virt)
+                vmpa2_virt_to_string(addr, MDS_UNDEFINED, alt + plen, NULL);
+            else
+                vmpa2_phys_to_string(addr, MDS_UNDEFINED, alt + plen, NULL);
+
+            result = alt;
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : loading = chargement pour ELF à compléter.                   *
+*                iter    = tête de lecture courante.                          *
+*                reloc   = relocalisation à conserver en mémoire.             *
+*                                                                             *
+*  Description : Intègre dans la liste adaptée une relocalisation chargée.    *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -278,14 +538,121 @@ static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status)
 *                                                                             *
 ******************************************************************************/
 
-void g_elf_loading_get_internal_info(GElfLoading *loading, const elf_shdr **section, bool *use_virt, const elf_shdr **strtab, bool *has_strtab, phys_t *first)
+void g_elf_loading_store_relocation(const GElfLoading *loading, const phys_t *iter, const elf_rel *reloc)
+{
+    GElfFormat *format;                     /* Format plus accessible      */
+    size_t index;                           /* Indice de l'élément         */
+
+    format = loading->format;
+
+    index = (*iter - loading->begin);
+
+    assert(index % sizeof(ELF_SIZEOF_REL(format)) == 0);
+
+    index /= sizeof(ELF_SIZEOF_REL(format));
+
+    /* La tête de lecture a consommé un élément ! */
+    index--;
+
+    memcpy(&loading->relocs_to_fill[index], reloc, sizeof(elf_rel));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : loading = chargement pour ELF à consulter.                   *
+*                offset = décalage à retrouver idéalement.                    *
+*                reloc  = informations quant à la relocalisation. [OUT]       *
+*                                                                             *
+*  Description : Recherche une relocalisation par son décalage.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_elf_loading_search_for_relocation(const GElfLoading *loading, const uint64_t *offset, elf_rel **reloc)
 {
-    *section = loading->section;
-    *use_virt = loading->use_virt;
+    bool result;                            /* Validité à faire remonter   */
+    void *found;                            /* Eventuel élément trouvé     */
+
+    int compare_relocations(const uint64_t *off, const elf_rel *rel)
+    {
+        return sort_uint64_t(*off, ELF_REL(loading->format, *rel, r_offset));
+    }
 
-    *strtab = &loading->strtab;
-    *has_strtab = loading->has_strtab;
+    found = bsearch(offset, loading->relocs, loading->rel_count,
+                    sizeof(elf_rel), (__compar_fn_t)compare_relocations);
 
-    *first = loading->first;
+    result = (found != NULL);
+
+    if (result)
+        *reloc = (elf_rel *)found;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : loading = chargement pour ELF à poursuivre.                  *
+*                index   = indice du symbole concerné.                        *
+*                                                                             *
+*  Description : Construit la désignation adaptée à un symbole importé.       *
+*                                                                             *
+*  Retour      : Nouvelle étiquette constituée ou NULL en cas d'échec.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *g_elf_loading_build_plt_name(const GElfLoading *loading, uint64_t index)
+{
+    char *result;                           /* Désignation à retourner     */
+    GElfFormat *format;                     /* Format plus accessible      */
+    phys_t offset;                          /* Tête de lecture brute       */
+    elf_sym sym;                            /* Symbole aux infos visées    */
+    bool status;                            /* Bilan de récupération       */
+    uint32_t name;                          /* Indice du nom du symbole    */
+    vmpa2t pos;                             /* Position de lecture         */
+    const GBinContent *content;             /* Contenu binaire à lire      */
+    const char *prefix;                     /* Première partie de nom      */
+
+    format = loading->format;
+
+    offset = loading->sym_start + index * ELF_SIZEOF_SYM(format);
+
+    status = read_elf_symbol(format, &offset, &sym);
+
+    if (!status)
+        result = NULL;
+
+    else
+    {
+        name = ELF_SYM(format, sym, st_name);
+
+        offset = loading->str_start + name;
+
+        init_vmpa(&pos, offset, VMPA_NO_VIRTUAL);
+
+        content = G_BIN_FORMAT(format)->content;
+
+        prefix = (const char *)g_binary_content_get_raw_access(content, &pos, 1);
+
+        if (prefix != NULL && prefix[0] == '\0')
+            result = NULL;
+
+        else
+        {
+            result = strdup(prefix);
+            result = stradd(result, "@plt");
+        }
+
+    }
+
+    return result;
 
 }
diff --git a/plugins/elf/loading.h b/plugins/elf/loading.h
index 03ac184..79ea67f 100644
--- a/plugins/elf/loading.h
+++ b/plugins/elf/loading.h
@@ -25,6 +25,7 @@
 #define _PLUGINS_ELF_LOADING_H
 
 
+#include <format/symiter.h>
 #include <gtkext/gtkstatusstack.h>
 
 
@@ -32,12 +33,12 @@
 
 
 
-#define G_TYPE_ELF_LOADING              g_elf_loading_get_type()
-#define G_ELF_LOADING(obj)              (G_TYPE_CHECK_INSTANCE_CAST((obj), g_elf_loading_get_type(), GElfLoading))
-#define G_IS_ELF_LOADING(obj)           (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_elf_loading_get_type()))
-#define G_ELF_LOADING_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ELF_LOADING, GElfLoadingClass))
-#define G_IS_ELF_LOADING_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ELF_LOADING))
-#define G_ELF_LOADING_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ELF_LOADING, GElfLoadingClass))
+#define G_TYPE_ELF_LOADING            g_elf_loading_get_type()
+#define G_ELF_LOADING(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ELF_LOADING, GElfLoading))
+#define G_IS_ELF_LOADING(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ELF_LOADING))
+#define G_ELF_LOADING_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ELF_LOADING, GElfLoadingClass))
+#define G_IS_ELF_LOADING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ELF_LOADING))
+#define G_ELF_LOADING_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ELF_LOADING, GElfLoadingClass))
 
 
 /* Fraction de loading à limiter (instance) */
@@ -50,15 +51,36 @@ typedef struct _GElfLoadingClass GElfLoadingClass;
 /* Assure un chargement pour ELF en différé. */
 typedef bool (* elf_loading_cb) (GElfLoading *, GElfFormat *, phys_t *);
 
+/* Assure l'intégration d'un symbole issu des relocalisations. */
+typedef bool (* elf_applying_cb) (GElfLoading *, GElfFormat *, GBinSymbol *);
+
 
 /* Indique le type défini pour les tâches de chargements pour format ELF. */
 GType g_elf_loading_get_type(void);
 
 /* Crée une tâche de chargement pour ELF différée. */
-GElfLoading *g_elf_loading_new(GElfFormat *, const elf_shdr *, bool, phys_t, phys_t, phys_t, activity_id_t, elf_loading_cb);
+GElfLoading *g_elf_loading_new_for_symbols(GElfFormat *, phys_t, phys_t, phys_t, phys_t, activity_id_t, elf_loading_cb);
+
+/* Crée une tâche de chargement pour ELF différée. */
+GElfLoading *g_elf_loading_new_for_relocations(GElfFormat *, phys_t, phys_t, elf_rel *, activity_id_t, elf_loading_cb);
+
+/* Crée une tâche de chargement pour ELF différée. */
+GElfLoading *g_elf_loading_new_for_applying(GElfFormat *, sym_iter_t *, phys_t, elf_rel *, size_t, phys_t, uint32_t, activity_id_t, elf_applying_cb);
+
+/* Fournit le bilan des traitements différés. */
+bool g_elf_loading_get_status(const GElfLoading *);
+
+/* Construit la désignation adaptée à un symbole. */
+const char *g_elf_loading_build_name(const GElfLoading *, uint32_t, virt_t, const char *, char *, vmpa2t *);
+
+/* Intègre dans la liste adaptée une relocalisation chargée. */
+void g_elf_loading_store_relocation(const GElfLoading *, const phys_t *, const elf_rel *);
+
+/* Recherche une relocalisation par son décalage. */
+bool g_elf_loading_search_for_relocation(const GElfLoading *, const uint64_t *, elf_rel **);
 
-/* Fournit les infos utiles au chargement de symbols internes. */
-void g_elf_loading_get_internal_info(GElfLoading *, const elf_shdr **, bool *, const elf_shdr **, bool *, phys_t *);
+/* Construit la désignation adaptée à un symbole importé. */
+char *g_elf_loading_build_plt_name(const GElfLoading *, uint64_t);
 
 
 
diff --git a/plugins/elf/section.c b/plugins/elf/section.c
index 556c0ed..5e42b0a 100644
--- a/plugins/elf/section.c
+++ b/plugins/elf/section.c
@@ -195,8 +195,11 @@ bool find_elf_sections_by_type(const GElfFormat *format, uint32_t type, elf_shdr
 
 void get_elf_section_content(const GElfFormat *format, const elf_shdr *section, phys_t *offset, phys_t *size, virt_t *addr)
 {
-    *offset = ELF_SHDR(format, *section, sh_offset);
-    *size = ELF_SHDR(format, *section, sh_size);
+    if (offset != NULL)
+        *offset = ELF_SHDR(format, *section, sh_offset);
+
+    if (size != NULL)
+        *size = ELF_SHDR(format, *section, sh_size);
 
     if (addr != NULL)
         *addr = ELF_SHDR(format, *section, sh_addr);
diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c
index 7bf68f5..4854d7b 100644
--- a/plugins/elf/symbols.c
+++ b/plugins/elf/symbols.c
@@ -26,15 +26,17 @@
 
 #include <assert.h>
 #include <malloc.h>
+#include <stdlib.h>
 #include <string.h>
 
 
 #include <i18n.h>
 #include <arch/raw.h>
 #include <common/extstr.h>
+#include <common/sort.h>
 #include <core/global.h>
 #include <core/logs.h>
-#include <core/params.h>
+#include <format/symiter.h>
 #include <format/mangling/demangler.h>
 
 
@@ -47,11 +49,7 @@
 
 
 
-
-
-
-
-
+/* ------------------------- CHARGEMENT GLOBAL DES SYMBOLES ------------------------- */
 
 
 /* Enregistre un point d'entrée au sein d'un binaire ELF. */
@@ -60,44 +58,59 @@ static void register_elf_entry_point(GElfFormat *, virt_t, phys_t, GBinRoutine *
 /* Enumère tous les points d'entrée principaux d'un binaire ELF. */
 static bool load_all_elf_basic_entry_points(GElfFormat *);
 
+/* Assure le chargement des symboles internes ELF en différé. */
+static bool do_elf_symbol_loading(GElfLoading *, GElfFormat *, bool, phys_t *, GBinSymbol **);
 
+/* Charge tous les symboles possibles. */
+static void add_all_elf_symbols(GElfFormat *, phys_t, size_t, phys_t, GWorkQueue *, wgroup_id_t, elf_loading_cb, GtkStatusStack *, activity_id_t);
 
 
 
+/* --------------------------- DETAIL DES SYMBOLES LOCAUX --------------------------- */
 
 
-
-
-/* -------------------------- DETAIL DES SYMBOLES INTERNES -------------------------- */
-
-
-/* Assure le chargement des symboles internes ELF en différé. */
-static bool do_elf_internal_symbol_loading(GElfLoading *, GElfFormat *, phys_t *);
+/* Assure le chargement des symboles locaux ELF en différé. */
+static bool do_elf_local_symbol_loading(GElfLoading *, GElfFormat *, phys_t *);
 
 /* Charge tous les symboles internes possibles. */
-static bool load_elf_internal_symbols(GElfFormat *, wgroup_id_t, GtkStatusStack *);
+static bool load_elf_local_symbols(GElfFormat *, wgroup_id_t, GtkStatusStack *);
+
 
 
+/* --------------------------- DETAIL DE SYMBOLES GLOBAUX --------------------------- */
 
-/* -------------------------- DETAIL DES SYMBOLES EXTERNES -------------------------- */
 
+/* Assure le chargement des symboles globaux ELF en différé. */
+static bool do_elf_global_symbol_loading(GElfLoading *, GElfFormat *, phys_t *);
 
-/* Retrouve un élément donné dans la section dynamique. */
-static bool find_elf_dynamic_item(const GElfFormat *, const elf_shdr *, int32_t, elf_dyn *);
+/* Dénombre le nombre de symboles en lien avec l'extérieur. */
+static bool count_elf_global_symbols(GElfFormat *, GExeFormat *, uint32_t *);
 
 /* Charge tous les éléments dynamiques externes possibles. */
-static bool load_elf_external_symbols(GElfFormat *, const elf_shdr *);
+static bool load_elf_global_symbols(GElfFormat *, wgroup_id_t, GtkStatusStack *);
 
 
 
+/* ----------------------- PRISE EN COMPTE DE RELOCALISATIONS ----------------------- */
 
 
+/* Assure le chargement des relocalisations ELF en différé. */
+static bool do_elf_relocation_loading(GElfLoading *, GElfFormat *, phys_t *);
 
+/* Charge en mémoire toutes les relocalisations présentes. */
+static bool load_elf_relocations(GElfFormat *, const elf_phdr *, elf_rel **, size_t *, GtkStatusStack *);
 
+/* Assure l'intégration d'un symbole issu des relocalisations. */
+static bool do_elf_relocation_renaming(GElfLoading *, GElfFormat *, GBinSymbol *);
 
+/* Applique les étiquettes issues des relocalisations. */
+static bool apply_elf_relocations(GElfFormat *, elf_rel *, size_t, sym_iter_t *, GtkStatusStack *);
 
 
 
+/* ---------------------------------------------------------------------------------- */
+/*                           CHARGEMENT GLOBAL DES SYMBOLES                           */
+/* ---------------------------------------------------------------------------------- */
 
 
 /******************************************************************************
@@ -118,46 +131,31 @@ bool load_elf_symbols(GElfFormat *format, GtkStatusStack *status)
     bool result;                            /* Bilan à retourner           */
     wgroup_id_t gid;                        /* Identifiant pour les tâches */
 
-    elf_shdr *sections;                     /* Groupe de sections trouvées */
-    size_t count;                           /* Quantité de données         */
-
     result = true;
 
     gid = g_work_queue_define_work_group(get_work_queue());
 
     /* Symboles internes */
 
-    result &= load_elf_internal_symbols(format, gid, status);
-
-
-
+    result &= load_elf_local_symbols(format, gid, status);
 
-    /* Symboles externes */
+    /* Symboles importés et/ou exportés */
 
-    if (find_elf_sections_by_type(format, SHT_DYNAMIC, &sections, &count))
+    if (find_elf_dynamic_program_header(format, (elf_phdr []) { 0 }))
     {
         log_variadic_message(LMT_INFO, _("Binary is dynamically linked"));
 
-        result &= load_elf_external_symbols(format, &sections[0]);
-
-        free(sections);
+        result &= load_elf_global_symbols(format, gid, status);
 
     }
     else log_variadic_message(LMT_INFO, _("Binary is statically linked"));
 
-
-
-
     /* Symboles d'entrée, si encore besoin */
 
     /**
      * Le tri en préalable
      */
 
-
-
-
-
     result &= load_all_elf_basic_entry_points(format);
 
     return result;
@@ -165,9 +163,6 @@ bool load_elf_symbols(GElfFormat *format, GtkStatusStack *status)
 }
 
 
-
-
-
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format  = description de l'exécutable à compléter.           *
@@ -429,68 +424,293 @@ static bool load_all_elf_basic_entry_points(GElfFormat *format)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : loading = chargement de symboles en cours.                   *
+*                format  = format ELF à compléter.                            *
+*                local   = s'apprête-t-on à constuire un symbole interne ?    *
+*                iter    = tête de lecture évoluant avec le temps. [OUT]      *
+*                new     = éventuel renseignement du nouveau symbole. [OUT]   *
+*                                                                             *
+*  Description : Assure le chargement des symboles internes ELF en différé.   *
+*                                                                             *
+*  Retour      : Bilan de l'exécution, utile pour la poursuite du traitement. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool do_elf_symbol_loading(GElfLoading *loading, GElfFormat *format, bool local, phys_t *iter, GBinSymbol **new)
+{
+    bool result;                            /* Bilan à retourner           */
+    elf_sym sym;                            /* Symbole aux infos visées    */
+    virt_t virt;                            /* Adresse virtuelle           */
+    SymbolStatus status;                    /* Visibilité du symbole       */
+    GBinFormat *base;                       /* Version basique du format   */
+    uint32_t index;                         /* Indice du nom du symbole    */
+    const char *name;                       /* Nom du symbole trouvé       */
+    GBinSymbol *symbol;                     /* Nouveau symbole construit   */
+    char alt_name[6 + VMPA_MAX_LEN];        /* Nom abstrait de substitution*/
+    virt_t original_virt;                   /* Adresse virtuelle retenue   */
+    vmpa2t addr;                            /* Localisation d'un symbole   */
+    mrange_t range;                         /* Couverture mémoire associée */
+    GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
+
+    if (new != NULL)
+        *new = NULL;
+
+    result = read_elf_symbol(format, iter, &sym);
+    if (!result) goto desl_done;
+
+    /**
+     * Si l'adresse virtuelle est nulle, on ne peut ratacher le symbole à aucune position...
+     *
+     * On ne réalise donc aucune opération ici, quitte à laisser une seconde passe
+     * s'occuper des symboles importés par exemple.
+     */
+
+    virt = ELF_SYM(format, sym, st_value);
+    if (virt == 0) goto desl_done;
+
+    /**
+     * En ce qui concerne la nature de la visibilité, on distingue les deux situations suivantes :
+     *  - zone DYNSYM : uniquement les importations / exportations.
+     *  - zone SYMTAB : tous les symboles.
+     *
+     * La première zone doit donc être traitée en amont, et la seconde complète les traitements
+     * avec à priori uniquement des symboles locaux.
+     */
+
+    if (local)
+        status = SSS_INTERNAL;
+
+    else
+        status = ELF_SYM(format, sym, st_shndx) == 0 ? SSS_IMPORTED : SSS_EXPORTED;
+
+    /* Traitements particuliers */
+
+    base = G_BIN_FORMAT(format);
+
+    index = ELF_SYM(format, sym, st_name);
 
+    switch (ELF_ST_TYPE(format, sym))
+    {
+        case STT_OBJECT:
+
+            name = g_elf_loading_build_name(loading, index, virt, "obj_", alt_name, &addr);
+            if (name == NULL) break;
+
+            init_mrange(&range, &addr, ELF_SYM(format, sym, st_size));
+
+            symbol = g_binary_symbol_new(&range, STP_OBJECT);
+
+            g_binary_symbol_set_alt_label(symbol, name);
+
+            break;
+
+        case STT_FUNC:
+
+            original_virt = virt;
+
+            /* Ajustement de la position */
+
+            if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
+                virt &= ~0x1;
+
+            /* Constitution d'une routine */
+
+            name = g_elf_loading_build_name(loading, index, virt, "func_", alt_name, &addr);
+            if (name == NULL) break;
+
+            routine = try_to_demangle_routine(name);
+            symbol = G_BIN_SYMBOL(routine);
+
+            init_mrange(&range, &addr, ELF_SYM(format, sym, st_size));
+
+            g_binary_symbol_set_range(symbol, &range);
+
+            /* Comptabilisation pour le désassemblage brut */
+
+            g_binary_format_register_code_point(base, original_virt, false);
+
+            break;
+
+        default:
+            symbol = NULL;
+            break;
+
+    }
+
+    if (symbol != NULL)
+    {
+        g_binary_symbol_set_status(symbol, status);
+
+        if (new != NULL)
+        {
+            g_object_ref(G_OBJECT(symbol));
+            *new = symbol;
+        }
+
+        g_binary_format_add_symbol(base, symbol);
 
+    }
 
+ desl_done:
 
+    return result;
 
+}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
-*                sym    = section comprenant les symboles à venir lire.       *
-*                index  = indice de l'entrée à venir lire.                    *
-*                symbol = ensemble d'informations lues. [OUT]                 *
+*  Paramètres  : format    = description de l'exécutable à compléter.         *
+*                sym_start = localisation du début de la zone de symboles.    *
+*                count     = nombre de descriptions de symbole attendues.     *
+*                str_start = début de la zone contenant les descriptions.     *
+*                wq        = espace de travail dédié.                         *
+*                gid       = groupe de travail impliqué.                      *
+*                callback  = routine de traitements particuliers.             *
+*                status    = barre de statut à tenir informée.                *
+*                msg       = identifiant du message de progression.           *
 *                                                                             *
-*  Description : Récupère la définition complète d'un symbole donné.          *
+*  Description : Charge tous les symboles possibles.                          *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool get_elf_symbol_by_index(GElfFormat *format, const elf_shdr *sym, off_t index, elf_sym *symbol)
+static void add_all_elf_symbols(GElfFormat *format, phys_t sym_start, size_t count, phys_t str_start, GWorkQueue *wq, wgroup_id_t gid, elf_loading_cb callback, GtkStatusStack *status, activity_id_t msg)
 {
-    phys_t sym_start;                       /* Début de section            */
-    phys_t sym_size;                        /* Taille de section           */
-    phys_t offset;                          /* Emplacement à venir lire    */
+    phys_t sym_size;                        /* Taille de chaque symbole lu */
+    guint runs_count;                       /* Qté d'exécutions parallèles */
+    phys_t run_size;                        /* Volume réparti par exécution*/
+    guint i;                                /* Boucle de parcours          */
+    phys_t begin;                           /* Début de zone de traitement */
+    phys_t end;                             /* Fin d'un zone de traitement */
+    GElfLoading *loading;                   /* Tâche de chargement à lancer*/
+
+    sym_size = ELF_SIZEOF_SYM(format);
+
+    runs_count = g_get_num_processors();
 
-    get_elf_section_content(format, sym, &sym_start, &sym_size, NULL);
+    run_size = count / runs_count;
 
-    offset = sym_start + index * ELF_SIZEOF_SYM(format);
-    if ((offset + ELF_SIZEOF_SYM(format)) > (sym_start + sym_size)) return NULL;
+    gtk_status_stack_extend_activity(status, msg, count);
 
-    return read_elf_symbol(format, &offset, symbol);
+    for (i = 0; i < runs_count; i++)
+    {
+        begin = sym_start + i * run_size * sym_size;
+
+        if ((i + 1) == runs_count)
+            end = sym_start + count * sym_size;
+        else
+            end = begin + run_size * sym_size;
+
+        loading = g_elf_loading_new_for_symbols(format, str_start, sym_start, begin, end, msg, callback);
+
+        g_work_queue_schedule_work(wq, G_DELAYED_WORK(loading), gid);
+
+    }
 
 }
 
 
+
+/* ---------------------------------------------------------------------------------- */
+/*                             DETAIL DES SYMBOLES LOCAUX                             */
+/* ---------------------------------------------------------------------------------- */
+
+
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
-*                sym    = section comprenant les symboles à venir lire.       *
-*                str    = section de chaînes de caractères pour les noms.     *
-*                index  = indice de l'entrée à venir lire.                    *
+*  Paramètres  : loading = chargement de symboles externes en cours.          *
+*                format  = format ELF à compléter.                            *
+*                iter    = tête de lecture évoluant avec le temps. [OUT]      *
 *                                                                             *
-*  Description : Récupère la désignation d'un symbole donné.                  *
+*  Description : Assure le chargement des symboles locaux ELF en différé.     *
 *                                                                             *
-*  Retour      : Nom du symbole trouvé, ou NULL si erreur ou non adapté.      *
+*  Retour      : Bilan de l'exécution, utile pour la poursuite du traitement. *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const char *get_elf_symbol_name(GElfFormat *format, const elf_shdr *sym, const elf_shdr *str, off_t index)
+static bool do_elf_local_symbol_loading(GElfLoading *loading, GElfFormat *format, phys_t *iter)
 {
-    const char *result;                     /* Résultat à retourner        */
-    elf_sym symbol;                         /* Symbole aux infos visées    */
+    bool result;                            /* Bilan à retourner           */
+
+    result = do_elf_symbol_loading(loading, format, true, iter, NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à compléter.            *
+*                gid    = groupe de travail impliqué.                         *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Charge tous les symboles internes possibles.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool load_elf_local_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à retourner           */
+    activity_id_t msg;                      /* Message de progression      */
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    size_t size;                            /* Taille de chaque symbole lu */
+    elf_shdr *symtabs;                      /* Groupe de sections trouvées */
+    size_t count;                           /* Quantité de données         */
+    size_t i;                               /* Boucle de parcours          */
+    phys_t sym_start;                       /* Début de la zone à traiter  */
+    phys_t sym_size;                        /* Taille de cette même zone   */
+    size_t sym_count;                       /* Nombre de symboles déduits  */
+    elf_shdr strtab;                        /* Section dédiées aux chaînes */
+    phys_t str_start;                       /* Début de cette section      */
+
+    result = true;
+
+    msg = gtk_status_stack_add_activity(status, _("Loading local symbols..."), 0);
+
+    queue = get_work_queue();
+
+    size = ELF_SIZEOF_SYM(format);
+
+    if (find_elf_sections_by_type(format, SHT_SYMTAB, &symtabs, &count))
+        for (i = 0; i < count; i++)
+        {
+            get_elf_section_content(format, &symtabs[i], &sym_start, &sym_size, NULL);
+
+            if (sym_size % size != 0)
+                continue;
+
+            sym_count = sym_size / size;
 
-    result = NULL;
+            if (!find_elf_section_by_index(format, ELF_SHDR(format, symtabs[i], sh_link), &strtab))
+                continue;
 
-    if (get_elf_symbol_by_index(format, sym, index, &symbol))
-        result = extract_name_from_elf_string_section(format, str, ELF_SYM(format, symbol, st_name));
+            get_elf_section_content(format, &strtab, &str_start, NULL, NULL);
+
+            add_all_elf_symbols(format, sym_start, sym_count, str_start,
+                                queue, gid, do_elf_local_symbol_loading, status, msg);
+
+        }
+
+    g_work_queue_wait_for_completion(queue, gid);
+
+    gtk_status_stack_remove_activity(status, msg);
+
+    if (symtabs != NULL) free(symtabs);
 
     return result;
 
@@ -499,181 +719,193 @@ const char *get_elf_symbol_name(GElfFormat *format, const elf_shdr *sym, const e
 
 
 /* ---------------------------------------------------------------------------------- */
-/*                            DETAIL DES SYMBOLES INTERNES                            */
+/*                             DETAIL DE SYMBOLES GLOBAUX                             */
 /* ---------------------------------------------------------------------------------- */
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : loading = chargement de symboles internes en cours.          *
+*  Paramètres  : loading = chargement de symboles externes en cours.          *
 *                format  = format ELF à compléter.                            *
 *                iter    = tête de lecture évoluant avec le temps. [OUT]      *
 *                                                                             *
-*  Description : Assure le chargement des symboles internes ELF en différé.   *
+*  Description : Assure le chargement des symboles globaux ELF en différé.    *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan de l'exécution, utile pour la poursuite du traitement. *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool do_elf_internal_symbol_loading(GElfLoading *loading, GElfFormat *format, phys_t *iter)
+static bool do_elf_global_symbol_loading(GElfLoading *loading, GElfFormat *format, phys_t *iter)
 {
     bool result;                            /* Bilan à retourner           */
-    elf_sym sym;                            /* Symbole aux infos visées    */
-    SymbolStatus status;                    /* Visibilité du symbole       */
-    vmpa2t addr;                            /* Localisation d'un symbole   */
-    virt_t virt;                            /* Adresse virtuelle           */
-    const elf_shdr *section;                /* Groupe de sections trouvées */
-    bool use_virt;                          /* Choix de construction de nom*/
-    const elf_shdr *strtab;                 /* Section .strtab trouvée     */
-    bool has_strtab;                        /* Présence de cette section   */
-    phys_t first;                           /* Position du premier élément */
-    const char *name;                       /* Nom du symbole trouvé       */
-    GBinFormat *base;                       /* Version basique du format   */
-    GBinSymbol *symbol;                     /* Nouveau symbole construit   */
-    char alt_name[6 + VMPA_MAX_LEN];        /* Nom abstrait de substitution*/
-    virt_t final_virt;                      /* Adresse virtuelle retenue   */
-    mrange_t range;                         /* Couverture mémoire associée */
-    GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
-
-    result = read_elf_symbol(format, iter, &sym);
-    if (!result) goto geslp_done;
+    GBinSymbol *symbol;                     /* Nouveau symbole en place    */
 
-    /* Nature de la visibilité et adresse associée */
+    result = do_elf_symbol_loading(loading, format, false, iter, &symbol);
 
-    if (ELF_SYM(format, sym, st_shndx) == 0)
-    {
-        status = SSS_IMPORTED;
-        init_vmpa(&addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
-
-    }
+    return result;
 
-    else
-    {
-        status = SSS_EXPORTED;
+}
 
-        virt = ELF_SYM(format, sym, st_value);
-        if (virt == 0) goto geslp_done;
 
-    }
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                exec   = autre vision de ce format.                          *
+*                count  = nombre de symboles présents. [OUT]                  *
+*                                                                             *
+*  Description : Dénombre le nombre de symboles en lien avec l'extérieur.     *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    /* Première ébauche de nom */
+static bool count_elf_global_symbols(GElfFormat *format, GExeFormat *exec, uint32_t *count)
+{
+    bool result;                            /* Bilan à retourner           */
+    elf_dyn hash;                           /* Table de type DT_HASH       */
+    bool found;                             /* Détection validée           */
+    vmpa2t addr;                            /* Position de départ brute    */
 
-    g_elf_loading_get_internal_info(loading, &section, &use_virt, &strtab, &has_strtab, &first);
+    result = false;
 
-    if (!has_strtab)
-        name = NULL;
+    /**
+     * Cf. l'astuce indiquée par :
+     *
+     *    - http://www.gabriel.urdhr.fr/2015/09/28/elf-file-format/#symbol-tables
+     *    - http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash
+     *
+     */
 
-    else
-        name = get_elf_symbol_name(format, section, strtab,
-                                   ((*iter - first) / ELF_SIZEOF_SYM(format)) - 1);
+    found = find_elf_dynamic_item(format, DT_HASH, &hash);
+    if (!found) goto cegs_exit;
 
-    /* Traitements particuliers */
+    exec = G_EXE_FORMAT(format);
 
-    base = G_BIN_FORMAT(format);
+    result = g_exe_format_translate_address_into_vmpa(exec, ELF_DYN(format, hash, d_un.d_ptr), &addr);
+    if (!result) goto cegs_exit;
 
-    switch (ELF_ST_TYPE(format, sym))
-    {
-        case STT_OBJECT:
+    advance_vmpa(&addr, 4);
 
-            /* Ajustement de la position */
+    result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, count);
+    if (!result) goto cegs_exit;
 
-            if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), virt, &addr))
-            {
-                symbol = NULL;
-                break;
-            }
+ cegs_exit:
 
-            /* Création d'un nom unique ? */
+    return result;
 
-            if (name == NULL)
-            {
-                strcpy(alt_name, "obj_");
+}
 
-                if (use_virt)
-                    vmpa2_virt_to_string(&addr, MDS_UNDEFINED, alt_name + 4, NULL);
-                else
-                    vmpa2_phys_to_string(&addr, MDS_UNDEFINED, alt_name + 4, NULL);
 
-                name = alt_name;
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à compléter.            *
+*                gid    = groupe de travail impliqué.                         *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Charge tous les éléments dynamiques externes possibles.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-            }
+static bool load_elf_global_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à retourner           */
+    GExeFormat *exec;                       /* Autre vision du format      */
+    elf_dyn strtab;                         /* Table de type DT_STRTAB     */
+    phys_t str_start;                       /* Début de zone des chaînes   */
+    elf_dyn symtab;                         /* Table de type DT_SYMTAB     */
+    phys_t sym_start;                       /* Début de zone des symboles  */
+    uint32_t count;                         /* Nombre de symboles présents */
+    activity_id_t msg;                      /* Message de progression      */
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
 
+    result = true;
 
-            /* TODO */
+    /**
+     * Les spécifications ne sont pas très claires sur le nombre de tables
+     * possible... On y parle de LA table des symboles, ce qui laisse penser
+     * qu'il ne peut y en avoir qu'une.
+     */
 
-            symbol = NULL;
+    exec = G_EXE_FORMAT(format);
 
+    /* Récupération du début des chaînes de description */
 
-            break;
+    result = find_elf_dynamic_item(format, DT_STRTAB, &strtab);
+    if (!result) goto lees_exit;
 
-        case STT_FUNC:
+    result = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, strtab, d_un.d_ptr), &str_start);
+    if (!result) goto lees_exit;
 
-            /* Ajustement de la position */
+    /* Récupération du début des définitions de symboles */
 
-            if (status == SSS_IMPORTED)
-                init_mrange(&range, &addr, 0);
+    result = find_elf_dynamic_item(format, DT_SYMTAB, &symtab);
+    if (!result) goto lees_exit;
 
-            else
-            {
-                if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
-                    final_virt = virt & ~0x1;
-                else
-                    final_virt = virt;
+    result = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, symtab, d_un.d_ptr), &sym_start);
+    if (!result) goto lees_exit;
 
-                if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_virt, &addr))
-                {
-                    symbol = NULL;
-                    break;
-                }
+    /* Détermination du nombre d'éléments */
 
-                init_mrange(&range, &addr, ELF_SYM(format, sym, st_size));
+    result = count_elf_global_symbols(format, exec, &count);
+    if (!result) goto lees_exit;
 
-            }
+    /* Chargement des symboles */
 
-            /* Création d'un nom unique ? */
+    msg = gtk_status_stack_add_activity(status, _("Loading global symbols..."), 0);
 
-            if (name == NULL)
-            {
-                strcpy(alt_name, "func_");
+    queue = get_work_queue();
 
-                if (use_virt)
-                    vmpa2_virt_to_string(&addr, MDS_UNDEFINED, alt_name + 5, NULL);
-                else
-                    vmpa2_phys_to_string(&addr, MDS_UNDEFINED, alt_name + 5, NULL);
+    add_all_elf_symbols(format, sym_start, count, str_start,
+                        queue, gid, do_elf_global_symbol_loading, status, msg);
 
-                name = alt_name;
+    g_work_queue_wait_for_completion(queue, gid);
 
-            }
+    gtk_status_stack_remove_activity(status, msg);
 
-            /* Routine */
+ lees_exit:
 
-            routine = try_to_demangle_routine(name);
-            symbol = G_BIN_SYMBOL(routine);
+    return result;
 
-            /* Comptabilisation pour le désassemblage brut */
+}
 
-            g_binary_format_register_code_point(G_BIN_FORMAT(format), virt, false);
 
-            break;
 
-        default:
-            symbol = NULL;
-            break;
+/* ---------------------------------------------------------------------------------- */
+/*                         PRISE EN COMPTE DE RELOCALISATIONS                         */
+/* ---------------------------------------------------------------------------------- */
 
-    }
 
-    if (symbol != NULL)
-    {
-        g_binary_symbol_set_range(symbol, &range);
-        g_binary_symbol_set_status(symbol, status);
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : loading = chargement de relocalisations en cours.            *
+*                format  = format ELF à compléter.                            *
+*                iter    = tête de lecture évoluant avec le temps. [OUT]      *
+*                                                                             *
+*  Description : Assure le chargement des relocalisations ELF en différé.     *
+*                                                                             *
+*  Retour      : Bilan de l'exécution, utile pour la poursuite du traitement. *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-        g_binary_format_add_symbol(base, symbol);
+static bool do_elf_relocation_loading(GElfLoading *loading, GElfFormat *format, phys_t *iter)
+{
+    bool result;                            /* Bilan à retourner           */
+    elf_rel reloc;                          /* Relocalisation constituée   */
 
-    }
+    result = read_elf_relocation(format, iter, &reloc);
 
- geslp_done:
+    if (result)
+        g_elf_loading_store_relocation(loading, iter, &reloc);
 
     return result;
 
@@ -682,11 +914,13 @@ static bool do_elf_internal_symbol_loading(GElfLoading *loading, GElfFormat *for
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à compléter.            *
-*                gid    = groupe de travail impliqué.                         *
-                 status = barre de statut à tenir informée.                   *
+*  Paramètres  : format  = informations chargées à consulter.                 *
+*                dynamic = en-tête de programme de type DYNAMIC.              *
+*                relocs  = liste des relocalisations triées à charger. [OUT]  *
+*                count   = taille de cette liste. [OUT]                       *
+*                status  = barre de statut à tenir informée.                  *
 *                                                                             *
-*  Description : Charge tous les symboles internes possibles.                 *
+*  Description : Charge en mémoire toutes les relocalisations présentes.      *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -694,101 +928,158 @@ static bool do_elf_internal_symbol_loading(GElfLoading *loading, GElfFormat *for
 *                                                                             *
 ******************************************************************************/
 
-static bool load_elf_internal_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+static bool load_elf_relocations(GElfFormat *format, const elf_phdr *dynamic, elf_rel **relocs, size_t *count, GtkStatusStack *status)
 {
     bool result;                            /* Bilan à retourner           */
-    bool no_name;                           /* Choix de construction de nom*/
+    GExeFormat *exec;                       /* Autre vision du format      */
+    elf_dyn jmprel;                         /* Table des relocalisations   */
+    vmpa2t start;                           /* Position de départ brute    */
+    elf_dyn pltrelsz;                       /* Taille de table en octets   */
+    uint64_t length;                        /* Nombre total des éléments   */
+    mrange_t shr_range;                     /* Emplacement des relocs. #1  */
+    mrange_t phr_range;                     /* Emplacement des relocs. #2  */
+    phys_t rel_size;                        /* Taille de chaque élément lu */
+    bool ret;                               /* Bilan d'un appel            */
     activity_id_t msg;                      /* Message de progression      */
     GWorkQueue *queue;                      /* Gestionnaire de différés    */
-    elf_shdr *dynsym_sections;              /* Groupe de sections trouvées */
-    size_t count;                           /* Quantité de données         */
-    elf_shdr *symtab_sections;              /* Groupe de sections trouvées */
-    size_t i;                               /* Boucle de parcours          */
+    wgroup_id_t gid;                        /* Identifiant pour les tâches */
+    guint runs_count;                       /* Qté d'exécutions parallèles */
+    phys_t run_size;                        /* Volume réparti par exécution*/
+    GElfLoading **loadings;                 /* Tâches de chargement        */
+    guint i;                                /* Boucle de parcours          */
+    phys_t begin;                           /* Début de zone de traitement */
+    phys_t end;                             /* Fin d'un zone de traitement */
 
     result = true;
 
-    /* Charge tous les symboles définis dans une section */
-    void add_all_symbols_from_section(const elf_shdr *section, bool use_virt, GWorkQueue *wq, activity_id_t id)
-    {
-        phys_t start;                       /* Début de la zone à traiter  */
-        phys_t size;                        /* Taille de cette même zone   */
-        phys_t sym_size;                    /* Taille de chaque symbole lu */
-        guint runs_count;                   /* Qté d'exécutions parallèles */
-        phys_t run_size;                    /* Volume réparti par exécution*/
-        guint i;                            /* Boucle de parcours          */
-        phys_t begin;                       /* Début de zone de traitement */
-        phys_t end;                         /* Fin d'un zone de traitement */
-        GElfLoading *loading;               /* Tâche de chargement à lancer*/
+    *relocs = NULL;
+    *count = 0;
 
-        get_elf_section_content(format, section, &start, &size, NULL);
+    exec = G_EXE_FORMAT(format);
 
-        sym_size = ELF_SIZEOF_SYM(format);
+    /* Collecte des informations */
 
-        runs_count = g_get_num_processors();
+    if (!find_elf_dynamic_item_from_pheader(format, dynamic, DT_JMPREL, &jmprel))
+        goto ler_exit;
 
-        run_size = size / (sym_size * runs_count);
+    result = g_exe_format_translate_address_into_vmpa(exec, ELF_DYN(format, jmprel, d_un.d_ptr), &start);
 
-        gtk_status_stack_extend_activity(status, id, size / sym_size);
+    if (!result)
+        goto ler_exit;
 
-        for (i = 0; i < runs_count; i++)
-        {
-            begin = start + i * run_size * sym_size;
+    if (!find_elf_dynamic_item_from_pheader(format, dynamic, DT_PLTRELSZ, &pltrelsz))
+        goto ler_exit;
 
-            if ((i + 1) == runs_count)
-                end = start + size;
-            else
-                end = begin + run_size * sym_size;
+    length = ELF_DYN(format, pltrelsz, d_un.d_val);
 
-            loading = g_elf_loading_new(format, section, use_virt, start, begin, end,
-                                        id, do_elf_internal_symbol_loading);
+    /* Corrélation des informations */
 
-            g_work_queue_schedule_work(wq, G_DELAYED_WORK(loading), gid);
+    ret = find_elf_section_range_by_name(format, ".rel.plt", &shr_range);
 
-        }
+    if (ret)
+    {
+        init_mrange(&phr_range, &start, length);
+
+        if (cmp_mrange(&phr_range, &shr_range) != 0)
+            log_simple_message(LMT_BAD_BINARY,
+                               _("The linker PLT and the PLT section differ by their area definition."));
 
     }
 
-    if (!g_generic_config_get_value(get_main_configuration(), MPK_FORMAT_NO_NAME, &no_name))
-        return false;
+    /* Détermination du nombre d'éléments */
 
-    msg = gtk_status_stack_add_activity(status, _("Loading internal symbols..."), 0);
+    rel_size = ELF_SIZEOF_REL(format);
+
+    if (length % rel_size != 0)
+    {
+        result = false;
+        goto ler_exit;
+    }
+
+    length /= rel_size;
+
+    /* Chargement en mémoire des relocalisations */
+
+    if (length == 0)
+        goto ler_exit;
+
+    *relocs = (elf_rel *)malloc(length * sizeof(elf_rel));
+    *count = length;
+
+    msg = gtk_status_stack_add_activity(status, _("Loading relocations..."), length);
 
     queue = get_work_queue();
+    gid = g_work_queue_define_work_group(queue);
 
-    if (find_elf_sections_by_type(format, SHT_DYNSYM, &dynsym_sections, &count))
-        for (i = 0; i < count; i++)
-            add_all_symbols_from_section(&dynsym_sections[i], no_name, queue, msg);
+    runs_count = g_get_num_processors();
 
-    if (find_elf_sections_by_type(format, SHT_SYMTAB, &symtab_sections, &count))
-        for (i = 0; i < count; i++)
-            add_all_symbols_from_section(&symtab_sections[i], no_name, queue, msg);
+    run_size = length / runs_count;
+
+    loadings = (GElfLoading **)malloc(runs_count * sizeof(GElfLoading *));
+
+    for (i = 0; i < runs_count; i++)
+    {
+        begin = get_phy_addr(&start) + i * run_size * rel_size;
+
+        if ((i + 1) == runs_count)
+            end = get_phy_addr(&start) + length * rel_size;
+        else
+            end = begin + run_size * rel_size;
+
+        loadings[i] = g_elf_loading_new_for_relocations(format, begin, end,
+                                                        (*relocs) + i * run_size,
+                                                        msg, do_elf_relocation_loading);
+
+        g_object_ref(G_OBJECT(loadings[i]));
+
+        g_work_queue_schedule_work(queue, G_DELAYED_WORK(loadings[i]), gid);
+
+    }
 
     g_work_queue_wait_for_completion(queue, gid);
 
     gtk_status_stack_remove_activity(status, msg);
 
-    if (dynsym_sections != NULL) free(dynsym_sections);
-    if (symtab_sections != NULL) free(symtab_sections);
+    /* Vérifications du bon déroulement */
 
-    return result;
+    for (i = 0; i < runs_count; i++)
+    {
+        result &= g_elf_loading_get_status(loadings[i]);
 
-}
+        g_object_ref(G_OBJECT(loadings[i]));
 
+    }
 
+    free(loadings);
 
-/* ---------------------------------------------------------------------------------- */
-/*                            DETAIL DES SYMBOLES EXTERNES                            */
-/* ---------------------------------------------------------------------------------- */
+    if (!result)
+    {
+        free(*relocs);
+        goto ler_exit;
+    }
+
+    /* Tri de la liste obtenue */
+
+    int compare_relocations(const elf_rel *a, const elf_rel *b)
+    {
+        return sort_uint64_t(ELF_REL(format, *a, r_offset), ELF_REL(format, *b, r_offset));
+    }
+
+    qsort(*relocs, *count, sizeof(elf_rel), (__compar_fn_t)compare_relocations);
+
+ ler_exit:
+
+    return result;
+
+}
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format  = informations chargées à consulter.                 *
-*                dynamic = section de type SHT_DYNAMIC.                       *
-*                type    = sorte d'élément recherché.                         *
-*                item    = élément retrouvé dans la section. [OUT]            *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                status = barre de statut à tenir informée.                   *
 *                                                                             *
-*  Description : Retrouve un élément donné dans la section dynamique.         *
+*  Description : Actualise la désignation des fonctions externes à reloger.   *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -796,55 +1087,71 @@ static bool load_elf_internal_symbols(GElfFormat *format, wgroup_id_t gid, GtkSt
 *                                                                             *
 ******************************************************************************/
 
-static bool find_elf_dynamic_item(const GElfFormat *format, const elf_shdr *section, int32_t type, elf_dyn *item)
+bool refresh_elf_relocations(GElfFormat *format, GtkStatusStack *status)
 {
     bool result;                            /* Bilan à retourner           */
-    const GBinContent *content;             /* Contenu binaire à lire      */
-    phys_t pos;                             /* Position de lecture         */
-    vmpa2t tmp;                             /* Position écrasable          */
-    int32_t tag32;                          /* Type de l'entrée (32 bits)  */
-    int64_t tag64;                          /* Type de l'entrée (64 bits)  */
+    elf_phdr dynamic;                       /* En-tête de programme DYNAMIC*/
+    elf_rel *relocs;                        /* Relocalisations présentes   */
+    size_t rel_count;                       /* Qté de ces relocalisations  */
+    virt_t plt_virt;                        /* Adresse de la PLT           */
+    GExeFormat *exec;                       /* Autre vision du format      */
+    vmpa2t plt_addr;                        /* Localisation complète       */
+    GBinFormat *base;                       /* Autre vision du format      */
+    size_t first;                           /* Indice du premier symbole   */
+    sym_iter_t *iter;                       /* Boucle de parcours          */
 
     result = true;
 
-    content = G_BIN_FORMAT(format)->content;
+    if (!find_elf_dynamic_program_header(format, &dynamic))
+        goto rer_quick_exit;
 
-    for (pos = ELF_SHDR(format, *section, sh_offset);
-         result;
-         pos += ELF_SIZEOF_DYN(format))
-    {
-        init_vmpa(&tmp, pos, VMPA_NO_VIRTUAL);
+    /* Chargement des relocalisations */
 
-        if (format->is_32b)
-        {
-            result = g_binary_content_read_s32(content, &tmp, format->endian, &tag32);
-            if (tag32 == type) break;
-        }
-        else
-        {
-            result = g_binary_content_read_s64(content, &tmp, format->endian, &tag64);
-            if (tag64 == type) break;
-        }
+    if (!load_elf_relocations(format, &dynamic, &relocs, &rel_count, status))
+        goto rer_quick_exit;
 
-    }
+    /* Localisation du code de la PLT */
+
+    if (!resolve_plt_using_got(format, &plt_virt))
+        goto rer_exit;
+
+    exec = G_EXE_FORMAT(format);
+
+    if (!g_exe_format_translate_address_into_vmpa(exec, plt_virt, &plt_addr))
+        goto rer_exit;
+
+    /* Parcours des symboles */
+
+    base = G_BIN_FORMAT(format);
+
+    /**
+     * Il existe normalement un symbole "plt_entry" créé au chargement des symboles...
+     */
+
+    g_binary_format_lock_symbols_rd(base);
+
+    result = g_binary_format_find_symbol_index_at(base, &plt_addr, &first);
+
+    if (result)
+        iter = create_symbol_iterator(base, first);
+
+    g_binary_format_unlock_symbols_rd(base);
 
     if (result)
     {
-        init_vmpa(&tmp, pos, VMPA_NO_VIRTUAL);
+        result = apply_elf_relocations(format, relocs, rel_count, iter, status);
 
-        if (format->is_32b)
-        {
-            result = g_binary_content_read_s32(content, &tmp, format->endian, &item->dyn32.d_tag);
-            result &= g_binary_content_read_s32(content, &tmp, format->endian, &item->dyn32.d_un.d_val);
-        }
-        else
-        {
-            result = g_binary_content_read_s64(content, &tmp, format->endian, &item->dyn64.d_tag);
-            result &= g_binary_content_read_s64(content, &tmp, format->endian, &item->dyn64.d_un.d_val);
-        }
+        delete_symbol_iterator(iter);
 
     }
 
+ rer_exit:
+
+    if (relocs != NULL)
+        free(relocs);
+
+ rer_quick_exit:
+
     return result;
 
 }
@@ -852,52 +1159,171 @@ static bool find_elf_dynamic_item(const GElfFormat *format, const elf_shdr *sect
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format  = informations chargées à consulter.                 *
-*                dynamic = section de type SHT_DYNAMIC.                       *
+*  Paramètres  : loading = chargement de relocalisations en cours.            *
+*                format  = format ELF à compléter.                            *
+*                symbol  = symbole courant issu de la liste à analyser.       *
 *                                                                             *
-*  Description : Charge tous les éléments dynamiques externes possibles.      *
+*  Description : Assure l'intégration d'un symbole issu des relocalisations.  *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : Bilan de l'exécution, utile pour la poursuite du traitement. *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool load_elf_external_symbols(GElfFormat *format, const elf_shdr *section)
+static bool do_elf_relocation_renaming(GElfLoading *loading, GElfFormat *format, GBinSymbol *symbol)
 {
     bool result;                            /* Bilan à retourner           */
-    elf_dyn item;                           /* Elément dynamique           */
-    elf_shdr relxxx;                        /* Section .rel.xxx trouvée    */
-    elf_shdr dynsym;                        /* Section .dynsym trouvée     */
-    elf_shdr dynstr;                        /* Section .dynstr trouvée     */
+    const mrange_t *range;                  /* Espace occupé par le symbole*/
+    SymbolType stype;                       /* Type de symbole présenté    */
+    uint64_t offset;                        /* Décalage à retrouver        */
+    elf_rel *reloc;                         /* Infos de relocalisation     */
+    uint64_t index;                         /* Indice du symbole concerné  */
+    char *name;                             /* Nouvelle désignation        */
+#ifndef NDEBUG
+    const char *label;                      /* Etiquette courante          */
+#endif
 
-    result = true;
+    result = false;
+
+    range = g_binary_symbol_get_range(symbol);
+
+    stype = g_binary_symbol_get_target_type(symbol);
 
-    /* Section .rel.plt */
-    if (find_elf_dynamic_item(format, section, DT_JMPREL, &item))
+    if (stype != STP_ROUTINE && stype != STP_CODE_LABEL && stype != STP_ENTRY_POINT)
     {
-        result &= find_elf_section_by_virtual_address(format, ELF_DYN(format, item, d_un.d_ptr), &relxxx);
+        g_binary_format_add_error(G_BIN_FORMAT(format), BFE_SPECIFICATION, get_mrange_addr(range),
+                                  _("The PLT seems to contains more than routines"));
 
-        if (result)
-            result = find_elf_section_by_index(format, ELF_SHDR(format, relxxx, sh_link), &dynsym);
+        goto derr_exit;
 
-        if (result)
-            result = find_elf_section_by_index(format, ELF_SHDR(format, dynsym, sh_link), &dynstr);
+    }
 
-        if (result)
-            switch (ELF_HDR(format, format->header, e_machine))
-            {
-                case EM_ARM:
-                    result = load_elf_arm_relocated_symbols(format, &relxxx, &dynsym, &dynstr);
-                    break;
+    /* Assurance du port du type adapté */
 
-                default:
-                    break;
+    g_binary_symbol_set_status(symbol, SSS_IMPORTED);
 
-            }
+    /* Détermination de la relocalisation associée */
+
+    if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
+        result = retrieve_arm_linkage_offset(format, range, &offset);
+    else
+        result = false;
 
+    if (!result) goto derr_exit;
+
+    result = g_elf_loading_search_for_relocation(loading, &offset, &reloc);
+    if (!result) goto derr_exit;
+
+    /* Récupération des données du symbole visé */
+
+    index = ELF_REL_SYM(format, *reloc);
+
+    name = g_elf_loading_build_plt_name(loading, index);
+
+#ifndef NDEBUG
+
+    label = g_binary_symbol_get_label(symbol);
+
+    if (strncmp(label, "sub_", 4) != 0 && strncmp(label, "loc_", 4) != 0)
+    {
+        if (strncmp(name, label, strlen(label)) != 0)
+            g_binary_format_add_error(G_BIN_FORMAT(format), BFE_SPECIFICATION, get_mrange_addr(range),
+                                      _("Mismatch detected in the ELF symbol address"));
     }
 
+#endif
+
+    g_binary_symbol_set_alt_label(symbol, name);
+
+    free(name);
+
+ derr_exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format    = format ELF à compléter.                          *
+*                relocs    = table des relocalisations chargées.              *
+*                rel_count = nombre de ces éléments à interpréter.            *
+*                iter      = itérateur sur les symboles à parcourir.          *
+*                status    = barre de statut à tenir informée.                *
+*                                                                             *
+*  Description : Applique les étiquettes issues des relocalisations.          *
+*                                                                             *
+*  Retour      : Bilan des traitements.                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool apply_elf_relocations(GElfFormat *format, elf_rel *relocs, size_t rel_count, sym_iter_t *iter, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à retourner           */
+    GExeFormat *exec;                       /* Autre vision du format      */
+    elf_dyn strtab;                         /* Table de type DT_STRTAB     */
+    phys_t str_start;                       /* Début de zone des chaînes   */
+    elf_dyn symtab;                         /* Table de type DT_SYMTAB     */
+    phys_t sym_start;                       /* Début de zone des symboles  */
+    uint32_t sym_count;                     /* Nombre de symboles présents */
+    activity_id_t msg;                      /* Message de progression      */
+    GWorkQueue *queue;                      /* Gestionnaire de différés    */
+    wgroup_id_t gid;                        /* Identifiant pour les tâches */
+    GElfLoading *loading;                   /* Tâche de chargement         */
+
+    exec = G_EXE_FORMAT(format);
+
+    /* Récupération du début des chaînes de description */
+
+    result = find_elf_dynamic_item(format, DT_STRTAB, &strtab);
+    if (!result) goto aer_exit;
+
+    result = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, strtab, d_un.d_ptr), &str_start);
+    if (!result) goto aer_exit;
+
+    /* Récupération du début des définitions de symboles */
+
+    result = find_elf_dynamic_item(format, DT_SYMTAB, &symtab);
+    if (!result) goto aer_exit;
+
+    result = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, symtab, d_un.d_ptr), &sym_start);
+    if (!result) goto aer_exit;
+
+    /* Détermination du nombre d'éléments */
+
+    result = count_elf_global_symbols(format, exec, &sym_count);
+    if (!result) goto aer_exit;
+
+    /* Mise en application des références externes */
+
+    msg = gtk_status_stack_add_activity(status, _("Applying relocations..."), rel_count);
+
+    queue = get_work_queue();
+    gid = g_work_queue_define_work_group(queue);
+
+    loading = g_elf_loading_new_for_applying(format, iter, str_start, relocs, rel_count,
+                                             sym_start, sym_count, msg, do_elf_relocation_renaming);
+
+    g_object_ref(G_OBJECT(loading));
+
+    g_work_queue_schedule_work(queue, G_DELAYED_WORK(loading), gid);
+
+    g_work_queue_wait_for_completion(queue, gid);
+
+    gtk_status_stack_remove_activity(status, msg);
+
+    /* Vérification du bon déroulement */
+
+    result = g_elf_loading_get_status(loading);
+
+    g_object_unref(G_OBJECT(loading));
+
+ aer_exit:
+
     return result;
 
 }
diff --git a/plugins/elf/symbols.h b/plugins/elf/symbols.h
index c5e150b..9e987eb 100644
--- a/plugins/elf/symbols.h
+++ b/plugins/elf/symbols.h
@@ -28,25 +28,25 @@
 #include "format.h"
 
 
+#include <arch/processor.h>
 #include <glibext/delayed.h>
 #include <gtkext/gtkstatusstack.h>
 
 
 
+/* ------------------------- CHARGEMENT GLOBAL DES SYMBOLES ------------------------- */
+
+
 /* Charge en mémoire la liste humaine des symboles. */
 bool load_elf_symbols(GElfFormat *, GtkStatusStack *);
 
-/* Récupère la définition complète d'un symbole donné. */
-bool get_elf_symbol_by_index(GElfFormat *, const elf_shdr *, off_t, elf_sym *);
 
-/* Récupère la désignation d'un symbole donné. */
-const char *get_elf_symbol_name(GElfFormat *, const elf_shdr *, const elf_shdr *, off_t);
 
-/* Récupère la définition complète d'un symbole donné. */
-bool get_elf_symbol_by_index(GElfFormat *, const elf_shdr *, off_t, elf_sym *);
+/* ----------------------- PRISE EN COMPTE DE RELOCALISATIONS ----------------------- */
+
 
-/* Récupère la désignation d'un symbole donné. */
-const char *get_elf_symbol_name(GElfFormat *, const elf_shdr *, const elf_shdr *, off_t);
+/* Actualise la désignation des fonctions externes à reloger. */
+bool refresh_elf_relocations(GElfFormat *, GtkStatusStack *);
 
 
 
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index f38cf66..1a93470 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -1694,7 +1694,7 @@ bool *g_loaded_binary_display_decomp_lines(GLoadedBinary *binary)
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
-
+#include "../gui/core/global.h"
 void ack_completed_disassembly(GDelayedDisassembly *disass, GLoadedBinary *binary)
 {
     //GRenderingLine *line;                   /* "Première" ligne de rendu   */
@@ -1706,7 +1706,7 @@ void ack_completed_disassembly(GDelayedDisassembly *disass, GLoadedBinary *binar
 
 
 
-
+    g_binary_format_complete_analysis(G_BIN_FORMAT(binary->format), get_global_status());
 
 
 
diff --git a/src/common/sort.c b/src/common/sort.c
index 014d6c7..5cf3132 100644
--- a/src/common/sort.c
+++ b/src/common/sort.c
@@ -94,6 +94,37 @@ int sort_unsigned_long(unsigned long a, unsigned long b)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : a = premier élément à consulter et comparer.                 *
+*                b = second élément à consulter et comparer.                  *
+*                                                                             *
+*  Description : Compare une valeur de 64 bits avec une autre.                *
+*                                                                             *
+*  Retour      : Bilan de la comparaison.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int sort_uint64_t(uint64_t a, uint64_t b)
+{
+    int result;                             /* Bilan à renvoyer            */
+
+    if (a < b)
+        result = -1;
+
+    else if (a > b)
+        result = 1;
+
+    else
+        result = 0;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : a      = premier élément à consulter et comparer.            *
 *                b      = second élément à consulter et comparer.             *
 *                compar = méthode de comparaison entre éléments.              *
diff --git a/src/common/sort.h b/src/common/sort.h
index a887543..4ec5214 100644
--- a/src/common/sort.h
+++ b/src/common/sort.h
@@ -26,6 +26,7 @@
 
 
 #include <stdbool.h>
+#include <stdint.h>
 #include <stdlib.h>
 
 
@@ -36,6 +37,9 @@ int sort_boolean(bool, bool);
 /* Compare une valeur avec une autre. */
 int sort_unsigned_long(unsigned long, unsigned long);
 
+/* Compare une valeur de 64 bits avec une autre. */
+int sort_uint64_t(uint64_t, uint64_t);
+
 /* Compare un pointeur avec un autre. */
 int sort_pointer(const void *, const void *, __compar_fn_t);
 
diff --git a/src/format/format-int.h b/src/format/format-int.h
index f377ca3..5c1ae07 100644
--- a/src/format/format-int.h
+++ b/src/format/format-int.h
@@ -39,6 +39,9 @@
 /* Indique le boutisme employé par le format binaire analysé. */
 typedef SourceEndian (* format_get_endian_fc) (const GBinFormat *);
 
+/* Réalise un traitement post-désassemblage. */
+typedef void (* format_complete_analysis_fc) (GBinFormat *, GtkStatusStack *);
+
 /* Procède à la décompilation complète du format. */
 typedef void (* format_decompile_fc) (const GBinFormat *, void/*GCodeBuffer*/ *, const char *);
 
@@ -105,6 +108,8 @@ struct _GBinFormatClass
 
     format_get_endian_fc get_endian;        /* Boutisme employé            */
 
+    format_complete_analysis_fc complete;   /* Terminaison d'analyse       */
+
 };
 
 
diff --git a/src/format/format.c b/src/format/format.c
index 5b96b59..88367f6 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -64,6 +64,9 @@ static void g_binary_format_delete_duplicated_symbols(GBinFormat *);
 /* Recherche le symbole associé à une adresse. */
 static bool _g_binary_format_find_symbol(const GBinFormat *, const vmpa2t *, __compar_fn_t, size_t *, GBinSymbol **);
 
+/* Recherche un symbole particulier. */
+static bool __g_binary_format_find_symbol(const GBinFormat *, const void *, __compar_fn_t, size_t *, GBinSymbol **);
+
 
 
 /* Indique le type défini pour un format binaire générique. */
@@ -369,6 +372,31 @@ void g_binary_format_activate_disassembling_context(GBinFormat *format, GProcCon
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à manipuler.            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Réalise un traitement post-désassemblage.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_binary_format_complete_analysis(GBinFormat *format, GtkStatusStack *status)
+{
+    GBinFormatClass *class;                 /* Classe de l'instance        */
+
+    class = G_BIN_FORMAT_GET_CLASS(format);
+
+    if (class->complete != NULL)
+        class->complete(format, status);
+
+}
+
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                        RASSEMBLEMENT ET GESTION DE SYMBOLES                        */
@@ -450,6 +478,26 @@ void g_binary_format_lock_unlock_symbols_wr(GBinFormat *format, bool state)
 *                                                                             *
 *  Paramètres  : format = architecture à consulter via la procédure.          *
 *                                                                             *
+*  Description : Assure qu'un verrou est bien posé pour l'accès aux symboles. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+#ifndef NDEBUG
+void g_binary_format_check_for_symbols_lock(const GBinFormat *format)
+{
+    assert(g_atomic_int_get(&format->sym_locked) > 0);
+
+}
+#endif
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = architecture à consulter via la procédure.          *
+*                                                                             *
 *  Description : Fournit la marque de dernière modification des symboles.     *
 *                                                                             *
 *  Retour      : Marque de la dernière modification de la liste de symboles.  *
@@ -882,11 +930,6 @@ bool g_binary_format_find_symbol_by_label(GBinFormat *format, const char *label,
 
 static bool _g_binary_format_find_symbol(const GBinFormat *format, const vmpa2t *addr, __compar_fn_t fn, size_t *index, GBinSymbol **symbol)
 {
-    bool result;                            /* Bilan à retourner           */
-    void *found;                            /* Résultat de recherches      */
-
-    assert(g_atomic_int_get(&format->sym_locked) > 0);
-
     /**
      * Pour ce qui est des justifications quant à la vérification suivante,
      * se référer aux commentaires placés dans g_binary_format_add_symbol().
@@ -894,7 +937,35 @@ static bool _g_binary_format_find_symbol(const GBinFormat *format, const vmpa2t
 
     assert(has_phys_addr(addr));
 
-    found = bsearch(addr, format->symbols, format->sym_count, sizeof(GBinSymbol *), fn);
+    return __g_binary_format_find_symbol(format, addr, fn, index, symbol);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                key    = clef fournie pour distinguer les éléments.          *
+*                fn     = méthode de comparaison des symboles.                *
+*                index  = indice de l'éventuel symbole trouvé ou NULL. [OUT]  *
+*                symbol = éventuel symbole trouvé à déréfenrencer. [OUT]      *
+*                                                                             *
+*  Description : Recherche un symbole particulier.                            *
+*                                                                             *
+*  Retour      : true si l'opération a été un succès, false sinon.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool __g_binary_format_find_symbol(const GBinFormat *format, const void *key, __compar_fn_t fn, size_t *index, GBinSymbol **symbol)
+{
+    bool result;                            /* Bilan à retourner           */
+    void *found;                            /* Résultat de recherches      */
+
+    assert(g_atomic_int_get(&format->sym_locked) > 0);
+
+    found = bsearch(key, format->symbols, format->sym_count, sizeof(GBinSymbol *), fn);
 
     if (found != NULL)
     {
@@ -913,8 +984,11 @@ static bool _g_binary_format_find_symbol(const GBinFormat *format, const vmpa2t
 
     else
     {
-        *symbol = NULL;
+        if (symbol != NULL)
+            *symbol = NULL;
+
         result = false;
+
     }
 
     return result;
@@ -926,6 +1000,45 @@ static bool _g_binary_format_find_symbol(const GBinFormat *format, const vmpa2t
 *                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
 *                addr   = adresse à cibler lors des recherches.               *
+*                index  = indice de l'éventuel symbole trouvé. [OUT]          *
+*                                                                             *
+*  Description : Recherche l'indice du symbole correspondant à une adresse.   *
+*                                                                             *
+*  Retour      : true si l'opération a été un succès, false sinon.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_binary_format_find_symbol_index_at(GBinFormat *format, const vmpa2t *addr, size_t *index)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    int find_symbol(const vmpa2t *addr, const GBinSymbol **sym)
+    {
+        const mrange_t *range;              /* Espace mémoire parcouru     */
+
+        range = g_binary_symbol_get_range(*sym);
+
+        return cmp_vmpa(addr, get_mrange_addr(range));
+
+    }
+
+    g_binary_format_lock_symbols_rd(format);
+
+    result = _g_binary_format_find_symbol(format, addr, (__compar_fn_t)find_symbol, index, NULL);
+
+    g_binary_format_unlock_symbols_rd(format);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                addr   = adresse à cibler lors des recherches.               *
 *                symbol = éventuel symbole trouvé à déréfenrencer. [OUT]      *
 *                                                                             *
 *  Description : Recherche le symbole correspondant à une adresse.            *
@@ -1056,6 +1169,68 @@ bool g_binary_format_find_next_symbol_at(GBinFormat *format, const vmpa2t *addr,
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
+*                range  = zone à cibler lors des recherches.                  *
+*                index  = indice de l'éventuel symbole trouvé. [OUT]          *
+*                                                                             *
+*  Description : Recherche le premier symbole inclus dans une zone mémoire.   *
+*                                                                             *
+*  Retour      : true si l'opération a été un succès, false sinon.            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_binary_format_find_first_symbol_inside(GBinFormat *format, const mrange_t *range, size_t *index)
+{
+    bool result;                            /* Bilan à retourner           */
+    const GBinSymbol *prev;                 /* Symbole précédent           */
+    const mrange_t *srange;                 /* Espace mémoire associé      */
+    int ret;                                /* Bilan de comparaison        */
+
+    int find_symbol(const mrange_t *ref_range, const GBinSymbol **sym)
+    {
+        const mrange_t *sym_range;          /* Espace mémoire parcouru     */
+
+        int ret;
+
+        sym_range = g_binary_symbol_get_range(*sym);
+
+        ret = cmp_mrange_with_vmpa(ref_range, get_mrange_addr(sym_range));
+
+        ret *= -1;
+
+        return ret;
+
+    }
+
+    g_rw_lock_reader_lock(&format->syms_lock);
+
+    result = __g_binary_format_find_symbol(format, range, (__compar_fn_t)find_symbol, index, NULL);
+
+    if (result)
+        while (*index > 0)
+        {
+            prev = format->symbols[*index - 1];
+            srange = g_binary_symbol_get_range(prev);
+
+            ret = cmp_mrange_with_vmpa(range, get_mrange_addr(srange));
+            assert(ret <= 0);
+
+            if (ret < 0) break;
+            else (*index)--;
+
+        }
+
+    g_rw_lock_reader_unlock(&format->syms_lock);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
 *                addr   = adresse à cibler lors des recherches.               *
 *                strict = indication de tolérance acceptée.                   *
 *                symbol = éventuel symbole trouvé à déréfenrencer. [OUT]      *
diff --git a/src/format/format.h b/src/format/format.h
index 9a3a6e3..4052482 100644
--- a/src/format/format.h
+++ b/src/format/format.h
@@ -70,6 +70,9 @@ void g_binary_format_preload_disassembling_context(GBinFormat *, GProcContext *,
 /* Définit les points de départ d'un contexte de désassemblage. */
 void g_binary_format_activate_disassembling_context(GBinFormat *, GProcContext *, GtkStatusStack *);
 
+/* Réalise un traitement post-désassemblage. */
+void g_binary_format_complete_analysis(GBinFormat *, GtkStatusStack *);
+
 
 
 /* ---------------------- RASSEMBLEMENT ET GESTION DE SYMBOLES ---------------------- */
@@ -87,6 +90,11 @@ void g_binary_format_lock_unlock_symbols_wr(GBinFormat *, bool);
 #define g_binary_format_lock_symbols_wr(f) g_binary_format_lock_unlock_symbols_wr(f, true)
 #define g_binary_format_unlock_symbols_wr(f) g_binary_format_lock_unlock_symbols_wr(f, false)
 
+/* Assure qu'un verrou est bien posé pour l'accès aux symboles. */
+#ifndef NDEBUG
+void g_binary_format_check_for_symbols_lock(const GBinFormat *);
+#endif
+
 /* Fournit la marque de dernière modification des symboles. */
 unsigned int g_binary_format_get_symbols_stamp(const GBinFormat *);
 
@@ -108,6 +116,9 @@ char *create_string_label(GBinFormat *, const vmpa2t *, size_t);
 /* Recherche le symbole correspondant à une étiquette. */
 bool g_binary_format_find_symbol_by_label(GBinFormat *, const char *, GBinSymbol **);
 
+/* Recherche l'indice du symbole correspondant à une adresse. */
+bool g_binary_format_find_symbol_index_at(GBinFormat *, const vmpa2t *, size_t *);
+
 /* Recherche le symbole correspondant à une adresse. */
 bool g_binary_format_find_symbol_at(GBinFormat *, const vmpa2t *, GBinSymbol **);
 
@@ -117,6 +128,9 @@ bool g_binary_format_find_symbol_for(GBinFormat *, const vmpa2t *, GBinSymbol **
 /* Recherche le symbole suivant celui lié à une adresse. */
 bool g_binary_format_find_next_symbol_at(GBinFormat *, const vmpa2t *, GBinSymbol **);
 
+/* Recherche le premier symbole inclus dans une zone mémoire. */
+bool g_binary_format_find_first_symbol_inside(GBinFormat *, const mrange_t *, size_t *);
+
 /* Recherche le symbole correspondant à une adresse. */
 bool g_binary_format_resolve_symbol(GBinFormat *, const vmpa2t *, bool, GBinSymbol **, phys_t *);
 
diff --git a/src/format/symiter.c b/src/format/symiter.c
index 74b4abb..230b4ac 100644
--- a/src/format/symiter.c
+++ b/src/format/symiter.c
@@ -63,6 +63,11 @@ sym_iter_t *create_symbol_iterator(GBinFormat *format, size_t index)
 {
     sym_iter_t *result;                     /* Structure à retourner       */
 
+#ifndef NDEBUG
+    if (index > 0)
+        g_binary_format_check_for_symbols_lock(format);
+#endif
+
     result = (sym_iter_t *)malloc(sizeof(sym_iter_t));
 
     g_object_ref(G_OBJECT(format));
-- 
cgit v0.11.2-87-g4458