From 04b1ee00d25383f977f59703e4c0bc66ad1faa81 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 15 Feb 2020 14:22:10 +0100
Subject: Identified Elf imported symbols without waiting for the end of
 disassembling.

---
 plugins/elf/elf-int.h    |   6 +-
 plugins/elf/format.c     |  35 +----
 plugins/elf/helper_arm.c |  66 +++++++--
 plugins/elf/helper_arm.h |   7 +-
 plugins/elf/loading.c    | 120 +++++++++++------
 plugins/elf/loading.h    |  11 +-
 plugins/elf/symbols.c    | 340 +++++++++++++++++++++--------------------------
 plugins/elf/symbols.h    |   8 --
 src/format/format.c      |   9 +-
 9 files changed, 311 insertions(+), 291 deletions(-)

diff --git a/plugins/elf/elf-int.h b/plugins/elf/elf-int.h
index 461c5af..6a90dfe 100644
--- a/plugins/elf/elf-int.h
+++ b/plugins/elf/elf-int.h
@@ -40,8 +40,11 @@ typedef const char * (* get_elf_prgm_type_desc_cb) (uint32_t);
 /* Fournit une adresse virtuelle prête à emploi. */
 typedef virt_t (* fix_elf_virt_addr_cb) (virt_t);
 
+/* Détermine l'emplacement de la première entrée dans la PLT. */
+typedef bool (* find_first_plt_entry_cb) (GElfFormat *, vmpa2t *);
+
 /* Retrouve le décalage appliqué lors d'une résolution. */
-typedef bool (* get_elf_linkage_offset_cb) (GElfFormat *, const mrange_t *, uint64_t *);
+typedef bool (* get_elf_linkage_offset_cb) (GElfFormat *, vmpa2t *, uint64_t *);
 
 
 
@@ -50,6 +53,7 @@ typedef struct _elf_arch_ops
 {
     get_elf_prgm_type_desc_cb get_type_desc;/* Description de type         */
     fix_elf_virt_addr_cb fix_virt;          /* Retire toute forme d'infos  */
+    find_first_plt_entry_cb find_first_plt; /* Recherche d'entrée de PLT   */
     get_elf_linkage_offset_cb get_linkage_offset; /* Décalage de relocation*/
 
 } elf_arch_ops;
diff --git a/plugins/elf/format.c b/plugins/elf/format.c
index c5f5530..d102ad8 100644
--- a/plugins/elf/format.c
+++ b/plugins/elf/format.c
@@ -74,9 +74,6 @@ static bool g_elf_format_analyze(GElfFormat *, wgroup_id_t, GtkStatusStack *);
 /* 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 *, wgroup_id_t, GtkStatusStack *);
-
 /* Indique le type d'architecture visée par le format. */
 static const char *g_elf_format_get_target_machine(const GElfFormat *);
 
@@ -155,8 +152,6 @@ static void g_elf_format_class_init(GElfFormatClass *klass)
     fmt->analyze = (format_analyze_fc)g_elf_format_analyze;
     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;
