summaryrefslogtreecommitdiff
path: root/plugins/elf/symbols.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/elf/symbols.c')
-rw-r--r--plugins/elf/symbols.c340
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;