From 4ff5e12f57a4c54e19a7ba987d243e5f86341aeb Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 12 Feb 2020 05:43:01 +0100
Subject: Refreshed the code registering Elf entry points.

---
 plugins/elf/dynamic.c |   8 +-
 plugins/elf/symbols.c | 590 ++++++++++++++++++++++++++------------------------
 2 files changed, 317 insertions(+), 281 deletions(-)

diff --git a/plugins/elf/dynamic.c b/plugins/elf/dynamic.c
index c6fce14..13292ec 100644
--- a/plugins/elf/dynamic.c
+++ b/plugins/elf/dynamic.c
@@ -333,15 +333,15 @@ bool resolve_plt_using_got(GElfFormat *format, virt_t *virt)
     result = false;
 
     if (!find_elf_program_by_type(format, PT_DYNAMIC, &dynamic))
-        goto rpug_exit;
+        goto exit;
 
     if (!_find_elf_dynamic_item_by_type(format, &dynamic, DT_PLTGOT, &pltgot))
-        goto rpug_exit;
+        goto 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;
+        goto exit;
 
     content = G_BIN_FORMAT(format)->content;
 
@@ -377,7 +377,7 @@ bool resolve_plt_using_got(GElfFormat *format, virt_t *virt)
 
     }
 
- rpug_exit:
+ exit:
 
     return result;
 
diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c
index 854d724..d24b6d6 100644
--- a/plugins/elf/symbols.c
+++ b/plugins/elf/symbols.c
@@ -52,12 +52,6 @@
 /* ------------------------- CHARGEMENT GLOBAL DES SYMBOLES ------------------------- */
 
 
-/* Enregistre un point d'entrée au sein d'un binaire ELF. */
-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 **);
 
