diff options
Diffstat (limited to 'src/format/elf/symbols.c')
-rw-r--r-- | src/format/elf/symbols.c | 288 |
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, §ions, &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. * |