summaryrefslogtreecommitdiff
path: root/src/format/elf/symbols.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-01-31 00:55:26 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-01-31 00:55:26 (GMT)
commit21a05df6423bdc13ca148ff2b96aec80bf7af2b2 (patch)
tree87043734800103178ee49e771dcacab18b19cc74 /src/format/elf/symbols.c
parentd246c98c515cb44c5bc4c742a674bae2e824872b (diff)
Defined many entry points from many identified potential candidates.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@463 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/format/elf/symbols.c')
-rw-r--r--src/format/elf/symbols.c288
1 files changed, 257 insertions, 31 deletions
diff --git a/src/format/elf/symbols.c b/src/format/elf/symbols.c
index d69e41a..2d8057e 100644
--- a/src/format/elf/symbols.c
+++ b/src/format/elf/symbols.c
@@ -24,6 +24,7 @@
#include "symbols.h"
+#include <assert.h>
#include <malloc.h>
#include <string.h>
@@ -31,9 +32,11 @@
#include <i18n.h>
+#include "dynamic.h"
#include "elf-int.h"
#include "helper_arm.h"
#include "helper_x86.h"
+#include "program.h"
#include "section.h"
#include "../mangling/demangler.h"
#include "../../arch/raw.h"
@@ -44,6 +47,12 @@
+/* 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 *);
+
@@ -115,18 +124,17 @@ bool load_elf_symbols(GElfFormat *format)
{
bool result; /* Bilan à retourner */
- virt_t entry_point;
- vmpa2t addr; /* Localisation d'une routine */
- mrange_t range; /* Couverture mémoire associée */
- GBinRoutine *routine; /* Nouvelle routine trouvée */
- GBinSymbol *symbol; /* Nouveau symbole construit */
-
elf_shdr *sections; /* Groupe de sections trouvées */
size_t count; /* Quantité de données */
result = true;
+
+ result &= load_all_elf_basic_entry_points(format);
+
+
+
#if 1
annotate_elf_header(format);
@@ -143,31 +151,6 @@ bool load_elf_symbols(GElfFormat *format)
- entry_point = ELF_HDR(format, format->header, e_entry);
-
- G_BIN_FORMAT(format)->entry_point = entry_point;
-
-
-
- printf("E_ENTRY : 0x%08lx\n", (unsigned long)entry_point);
-
- if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
- entry_point &= ~0x1;
-
-
- init_vmpa(&addr, VMPA_NO_PHYSICAL, entry_point);
-
- init_mrange(&range, &addr, 0);
-
- routine = try_to_demangle_routine("entry_point");
-
- g_binary_routine_set_range(routine, &range);
-
- symbol = g_binary_symbol_new(STP_ROUTINE, "entry_point", ~0);
- g_binary_symbol_attach_routine(symbol, routine);
- g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
-
-
/* Symboles externes */
#if 1
if (find_elf_sections_by_type(format, SHT_DYNAMIC, &sections, &count))
@@ -222,6 +205,249 @@ bool load_elf_symbols(GElfFormat *format)
/******************************************************************************
* *
+* 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 de l'instance */
+ vmpa2t addr; /* Localisation d'une routine */
+ mrange_t range; /* Couverture mémoire associée */
+ GBinSymbol *symbol; /* Nouveau symbole construit */
+
+ base = G_BIN_FORMAT(format);
+
+ /* Comptabilisation pour le désassemblage brut */
+
+ base->entry_points = (virt_t *)realloc(base->entry_points, ++base->ep_count * sizeof(virt_t));
+
+ base->entry_points[base->ep_count - 1] = vaddr;
+
+ /* Comptabilisation en tant que symbole */
+
+ if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
+ vaddr &= ~0x1;
+
+ init_vmpa(&addr, VMPA_NO_PHYSICAL, vaddr);
+
+ init_mrange(&range, &addr, len);
+
+ g_binary_routine_set_range(routine, &range);
+
+ symbol = g_binary_symbol_new(STP_ROUTINE, "XXX", ~0);
+ g_binary_symbol_attach_routine(symbol, routine);
+ g_binary_format_add_symbol(base, symbol);
+
+}
+
+
+/******************************************************************************
+* *
+* 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)
+{
+ 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 bin_t *content; /* Contenu binaire à lire */
+ off_t length; /* Taille totale du contenu */
+ off_t pos; /* Tête de lecture courante */
+ uint32_t virt_32; /* Adresse virtuelle sur 32b */
+ uint64_t virt_64; /* Adresse virtuelle sur 64b */
+ bool status; /* Bilan d'une opération */
+
+ /* Point d'entrée principal éventuel */
+
+ ep = ELF_HDR(format, format->header, e_entry);
+
+ if (ep != 0x0)
+ {
+ routine = try_to_demangle_routine("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_from_pheader(format, &dynamic, DT_INIT, &item_a))
+ {
+ ep = ELF_DYN(format, item_a, d_un.d_ptr);
+
+ if (ep != 0x0)
+ {
+ routine = try_to_demangle_routine("init_function");
+ register_elf_entry_point(format, ep, 0, routine);
+ }
+
+ }
+
+ if (find_elf_dynamic_item_from_pheader(format, &dynamic, DT_FINI, &item_a))
+ {
+ ep = ELF_DYN(format, item_a, d_un.d_ptr);
+
+ if (ep != 0x0)
+ {
+ routine = try_to_demangle_routine("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;
+ length = G_BIN_FORMAT(fmt)->length;
+
+ if (!translate_address_into_offset_using_elf_programs(fmt, ELF_DYN(fmt, *ar, d_un.d_val), &pos))
+ return;
+
+ if ((pos + ELF_DYN(fmt, *sz, d_un.d_val)) < length)
+ length = pos + ELF_DYN(fmt, *sz, d_un.d_val);
+
+ for (i = 0; pos < length; i++)
+ {
+ if (fmt->is_32b)
+ {
+ status = read_u32(&virt_32, content, &pos, length, fmt->endian);
+ ep = virt_32;
+ }
+ else
+ {
+ status = read_u64(&virt_64, content, &pos, length, fmt->endian);
+ ep = virt_64;
+ }
+
+ if (!status) break;
+
+ if (ep != 0x0)
+ {
+ snprintf(fullname, sizeof(fullname), "%s%u", prefix, i);
+
+ routine = try_to_demangle_routine(fullname);
+ register_elf_entry_point(fmt, ep, 0, routine);
+
+ }
+
+ }
+
+ }
+
+ if (find_elf_dynamic_item_from_pheader(format, &dynamic, DT_INIT_ARRAY, &item_a))
+ {
+ if (find_elf_dynamic_item_from_pheader(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_from_pheader(format, &dynamic, DT_FINI_ARRAY, &item_a))
+ {
+ if (find_elf_dynamic_item_from_pheader(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_from_pheader(format, &dynamic, DT_PREINIT_ARRAY, &item_a))
+ {
+ if (find_elf_dynamic_item_from_pheader(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_from_pheader(format, &dynamic, DT_PLTGOT, &item_a))
+ {
+ if (translate_address_into_offset_using_elf_programs(format, ELF_DYN(format, item_a, d_un.d_val), &pos))
+ {
+ content = G_BIN_FORMAT(format)->content;
+ length = G_BIN_FORMAT(format)->length;
+
+ /* On saute le premier élément... */
+ if (format->is_32b)
+ status = read_u32(&virt_32, content, &pos, length, format->endian);
+ else
+ status = read_u64(&virt_64, content, &pos, length, format->endian);
+
+ while (1)
+ {
+ if (format->is_32b)
+ {
+ status = read_u32(&virt_32, content, &pos, length, format->endian);
+ ep = virt_32;
+ }
+ else
+ {
+ status = read_u64(&virt_64, content, &pos, length, format->endian);
+ ep = virt_64;
+ }
+
+ if (!status) break;
+
+ if (ep != 0x0)
+ {
+ routine = try_to_demangle_routine("plt_entry");
+ register_elf_entry_point(format, ep, 0, routine);
+ break;
+ }
+
+ }
+
+ }
+
+ }
+
+ laebep_exit:
+
+ return true;
+
+}
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
* Paramètres : format = description de l'exécutable à consulter. *
* sym = section comprenant les symboles à venir lire. *
* index = indice de l'entrée à venir lire. *