@@ -108,6 +102,20 @@ static bool apply_elf_relocations(GElfFormat *, elf_rel *, size_t, sym_iter_t *,
 
 
 
+/* ------------------------- INSCRIPTION DE POINTS D'ENTREE ------------------------- */
+
+
+/* Enregistre un point d'entrée au sein d'un binaire ELF. */
+static bool register_elf_entry_point(GElfFormat *, virt_t, GBinRoutine *);
+
+/* Désigne tous les points d'entrée par une étiquette dédiée. */
+static bool load_elf_entry_points_from_array(GElfFormat *, const elf_dyn *, const elf_dyn *, const char *);
+
+/* Enumère tous les points d'entrée principaux d'un binaire ELF. */
+static bool load_all_elf_basic_entry_points(GElfFormat *, GtkStatusStack *);
+
+
+
 /* ---------------------------------------------------------------------------------- */
 /*                           CHARGEMENT GLOBAL DES SYMBOLES                           */
 /* ---------------------------------------------------------------------------------- */
@@ -150,11 +158,8 @@ bool load_elf_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *statu
 
     /* Symboles d'entrée, si encore besoin */
 
-    /**
-     * Le tri en préalable
-     */
-
-    result &= load_all_elf_basic_entry_points(format);
+    if (result)
+        result = load_all_elf_basic_entry_points(format, status);
 
     return result;
 
@@ -163,272 +168,6 @@ bool load_elf_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *statu
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format  = description de l'exécutable à compléter.           *
-*                vaddr   = adresse virtuelle du symbole à insérer.            *
-*                len     = taille de la routine à ajouter.                    *
-*                routine = représentation de la fonction repérée.             *
-*                                                                             *
-*  Description : Enregistre un point d'entrée au sein d'un binaire ELF.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void register_elf_entry_point(GElfFormat *format, virt_t vaddr, phys_t len, GBinRoutine *routine)
-{
-    GBinFormat *base;                       /* Version basique du format   */
-    virt_t final_vaddr;                     /* Adresse virtuelle retenue   */
-    bool status;                            /* Bilan d'une opération       */
-    vmpa2t addr;                            /* Localisation d'une routine  */
-    mrange_t range;                         /* Couverture mémoire associée */
-    GBinSymbol *symbol;                     /* Nouveau symbole construit   */
-
-    /* Localisation complète du symbole */
-
-    final_vaddr = format->ops.fix_virt(vaddr);
-
-    status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_vaddr, &addr);
-    if (!status) return;
-
-    /* Comptabilisation en tant que symbole */
-
-    if (g_binary_format_find_symbol_at(G_BIN_FORMAT(format), &addr, &symbol))
-    {
-        g_object_unref(G_OBJECT(symbol));
-        g_object_unref(G_OBJECT(routine));
-    }
-
-    else
-    {
-        base = G_BIN_FORMAT(format);
-
-        init_mrange(&range, &addr, len);
-
-        symbol = G_BIN_SYMBOL(routine);
-
-        g_binary_symbol_set_range(symbol, &range);
-        g_binary_symbol_set_stype(symbol, STP_ENTRY_POINT);
-
-        g_binary_format_add_symbol(base, symbol);
-
-        /* Comptabilisation pour le désassemblage brut */
-        g_binary_format_register_code_point(base, vaddr, true);
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
-*                                                                             *
-*  Description : Enumère tous les points d'entrée principaux d'un binaire ELF.*
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool load_all_elf_basic_entry_points(GElfFormat *format)
-{
-    GBinFormat *base;                       /* Autre version du format     */
-    virt_t ep;                              /* Point d'entrée détecté      */
-    GBinRoutine *routine;                   /* Routine à associer à un pt. */
-    elf_phdr dynamic;                       /* En-tête de programme DYNAMIC*/
-    elf_dyn item_a;                         /* Premier élément DYNAMIC     */
-    elf_dyn item_b;                         /* Second élément DYNAMIC      */
-    const GBinContent *content;             /* Contenu binaire à lire      */
-    phys_t length;                          /* Taille totale du contenu    */
-    bool status;                            /* Bilan d'une opération       */
-    vmpa2t pos;                             /* Tête de lecture courante    */
-    uint32_t virt_32;                       /* Adresse virtuelle sur 32b   */
-    uint64_t virt_64;                       /* Adresse virtuelle sur 64b   */
-
-    base = G_BIN_FORMAT(format);
-
-    /* Point d'entrée principal éventuel */
-
-    ep = ELF_HDR(format, format->header, e_entry);
-
-    if (ep != 0x0)
-    {
-        routine = g_binary_format_decode_routine(base, "entry_point");
-        register_elf_entry_point(format, ep, 0, routine);
-    }
-
-    /* Chargemet de l'en-tête de programme DYNAMIC */
-
-    if (!find_elf_dynamic_program_header(format, &dynamic))
-        goto laebep_exit;
-
-    /* Détection des constructeurs & destructeurs */
-
-    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT, &item_a))
-    {
-        ep = ELF_DYN(format, item_a, d_un.d_ptr);
-
-        if (ep != 0x0)
-        {
-            routine = g_binary_format_decode_routine(base, "init_function");
-            register_elf_entry_point(format, ep, 0, routine);
-        }
-
-    }
-
-    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI, &item_a))
-    {
-        ep = ELF_DYN(format, item_a, d_un.d_ptr);
-
-        if (ep != 0x0)
-        {
-            routine = g_binary_format_decode_routine(base, "termination_function");
-            register_elf_entry_point(format, ep, 0, routine);
-        }
-
-    }
-
-    void load_entry_points_from_array(GElfFormat *fmt, const elf_dyn *ar, const elf_dyn *sz, const char *prefix)
-    {
-        unsigned int i;                     /* Boucle de parcours          */
-        char fullname[64];                  /* Désignation humaine         */
-
-        assert(sizeof(fullname) >= (strlen(prefix) + sizeof(XSTR(UINT64_MAX) + 1)));
-
-        content = G_BIN_FORMAT(fmt)->content;
-
-        status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format),
-                                                          ELF_DYN(fmt, *ar, d_un.d_val),
-                                                          &pos);
-        if (!status) return;
-
-        length = get_phy_addr(&pos) + ELF_DYN(fmt, *sz, d_un.d_val);
-
-        for (i = 0; get_phy_addr(&pos) < length; i++)
-        {
-            /**
-             * Selon la libc d'Android (https://www.codeaurora.org/.../android/bionic/linker/README.TXT) :
-             *
-             *      DT_INIT_ARRAY
-             *          Points to an array of function addresses that must be
-             *          called, in-order, to perform initialization. Some of
-             *          the entries in the array can be 0 or -1, and should
-             *          be ignored.
-             *
-             * On étend le principe aux sections DT_FINI_ARRAY et DT_PREINIT_ARRAY.
-             */
-
-            if (fmt->is_32b)
-            {
-                status = g_binary_content_read_u32(content, &pos, fmt->endian, &virt_32);
-                status &= (virt_32 != 0x0 && virt_32 != 0xffffffff);
-                ep = virt_32;
-            }
-            else
-            {
-                status = g_binary_content_read_u64(content, &pos, fmt->endian, &virt_64);
-                status &= (virt_64 != 0x0 && virt_64 != 0xffffffffffffffff);
-                ep = virt_64;
-            }
-
-            if (status)
-            {
-                snprintf(fullname, sizeof(fullname), "%s%u", prefix, i);
-
-                routine = g_binary_format_decode_routine(base, fullname);
-                register_elf_entry_point(fmt, ep, 0, routine);
-
-            }
-
-        }
-
-    }
-
-    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAY, &item_a))
-    {
-        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAYSZ, &item_b))
-        {
-            load_entry_points_from_array(format, &item_a, &item_b, "init_array_function_");
-        }
-
-    }
-
-    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAY, &item_a))
-    {
-        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAYSZ, &item_b))
-        {
-            load_entry_points_from_array(format, &item_a, &item_b, "fini_array_function_");
-        }
-
-    }
-
-    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAY, &item_a))
-    {
-        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAYSZ, &item_b))
-        {
-            load_entry_points_from_array(format, &item_a, &item_b, "preinit_array_function_");
-        }
-
-    }
-
-    /* Identification de l'entrée de la PLT */
-
-    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PLTGOT, &item_a))
-    {
-        status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format),
-                                                          ELF_DYN(format, item_a, d_un.d_val),
-                                                          &pos);
-
-        if (status)
-        {
-            content = G_BIN_FORMAT(format)->content;
-
-            /* On saute le premier élément... */
-            if (format->is_32b)
-                status = g_binary_content_read_u32(content, &pos, format->endian, &virt_32);
-            else
-                status = g_binary_content_read_u64(content, &pos, format->endian, &virt_64);
-
-            while (1)
-            {
-                if (format->is_32b)
-                {
-                    status = g_binary_content_read_u32(content, &pos, format->endian, &virt_32);
-                    ep = virt_32;
-                }
-                else
-                {
-                    status = g_binary_content_read_u64(content, &pos, format->endian, &virt_64);
-                    ep = virt_64;
-                }
-
-                if (!status) break;
-
-                if (ep != 0x0)
-                {
-                    routine = g_binary_format_decode_routine(base, "plt_entry");
-                    register_elf_entry_point(format, ep, 0, routine);
-                    break;
-                }
-
-            }
-
-        }
-
-    }
-
- laebep_exit:
-
-    return true;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : loading = chargement de symboles en cours.                   *
 *                format  = format ELF à compléter.                            *
 *                local   = s'apprête-t-on à constuire un symbole interne ?    *