@@ -372,6 +367,7 @@ static bool g_elf_format_analyze(GElfFormat *format, wgroup_id_t gid, GtkStatusS
         case EM_ARM:
             format->ops.get_type_desc = (get_elf_prgm_type_desc_cb)get_elf_program_arm_type_desc;
             format->ops.fix_virt = (fix_elf_virt_addr_cb)fix_elf_arm_virtual_address;
+            format->ops.find_first_plt = (find_first_plt_entry_cb)find_first_plt_entry;
             format->ops.get_linkage_offset = (get_elf_linkage_offset_cb)retrieve_arm_linkage_offset;
             break;
 
@@ -436,35 +432,6 @@ static SourceEndian g_elf_format_get_endianness(const GElfFormat *format)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = description de l'exécutable à manipuler.            *
-*                gid    = groupe de travail dédié.                            *
-*                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, wgroup_id_t gid, GtkStatusStack *status)
-{
-    /**
-     * C'est la phase de désassemblage qui produit les symboles externes appelés
-     * au sein du code.
-     *
-     * Le renommage de ces symboles doit donc intervenir une fois les symboles
-     * en place, donc après les opérations de désassemblage terminées.
-     */
-
-    refresh_elf_relocations(format, gid, 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 3632f54..cc0a233 100644
--- a/plugins/elf/helper_arm.c
+++ b/plugins/elf/helper_arm.c
@@ -87,10 +87,9 @@ virt_t fix_elf_arm_virtual_address(virt_t virt)
 /******************************************************************************
 *                                                                             *
 *  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]        *
+*                addr   = position de la PLT à faire évoluer. [OUT]           *
 *                                                                             *
-*  Description : Retrouve le décalage appliqué lors d'une résolution.         *
+*  Description : Détermine l'emplacement de la première entrée dans la PLT.   *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -98,12 +97,61 @@ virt_t fix_elf_arm_virtual_address(virt_t virt)
 *                                                                             *
 ******************************************************************************/
 
-bool retrieve_arm_linkage_offset(GElfFormat *format, const mrange_t *range, uint64_t *offset)
+bool find_first_plt_entry(GElfFormat *format, vmpa2t *addr)
 {
     bool result;                            /* Bilan à retourner           */
     GBinContent *content;                   /* Contenu binaire à parcourir */
     vmpa2t pos;                             /* Tete de lecture             */
     uint32_t raw;                           /* Valeur brute lue            */
+    bool status;                            /* Bilan d'une lecture         */
+
+    result = false;
+
+    content = G_BIN_FORMAT(format)->content;
+
+    while (!result)
+    {
+        copy_vmpa(&pos, addr);
+
+        status = g_binary_content_read_u32(content, &pos, format->endian, &raw);
+        if (!status) break;
+
+        /**
+         * Analyse à mettre en relation avec la fonction retrieve_arm_linkage_offset().
+         */
+
+        if ((raw & 0xfffff000) == 0xe28fc000)
+            result = true;
+
+        else
+            copy_vmpa(addr, &pos);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à manipuler.            *
+*                addr   = position de la PLT à faire évoluer. [OUT]           *
+*                offset = décalage retrouvé par désassemblage. [OUT]          *
+*                                                                             *
+*  Description : Retrouve le décalage appliqué lors d'une résolution.         *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool retrieve_arm_linkage_offset(GElfFormat *format, vmpa2t *addr, uint64_t *offset)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinContent *content;                   /* Contenu binaire à parcourir */
+    uint32_t raw;                           /* Valeur brute lue            */
     uint32_t shift;                         /* Décalage arithmétique       */
 
     /**
@@ -115,9 +163,7 @@ bool retrieve_arm_linkage_offset(GElfFormat *format, const mrange_t *range, uint
 
     content = G_BIN_FORMAT(format)->content;
 
-    copy_vmpa(&pos, get_mrange_addr(range));
-
-    result = g_binary_content_read_u32(content, &pos, format->endian, &raw);
+    result = g_binary_content_read_u32(content, addr, format->endian, &raw);
     if (!result) goto exit;
 
     /**
@@ -142,7 +188,7 @@ bool retrieve_arm_linkage_offset(GElfFormat *format, const mrange_t *range, uint
 
     if ((raw & 0xfffff000) == 0xe28fc000)
     {
-        *offset = get_virt_addr(get_mrange_addr(range)) + 8;
+        *offset = get_virt_addr(addr) + 4;
 
         /**
          * Les deux premières instructions répondent à l'encodage spécifié dans :
@@ -187,7 +233,7 @@ bool retrieve_arm_linkage_offset(GElfFormat *format, const mrange_t *range, uint
          * Seconde instruction...
          */
 
-        result = g_binary_content_read_u32(content, &pos, format->endian, &raw);
+        result = g_binary_content_read_u32(content, addr, format->endian, &raw);
         if (!result) goto exit;
 
         if ((raw & 0xfffff000) != 0xe28cc000)
@@ -222,7 +268,7 @@ bool retrieve_arm_linkage_offset(GElfFormat *format, const mrange_t *range, uint
          *
          */
 
-        result = g_binary_content_read_u32(content, &pos, format->endian, &raw);
+        result = g_binary_content_read_u32(content, addr, format->endian, &raw);
         if (!result) goto exit;
 
         if ((raw & 0xfffff000) != 0xe5bcf000)
diff --git a/plugins/elf/helper_arm.h b/plugins/elf/helper_arm.h
index d8c9ca3..88d75bf 100644
--- a/plugins/elf/helper_arm.h
+++ b/plugins/elf/helper_arm.h
@@ -25,7 +25,7 @@
 #define _PLUGINS_ELF_HELPER_ARM_H
 
 
-#include "section.h"
+#include "format.h"
 
 
 
@@ -35,8 +35,11 @@ const char *get_elf_program_arm_type_desc(uint32_t);
 /* Fournit une adresse virtuelle prête à emploi. */
 virt_t fix_elf_arm_virtual_address(virt_t);
 
+/* Détermine l'emplacement de la première entrée dans la PLT. */
+bool find_first_plt_entry(GElfFormat *, vmpa2t *);
+
 /* Retrouve le décalage appliqué lors d'une résolution. */
-bool retrieve_arm_linkage_offset(GElfFormat *, const mrange_t *, uint64_t *);
+bool retrieve_arm_linkage_offset(GElfFormat *, vmpa2t *, uint64_t *);
 
 
 
diff --git a/plugins/elf/loading.c b/plugins/elf/loading.c
index 5bd7daa..bf79f13 100644
--- a/plugins/elf/loading.c
+++ b/plugins/elf/loading.c
@@ -75,6 +75,8 @@ struct _GElfLoading
             phys_t sym_start;               /* Début de zone des symboles  */
             uint32_t sym_count;             /* Nombre de symboles présents */
 
+            GBinSymbol **imports_to_fill;   /* Liste de symboles constitués*/
+
         };
 
         struct
@@ -107,9 +109,9 @@ struct _GElfLoading
 
         struct
         {
-            sym_iter_t *iter;               /* Symboles à parcourir        */
+            vmpa2t start;                   /* Point de départ du parcours */
 
-            elf_applying_cb callback_1;     /* Routine de traitement #1    */
+            elf_importing_cb callback_1;    /* Routine de traitement #1    */
 
         };
 
@@ -213,7 +215,13 @@ static void g_elf_loading_init(GElfLoading *loading)
 
 static void g_elf_loading_dispose(GElfLoading *loading)
 {
-    if (loading->kind == 2)
+    size_t i;                               /* Boucle de parcours          */
+
+    if (loading->kind == 1)
+        for (i = 0; i < loading->rel_count; i++)
+            g_clear_object(&loading->imports_to_fill[i]);
+
+    else if (loading->kind == 2)
         g_clear_object(&loading->content);
 
     G_OBJECT_CLASS(g_elf_loading_parent_class)->dispose(G_OBJECT(loading));
@@ -336,7 +344,7 @@ GElfLoading *g_elf_loading_new_for_relocations(GElfFormat *format, phys_t begin,
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format    = ensemble d'instructions désassemblées.           *
-*                iter      = itérateur sur les symboles à parcourir.          *
+*                start     = point de départ du parcours de la PLT.           *
 *                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.            *
@@ -353,7 +361,7 @@ GElfLoading *g_elf_loading_new_for_relocations(GElfFormat *format, phys_t begin,
 *                                                                             *
 ******************************************************************************/
 
-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 *g_elf_loading_new_for_imported(GElfFormat *format, const vmpa2t *start, phys_t str_start, elf_rel *relocs, size_t rel_count, phys_t sym_start, uint32_t sym_count, activity_id_t id, elf_importing_cb callback)
 {
     GElfLoading *result;                    /* Tâche à retourner           */
 
@@ -368,7 +376,9 @@ GElfLoading *g_elf_loading_new_for_applying(GElfFormat *format, sym_iter_t *iter
     result->sym_start = sym_start;
     result->sym_count = sym_count;
 
-    result->iter = iter;
+    result->imports_to_fill = calloc(rel_count, sizeof(GBinSymbol *));
+
+    copy_vmpa(&result->start, start);
     result->callback_1 = callback;
 
     result->kind = 1;
@@ -454,11 +464,10 @@ GElfLoading *g_elf_loading_new_for_strings(GElfFormat *format, phys_t begin, phy
 static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status)
 {
     GElfFormat *format;                     /* Format plus accessible      */
-    phys_t iter;                            /* Boucle de parcours          */
+    phys_t iter;                            /* Boucle de parcours #1       */
     phys_t old;                             /* Sauvegarde du point d'avant */
     bool ret;                               /* Bilan d'un appel            */
-    size_t processed;                       /* Nombre de symboles traités  */
-    virt_t valid;                           /* Adresse virtuelle valide    */
+    size_t i;                               /* Boucle de parcours #2       */
     GBinSymbol *symbol;                     /* Symbole analysé             */
 
     format = loading->format;
@@ -487,35 +496,23 @@ static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status)
 
         case 1:
 
-            ret = true;
-
-            processed = 0;
-            valid = 0;
-
-            for (symbol = get_symbol_iterator_next(loading->iter);
-                 symbol != NULL && ret;
-                 symbol = get_symbol_iterator_next(loading->iter))
+            for (i = 0; i < loading->rel_count; i++)
             {
-                ret = loading->callback_1(loading, format, &valid, symbol);
-
-                g_object_unref(G_OBJECT(symbol));
+                symbol = loading->callback_1(loading, format, &loading->start);
 
-                if (!ret)
+                if (symbol == NULL)
                 {
-                    log_variadic_message(LMT_ERROR, _("Error while applying ELF relocation %zu!"), processed);
+                    log_variadic_message(LMT_ERROR, _("Error while applying ELF relocation %zu!"), i);
                     break;
                 }
 
-                processed++;
+                loading->imports_to_fill[i] = symbol;
 
                 gtk_status_stack_update_activity_value(status, loading->id, 1);
 
-                if (processed == loading->rel_count)
-                    break;
-
             }
 
-            loading->status = (processed == loading->rel_count);
+            loading->status = (i == loading->rel_count);
             break;
 
         case 2:
@@ -702,25 +699,28 @@ bool g_elf_loading_search_for_relocation(const GElfLoading *loading, const uint6
 *  Paramètres  : loading = chargement pour ELF à poursuivre.                  *
 *                index   = indice du symbole concerné.                        *
 *                                                                             *
-*  Description : Construit la désignation adaptée à un symbole importé.       *
+*  Description : Construit le symbole adapté à un symbole importé.            *
 *                                                                             *
-*  Retour      : Nouvelle étiquette constituée ou NULL en cas d'échec.        *
+*  Retour      : Nouveau symbole constitué ou NULL en cas d'échec.            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-char *g_elf_loading_build_plt_name(const GElfLoading *loading, uint64_t index)
+GBinSymbol *g_elf_loading_build_plt_symbol(const GElfLoading *loading, uint64_t index)
 {
-    char *result;                           /* Désignation à retourner     */
+    GBinSymbol *result;                     /* Symbole à 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         */
+    GBinFormat *base;                       /* Autre version du format     */
     const GBinContent *content;             /* Contenu binaire à lire      */
-    const char *prefix;                     /* Première partie de nom      */
+    const char *raw_label;                  /* Première partie de nom      */
+    GBinRoutine *routine;                   /* Routine à mettre en place   */
+    char *new_label;                        /* Nouvelle étiquette          */
 
     format = loading->format;
 
@@ -739,17 +739,27 @@ char *g_elf_loading_build_plt_name(const GElfLoading *loading, uint64_t index)
 
         init_vmpa(&pos, offset, VMPA_NO_VIRTUAL);
 
-        content = G_BIN_FORMAT(format)->content;
+        base = G_BIN_FORMAT(format);
+        content = base->content;
 
-        prefix = (const char *)g_binary_content_get_raw_access(content, &pos, 1);
+        raw_label = (const char *)g_binary_content_get_raw_access(content, &pos, 1);
 
-        if (prefix != NULL && prefix[0] == '\0')
+        if (raw_label != NULL && raw_label[0] == '\0')
             result = NULL;
 
         else
         {
-            result = strdup(prefix);
-            result = stradd(result, "@plt");
+            routine = g_binary_format_decode_routine(base, raw_label);
+
+            raw_label = g_binary_routine_get_name(routine);
+
+            new_label = strdup(raw_label);
+            new_label = stradd(new_label, "@plt");
+
+            g_binary_routine_set_name(routine, new_label);
+
+            result = G_BIN_SYMBOL(routine);
+
         }
 
     }
@@ -761,6 +771,42 @@ char *g_elf_loading_build_plt_name(const GElfLoading *loading, uint64_t index)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : loading = chargement pour ELF à poursuivre.                  *
+*                count   = taille de la liste retournée. [OUT]                *
+*                                                                             *
+*  Description : Fournit la liste de symboles importés constituée.            *
+*                                                                             *
+*  Retour      : Liste des symboles importés ou NULL en cas d'échec.          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GBinSymbol **g_elf_loading_get_imported_symbols(const GElfLoading *loading, size_t *count)
+{
+    GBinSymbol **result;                    /* Liste à retourner           */
+    size_t i;                               /* Boucle de parcours          */
+
+    *count = loading->rel_count;
+
+    result = malloc(*count * sizeof(GBinSymbol *));
+
+    for (i = 0; i < *count; i++)
+    {
+        result[i] = loading->imports_to_fill[i];
+        assert(result[i] != NULL);
+
+        g_object_ref(G_OBJECT(result[i]));
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : loading = chargement pour ELF à mener.                       *
 *                content = gestionnaire de contenu utilisé. [OUT]             *
 *                first   = première position traitée par la tâche. [OUT]      *
diff --git a/plugins/elf/loading.h b/plugins/elf/loading.h
index 8fb4ce9..e3016d4 100644
--- a/plugins/elf/loading.h
+++ b/plugins/elf/loading.h
@@ -52,7 +52,7 @@ typedef struct _GElfLoadingClass GElfLoadingClass;
 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 *, virt_t *, GBinSymbol *);
+typedef GBinSymbol * (* elf_importing_cb) (GElfLoading *, GElfFormat *, vmpa2t *);
 
 
 /* Indique le type défini pour les tâches de chargements pour format ELF. */
@@ -65,7 +65,7 @@ GElfLoading *g_elf_loading_new_for_symbols(GElfFormat *, phys_t, phys_t, phys_t,
 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);
+GElfLoading *g_elf_loading_new_for_imported(GElfFormat *, const vmpa2t *, phys_t, elf_rel *, size_t, phys_t, uint32_t, activity_id_t, elf_importing_cb);
 
 /* Crée une tâche de chargement de chaînes pour ELF différée. */
 GElfLoading *g_elf_loading_new_for_strings(GElfFormat *, phys_t, phys_t, phys_t, phys_t, virt_t, activity_id_t, elf_loading_cb);
@@ -82,8 +82,11 @@ void g_elf_loading_store_relocation(const GElfLoading *, const phys_t *, const e
 /* Recherche une relocalisation par son décalage. */
 bool g_elf_loading_search_for_relocation(const GElfLoading *, const uint64_t *, elf_rel **);
 
-/* Construit la désignation adaptée à un symbole importé. */
-char *g_elf_loading_build_plt_name(const GElfLoading *, uint64_t);
+/* Construit le symbole adapté à un symbole importé. */
+GBinSymbol *g_elf_loading_build_plt_symbol(const GElfLoading *, uint64_t);
+
+/* Fournit la liste de symboles importés constituée. */
+GBinSymbol **g_elf_loading_get_imported_symbols(const GElfLoading *, size_t *);
 
 /* Donne les informations utiles à la recherche de chaînes. */
 const bin_t *g_elf_loading_get_info_for_strings(const GElfLoading *, GBinContent **, phys_t *, phys_t *, phys_t *);
diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c
index d24b6d6..80a9143 100644
--- a/plugins/elf/symbols.c
+++ b/plugins/elf/symbols.c
@@ -85,7 +85,7 @@ static bool load_elf_global_symbols(GElfFormat *, wgroup_id_t, GtkStatusStack *)
 
 
 
-/* ----------------------- PRISE EN COMPTE DE RELOCALISATIONS ----------------------- */
+/* ------------------------ INSCRIPTION DE SYMBOLES IMPORTES ------------------------ */
 
 
 /* Assure le chargement des relocalisations ELF en différé. */
@@ -94,11 +94,14 @@ 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 *, wgroup_id_t, GtkStatusStack *);
 
-/* Assure l'intégration d'un symbole issu des relocalisations. */
-static bool do_elf_relocation_renaming(GElfLoading *, GElfFormat *, virt_t *, GBinSymbol *);
+/* Assure la construction d'un symbole issu des relocalisations. */
+static GBinSymbol *do_elf_relocation_convert(GElfLoading *, GElfFormat *, vmpa2t *);
 
-/* Applique les étiquettes issues des relocalisations. */
-static bool apply_elf_relocations(GElfFormat *, elf_rel *, size_t, sym_iter_t *, wgroup_id_t, GtkStatusStack *);
+/* Construit une liste de symboles issus des relocalisations. */
+static GBinSymbol **convert_elf_relocations_to_symbols(GElfFormat *, elf_rel *, size_t, vmpa2t *, wgroup_id_t, GtkStatusStack *, size_t *);
+
+/* Ajoute l'ensemble des symboles importés. */
+static bool load_imported_elf_symbols(GElfFormat *, wgroup_id_t, GtkStatusStack *);
 
 
 
@@ -153,6 +156,8 @@ bool load_elf_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *statu
 
         result &= load_elf_global_symbols(format, gid, status);
 
+        result &= load_imported_elf_symbols(format, gid, status);
+
     }
     else log_variadic_message(LMT_INFO, _("Binary is statically linked"));
 
@@ -227,8 +232,18 @@ static bool do_elf_symbol_loading(GElfLoading *loading, GElfFormat *format, bool
         status = SSS_INTERNAL;
 
     else
+    {
         status = ELF_SYM(format, sym, st_shndx) == 0 ? SSS_IMPORTED : SSS_EXPORTED;
 
+        /**
+         * Si le symbol doit être traité ailleurs...
+         */
+
+        if (status == SSS_IMPORTED)
+            goto desl_done;
+
+    }
+
     /* Traitements particuliers */
 
     base = G_BIN_FORMAT(format);
@@ -722,7 +737,7 @@ static bool load_elf_global_symbols(GElfFormat *format, wgroup_id_t gid, GtkStat
 
 
 /* ---------------------------------------------------------------------------------- */
-/*                         PRISE EN COMPTE DE RELOCALISATIONS                         */
+/*                          INSCRIPTION DE SYMBOLES IMPORTES                          */
 /* ---------------------------------------------------------------------------------- */
 
 
@@ -803,15 +818,15 @@ static bool load_elf_relocations(GElfFormat *format, const elf_phdr *dynamic, el
     /* Collecte des informations */
 
     if (!_find_elf_dynamic_item_by_type(format, dynamic, DT_JMPREL, &jmprel))
-        goto ler_exit;
+        goto exit;
 
     result = g_exe_format_translate_address_into_vmpa(exec, ELF_DYN(format, jmprel, d_un.d_ptr), &start);
 
     if (!result)
-        goto ler_exit;
+        goto exit;
 
     if (!_find_elf_dynamic_item_by_type(format, dynamic, DT_PLTRELSZ, &pltrelsz))
-        goto ler_exit;
+        goto exit;
 
     length = ELF_DYN(format, pltrelsz, d_un.d_val);
 
@@ -836,7 +851,7 @@ static bool load_elf_relocations(GElfFormat *format, const elf_phdr *dynamic, el
     if (length % rel_size != 0)
     {
         result = false;
-        goto ler_exit;
+        goto exit;
     }
 
     length /= rel_size;
@@ -844,9 +859,9 @@ static bool load_elf_relocations(GElfFormat *format, const elf_phdr *dynamic, el
     /* Chargement en mémoire des relocalisations */
 
     if (length == 0)
-        goto ler_exit;
+        goto exit;
 
-    *relocs = (elf_rel *)malloc(length * sizeof(elf_rel));
+    *relocs = malloc(length * sizeof(elf_rel));
     *count = length;
 
     msg = gtk_status_stack_add_activity(status, _("Loading relocations..."), length);
@@ -855,7 +870,7 @@ static bool load_elf_relocations(GElfFormat *format, const elf_phdr *dynamic, el
 
     run_size = compute_run_size(length, &runs_count);
 
-    loadings = (GElfLoading **)malloc(runs_count * sizeof(GElfLoading *));
+    loadings = malloc(runs_count * sizeof(GElfLoading *));
 
     for (i = 0; i < runs_count; i++)
     {
@@ -895,7 +910,7 @@ static bool load_elf_relocations(GElfFormat *format, const elf_phdr *dynamic, el
     if (!result)
     {
         free(*relocs);
-        goto ler_exit;
+        goto exit;
     }
 
     /* Tri de la liste obtenue */
@@ -907,7 +922,7 @@ static bool load_elf_relocations(GElfFormat *format, const elf_phdr *dynamic, el
 
     qsort(*relocs, *count, sizeof(elf_rel), (__compar_fn_t)compare_relocations);
 
- ler_exit:
+ exit:
 
     return result;
 
@@ -916,82 +931,58 @@ static bool load_elf_relocations(GElfFormat *format, const elf_phdr *dynamic, el
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format = informations chargées à consulter.                  *
-*                gid    = groupe de travail dédié.                            *
-*                status = barre de statut à tenir informée.                   *
+*  Paramètres  : loading = chargement de relocalisations en cours.            *
+*                format  = format ELF à compléter.                            *
+*                addr    = emplacement de code à traiter. [OUT]               *
 *                                                                             *
-*  Description : Actualise la désignation des fonctions externes à reloger.   *
+*  Description : Assure la construction d'un symbole issu des relocalisations.*
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : Nouveau symbole constitué ou NULL en cas d'échec.            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool refresh_elf_relocations(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+static GBinSymbol *do_elf_relocation_convert(GElfLoading *loading, GElfFormat *format, vmpa2t *addr)
 {
-    bool result;                            /* Bilan à retourner           */
-    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;
-
-    if (!find_elf_dynamic_program_header(format, &dynamic))
-        goto rer_quick_exit;
-
-    /* Chargement des relocalisations */
-
-    if (!load_elf_relocations(format, &dynamic, &relocs, &rel_count, gid, 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;
+    GBinSymbol *result;                     /* Symbole à retourner         */
+    vmpa2t start;                           /* Sauvegarde du départ        */
+    uint64_t offset;                        /* Décalage à retrouver        */
+    bool status;                            /* Bilan d'une opération       */
+    elf_rel *reloc;                         /* Infos de relocalisation     */
+    uint64_t index;                         /* Indice du symbole concerné  */
+    phys_t length;                          /* Taille du nouveau symbole   */
+    mrange_t range;                         /* Couverture mémoire associée */
 
-    /* Parcours des symboles */
+    result = NULL;
 
-    base = G_BIN_FORMAT(format);
+    /* Détermination de la relocalisation associée */
 
-    /**
-     * Il existe normalement un symbole "plt_entry" créé au chargement des symboles...
-     */
+    copy_vmpa(&start, addr);
 
-    g_binary_format_lock_symbols_rd(base);
+    status = format->ops.get_linkage_offset(format, addr, &offset);
+    if (!status) goto exit;
 
-    result = g_binary_format_find_symbol_index_at(base, &plt_addr, &first);
+    status = g_elf_loading_search_for_relocation(loading, &offset, &reloc);
+    if (!status) goto exit;
 
-    if (result)
-        iter = create_symbol_iterator(base, first);
+    /* Récupération des données du symbole visé */
 
-    g_binary_format_unlock_symbols_rd(base);
+    index = ELF_REL_SYM(format, *reloc);
 
-    if (result)
-    {
-        result = apply_elf_relocations(format, relocs, rel_count, iter, gid, status);
+    result = g_elf_loading_build_plt_symbol(loading, index);
+    if (result == NULL) goto exit;
 
-        delete_symbol_iterator(iter);
+    /* Inscription des propriétés associées */
 
-    }
+    length = compute_vmpa_diff(&start, addr);
 
- rer_exit:
+    init_mrange(&range, &start, length);
+    g_binary_symbol_set_range(result, &range);
 
-    if (relocs != NULL)
-        free(relocs);
+    g_binary_symbol_set_status(result, SSS_IMPORTED);
 
- rer_quick_exit:
+ exit:
 
     return result;
 
@@ -1000,107 +991,88 @@ bool refresh_elf_relocations(GElfFormat *format, wgroup_id_t gid, GtkStatusStack
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : loading = chargement de relocalisations en cours.            *
-*                format  = format ELF à compléter.                            *
-*                valid   = dernière adresse virtuelle non couverte. [OUT]     *
-*                symbol  = symbole courant issu de la liste à analyser.       *
+*  Paramètres  : format    = format ELF à compléter.                          *
+*                relocs    = table des relocalisations chargées.              *
+*                rel_count = nombre de ces éléments à interpréter.            *
+*                start     = emplacement du premier symbole.                  *
+*                gid       = groupe de travail dédié.                         *
+*                status    = barre de statut à tenir informée.                *
+*                count     = nombre de symboles mis en place. [OUT]           *
 *                                                                             *
-*  Description : Assure l'intégration d'un symbole issu des relocalisations.  *
+*  Description : Construit une liste de symboles issus des relocalisations.   *
 *                                                                             *
-*  Retour      : Bilan de l'exécution, utile pour la poursuite du traitement. *
+*  Retour      : Liste de symboles triée ou NULL en cas d'erreur.             *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool do_elf_relocation_renaming(GElfLoading *loading, GElfFormat *format, virt_t *valid, GBinSymbol *symbol)
+static GBinSymbol **convert_elf_relocations_to_symbols(GElfFormat *format, elf_rel *relocs, size_t rel_count, vmpa2t *start, wgroup_id_t gid, GtkStatusStack *status, size_t *count)
 {
-    bool result;                            /* Bilan à retourner           */
-    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
-    char *label;                            /* Etiquette courante          */
-#endif
-
-    result = false;
-
-    range = g_binary_symbol_get_range(symbol);
+    GBinSymbol **result;                    /* Liste à retourner           */
+    GExeFormat *exec;                       /* Autre vision du format      */
+    elf_dyn strtab;                         /* Table de type DT_STRTAB     */
+    bool ret;                               /* Bilan d'une opération       */
+    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    */
+    GElfLoading *loading;                   /* Tâche de chargement         */
 
-    /**
-     * Il peut arriver qu'un symbole figure par erreur dans la liste des symboles
-     * importés. Cela fait par exemple suite au désassemblage d'une zone considèrée
-     * de façon erronée comme du code, opération qui conduit à la création fortuite
-     * d'un symbole non désiré.
-     *
-     * On se prémunit ici d'une erreur de traitement en vérifiant simplement la
-     * couverture des symboles externes, qui englobe un éventuel symbole superflu.
-     */
+    result = NULL;
 
-    if (range->addr.virtual < *valid)
-    {
-        result = true;
-        goto exit;
-    }
+    exec = G_EXE_FORMAT(format);
 
-    stype = g_binary_symbol_get_stype(symbol);
+    /* Récupération du début des chaînes de description */
 
-    if (stype != STP_ROUTINE && stype != STP_CODE_LABEL && stype != STP_ENTRY_POINT)
-    {
-        g_binary_format_add_error(G_BIN_FORMAT(format), BFE_SPECIFICATION, get_mrange_addr(range),
-                                  _("The PLT seems to contains more than routines"));
+    ret = find_elf_dynamic_item_by_type(format, DT_STRTAB, &strtab);
+    if (!ret) goto aer_exit;
 
-        goto exit;
+    ret = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, strtab, d_un.d_ptr), &str_start);
+    if (!ret) goto aer_exit;
 
-    }
+    /* Récupération du début des définitions de symboles */
 
-    /* Assurance du port du type adapté */
+    ret = find_elf_dynamic_item_by_type(format, DT_SYMTAB, &symtab);
+    if (!ret) goto aer_exit;
 
-    g_binary_symbol_set_status(symbol, SSS_IMPORTED);
+    ret = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, symtab, d_un.d_ptr), &sym_start);
+    if (!ret) goto aer_exit;
 
-    /* Détermination de la relocalisation associée */
+    /* Détermination du nombre d'éléments */
 
-    result = format->ops.get_linkage_offset(format, range, &offset);
-    if (!result) goto exit;
+    ret = count_elf_global_symbols(format, exec, &sym_count);
+    if (!ret) goto aer_exit;
 
-    result = g_elf_loading_search_for_relocation(loading, &offset, &reloc);
-    if (!result) goto exit;
-
-    /* Récupération des données du symbole visé */
+    /* Mise en application des références externes */
 
-    index = ELF_REL_SYM(format, *reloc);
+    msg = gtk_status_stack_add_activity(status, _("Applying relocations..."), rel_count);
 
-    name = g_elf_loading_build_plt_name(loading, index);
+    queue = get_work_queue();
 
-#ifndef NDEBUG
+    loading = g_elf_loading_new_for_imported(format, start, str_start, relocs, rel_count,
+                                             sym_start, sym_count, msg, do_elf_relocation_convert);
 
-    label = g_binary_symbol_get_label(symbol);
+    g_object_ref(G_OBJECT(loading));
 
-    if (label != NULL)
-    {
-        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"));
-        }
+    g_work_queue_schedule_work(queue, G_DELAYED_WORK(loading), gid);
 
-        free(label);
+    g_work_queue_wait_for_completion(queue, gid);
 
-    }
+    gtk_status_stack_remove_activity(status, msg);
 
-#endif
+    /* Vérification du bon déroulement */
 
-    g_binary_symbol_set_alt_label(symbol, name);
+    ret = g_elf_loading_get_status(loading);
 
-    free(name);
+    if (ret)
+        result = g_elf_loading_get_imported_symbols(loading, count);
 
-    *valid = range->addr.virtual + range->length;
+    g_object_unref(G_OBJECT(loading));
 
- exit:
+ aer_exit:
 
     return result;
 
@@ -1109,81 +1081,73 @@ static bool do_elf_relocation_renaming(GElfLoading *loading, GElfFormat *format,
 
 /******************************************************************************
 *                                                                             *
-*  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.          *
-*                gid       = groupe de travail dédié.                         *
-*                status    = barre de statut à tenir informée.                *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                gid    = groupe de travail dédié.                            *
+*                status = barre de statut à tenir informée.                   *
 *                                                                             *
-*  Description : Applique les étiquettes issues des relocalisations.          *
+*  Description : Ajoute l'ensemble des symboles importés.                     *
 *                                                                             *
-*  Retour      : Bilan des traitements.                                       *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static bool apply_elf_relocations(GElfFormat *format, elf_rel *relocs, size_t rel_count, sym_iter_t *iter, wgroup_id_t gid, GtkStatusStack *status)
+static bool load_imported_elf_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)
 {
     bool result;                            /* Bilan à retourner           */
+    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      */
-    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    */
-    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_by_type(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;
+    vmpa2t plt_addr;                        /* Localisation complète       */
+    size_t count;                           /* Quantité de symboles chargés*/
+    GBinSymbol **symbols;                   /* Liste de ces symboles       */
+    size_t i;                               /* Boucle de parcours          */
 
-    /* Récupération du début des définitions de symboles */
+    result = false;
 
-    result = find_elf_dynamic_item_by_type(format, DT_SYMTAB, &symtab);
-    if (!result) goto aer_exit;
+    if (!find_elf_dynamic_program_header(format, &dynamic))
+        goto quick_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;
+    /* Chargement des relocalisations */
 
-    /* Détermination du nombre d'éléments */
+    if (!load_elf_relocations(format, &dynamic, &relocs, &rel_count, gid, status))
+        goto quick_exit;
 
-    result = count_elf_global_symbols(format, exec, &sym_count);
-    if (!result) goto aer_exit;
+    /* Localisation du code de la PLT */
 
-    /* Mise en application des références externes */
+    if (!resolve_plt_using_got(format, &plt_virt))
+        goto exit;
 
-    msg = gtk_status_stack_add_activity(status, _("Applying relocations..."), rel_count);
+    exec = G_EXE_FORMAT(format);
 
-    queue = get_work_queue();
+    if (!g_exe_format_translate_address_into_vmpa(exec, plt_virt, &plt_addr))
+        goto exit;
 
-    loading = g_elf_loading_new_for_applying(format, iter, str_start, relocs, rel_count,
-                                             sym_start, sym_count, msg, do_elf_relocation_renaming);
+    /* Inscription des symboles */
 
-    g_object_ref(G_OBJECT(loading));
+    result = format->ops.find_first_plt(format, &plt_addr);
+    if (!result) goto exit;
 
-    g_work_queue_schedule_work(queue, G_DELAYED_WORK(loading), gid);
+    symbols = convert_elf_relocations_to_symbols(format, relocs, rel_count, &plt_addr, gid, status, &count);
+    if (symbols == NULL) goto exit;
 
-    g_work_queue_wait_for_completion(queue, gid);
+    result = g_binary_format_add_symbols(G_BIN_FORMAT(format), symbols, count);
 
-    gtk_status_stack_remove_activity(status, msg);
+    for (i = 0; i < count; i++)
+        g_object_unref(symbols[i]);
 
-    /* Vérification du bon déroulement */
+    if (symbols != NULL)
+        free(symbols);
 
-    result = g_elf_loading_get_status(loading);
+ exit:
 
-    g_object_unref(G_OBJECT(loading));
+    if (relocs != NULL)
+        free(relocs);
 
- aer_exit:
+ quick_exit:
 
     return result;
 
diff --git a/plugins/elf/symbols.h b/plugins/elf/symbols.h
index ff735c7..f4a6eec 100644
--- a/plugins/elf/symbols.h
+++ b/plugins/elf/symbols.h
@@ -41,12 +41,4 @@ bool load_elf_symbols(GElfFormat *, wgroup_id_t , GtkStatusStack *);
 
 
 
-/* ----------------------- PRISE EN COMPTE DE RELOCALISATIONS ----------------------- */
-
-
-/* Actualise la désignation des fonctions externes à reloger. */
-bool refresh_elf_relocations(GElfFormat *, wgroup_id_t , GtkStatusStack *);
-
-
-
 #endif  /* _PLUGINS_ELF_SYMBOLS_H */
diff --git a/src/format/format.c b/src/format/format.c
index 6968dcc..e782996 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -827,9 +827,7 @@ bool g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
     range = g_binary_symbol_get_range(symbol);
     addr = get_mrange_addr(range);
 
-    assert(has_phys_addr(addr)
-           || g_binary_symbol_get_status(symbol) == SSS_IMPORTED
-           || g_binary_symbol_get_status(symbol) == SSS_DYNAMIC);
+    assert(has_phys_addr(addr) || g_binary_symbol_get_status(symbol) == SSS_DYNAMIC);
 #endif
 
     g_binary_format_lock_unlock_symbols_wr(format, true);
@@ -923,10 +921,7 @@ bool g_binary_format_add_symbols(GBinFormat *format, GBinSymbol **symbols, size_
         range = g_binary_symbol_get_range(symbols[i]);
         addr = get_mrange_addr(range);
 
-        assert(has_phys_addr(addr)
-               || g_binary_symbol_get_status(symbols[i]) == SSS_IMPORTED
-               || g_binary_symbol_get_status(symbols[i]) == SSS_DYNAMIC);
-
+        assert(has_phys_addr(addr) || g_binary_symbol_get_status(symbols[i]) == SSS_DYNAMIC);
 
         if (has_phys_addr(addr))
         {
-- 
cgit v0.11.2-87-g4458