From 04b1ee00d25383f977f59703e4c0bc66ad1faa81 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard 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