@@ -1449,3 +1188,300 @@ static bool apply_elf_relocations(GElfFormat *format, elf_rel *relocs, size_t re
     return result;
 
 }
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                           INSCRIPTION DE POINTS D'ENTREE                           */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format  = description de l'exécutable à compléter.           *
+*                vaddr   = adresse virtuelle du symbole à insérer.            *
+*                routine = représentation de la fonction repérée.             *
+*                                                                             *
+*  Description : Enregistre un point d'entrée au sein d'un binaire ELF.       *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool register_elf_entry_point(GElfFormat *format, virt_t vaddr, GBinRoutine *routine)
+{
+    bool result;                            /* Bilan à renvoyer            */
+    virt_t final_vaddr;                     /* Adresse virtuelle retenue   */
+    vmpa2t addr;                            /* Localisation d'une routine  */
+    GBinFormat *base;                       /* Version basique du format   */
+    GBinSymbol *symbol;                     /* Nouveau symbole construit   */
+    mrange_t range;                         /* Couverture mémoire associée */
+
+    /* Localisation complète du symbole */
+
+    final_vaddr = format->ops.fix_virt(vaddr);
+
+    result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_vaddr, &addr);
+    if (!result) goto exit;
+
+    base = G_BIN_FORMAT(format);
+
+    /* Comptabilisation en tant que symbole */
+
+    if (g_binary_format_find_symbol_at(G_BIN_FORMAT(format), &addr, &symbol))
+    {
+        /**
+         * On ne relâche pas tout de suite le symbole trouvé, afin de le traiter
+         * en fin de fonction.
+         *
+         * Par contre, la routine proposée est détruite ici.
+         */
+
+        g_object_unref(G_OBJECT(routine));
+
+    }
+
+    else
+    {
+        symbol = G_BIN_SYMBOL(routine);
+        g_object_ref(G_OBJECT(symbol));
+
+        init_mrange(&range, &addr, 0);
+        g_binary_symbol_set_range(symbol, &range);
+
+        g_binary_format_add_symbol(base, symbol);
+
+    }
+
+    /* Marquage */
+
+    g_binary_symbol_set_stype(symbol, STP_ENTRY_POINT);
+
+    g_object_unref(G_OBJECT(symbol));
+
+    /* Comptabilisation pour le désassemblage brut */
+    g_binary_format_register_code_point(base, vaddr, true);
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                array  = indications quant au tableau à charger.             *
+*                size   = indications quant à la taille de ce tableau.        *
+*                prefix = désignation de base des éléments du tableau.        *
+*                                                                             *
+*  Description : Désigne tous les points d'entrée par une étiquette dédiée.   *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool load_elf_entry_points_from_array(GElfFormat *format, const elf_dyn *array, const elf_dyn *size, const char *prefix)
+{
+    bool result;                            /* Bilan à renvoyer            */
+    GBinFormat *base;                       /* Autre version du format     */
+    GBinContent *content;                   /* Contenu binaire à lire      */
+    vmpa2t pos;                             /* Tête de lecture courante    */
+    phys_t length;                          /* Taille totale du contenu    */
+    uint32_t virt_32;                       /* Adresse virtuelle sur 32b   */
+    uint64_t virt_64;                       /* Adresse virtuelle sur 64b   */
+    unsigned int i;                         /* Boucle de parcours          */
+    bool status;                            /* Bilan d'une opération       */
+    virt_t ep;                              /* Point d'entrée détecté      */
+    char fullname[64];                      /* Désignation humaine         */
+    GBinRoutine *routine;                   /* Routine à associer à un pt. */
+
+    assert(sizeof(fullname) >= (strlen(prefix) + sizeof(XSTR(UINT64_MAX) + 1)));
+
+    base = G_BIN_FORMAT(format);
+    content = base->content;
+
+    result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format),
+                                                      ELF_DYN(format, *array, d_un.d_val),
+                                                      &pos);
+    if (!result) goto exit;
+
+    length = get_phy_addr(&pos) + ELF_DYN(format, *size, d_un.d_val);
+
+    for (i = 0; get_phy_addr(&pos) < length && result; i++)
+    {
+        /**
+         * Selon la libc d'Android (https://www.codeaurora.org/.../android/bionic/linker/README.TXT) :
+         *
+         *      DT_INIT_ARRAY
+         *          Points to an array of function addresses that must be
+         *          called, in-order, to perform initialization. Some of
+         *          the entries in the array can be 0 or -1, and should
+         *          be ignored.
+         *
+         * On étend le principe aux sections DT_FINI_ARRAY et DT_PREINIT_ARRAY.
+         */
+
+        if (format->is_32b)
+        {
+            result = g_binary_content_read_u32(content, &pos, format->endian, &virt_32);
+
+            status = (virt_32 != 0x0 && virt_32 != 0xffffffff);
+            ep = virt_32;
+
+        }
+        else
+        {
+            result = g_binary_content_read_u64(content, &pos, format->endian, &virt_64);
+
+            status = (virt_64 != 0x0 && virt_64 != 0xffffffffffffffff);
+            ep = virt_64;
+
+        }
+
+        if (result && status)
+        {
+            snprintf(fullname, sizeof(fullname), "%s%u", prefix, i);
+
+            routine = g_binary_format_decode_routine(base, fullname);
+            result = register_elf_entry_point(format, ep, routine);
+
+        }
+
+    }
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Enumère tous les points d'entrée principaux d'un binaire ELF.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool load_all_elf_basic_entry_points(GElfFormat *format, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à renvoyer            */
+    activity_id_t msg;                      /* Message de progression      */
+    GBinFormat *base;                       /* Autre version du format     */
+    virt_t ep;                              /* Point d'entrée détecté      */
+    GBinRoutine *routine;                   /* Routine à associer à un pt. */
+    elf_phdr dynamic;                       /* En-tête de programme DYNAMIC*/
+    elf_dyn item_a;                         /* Premier élément DYNAMIC     */
+    elf_dyn item_b;                         /* Second élément DYNAMIC      */
+
+    result = true;
+
+    msg = gtk_status_stack_add_activity(status, _("Registering entry points..."), 0);
+
+    base = G_BIN_FORMAT(format);
+
+    /* Point d'entrée principal éventuel */
+
+    ep = ELF_HDR(format, format->header, e_entry);
+
+    if (ep != 0x0)
+    {
+        routine = g_binary_format_decode_routine(base, "entry_point");
+        result = register_elf_entry_point(format, ep, routine);
+        if (!result) goto exit;
+    }
+
+    /* Chargemet de l'en-tête de programme DYNAMIC */
+
+    if (!find_elf_dynamic_program_header(format, &dynamic))
+        goto exit;
+
+    /* Détection des constructeurs & destructeurs */
+
+    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT, &item_a))
+    {
+        ep = ELF_DYN(format, item_a, d_un.d_ptr);
+
+        if (ep != 0x0)
+        {
+            routine = g_binary_format_decode_routine(base, "init_function");
+            result = register_elf_entry_point(format, ep, routine);
+            if (!result) goto exit;
+        }
+
+    }
+
+    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI, &item_a))
+    {
+        ep = ELF_DYN(format, item_a, d_un.d_ptr);
+
+        if (ep != 0x0)
+        {
+            routine = g_binary_format_decode_routine(base, "termination_function");
+            result = register_elf_entry_point(format, ep, routine);
+            if (!result) goto exit;
+        }
+
+    }
+
+    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAY, &item_a))
+    {
+        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_INIT_ARRAYSZ, &item_b))
+        {
+            result = load_elf_entry_points_from_array(format, &item_a, &item_b, "init_array_function_");
+            if (!result) goto exit;
+        }
+
+    }
+
+    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAY, &item_a))
+    {
+        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_FINI_ARRAYSZ, &item_b))
+        {
+            result = load_elf_entry_points_from_array(format, &item_a, &item_b, "fini_array_function_");
+            if (!result) goto exit;
+        }
+
+    }
+
+    if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAY, &item_a))
+    {
+        if (_find_elf_dynamic_item_by_type(format, &dynamic, DT_PREINIT_ARRAYSZ, &item_b))
+        {
+            result = load_elf_entry_points_from_array(format, &item_a, &item_b, "preinit_array_function_");
+            if (!result) goto exit;
+        }
+
+    }
+
+    /* Identification de l'entrée de la PLT */
+
+    if (resolve_plt_using_got(format, &ep))
+    {
+        if (ep != 0x0)
+        {
+            routine = g_binary_format_decode_routine(base, "plt_entry");
+            result = register_elf_entry_point(format, ep, routine);
+        }
+
+    }
+
+ exit:
+
+    gtk_status_stack_remove_activity(status, msg);
+
+    return result;
+
+}
-- 
cgit v0.11.2-87-g4458