From 896b31fbbef2fba442566a422fa4d409771b61dd Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 29 Jan 2018 23:49:43 +0100
Subject: Introduced specific operations for ELF architectures.

---
 ChangeLog                | 14 ++++++++++++++
 plugins/elf/elf-int.h    | 23 +++++++++++++++++++++++
 plugins/elf/format.c     | 20 ++++++++++++++++++++
 plugins/elf/helper_arm.c | 23 +++++++++++++++++++++++
 plugins/elf/helper_arm.h |  3 +++
 plugins/elf/program.c    | 16 +---------------
 plugins/elf/symbols.c    | 15 +++------------
 7 files changed, 87 insertions(+), 27 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index da7fe01..c1443d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 18-01-29  Cyrille Bagard <nocbos@gmail.com>
 
+	* plugins/elf/elf-int.h:
+	* plugins/elf/format.c:
+	Introduce specific operations for ELF architectures.
+
+	* plugins/elf/helper_arm.c:
+	* plugins/elf/helper_arm.h:
+	Fix virtual addresses for the Thumb mode.
+
+	* plugins/elf/program.c:
+	* plugins/elf/symbols.c:
+	Update code.
+
+18-01-29  Cyrille Bagard <nocbos@gmail.com>
+
 	* plugins/elf/dynamic.c:
 	* plugins/elf/dynamic.h:
 	Extract more information from the PT_DYNAMIC segment.
diff --git a/plugins/elf/elf-int.h b/plugins/elf/elf-int.h
index 3b4b67c..291000d 100644
--- a/plugins/elf/elf-int.h
+++ b/plugins/elf/elf-int.h
@@ -34,6 +34,27 @@
 
 
 
+/* Fournit la description humaine d'un type de segment ELF. */
+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);
+
+/* Retrouve le décalage appliqué lors d'une résolution. */
+typedef bool (* get_elf_linkage_offset_cb) (GElfFormat *, const mrange_t *, uint64_t *);
+
+
+
+/* Particularités propre aux architectures */
+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  */
+    get_elf_linkage_offset_cb get_linkage_offset; /* Décalage de relocation*/
+
+} elf_arch_ops;
+
+
 /* Format d'exécutable générique (instance) */
 struct _GElfFormat
 {
@@ -43,6 +64,8 @@ struct _GElfFormat
     bool is_32b;                            /* Format du binaire           */
     SourceEndian endian;                    /* Boutisme du format          */
 
+    elf_arch_ops ops;                       /* Opérations spécifiques      */
+
 };
 
 /* Format d'exécutable générique (classe) */
diff --git a/plugins/elf/format.c b/plugins/elf/format.c
index d48eef9..755bc12 100644
--- a/plugins/elf/format.c
+++ b/plugins/elf/format.c
@@ -36,6 +36,7 @@
 
 
 #include "elf-int.h"
+#include "helper_arm.h"
 #include "program.h"
 #include "section.h"
 #include "strings.h"
@@ -292,6 +293,25 @@ GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent, GtkStatus
 
     }
 
+    /* Opérations spécifiques à l'architecture */
+
+    switch (ELF_HDR(result, result->header, e_machine))
+    {
+        case EM_ARM:
+            result->ops.get_type_desc = (get_elf_prgm_type_desc_cb)get_elf_program_arm_type_desc;
+            result->ops.fix_virt = (fix_elf_virt_addr_cb)fix_elf_arm_virtual_address;
+            result->ops.get_linkage_offset = (get_elf_linkage_offset_cb)retrieve_arm_linkage_offset;
+            break;
+
+        default:
+            log_variadic_message(LMT_ERROR, "Architecture not supported for ELF binaries");
+            goto gefn_error;
+            break;
+
+    }
+
+    /* Chargements des informations utiles */
+
     /**
      * On inscrit les éléments préchargés avant tout !
      *
diff --git a/plugins/elf/helper_arm.c b/plugins/elf/helper_arm.c
index 4c34d78..51bdb99 100644
--- a/plugins/elf/helper_arm.c
+++ b/plugins/elf/helper_arm.c
@@ -63,6 +63,29 @@ const char *get_elf_program_arm_type_desc(uint32_t p_type)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : virt = adresse virtuelle éventuellement porteuse d'infos.    *
+*                                                                             *
+*  Description : Fournit une adresse virtuelle prête à emploi.                *
+*                                                                             *
+*  Retour      : Adresse virtuelle réellement utilisable.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+virt_t fix_elf_arm_virtual_address(virt_t virt)
+{
+    virt_t result;                          /* Résultat à retourner        */
+
+    result = virt & ~0x1;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  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]        *
diff --git a/plugins/elf/helper_arm.h b/plugins/elf/helper_arm.h
index 07549ad..3db9324 100644
--- a/plugins/elf/helper_arm.h
+++ b/plugins/elf/helper_arm.h
@@ -32,6 +32,9 @@
 /* Fournit la description humaine d'un type de segment ELF. */
 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);
