summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-02-15 13:22:10 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-02-15 13:22:10 (GMT)
commit04b1ee00d25383f977f59703e4c0bc66ad1faa81 (patch)
treea2c30ff10b9720f5377d230a4a23bd85aa3dcdc6
parentcf0d30509224a887ecb9bf371a76eb070d3f2eb3 (diff)
Identified Elf imported symbols without waiting for the end of disassembling.
-rw-r--r--plugins/elf/elf-int.h6
-rw-r--r--plugins/elf/format.c35
-rw-r--r--plugins/elf/helper_arm.c66
-rw-r--r--plugins/elf/helper_arm.h7
-rw-r--r--plugins/elf/loading.c120
-rw-r--r--plugins/elf/loading.h11
-rw-r--r--plugins/elf/symbols.c340
-rw-r--r--plugins/elf/symbols.h8
-rw-r--r--src/format/format.c9
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))
{