diff options
Diffstat (limited to 'plugins/elf/symbols.c')
-rw-r--r-- | plugins/elf/symbols.c | 340 |
1 files changed, 152 insertions, 188 deletions
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; |