+
 /* 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/program.c b/plugins/elf/program.c
index 7e6f2e4..83fdc6f 100644
--- a/plugins/elf/program.c
+++ b/plugins/elf/program.c
@@ -25,7 +25,6 @@
 
 
 #include "elf-int.h"
-#include "helper_arm.h"
 
 
 
@@ -59,15 +58,11 @@ const char *get_elf_program_type_desc(const GElfFormat *format, uint32_t p_type)
         MAKE_STRING_FROM_PT(PT_PHDR);
         MAKE_STRING_FROM_PT(PT_TLS);
         MAKE_STRING_FROM_PT(PT_NUM);
-        MAKE_STRING_FROM_PT(PT_LOOS);
         MAKE_STRING_FROM_PT(PT_GNU_EH_FRAME);
         MAKE_STRING_FROM_PT(PT_GNU_STACK);
         MAKE_STRING_FROM_PT(PT_GNU_RELRO);
         MAKE_STRING_FROM_PT(PT_LOSUNW);
         MAKE_STRING_FROM_PT(PT_SUNWSTACK);
-        MAKE_STRING_FROM_PT(PT_HIOS);
-        MAKE_STRING_FROM_PT(PT_LOPROC);
-        MAKE_STRING_FROM_PT(PT_HIPROC);
 
         default:
             result = NULL;
@@ -76,16 +71,7 @@ const char *get_elf_program_type_desc(const GElfFormat *format, uint32_t p_type)
     }
 
     if (result == NULL)
-        switch (ELF_HDR(format, format->header, e_machine))
-        {
-            case EM_ARM:
-                result = get_elf_program_arm_type_desc(p_type);
-                break;
-
-            default:
-                break;
-
-        }
+        result = format->ops.get_type_desc(p_type);
 
     if (result == NULL)
         switch(p_type)
diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c
index 4854d7b..dbf3305 100644
--- a/plugins/elf/symbols.c
+++ b/plugins/elf/symbols.c
@@ -42,7 +42,6 @@
 
 #include "dynamic.h"
 #include "elf-int.h"
-#include "helper_arm.h"
 #include "loading.h"
 #include "program.h"
 #include "section.h"
@@ -189,10 +188,7 @@ static void register_elf_entry_point(GElfFormat *format, virt_t vaddr, phys_t le
 
     /* Localisation complète du symbole */
 
-	if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
-		final_vaddr = vaddr & ~0x1;
-    else
-        final_vaddr = vaddr;
+    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;
@@ -514,8 +510,7 @@ static bool do_elf_symbol_loading(GElfLoading *loading, GElfFormat *format, bool
 
             /* Ajustement de la position */
 
-            if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
-                virt &= ~0x1;
+            virt = format->ops.fix_virt(virt);
 
             /* Constitution d'une routine */
 
@@ -1205,11 +1200,7 @@ static bool do_elf_relocation_renaming(GElfLoading *loading, GElfFormat *format,
 
     /* 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;
-
+    result = format->ops.get_linkage_offset(format, range, &offset);
     if (!result) goto derr_exit;
 
     result = g_elf_loading_search_for_relocation(loading, &offset, &reloc);
-- 
cgit v0.11.2-87-g4458