summaryrefslogtreecommitdiff
path: root/plugins/elf
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-01-29 20:56:31 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-01-29 21:04:47 (GMT)
commit6c51b9eed427fd55ce1457834853386cc8d543cd (patch)
tree47b8106bdb086278386d05c838178a06cc00f805 /plugins/elf
parent8a7d7b3303dee1a381893391c04acab35dec6942 (diff)
Handled properly imported/exported ELF symbols, as well as all other symbols.
Diffstat (limited to 'plugins/elf')
-rw-r--r--plugins/elf/dynamic.c107
-rw-r--r--plugins/elf/dynamic.h6
-rw-r--r--plugins/elf/elf_def.h4
-rw-r--r--plugins/elf/format.c25
-rw-r--r--plugins/elf/helper_arm.c195
-rw-r--r--plugins/elf/helper_arm.h4
-rw-r--r--plugins/elf/loading.c453
-rw-r--r--plugins/elf/loading.h40
-rw-r--r--plugins/elf/section.c7
-rw-r--r--plugins/elf/symbols.c1020
-rw-r--r--plugins/elf/symbols.h16
11 files changed, 1431 insertions, 446 deletions
diff --git a/plugins/elf/dynamic.c b/plugins/elf/dynamic.c
index ed681d1..f1d5e02 100644
--- a/plugins/elf/dynamic.c
+++ b/plugins/elf/dynamic.c
@@ -111,6 +111,35 @@ bool find_elf_dynamic_item_from_pheader(const GElfFormat *format, const elf_phdr
/******************************************************************************
* *
+* Paramètres : format = informations chargées à consulter. *
+* type = sorte d'élément recherché. *
+* item = élément retrouvé dans la section. [OUT] *
+* *
+* Description : Retrouve rapidement un élément dans la section dynamique. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool find_elf_dynamic_item(const GElfFormat *format, int64_t type, elf_dyn *item)
+{
+ bool result; /* Bilan à retourner */
+ elf_phdr dynamic; /* En-tête de programme DYNAMIC*/
+
+ result = find_elf_dynamic_program_header(format, &dynamic);
+
+ if (result)
+ result = find_elf_dynamic_item_from_pheader(format, &dynamic, type, item);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : format = description de l'exécutable à consulter. *
* count = nombre d'éléments dans la liste constituée. *
* *
@@ -202,3 +231,81 @@ const char **list_elf_needed_objects(const GElfFormat *format, size_t *count)
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à manipuler. *
+* virt = position en mémoire de la PLT. [OUT] *
+* *
+* Description : Retrouve l'adresse de la PLT en se basant sur la GOT. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool resolve_plt_using_got(GElfFormat *format, virt_t *virt)
+{
+ bool result; /* Bilan à retourner */
+ elf_phdr dynamic; /* Programme à analyser */
+ elf_dyn pltgot; /* Table de type DT_PLTGOT */
+ virt_t got_virt; /* Adresse mémoire de la GOT */
+ vmpa2t got_addr; /* Localisation complète */
+ GBinContent *content; /* Contenu binaire à parcourir */
+ uint32_t raw_32; /* Valeur brute de 32 bits lue */
+ uint64_t raw_64; /* Valeur brute de 64 bits lue */
+
+ result = false;
+
+ if (!find_elf_program_by_type(format, PT_DYNAMIC, &dynamic))
+ goto rpug_exit;
+
+ if (!find_elf_dynamic_item_from_pheader(format, &dynamic, DT_PLTGOT, &pltgot))
+ goto rpug_exit;
+
+ got_virt = ELF_DYN(format, pltgot, d_un.d_ptr);
+
+ if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), got_virt, &got_addr))
+ goto rpug_exit;
+
+ content = G_BIN_FORMAT(format)->content;
+
+ /**
+ * Quelques pistes pour la connaissance des premières cellules d'une GOT :
+ *
+ * "Lazy procedure linkage with the PLT" (mot clef : GOT+4).
+ * http://www.iecc.com/linker/linker10.html
+ *
+ * "How the ELF Ruined Christmas" (mot clef : GOT[1]).
+ * https://www.usenix.org/system/files/conference/usenixsecurity15/sec15-paper-di-frederico.pdf
+ */
+
+ if (format->is_32b)
+ {
+ advance_vmpa(&got_addr, 3 * sizeof(uint32_t));
+
+ result = g_binary_content_read_u32(content, &got_addr, format->endian, &raw_32);
+
+ if (result)
+ *virt = raw_32;
+
+ }
+
+ else
+ {
+ advance_vmpa(&got_addr, 3 * sizeof(uint64_t));
+
+ result = g_binary_content_read_u64(content, &got_addr, format->endian, &raw_64);
+
+ if (result)
+ *virt = raw_64;
+
+ }
+
+ rpug_exit:
+
+ return result;
+
+}
diff --git a/plugins/elf/dynamic.h b/plugins/elf/dynamic.h
index c166712..1ca4785 100644
--- a/plugins/elf/dynamic.h
+++ b/plugins/elf/dynamic.h
@@ -36,9 +36,15 @@ bool find_elf_dynamic_program_header(const GElfFormat *, elf_phdr *);
/* Retrouve un élément donné dans la section dynamique. */
bool find_elf_dynamic_item_from_pheader(const GElfFormat *, const elf_phdr *, int64_t, elf_dyn *);
+/* Retrouve rapidement un élément dans la section dynamique. */
+bool find_elf_dynamic_item(const GElfFormat *, int64_t, elf_dyn *);
+
/* Fournit la liste des objets partagés requis. */
const char **list_elf_needed_objects(const GElfFormat *, size_t *);
+/* Retrouve l'adresse de la PLT en se basant sur la GOT. */
+bool resolve_plt_using_got(GElfFormat *, virt_t *);
+
#endif /* _PLUGINS_ELF_DYNAMIC_H */
diff --git a/plugins/elf/elf_def.h b/plugins/elf/elf_def.h
index 06adff7..2120afa 100644
--- a/plugins/elf/elf_def.h
+++ b/plugins/elf/elf_def.h
@@ -599,8 +599,8 @@ typedef union _elf_rel
#define ELF_REL(fmt, rl, fld) (fmt->is_32b ? (rl).rel32.fld : (rl).rel64.fld)
-#define ELF_REL_SYM(fmt, rl) (fmt->is_32b ? ELF32_R_SYM(rl.rel32.r_info) : ELF64_R_SYM(rl.rel64.r_info))
-#define ELF_REL_TYPE(fmt, rl) (fmt->is_32b ? ELF32_R_TYPE(rl.rel32.r_info) : ELF64_R_TYPE(rl.rel64.r_info))
+#define ELF_REL_SYM(fmt, rl) (fmt->is_32b ? ELF32_R_SYM((rl).rel32.r_info) : ELF64_R_SYM((rl).rel64.r_info))
+#define ELF_REL_TYPE(fmt, rl) (fmt->is_32b ? ELF32_R_TYPE((rl).rel32.r_info) : ELF64_R_TYPE((rl).rel64.r_info))
#define ELF_SIZEOF_REL(fmt) (fmt->is_32b ? sizeof(elf32_rel) : sizeof(elf64_rel))
diff --git a/plugins/elf/format.c b/plugins/elf/format.c
index 9e3b636..d48eef9 100644
--- a/plugins/elf/format.c
+++ b/plugins/elf/format.c
@@ -62,6 +62,9 @@ static void g_elf_format_finalize(GElfFormat *);
/* 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 *, GtkStatusStack *);
+
/* Indique le type d'architecture visée par le format. */
static const char *g_elf_format_get_target_machine(const GElfFormat *);
@@ -157,6 +160,8 @@ static void g_elf_format_class_init(GElfFormatClass *klass)
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;
@@ -340,6 +345,26 @@ static SourceEndian g_elf_format_get_endianness(const GElfFormat *format)
/******************************************************************************
* *
+* Paramètres : format = description de l'exécutable à manipuler. *
+* 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, GtkStatusStack *status)
+{
+ refresh_elf_relocations(format, 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 a037469..4c34d78 100644
--- a/plugins/elf/helper_arm.c
+++ b/plugins/elf/helper_arm.c
@@ -24,15 +24,8 @@
#include "helper_arm.h"
-#include <assert.h>
-
-
-#include <format/mangling/demangler.h>
-
-
#include "elf_def_arm.h"
#include "elf-int.h"
-#include "symbols.h"
@@ -70,12 +63,11 @@ const char *get_elf_program_arm_type_desc(uint32_t p_type)
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à compléter. *
-* relxxx = section .rel.xxx trouvée (zone à traiter). *
-* dynsym = section .dynsym trouvée (info. dynamiques). *
-* dynstr = section .dynstr trouvée (chaînes de caractères). *
+* 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] *
* *
-* Description : Charge en mémoire la liste des symboles relogés. *
+* Description : Retrouve le décalage appliqué lors d'une résolution. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -83,87 +75,124 @@ const char *get_elf_program_arm_type_desc(uint32_t p_type)
* *
******************************************************************************/
-bool load_elf_arm_relocated_symbols(GElfFormat *format, const elf_shdr *relxxx, const elf_shdr *dynsym, const elf_shdr *dynstr)
+bool retrieve_arm_linkage_offset(GElfFormat *format, const mrange_t *range, uint64_t *offset)
{
bool result; /* Bilan à retourner */
- phys_t rel_start; /* Début de la zone à traiter */
- phys_t rel_size; /* Taille de cette même zone */
- GBinFormat *base; /* Autre version du format */
- phys_t iter; /* Boucle de parcours */
- elf_rel reloc; /* Infos de relocalisation */
- off_t index; /* Indice de la portion visée */
- elf_sym sym; /* Définition complète */
- const char *name; /* Nom du symbole trouvé */
- char *plt_name; /* Adaptation de l'étiquette */
- virt_t virt; /* Adresse en mémoire virtuelle*/
- virt_t final_virt; /* Adresse virtuelle retenue */
- bool status; /* Bilan d'une opération */
- vmpa2t addr; /* Localisation d'une routine */
- GBinRoutine *routine; /* Nouvelle routine trouvée */
- GBinSymbol *symbol; /* Nouveau symbole construit */
- mrange_t range; /* Couverture mémoire associée */
-
- result = true;
-
- get_elf_section_content(format, relxxx, &rel_start, &rel_size, NULL);
-
- base = G_BIN_FORMAT(format);
-
- for (iter = rel_start; iter < (rel_start + rel_size); )
+ GBinContent *content; /* Contenu binaire à parcourir */
+ vmpa2t pos; /* Tete de lecture */
+ uint32_t raw; /* Valeur brute lue */
+ uint32_t shift; /* Décalage arithmétique */
+
+ /**
+ * Pour faciliter la compréhension, on peut s'appuyer sur la lecture de :
+ *
+ * http://blog.qt.io/blog/2010/12/04/moving-code-around/
+ *
+ */
+
+ content = G_BIN_FORMAT(format)->content;
+
+ copy_vmpa(&pos, get_mrange_addr(range));
+
+ result = g_binary_content_read_u32(content, &pos, format->endian, &raw);
+ if (!result) goto ralo_exit;
+
+ /**
+ * On ne reconnaît pour l'instant que la seule combinaison suivante.
+ *
+ * Charge de compléter cette reconnaissance en fonction de nouvelles
+ * découvertes !
+ */
+
+ /**
+ * R_ARM_JUMP_SLOT :
+ *
+ * e28fc600 add ip, pc, #0, 12
+ * e28cca08 add ip, ip, #8, 20 ; 0x8000
+ * e5bcf310 ldr pc, [ip, #784]! ; 0x310
+ */
+
+ if (raw == 0xe28fc600)
{
- result = read_elf_relocation(format, &iter, &reloc);
- if (!result) break;
-
- index = ELF_REL_SYM(format, reloc);
-
- if (!get_elf_symbol_by_index(format, dynsym, index, &sym))
- continue;
-
- name = get_elf_symbol_name(format, dynsym, dynstr, index);
-
- if (name == NULL)
- name = "unknown";
-
- asprintf(&plt_name, "%s@plt", name);
-
- switch (ELF_REL_TYPE(format, reloc))
+ *offset = get_virt_addr(get_mrange_addr(range)) + 8;
+
+ result = g_binary_content_read_u32(content, &pos, format->endian, &raw);
+ if (!result) goto ralo_exit;
+
+ /**
+ * La seconde instruction répond à l'encodage spécifié dans :
+ *
+ * A8.8.5 - ADD (immediate, ARM)
+ *
+ * 31 30 29 28 | 27 26 25 24 23 22 21 20 | 19 18 17 16 | 15 14 13 12 | 11 10 9 8 7 6 5 4 3 2 1 0
+ * cond | 0 0 1 0 1 0 0 S | Rn | Rd | imm12
+ *
+ * On a donc :
+ *
+ * ADD{S}{<c>}{<q>} {<Rd>,} <Rn>, #<const>
+ *
+ * Avec :
+ *
+ * - S = 0.
+ * - Rn = ip = r12 = 0xc
+ * - Rd = ip = r12 = 0xc
+ * - const = ARMExpandImm(imm12)
+ *
+ * Le fonctionnement de la macro ARMExpandImm est détaillé dans :
+ *
+ * A5.2.4 - Modified immediate constants in ARM instructions
+ *
+ */
+
+ if ((raw & 0xfffff000) != 0xe28cc000)
{
- case R_ARM_JUMP_SLOT:
-
- virt = ELF_SYM(format, sym, st_value);
- if (virt == 0) goto lears_next;
-
- final_virt = virt & ~0x1;
-
- status = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_virt, &addr);
- if (!status) goto lears_next;
-
- routine = try_to_demangle_routine(plt_name);
- symbol = G_BIN_SYMBOL(routine);
-
- init_mrange(&range, &addr, 0);
- g_binary_symbol_set_range(symbol, &range);
-
- /* Comptabilisation pour le désassemblage brut */
- g_binary_format_register_code_point(base, virt, false);
-
- break;
-
- default:
- assert(false);
- symbol = NULL;
- break;
+ result = false;
+ goto ralo_exit;
+ }
+ shift = 32 - ((raw & 0xf00) >> 8) * 2;
+
+ *offset += (raw & 0xf) << shift;
+
+ result = g_binary_content_read_u32(content, &pos, format->endian, &raw);
+ if (!result) goto ralo_exit;
+
+ /**
+ * La dernière instruction répond à l'encodage spéficié dans :
+ *
+ * A8.8.63 - LDR (immediate, ARM)
+ *
+ * 31 30 29 28 | 27 26 25 24 23 22 21 20 | 19 18 17 16 | 15 14 13 12 | 11 10 9 8 7 6 5 4 3 2 1 0
+ * cond | 0 1 0 P U 0 W 1 | Rn | Rt | imm12
+ *
+ * On a donc :
+ *
+ * LDR{<c>}{<q>} <Rt>, [<Rn>, #+/-<imm>]!
+ *
+ * Avec :
+ *
+ * - P = 1 (index).
+ * - U = 1 (add).
+ * - W = 1 (wback).
+ * - Rn = ip = r12 = 0xc
+ * - Rt = pc = r15 = 0xf
+ *
+ */
+
+ if ((raw & 0xfffff000) != 0xe5bcf000)
+ {
+ result = false;
+ goto ralo_exit;
}
- if (symbol != NULL)
- g_binary_format_add_symbol(base, symbol);
+ *offset += (raw & 0xfff);
- lears_next:
+ }
- free(plt_name);
+ else
+ result = false;
- }
+ ralo_exit:
return result;
diff --git a/plugins/elf/helper_arm.h b/plugins/elf/helper_arm.h
index d4be96c..07549ad 100644
--- a/plugins/elf/helper_arm.h
+++ b/plugins/elf/helper_arm.h
@@ -32,8 +32,8 @@
/* Fournit la description humaine d'un type de segment ELF. */
const char *get_elf_program_arm_type_desc(uint32_t);
-/* Charge en mémoire la liste des symboles relogés. */
-bool load_elf_arm_relocated_symbols(GElfFormat *, const elf_shdr *, const elf_shdr *, const elf_shdr *);
+/* Retrouve le décalage appliqué lors d'une résolution. */
+bool retrieve_arm_linkage_offset(GElfFormat *, const mrange_t *, uint64_t *);
diff --git a/plugins/elf/loading.c b/plugins/elf/loading.c
index 377eb14..5d82fcc 100644
--- a/plugins/elf/loading.c
+++ b/plugins/elf/loading.c
@@ -24,13 +24,19 @@
#include "loading.h"
+#include <assert.h>
+#include <string.h>
+
+
#include <i18n.h>
+#include <common/extstr.h>
+#include <common/sort.h>
#include <core/logs.h>
+#include <core/params.h>
#include <glibext/delayed-int.h>
#include "elf-int.h"
-#include "section.h"
@@ -41,24 +47,58 @@ struct _GElfLoading
GElfFormat *format; /* Format à faire évoluer */
+ phys_t str_start; /* Chaînes à disposition */
+
union
{
struct
{
- const elf_shdr *section; /* Section à éplucher */
bool use_virt; /* Représentatio par défaut */
- elf_shdr strtab; /* Section .strtab trouvée */
- bool has_strtab; /* Présence de cette section */
+ };
+
+ struct
+ {
+ elf_rel *relocs_to_fill; /* Tableau à remplir */
+
+ };
+
+ struct
+ {
+ elf_rel *relocs; /* Relocalisations présentes */
+ size_t rel_count; /* Qté de ces relocalisations */
+
+ phys_t sym_start; /* Début de zone des symboles */
+ uint32_t sym_count; /* Nombre de symboles présents */
};
+
};
- elf_loading_cb callback; /* Routine de traitement finale*/
- phys_t first; /* Position du premier élément */
- phys_t begin; /* Point de départ du parcours */
- phys_t end; /* Point d'arrivée exclu */
+ union
+ {
+ struct
+ {
+ phys_t begin; /* Point de départ du parcours */
+ phys_t end; /* Point d'arrivée exclu */
+
+ elf_loading_cb callback_0; /* Routine de traitement #0 */
+
+ };
+
+ struct
+ {
+ sym_iter_t *iter; /* Symboles à parcourir */
+
+ elf_applying_cb callback_1; /* Routine de traitement #1 */
+
+ };
+
+ };
+
+ unsigned int kind; /* Type de traitements */
+ bool status; /* Bilan des traitements */
activity_id_t id; /* Identifiant pour messages */
@@ -136,6 +176,7 @@ static void g_elf_loading_class_init(GElfLoadingClass *klass)
static void g_elf_loading_init(GElfLoading *loading)
{
+ loading->status = false;
}
@@ -180,12 +221,61 @@ static void g_elf_loading_finalize(GElfLoading *loading)
/******************************************************************************
* *
-* Paramètres : format = = ensemble d'instructions désassemblées. *
-* section = prototypes existants à insérer. *
-* use_virt = quantité de ces prototypes. *
-* first = position du premier élément. *
+* Paramètres : format = ensemble d'instructions désassemblées. *
+* str_start = début des chaînes de caractères à consulter. *
+* first = position du premier élément. *
+* begin = point de départ du parcours de liste. *
+* end = point d'arrivée exclu du parcours. *
+* id = identifiant du message affiché à l'utilisateur. *
+* callback = routine de traitements particuliers. *
+* *
+* Description : Crée une tâche de chargement pour ELF différée. *
+* *
+* Retour : Tâche créée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GElfLoading *g_elf_loading_new_for_symbols(GElfFormat *format, phys_t str_start, phys_t first, phys_t begin, phys_t end, activity_id_t id, elf_loading_cb callback)
+{
+ GElfLoading *result; /* Tâche à retourner */
+#ifndef NDEBUG
+ bool status; /* Etat d'une consultation */
+#endif
+
+ result = g_object_new(G_TYPE_ELF_LOADING, NULL);
+
+ result->format = format;
+
+ result->str_start = str_start;
+
+#ifndef NDEBUG
+ status = g_generic_config_get_value(get_main_configuration(), MPK_FORMAT_NO_NAME, &result->use_virt);
+ assert(status);
+#else
+ g_generic_config_get_value(get_main_configuration(), MPK_FORMAT_NO_NAME, &result->use_virt);
+#endif
+
+ result->begin = begin;
+ result->end = end;
+ result->callback_0 = callback;
+
+ result->kind = 0;
+
+ result->id = id;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = ensemble d'instructions désassemblées. *
* begin = point de départ du parcours de liste. *
* end = point d'arrivée exclu du parcours. *
+* relocs = table des relocalisations à remplir. *
* id = identifiant du message affiché à l'utilisateur. *
* callback = routine de traitements particuliers. *
* *
@@ -197,7 +287,7 @@ static void g_elf_loading_finalize(GElfLoading *loading)
* *
******************************************************************************/
-GElfLoading *g_elf_loading_new(GElfFormat *format, const elf_shdr *section, bool use_virt, phys_t first, phys_t begin, phys_t end, activity_id_t id, elf_loading_cb callback)
+GElfLoading *g_elf_loading_new_for_relocations(GElfFormat *format, phys_t begin, phys_t end, elf_rel *relocs, activity_id_t id, elf_loading_cb callback)
{
GElfLoading *result; /* Tâche à retourner */
@@ -205,17 +295,15 @@ GElfLoading *g_elf_loading_new(GElfFormat *format, const elf_shdr *section, bool
result->format = format;
- result->section = section;
- result->use_virt = use_virt;
+ result->str_start = VMPA_NO_PHYSICAL;
- result->has_strtab = find_elf_section_by_index(format,
- ELF_SHDR(format, *section, sh_link),
- &result->strtab);
+ result->relocs_to_fill = relocs;
- result->callback = callback;
- result->first = first;
result->begin = begin;
result->end = end;
+ result->callback_0 = callback;
+
+ result->kind = 0;
result->id = id;
@@ -226,8 +314,55 @@ GElfLoading *g_elf_loading_new(GElfFormat *format, const elf_shdr *section, bool
/******************************************************************************
* *
-* Paramètres : study = étude de routines à mener. *
-* status = barre de statut à tenir informée. *
+* Paramètres : format = ensemble d'instructions désassemblées. *
+* iter = itérateur sur les symboles à parcourir. *
+* 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. *
+* sym_start = localisation du début de la zone de symboles. *
+* sym_count = nombre de descriptions de symbole attendues. *
+* id = identifiant du message affiché à l'utilisateur. *
+* callback = routine de traitements particuliers. *
+* *
+* Description : Crée une tâche de chargement pour ELF différée. *
+* *
+* Retour : Tâche créée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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 *result; /* Tâche à retourner */
+
+ result = g_object_new(G_TYPE_ELF_LOADING, NULL);
+
+ result->format = format;
+
+ result->str_start = str_start;
+
+ result->relocs = relocs;
+ result->rel_count = rel_count;
+ result->sym_start = sym_start;
+ result->sym_count = sym_count;
+
+ result->iter = iter;
+ result->callback_1 = callback;
+
+ result->kind = 1;
+
+ result->id = id;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : loading = traitements différés à mener. *
+* status = barre de statut à tenir informée. *
* *
* Description : Assure le chargement pour un format ELF en différé. *
* *
@@ -239,22 +374,66 @@ GElfLoading *g_elf_loading_new(GElfFormat *format, const elf_shdr *section, bool
static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status)
{
+ GElfFormat *format; /* Format plus accessible */
phys_t iter; /* Boucle de parcours */
phys_t old; /* Sauvegarde du point d'avant */
bool ret; /* Bilan d'un appel */
+ size_t processed; /* Nombre de symboles traités */
+ GBinSymbol *symbol; /* Symbole analysé */
+
+ format = loading->format;
- for (iter = loading->begin; iter < loading->end; )
+ switch (loading->kind)
{
- old = iter;
- ret = loading->callback(loading, loading->format, &iter);
+ case 0:
- if (!ret)
- {
- log_variadic_message(LMT_ERROR, _("Error while loading ELF data @ 0x%08x!"), old);
+ for (iter = loading->begin; iter < loading->end; )
+ {
+ old = iter;
+ ret = loading->callback_0(loading, format, &iter);
+
+ if (!ret)
+ {
+ log_variadic_message(LMT_ERROR, _("Error while loading ELF data @ 0x%08x!"), old);
+ break;
+ }
+
+ gtk_status_stack_update_activity_value(status, loading->id, 1);
+
+ }
+
+ loading->status = (iter == loading->end);
break;
- }
- gtk_status_stack_update_activity_value(status, loading->id, 1);
+ case 1:
+
+ ret = true;
+
+ processed = 0;
+
+ for (symbol = get_symbol_iterator_next(loading->iter);
+ symbol != NULL && ret;
+ symbol = get_symbol_iterator_next(loading->iter))
+ {
+ ret = loading->callback_1(loading, format, symbol);
+
+ if (!ret)
+ {
+ log_variadic_message(LMT_ERROR, _("Error while applying ELF relocation %zu!"), processed);
+ break;
+ }
+
+ processed++;
+
+ gtk_status_stack_update_activity_value(status, loading->id, 1);
+
+ if (processed == loading->rel_count)
+ break;
+
+ }
+
+ loading->status = (processed == loading->rel_count);
+ break;
}
@@ -263,14 +442,95 @@ static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status)
/******************************************************************************
* *
-* Paramètres : loading = chargement pour ELF à mener. *
-* section = prototypes existants à insérer. [OUT] *
-* use_virt = quantité de ces prototypes. [OUT] *
-* strtab = informations quant à la table des chaînes. [OUT]*
-* has_strtab = validité du champ précédemment renseigné. [OUT] *
-* first = position du premier élément. [OUT] *
+* Paramètres : loading = procédure de chargements écoulés à consulter. *
+* *
+* Description : Fournit le bilan des traitements différés. *
+* *
+* Retour : true si tout s'est bien déroulé. *
* *
-* Description : Fournit les infos utiles au chargement de symbols internes. *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_elf_loading_get_status(const GElfLoading *loading)
+{
+ return loading->status;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : loading = chargement pour ELF à mener. *
+* name = indice de la désignation du symbole concerné. *
+* virt = adresse virtuelle du symbole en mémoire. *
+* prefix = préfixe d'une désignation par défaut. *
+* alt = zone de constitution d'un nom alternatif. [OUT] *
+* addr = localisation compléte à associer au symbole. [OUT] *
+* *
+* Description : Construit la désignation adaptée à un symbole. *
+* *
+* Retour : Pointeur vers une étiquette constituée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_elf_loading_build_name(const GElfLoading *loading, uint32_t name, virt_t virt, const char *prefix, char *alt, vmpa2t *addr)
+{
+ const char *result; /* Désignation à retourner */
+ GElfFormat *format; /* Format plus accessible */
+ vmpa2t pos; /* Position de lecture */
+ const GBinContent *content; /* Contenu binaire à lire */
+ size_t plen; /* Taille du préfixe */
+
+ result = NULL;
+
+ format = loading->format;
+
+ if (g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), virt, addr))
+ {
+ init_vmpa(&pos, loading->str_start + name, VMPA_NO_VIRTUAL);
+
+ content = G_BIN_FORMAT(format)->content;
+
+ result = (const char *)g_binary_content_get_raw_access(content, &pos, 1);
+
+ if (result != NULL && result[0] == '\0')
+ result = NULL;
+
+ if (result == NULL)
+ {
+ /**
+ * Charge à l'appelant de s'assurer que la zone tampon est assez grande !
+ */
+
+ strcpy(alt, prefix);
+ plen = strlen(prefix);
+
+ if (loading->use_virt)
+ vmpa2_virt_to_string(addr, MDS_UNDEFINED, alt + plen, NULL);
+ else
+ vmpa2_phys_to_string(addr, MDS_UNDEFINED, alt + plen, NULL);
+
+ result = alt;
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : loading = chargement pour ELF à compléter. *
+* iter = tête de lecture courante. *
+* reloc = relocalisation à conserver en mémoire. *
+* *
+* Description : Intègre dans la liste adaptée une relocalisation chargée. *
* *
* Retour : - *
* *
@@ -278,14 +538,121 @@ static void g_elf_loading_process(GElfLoading *loading, GtkStatusStack *status)
* *
******************************************************************************/
-void g_elf_loading_get_internal_info(GElfLoading *loading, const elf_shdr **section, bool *use_virt, const elf_shdr **strtab, bool *has_strtab, phys_t *first)
+void g_elf_loading_store_relocation(const GElfLoading *loading, const phys_t *iter, const elf_rel *reloc)
+{
+ GElfFormat *format; /* Format plus accessible */
+ size_t index; /* Indice de l'élément */
+
+ format = loading->format;
+
+ index = (*iter - loading->begin);
+
+ assert(index % sizeof(ELF_SIZEOF_REL(format)) == 0);
+
+ index /= sizeof(ELF_SIZEOF_REL(format));
+
+ /* La tête de lecture a consommé un élément ! */
+ index--;
+
+ memcpy(&loading->relocs_to_fill[index], reloc, sizeof(elf_rel));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : loading = chargement pour ELF à consulter. *
+* offset = décalage à retrouver idéalement. *
+* reloc = informations quant à la relocalisation. [OUT] *
+* *
+* Description : Recherche une relocalisation par son décalage. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_elf_loading_search_for_relocation(const GElfLoading *loading, const uint64_t *offset, elf_rel **reloc)
{
- *section = loading->section;
- *use_virt = loading->use_virt;
+ bool result; /* Validité à faire remonter */
+ void *found; /* Eventuel élément trouvé */
+
+ int compare_relocations(const uint64_t *off, const elf_rel *rel)
+ {
+ return sort_uint64_t(*off, ELF_REL(loading->format, *rel, r_offset));
+ }
- *strtab = &loading->strtab;
- *has_strtab = loading->has_strtab;
+ found = bsearch(offset, loading->relocs, loading->rel_count,
+ sizeof(elf_rel), (__compar_fn_t)compare_relocations);
- *first = loading->first;
+ result = (found != NULL);
+
+ if (result)
+ *reloc = (elf_rel *)found;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : loading = chargement pour ELF à poursuivre. *
+* index = indice du symbole concerné. *
+* *
+* Description : Construit la désignation adaptée à un symbole importé. *
+* *
+* Retour : Nouvelle étiquette constituée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *g_elf_loading_build_plt_name(const GElfLoading *loading, uint64_t index)
+{
+ char *result; /* Désignation à 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 */
+ const GBinContent *content; /* Contenu binaire à lire */
+ const char *prefix; /* Première partie de nom */
+
+ format = loading->format;
+
+ offset = loading->sym_start + index * ELF_SIZEOF_SYM(format);
+
+ status = read_elf_symbol(format, &offset, &sym);
+
+ if (!status)
+ result = NULL;
+
+ else
+ {
+ name = ELF_SYM(format, sym, st_name);
+
+ offset = loading->str_start + name;
+
+ init_vmpa(&pos, offset, VMPA_NO_VIRTUAL);
+
+ content = G_BIN_FORMAT(format)->content;
+
+ prefix = (const char *)g_binary_content_get_raw_access(content, &pos, 1);
+
+ if (prefix != NULL && prefix[0] == '\0')
+ result = NULL;
+
+ else
+ {
+ result = strdup(prefix);
+ result = stradd(result, "@plt");
+ }
+
+ }
+
+ return result;
}
diff --git a/plugins/elf/loading.h b/plugins/elf/loading.h
index 03ac184..79ea67f 100644
--- a/plugins/elf/loading.h
+++ b/plugins/elf/loading.h
@@ -25,6 +25,7 @@
#define _PLUGINS_ELF_LOADING_H
+#include <format/symiter.h>
#include <gtkext/gtkstatusstack.h>
@@ -32,12 +33,12 @@
-#define G_TYPE_ELF_LOADING g_elf_loading_get_type()
-#define G_ELF_LOADING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_elf_loading_get_type(), GElfLoading))
-#define G_IS_ELF_LOADING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_elf_loading_get_type()))
-#define G_ELF_LOADING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ELF_LOADING, GElfLoadingClass))
-#define G_IS_ELF_LOADING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ELF_LOADING))
-#define G_ELF_LOADING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ELF_LOADING, GElfLoadingClass))
+#define G_TYPE_ELF_LOADING g_elf_loading_get_type()
+#define G_ELF_LOADING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ELF_LOADING, GElfLoading))
+#define G_IS_ELF_LOADING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ELF_LOADING))
+#define G_ELF_LOADING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ELF_LOADING, GElfLoadingClass))
+#define G_IS_ELF_LOADING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ELF_LOADING))
+#define G_ELF_LOADING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ELF_LOADING, GElfLoadingClass))
/* Fraction de loading à limiter (instance) */
@@ -50,15 +51,36 @@ typedef struct _GElfLoadingClass GElfLoadingClass;
/* Assure un chargement pour ELF en différé. */
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 *, GBinSymbol *);
+
/* Indique le type défini pour les tâches de chargements pour format ELF. */
GType g_elf_loading_get_type(void);
/* Crée une tâche de chargement pour ELF différée. */
-GElfLoading *g_elf_loading_new(GElfFormat *, const elf_shdr *, bool, phys_t, phys_t, phys_t, activity_id_t, elf_loading_cb);
+GElfLoading *g_elf_loading_new_for_symbols(GElfFormat *, phys_t, phys_t, phys_t, phys_t, activity_id_t, elf_loading_cb);
+
+/* Crée une tâche de chargement pour ELF différée. */
+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);
+
+/* Fournit le bilan des traitements différés. */
+bool g_elf_loading_get_status(const GElfLoading *);
+
+/* Construit la désignation adaptée à un symbole. */
+const char *g_elf_loading_build_name(const GElfLoading *, uint32_t, virt_t, const char *, char *, vmpa2t *);
+
+/* Intègre dans la liste adaptée une relocalisation chargée. */
+void g_elf_loading_store_relocation(const GElfLoading *, const phys_t *, const elf_rel *);
+
+/* Recherche une relocalisation par son décalage. */
+bool g_elf_loading_search_for_relocation(const GElfLoading *, const uint64_t *, elf_rel **);
-/* Fournit les infos utiles au chargement de symbols internes. */
-void g_elf_loading_get_internal_info(GElfLoading *, const elf_shdr **, bool *, const elf_shdr **, bool *, phys_t *);
+/* Construit la désignation adaptée à un symbole importé. */
+char *g_elf_loading_build_plt_name(const GElfLoading *, uint64_t);
diff --git a/plugins/elf/section.c b/plugins/elf/section.c
index 556c0ed..5e42b0a 100644
--- a/plugins/elf/section.c
+++ b/plugins/elf/section.c
@@ -195,8 +195,11 @@ bool find_elf_sections_by_type(const GElfFormat *format, uint32_t type, elf_shdr
void get_elf_section_content(const GElfFormat *format, const elf_shdr *section, phys_t *offset, phys_t *size, virt_t *addr)
{
- *offset = ELF_SHDR(format, *section, sh_offset);
- *size = ELF_SHDR(format, *section, sh_size);
+ if (offset != NULL)
+ *offset = ELF_SHDR(format, *section, sh_offset);
+
+ if (size != NULL)
+ *size = ELF_SHDR(format, *section, sh_size);
if (addr != NULL)
*addr = ELF_SHDR(format, *section, sh_addr);
diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c
index 7bf68f5..4854d7b 100644
--- a/plugins/elf/symbols.c
+++ b/plugins/elf/symbols.c
@@ -26,15 +26,17 @@
#include <assert.h>
#include <malloc.h>
+#include <stdlib.h>
#include <string.h>
#include <i18n.h>
#include <arch/raw.h>
#include <common/extstr.h>
+#include <common/sort.h>
#include <core/global.h>
#include <core/logs.h>
-#include <core/params.h>
+#include <format/symiter.h>
#include <format/mangling/demangler.h>
@@ -47,11 +49,7 @@
-
-
-
-
-
+/* ------------------------- CHARGEMENT GLOBAL DES SYMBOLES ------------------------- */
/* Enregistre un point d'entrée au sein d'un binaire ELF. */
@@ -60,44 +58,59 @@ static void register_elf_entry_point(GElfFormat *, virt_t, phys_t, GBinRoutine *
/* Enumère tous les points d'entrée principaux d'un binaire ELF. */
static bool load_all_elf_basic_entry_points(GElfFormat *);
+/* Assure le chargement des symboles internes ELF en différé. */
+static bool do_elf_symbol_loading(GElfLoading *, GElfFormat *, bool, phys_t *, GBinSymbol **);
+/* Charge tous les symboles possibles. */
+static void add_all_elf_symbols(GElfFormat *, phys_t, size_t, phys_t, GWorkQueue *, wgroup_id_t, elf_loading_cb, GtkStatusStack *, activity_id_t);
+/* --------------------------- DETAIL DES SYMBOLES LOCAUX --------------------------- */
-
-
-/* -------------------------- DETAIL DES SYMBOLES INTERNES -------------------------- */
-
-
-/* Assure le chargement des symboles internes ELF en différé. */
-static bool do_elf_internal_symbol_loading(GElfLoading *, GElfFormat *, phys_t *);
+/* Assure le chargement des symboles locaux ELF en différé. */
+static bool do_elf_local_symbol_loading(GElfLoading *, GElfFormat *, phys_t *);
/* Charge tous les symboles internes possibles. */
-static bool load_elf_internal_symbols(GElfFormat *, wgroup_id_t, GtkStatusStack *);
+static bool load_elf_local_symbols(GElfFormat *, wgroup_id_t, GtkStatusStack *);
+
+/* --------------------------- DETAIL DE SYMBOLES GLOBAUX --------------------------- */
-/* -------------------------- DETAIL DES SYMBOLES EXTERNES -------------------------- */
+/* Assure le chargement des symboles globaux ELF en différé. */
+static bool do_elf_global_symbol_loading(GElfLoading *, GElfFormat *, phys_t *);
-/* Retrouve un élément donné dans la section dynamique. */
-static bool find_elf_dynamic_item(const GElfFormat *, const elf_shdr *, int32_t, elf_dyn *);
+/* Dénombre le nombre de symboles en lien avec l'extérieur. */
+static bool count_elf_global_symbols(GElfFormat *, GExeFormat *, uint32_t *);
/* Charge tous les éléments dynamiques externes possibles. */
-static bool load_elf_external_symbols(GElfFormat *, const elf_shdr *);
+static bool load_elf_global_symbols(GElfFormat *, wgroup_id_t, GtkStatusStack *);
+/* ----------------------- PRISE EN COMPTE DE RELOCALISATIONS ----------------------- */
+/* Assure le chargement des relocalisations ELF en différé. */
+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 *, GtkStatusStack *);
+/* Assure l'intégration d'un symbole issu des relocalisations. */
+static bool do_elf_relocation_renaming(GElfLoading *, GElfFormat *, GBinSymbol *);
+/* Applique les étiquettes issues des relocalisations. */
+static bool apply_elf_relocations(GElfFormat *, elf_rel *, size_t, sym_iter_t *, GtkStatusStack *);
+/* ---------------------------------------------------------------------------------- */
+/* CHARGEMENT GLOBAL DES SYMBOLES */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
@@ -118,46 +131,31 @@ bool load_elf_symbols(GElfFormat *format, GtkStatusStack *status)
bool result; /* Bilan à retourner */
wgroup_id_t gid; /* Identifiant pour les tâches */
- elf_shdr *sections; /* Groupe de sections trouvées */
- size_t count; /* Quantité de données */
-
result = true;
gid = g_work_queue_define_work_group(get_work_queue());
/* Symboles internes */
- result &= load_elf_internal_symbols(format, gid, status);
-
-
-
+ result &= load_elf_local_symbols(format, gid, status);
- /* Symboles externes */
+ /* Symboles importés et/ou exportés */
- if (find_elf_sections_by_type(format, SHT_DYNAMIC, &sections, &count))
+ if (find_elf_dynamic_program_header(format, (elf_phdr []) { 0 }))
{
log_variadic_message(LMT_INFO, _("Binary is dynamically linked"));
- result &= load_elf_external_symbols(format, &sections[0]);
-
- free(sections);
+ result &= load_elf_global_symbols(format, gid, status);
}
else log_variadic_message(LMT_INFO, _("Binary is statically linked"));
-
-
-
/* Symboles d'entrée, si encore besoin */
/**
* Le tri en préalable
*/
-
-
-
-
result &= load_all_elf_basic_entry_points(format);
return result;
@@ -165,9 +163,6 @@ bool load_elf_symbols(GElfFormat *format, GtkStatusStack *status)
}
-
-
-
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à compléter. *
@@ -429,68 +424,293 @@ static bool load_all_elf_basic_entry_points(GElfFormat *format)
}
+/******************************************************************************
+* *
+* Paramètres : loading = chargement de symboles en cours. *
+* format = format ELF à compléter. *
+* local = s'apprête-t-on à constuire un symbole interne ? *
+* iter = tête de lecture évoluant avec le temps. [OUT] *
+* new = éventuel renseignement du nouveau symbole. [OUT] *
+* *
+* Description : Assure le chargement des symboles internes ELF en différé. *
+* *
+* Retour : Bilan de l'exécution, utile pour la poursuite du traitement. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool do_elf_symbol_loading(GElfLoading *loading, GElfFormat *format, bool local, phys_t *iter, GBinSymbol **new)
+{
+ bool result; /* Bilan à retourner */
+ elf_sym sym; /* Symbole aux infos visées */
+ virt_t virt; /* Adresse virtuelle */
+ SymbolStatus status; /* Visibilité du symbole */
+ GBinFormat *base; /* Version basique du format */
+ uint32_t index; /* Indice du nom du symbole */
+ const char *name; /* Nom du symbole trouvé */
+ GBinSymbol *symbol; /* Nouveau symbole construit */
+ char alt_name[6 + VMPA_MAX_LEN]; /* Nom abstrait de substitution*/
+ virt_t original_virt; /* Adresse virtuelle retenue */
+ vmpa2t addr; /* Localisation d'un symbole */
+ mrange_t range; /* Couverture mémoire associée */
+ GBinRoutine *routine; /* Nouvelle routine trouvée */
+
+ if (new != NULL)
+ *new = NULL;
+
+ result = read_elf_symbol(format, iter, &sym);
+ if (!result) goto desl_done;
+
+ /**
+ * Si l'adresse virtuelle est nulle, on ne peut ratacher le symbole à aucune position...
+ *
+ * On ne réalise donc aucune opération ici, quitte à laisser une seconde passe
+ * s'occuper des symboles importés par exemple.
+ */
+
+ virt = ELF_SYM(format, sym, st_value);
+ if (virt == 0) goto desl_done;
+
+ /**
+ * En ce qui concerne la nature de la visibilité, on distingue les deux situations suivantes :
+ * - zone DYNSYM : uniquement les importations / exportations.
+ * - zone SYMTAB : tous les symboles.
+ *
+ * La première zone doit donc être traitée en amont, et la seconde complète les traitements
+ * avec à priori uniquement des symboles locaux.
+ */
+
+ if (local)
+ status = SSS_INTERNAL;
+
+ else
+ status = ELF_SYM(format, sym, st_shndx) == 0 ? SSS_IMPORTED : SSS_EXPORTED;
+
+ /* Traitements particuliers */
+
+ base = G_BIN_FORMAT(format);
+
+ index = ELF_SYM(format, sym, st_name);
+ switch (ELF_ST_TYPE(format, sym))
+ {
+ case STT_OBJECT:
+
+ name = g_elf_loading_build_name(loading, index, virt, "obj_", alt_name, &addr);
+ if (name == NULL) break;
+
+ init_mrange(&range, &addr, ELF_SYM(format, sym, st_size));
+
+ symbol = g_binary_symbol_new(&range, STP_OBJECT);
+
+ g_binary_symbol_set_alt_label(symbol, name);
+
+ break;
+
+ case STT_FUNC:
+
+ original_virt = virt;
+
+ /* Ajustement de la position */
+
+ if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
+ virt &= ~0x1;
+
+ /* Constitution d'une routine */
+
+ name = g_elf_loading_build_name(loading, index, virt, "func_", alt_name, &addr);
+ if (name == NULL) break;
+
+ routine = try_to_demangle_routine(name);
+ symbol = G_BIN_SYMBOL(routine);
+
+ init_mrange(&range, &addr, ELF_SYM(format, sym, st_size));
+
+ g_binary_symbol_set_range(symbol, &range);
+
+ /* Comptabilisation pour le désassemblage brut */
+
+ g_binary_format_register_code_point(base, original_virt, false);
+
+ break;
+
+ default:
+ symbol = NULL;
+ break;
+
+ }
+
+ if (symbol != NULL)
+ {
+ g_binary_symbol_set_status(symbol, status);
+
+ if (new != NULL)
+ {
+ g_object_ref(G_OBJECT(symbol));
+ *new = symbol;
+ }
+
+ g_binary_format_add_symbol(base, symbol);
+ }
+ desl_done:
+ return result;
+}
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à consulter. *
-* sym = section comprenant les symboles à venir lire. *
-* index = indice de l'entrée à venir lire. *
-* symbol = ensemble d'informations lues. [OUT] *
+* Paramètres : format = description de l'exécutable à compléter. *
+* sym_start = localisation du début de la zone de symboles. *
+* count = nombre de descriptions de symbole attendues. *
+* str_start = début de la zone contenant les descriptions. *
+* wq = espace de travail dédié. *
+* gid = groupe de travail impliqué. *
+* callback = routine de traitements particuliers. *
+* status = barre de statut à tenir informée. *
+* msg = identifiant du message de progression. *
* *
-* Description : Récupère la définition complète d'un symbole donné. *
+* Description : Charge tous les symboles possibles. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-bool get_elf_symbol_by_index(GElfFormat *format, const elf_shdr *sym, off_t index, elf_sym *symbol)
+static void add_all_elf_symbols(GElfFormat *format, phys_t sym_start, size_t count, phys_t str_start, GWorkQueue *wq, wgroup_id_t gid, elf_loading_cb callback, GtkStatusStack *status, activity_id_t msg)
{
- phys_t sym_start; /* Début de section */
- phys_t sym_size; /* Taille de section */
- phys_t offset; /* Emplacement à venir lire */
+ phys_t sym_size; /* Taille de chaque symbole lu */
+ guint runs_count; /* Qté d'exécutions parallèles */
+ phys_t run_size; /* Volume réparti par exécution*/
+ guint i; /* Boucle de parcours */
+ phys_t begin; /* Début de zone de traitement */
+ phys_t end; /* Fin d'un zone de traitement */
+ GElfLoading *loading; /* Tâche de chargement à lancer*/
+
+ sym_size = ELF_SIZEOF_SYM(format);
+
+ runs_count = g_get_num_processors();
- get_elf_section_content(format, sym, &sym_start, &sym_size, NULL);
+ run_size = count / runs_count;
- offset = sym_start + index * ELF_SIZEOF_SYM(format);
- if ((offset + ELF_SIZEOF_SYM(format)) > (sym_start + sym_size)) return NULL;
+ gtk_status_stack_extend_activity(status, msg, count);
- return read_elf_symbol(format, &offset, symbol);
+ for (i = 0; i < runs_count; i++)
+ {
+ begin = sym_start + i * run_size * sym_size;
+
+ if ((i + 1) == runs_count)
+ end = sym_start + count * sym_size;
+ else
+ end = begin + run_size * sym_size;
+
+ loading = g_elf_loading_new_for_symbols(format, str_start, sym_start, begin, end, msg, callback);
+
+ g_work_queue_schedule_work(wq, G_DELAYED_WORK(loading), gid);
+
+ }
}
+
+/* ---------------------------------------------------------------------------------- */
+/* DETAIL DES SYMBOLES LOCAUX */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à consulter. *
-* sym = section comprenant les symboles à venir lire. *
-* str = section de chaînes de caractères pour les noms. *
-* index = indice de l'entrée à venir lire. *
+* Paramètres : loading = chargement de symboles externes en cours. *
+* format = format ELF à compléter. *
+* iter = tête de lecture évoluant avec le temps. [OUT] *
* *
-* Description : Récupère la désignation d'un symbole donné. *
+* Description : Assure le chargement des symboles locaux ELF en différé. *
* *
-* Retour : Nom du symbole trouvé, ou NULL si erreur ou non adapté. *
+* Retour : Bilan de l'exécution, utile pour la poursuite du traitement. *
* *
* Remarques : - *
* *
******************************************************************************/
-const char *get_elf_symbol_name(GElfFormat *format, const elf_shdr *sym, const elf_shdr *str, off_t index)
+static bool do_elf_local_symbol_loading(GElfLoading *loading, GElfFormat *format, phys_t *iter)
{
- const char *result; /* Résultat à retourner */
- elf_sym symbol; /* Symbole aux infos visées */
+ bool result; /* Bilan à retourner */
+
+ result = do_elf_symbol_loading(loading, format, true, iter, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à compléter. *
+* gid = groupe de travail impliqué. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Charge tous les symboles internes possibles. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool load_elf_local_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+ bool result; /* Bilan à retourner */
+ activity_id_t msg; /* Message de progression */
+ GWorkQueue *queue; /* Gestionnaire de différés */
+ size_t size; /* Taille de chaque symbole lu */
+ elf_shdr *symtabs; /* Groupe de sections trouvées */
+ size_t count; /* Quantité de données */
+ size_t i; /* Boucle de parcours */
+ phys_t sym_start; /* Début de la zone à traiter */
+ phys_t sym_size; /* Taille de cette même zone */
+ size_t sym_count; /* Nombre de symboles déduits */
+ elf_shdr strtab; /* Section dédiées aux chaînes */
+ phys_t str_start; /* Début de cette section */
+
+ result = true;
+
+ msg = gtk_status_stack_add_activity(status, _("Loading local symbols..."), 0);
+
+ queue = get_work_queue();
+
+ size = ELF_SIZEOF_SYM(format);
+
+ if (find_elf_sections_by_type(format, SHT_SYMTAB, &symtabs, &count))
+ for (i = 0; i < count; i++)
+ {
+ get_elf_section_content(format, &symtabs[i], &sym_start, &sym_size, NULL);
+
+ if (sym_size % size != 0)
+ continue;
+
+ sym_count = sym_size / size;
- result = NULL;
+ if (!find_elf_section_by_index(format, ELF_SHDR(format, symtabs[i], sh_link), &strtab))
+ continue;
- if (get_elf_symbol_by_index(format, sym, index, &symbol))
- result = extract_name_from_elf_string_section(format, str, ELF_SYM(format, symbol, st_name));
+ get_elf_section_content(format, &strtab, &str_start, NULL, NULL);
+
+ add_all_elf_symbols(format, sym_start, sym_count, str_start,
+ queue, gid, do_elf_local_symbol_loading, status, msg);
+
+ }
+
+ g_work_queue_wait_for_completion(queue, gid);
+
+ gtk_status_stack_remove_activity(status, msg);
+
+ if (symtabs != NULL) free(symtabs);
return result;
@@ -499,181 +719,193 @@ const char *get_elf_symbol_name(GElfFormat *format, const elf_shdr *sym, const e
/* ---------------------------------------------------------------------------------- */
-/* DETAIL DES SYMBOLES INTERNES */
+/* DETAIL DE SYMBOLES GLOBAUX */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : loading = chargement de symboles internes en cours. *
+* Paramètres : loading = chargement de symboles externes en cours. *
* format = format ELF à compléter. *
* iter = tête de lecture évoluant avec le temps. [OUT] *
* *
-* Description : Assure le chargement des symboles internes ELF en différé. *
+* Description : Assure le chargement des symboles globaux ELF en différé. *
* *
-* Retour : - *
+* Retour : Bilan de l'exécution, utile pour la poursuite du traitement. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool do_elf_internal_symbol_loading(GElfLoading *loading, GElfFormat *format, phys_t *iter)
+static bool do_elf_global_symbol_loading(GElfLoading *loading, GElfFormat *format, phys_t *iter)
{
bool result; /* Bilan à retourner */
- elf_sym sym; /* Symbole aux infos visées */
- SymbolStatus status; /* Visibilité du symbole */
- vmpa2t addr; /* Localisation d'un symbole */
- virt_t virt; /* Adresse virtuelle */
- const elf_shdr *section; /* Groupe de sections trouvées */
- bool use_virt; /* Choix de construction de nom*/
- const elf_shdr *strtab; /* Section .strtab trouvée */
- bool has_strtab; /* Présence de cette section */
- phys_t first; /* Position du premier élément */
- const char *name; /* Nom du symbole trouvé */
- GBinFormat *base; /* Version basique du format */
- GBinSymbol *symbol; /* Nouveau symbole construit */
- char alt_name[6 + VMPA_MAX_LEN]; /* Nom abstrait de substitution*/
- virt_t final_virt; /* Adresse virtuelle retenue */
- mrange_t range; /* Couverture mémoire associée */
- GBinRoutine *routine; /* Nouvelle routine trouvée */
-
- result = read_elf_symbol(format, iter, &sym);
- if (!result) goto geslp_done;
+ GBinSymbol *symbol; /* Nouveau symbole en place */
- /* Nature de la visibilité et adresse associée */
+ result = do_elf_symbol_loading(loading, format, false, iter, &symbol);
- if (ELF_SYM(format, sym, st_shndx) == 0)
- {
- status = SSS_IMPORTED;
- init_vmpa(&addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
-
- }
+ return result;
- else
- {
- status = SSS_EXPORTED;
+}
- virt = ELF_SYM(format, sym, st_value);
- if (virt == 0) goto geslp_done;
- }
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à consulter. *
+* exec = autre vision de ce format. *
+* count = nombre de symboles présents. [OUT] *
+* *
+* Description : Dénombre le nombre de symboles en lien avec l'extérieur. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- /* Première ébauche de nom */
+static bool count_elf_global_symbols(GElfFormat *format, GExeFormat *exec, uint32_t *count)
+{
+ bool result; /* Bilan à retourner */
+ elf_dyn hash; /* Table de type DT_HASH */
+ bool found; /* Détection validée */
+ vmpa2t addr; /* Position de départ brute */
- g_elf_loading_get_internal_info(loading, &section, &use_virt, &strtab, &has_strtab, &first);
+ result = false;
- if (!has_strtab)
- name = NULL;
+ /**
+ * Cf. l'astuce indiquée par :
+ *
+ * - http://www.gabriel.urdhr.fr/2015/09/28/elf-file-format/#symbol-tables
+ * - http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash
+ *
+ */
- else
- name = get_elf_symbol_name(format, section, strtab,
- ((*iter - first) / ELF_SIZEOF_SYM(format)) - 1);
+ found = find_elf_dynamic_item(format, DT_HASH, &hash);
+ if (!found) goto cegs_exit;
- /* Traitements particuliers */
+ exec = G_EXE_FORMAT(format);
- base = G_BIN_FORMAT(format);
+ result = g_exe_format_translate_address_into_vmpa(exec, ELF_DYN(format, hash, d_un.d_ptr), &addr);
+ if (!result) goto cegs_exit;
- switch (ELF_ST_TYPE(format, sym))
- {
- case STT_OBJECT:
+ advance_vmpa(&addr, 4);
- /* Ajustement de la position */
+ result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, count);
+ if (!result) goto cegs_exit;
- if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), virt, &addr))
- {
- symbol = NULL;
- break;
- }
+ cegs_exit:
- /* Création d'un nom unique ? */
+ return result;
- if (name == NULL)
- {
- strcpy(alt_name, "obj_");
+}
- if (use_virt)
- vmpa2_virt_to_string(&addr, MDS_UNDEFINED, alt_name + 4, NULL);
- else
- vmpa2_phys_to_string(&addr, MDS_UNDEFINED, alt_name + 4, NULL);
- name = alt_name;
+/******************************************************************************
+* *
+* Paramètres : format = description de l'exécutable à compléter. *
+* gid = groupe de travail impliqué. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Charge tous les éléments dynamiques externes possibles. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- }
+static bool load_elf_global_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+ bool result; /* Bilan à retourner */
+ 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 count; /* Nombre de symboles présents */
+ activity_id_t msg; /* Message de progression */
+ GWorkQueue *queue; /* Gestionnaire de différés */
+ result = true;
- /* TODO */
+ /**
+ * Les spécifications ne sont pas très claires sur le nombre de tables
+ * possible... On y parle de LA table des symboles, ce qui laisse penser
+ * qu'il ne peut y en avoir qu'une.
+ */
- symbol = NULL;
+ exec = G_EXE_FORMAT(format);
+ /* Récupération du début des chaînes de description */
- break;
+ result = find_elf_dynamic_item(format, DT_STRTAB, &strtab);
+ if (!result) goto lees_exit;
- case STT_FUNC:
+ result = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, strtab, d_un.d_ptr), &str_start);
+ if (!result) goto lees_exit;
- /* Ajustement de la position */
+ /* Récupération du début des définitions de symboles */
- if (status == SSS_IMPORTED)
- init_mrange(&range, &addr, 0);
+ result = find_elf_dynamic_item(format, DT_SYMTAB, &symtab);
+ if (!result) goto lees_exit;
- else
- {
- if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
- final_virt = virt & ~0x1;
- else
- final_virt = virt;
+ result = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, symtab, d_un.d_ptr), &sym_start);
+ if (!result) goto lees_exit;
- if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_virt, &addr))
- {
- symbol = NULL;
- break;
- }
+ /* Détermination du nombre d'éléments */
- init_mrange(&range, &addr, ELF_SYM(format, sym, st_size));
+ result = count_elf_global_symbols(format, exec, &count);
+ if (!result) goto lees_exit;
- }
+ /* Chargement des symboles */
- /* Création d'un nom unique ? */
+ msg = gtk_status_stack_add_activity(status, _("Loading global symbols..."), 0);
- if (name == NULL)
- {
- strcpy(alt_name, "func_");
+ queue = get_work_queue();
- if (use_virt)
- vmpa2_virt_to_string(&addr, MDS_UNDEFINED, alt_name + 5, NULL);
- else
- vmpa2_phys_to_string(&addr, MDS_UNDEFINED, alt_name + 5, NULL);
+ add_all_elf_symbols(format, sym_start, count, str_start,
+ queue, gid, do_elf_global_symbol_loading, status, msg);
- name = alt_name;
+ g_work_queue_wait_for_completion(queue, gid);
- }
+ gtk_status_stack_remove_activity(status, msg);
- /* Routine */
+ lees_exit:
- routine = try_to_demangle_routine(name);
- symbol = G_BIN_SYMBOL(routine);
+ return result;
- /* Comptabilisation pour le désassemblage brut */
+}
- g_binary_format_register_code_point(G_BIN_FORMAT(format), virt, false);
- break;
- default:
- symbol = NULL;
- break;
+/* ---------------------------------------------------------------------------------- */
+/* PRISE EN COMPTE DE RELOCALISATIONS */
+/* ---------------------------------------------------------------------------------- */
- }
- if (symbol != NULL)
- {
- g_binary_symbol_set_range(symbol, &range);
- g_binary_symbol_set_status(symbol, status);
+/******************************************************************************
+* *
+* Paramètres : loading = chargement de relocalisations en cours. *
+* format = format ELF à compléter. *
+* iter = tête de lecture évoluant avec le temps. [OUT] *
+* *
+* Description : Assure le chargement des relocalisations ELF en différé. *
+* *
+* Retour : Bilan de l'exécution, utile pour la poursuite du traitement. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- g_binary_format_add_symbol(base, symbol);
+static bool do_elf_relocation_loading(GElfLoading *loading, GElfFormat *format, phys_t *iter)
+{
+ bool result; /* Bilan à retourner */
+ elf_rel reloc; /* Relocalisation constituée */
- }
+ result = read_elf_relocation(format, iter, &reloc);
- geslp_done:
+ if (result)
+ g_elf_loading_store_relocation(loading, iter, &reloc);
return result;
@@ -682,11 +914,13 @@ static bool do_elf_internal_symbol_loading(GElfLoading *loading, GElfFormat *for
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à compléter. *
-* gid = groupe de travail impliqué. *
- status = barre de statut à tenir informée. *
+* Paramètres : format = informations chargées à consulter. *
+* dynamic = en-tête de programme de type DYNAMIC. *
+* relocs = liste des relocalisations triées à charger. [OUT] *
+* count = taille de cette liste. [OUT] *
+* status = barre de statut à tenir informée. *
* *
-* Description : Charge tous les symboles internes possibles. *
+* Description : Charge en mémoire toutes les relocalisations présentes. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -694,101 +928,158 @@ static bool do_elf_internal_symbol_loading(GElfLoading *loading, GElfFormat *for
* *
******************************************************************************/
-static bool load_elf_internal_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+static bool load_elf_relocations(GElfFormat *format, const elf_phdr *dynamic, elf_rel **relocs, size_t *count, GtkStatusStack *status)
{
bool result; /* Bilan à retourner */
- bool no_name; /* Choix de construction de nom*/
+ GExeFormat *exec; /* Autre vision du format */
+ elf_dyn jmprel; /* Table des relocalisations */
+ vmpa2t start; /* Position de départ brute */
+ elf_dyn pltrelsz; /* Taille de table en octets */
+ uint64_t length; /* Nombre total des éléments */
+ mrange_t shr_range; /* Emplacement des relocs. #1 */
+ mrange_t phr_range; /* Emplacement des relocs. #2 */
+ phys_t rel_size; /* Taille de chaque élément lu */
+ bool ret; /* Bilan d'un appel */
activity_id_t msg; /* Message de progression */
GWorkQueue *queue; /* Gestionnaire de différés */
- elf_shdr *dynsym_sections; /* Groupe de sections trouvées */
- size_t count; /* Quantité de données */
- elf_shdr *symtab_sections; /* Groupe de sections trouvées */
- size_t i; /* Boucle de parcours */
+ wgroup_id_t gid; /* Identifiant pour les tâches */
+ guint runs_count; /* Qté d'exécutions parallèles */
+ phys_t run_size; /* Volume réparti par exécution*/
+ GElfLoading **loadings; /* Tâches de chargement */
+ guint i; /* Boucle de parcours */
+ phys_t begin; /* Début de zone de traitement */
+ phys_t end; /* Fin d'un zone de traitement */
result = true;
- /* Charge tous les symboles définis dans une section */
- void add_all_symbols_from_section(const elf_shdr *section, bool use_virt, GWorkQueue *wq, activity_id_t id)
- {
- phys_t start; /* Début de la zone à traiter */
- phys_t size; /* Taille de cette même zone */
- phys_t sym_size; /* Taille de chaque symbole lu */
- guint runs_count; /* Qté d'exécutions parallèles */
- phys_t run_size; /* Volume réparti par exécution*/
- guint i; /* Boucle de parcours */
- phys_t begin; /* Début de zone de traitement */
- phys_t end; /* Fin d'un zone de traitement */
- GElfLoading *loading; /* Tâche de chargement à lancer*/
+ *relocs = NULL;
+ *count = 0;
- get_elf_section_content(format, section, &start, &size, NULL);
+ exec = G_EXE_FORMAT(format);
- sym_size = ELF_SIZEOF_SYM(format);
+ /* Collecte des informations */
- runs_count = g_get_num_processors();
+ if (!find_elf_dynamic_item_from_pheader(format, dynamic, DT_JMPREL, &jmprel))
+ goto ler_exit;
- run_size = size / (sym_size * runs_count);
+ result = g_exe_format_translate_address_into_vmpa(exec, ELF_DYN(format, jmprel, d_un.d_ptr), &start);
- gtk_status_stack_extend_activity(status, id, size / sym_size);
+ if (!result)
+ goto ler_exit;
- for (i = 0; i < runs_count; i++)
- {
- begin = start + i * run_size * sym_size;
+ if (!find_elf_dynamic_item_from_pheader(format, dynamic, DT_PLTRELSZ, &pltrelsz))
+ goto ler_exit;
- if ((i + 1) == runs_count)
- end = start + size;
- else
- end = begin + run_size * sym_size;
+ length = ELF_DYN(format, pltrelsz, d_un.d_val);
- loading = g_elf_loading_new(format, section, use_virt, start, begin, end,
- id, do_elf_internal_symbol_loading);
+ /* Corrélation des informations */
- g_work_queue_schedule_work(wq, G_DELAYED_WORK(loading), gid);
+ ret = find_elf_section_range_by_name(format, ".rel.plt", &shr_range);
- }
+ if (ret)
+ {
+ init_mrange(&phr_range, &start, length);
+
+ if (cmp_mrange(&phr_range, &shr_range) != 0)
+ log_simple_message(LMT_BAD_BINARY,
+ _("The linker PLT and the PLT section differ by their area definition."));
}
- if (!g_generic_config_get_value(get_main_configuration(), MPK_FORMAT_NO_NAME, &no_name))
- return false;
+ /* Détermination du nombre d'éléments */
- msg = gtk_status_stack_add_activity(status, _("Loading internal symbols..."), 0);
+ rel_size = ELF_SIZEOF_REL(format);
+
+ if (length % rel_size != 0)
+ {
+ result = false;
+ goto ler_exit;
+ }
+
+ length /= rel_size;
+
+ /* Chargement en mémoire des relocalisations */
+
+ if (length == 0)
+ goto ler_exit;
+
+ *relocs = (elf_rel *)malloc(length * sizeof(elf_rel));
+ *count = length;
+
+ msg = gtk_status_stack_add_activity(status, _("Loading relocations..."), length);
queue = get_work_queue();
+ gid = g_work_queue_define_work_group(queue);
- if (find_elf_sections_by_type(format, SHT_DYNSYM, &dynsym_sections, &count))
- for (i = 0; i < count; i++)
- add_all_symbols_from_section(&dynsym_sections[i], no_name, queue, msg);
+ runs_count = g_get_num_processors();
- if (find_elf_sections_by_type(format, SHT_SYMTAB, &symtab_sections, &count))
- for (i = 0; i < count; i++)
- add_all_symbols_from_section(&symtab_sections[i], no_name, queue, msg);
+ run_size = length / runs_count;
+
+ loadings = (GElfLoading **)malloc(runs_count * sizeof(GElfLoading *));
+
+ for (i = 0; i < runs_count; i++)
+ {
+ begin = get_phy_addr(&start) + i * run_size * rel_size;
+
+ if ((i + 1) == runs_count)
+ end = get_phy_addr(&start) + length * rel_size;
+ else
+ end = begin + run_size * rel_size;
+
+ loadings[i] = g_elf_loading_new_for_relocations(format, begin, end,
+ (*relocs) + i * run_size,
+ msg, do_elf_relocation_loading);
+
+ g_object_ref(G_OBJECT(loadings[i]));
+
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(loadings[i]), gid);
+
+ }
g_work_queue_wait_for_completion(queue, gid);
gtk_status_stack_remove_activity(status, msg);
- if (dynsym_sections != NULL) free(dynsym_sections);
- if (symtab_sections != NULL) free(symtab_sections);
+ /* Vérifications du bon déroulement */
- return result;
+ for (i = 0; i < runs_count; i++)
+ {
+ result &= g_elf_loading_get_status(loadings[i]);
-}
+ g_object_ref(G_OBJECT(loadings[i]));
+ }
+ free(loadings);
-/* ---------------------------------------------------------------------------------- */
-/* DETAIL DES SYMBOLES EXTERNES */
-/* ---------------------------------------------------------------------------------- */
+ if (!result)
+ {
+ free(*relocs);
+ goto ler_exit;
+ }
+
+ /* Tri de la liste obtenue */
+
+ int compare_relocations(const elf_rel *a, const elf_rel *b)
+ {
+ return sort_uint64_t(ELF_REL(format, *a, r_offset), ELF_REL(format, *b, r_offset));
+ }
+
+ qsort(*relocs, *count, sizeof(elf_rel), (__compar_fn_t)compare_relocations);
+
+ ler_exit:
+
+ return result;
+
+}
/******************************************************************************
* *
-* Paramètres : format = informations chargées à consulter. *
-* dynamic = section de type SHT_DYNAMIC. *
-* type = sorte d'élément recherché. *
-* item = élément retrouvé dans la section. [OUT] *
+* Paramètres : format = informations chargées à consulter. *
+* status = barre de statut à tenir informée. *
* *
-* Description : Retrouve un élément donné dans la section dynamique. *
+* Description : Actualise la désignation des fonctions externes à reloger. *
* *
* Retour : Bilan de l'opération. *
* *
@@ -796,55 +1087,71 @@ static bool load_elf_internal_symbols(GElfFormat *format, wgroup_id_t gid, GtkSt
* *
******************************************************************************/
-static bool find_elf_dynamic_item(const GElfFormat *format, const elf_shdr *section, int32_t type, elf_dyn *item)
+bool refresh_elf_relocations(GElfFormat *format, GtkStatusStack *status)
{
bool result; /* Bilan à retourner */
- const GBinContent *content; /* Contenu binaire à lire */
- phys_t pos; /* Position de lecture */
- vmpa2t tmp; /* Position écrasable */
- int32_t tag32; /* Type de l'entrée (32 bits) */
- int64_t tag64; /* Type de l'entrée (64 bits) */
+ 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;
- content = G_BIN_FORMAT(format)->content;
+ if (!find_elf_dynamic_program_header(format, &dynamic))
+ goto rer_quick_exit;
- for (pos = ELF_SHDR(format, *section, sh_offset);
- result;
- pos += ELF_SIZEOF_DYN(format))
- {
- init_vmpa(&tmp, pos, VMPA_NO_VIRTUAL);
+ /* Chargement des relocalisations */
- if (format->is_32b)
- {
- result = g_binary_content_read_s32(content, &tmp, format->endian, &tag32);
- if (tag32 == type) break;
- }
- else
- {
- result = g_binary_content_read_s64(content, &tmp, format->endian, &tag64);
- if (tag64 == type) break;
- }
+ if (!load_elf_relocations(format, &dynamic, &relocs, &rel_count, 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;
+
+ /* Parcours des symboles */
+
+ base = G_BIN_FORMAT(format);
+
+ /**
+ * Il existe normalement un symbole "plt_entry" créé au chargement des symboles...
+ */
+
+ g_binary_format_lock_symbols_rd(base);
+
+ result = g_binary_format_find_symbol_index_at(base, &plt_addr, &first);
+
+ if (result)
+ iter = create_symbol_iterator(base, first);
+
+ g_binary_format_unlock_symbols_rd(base);
if (result)
{
- init_vmpa(&tmp, pos, VMPA_NO_VIRTUAL);
+ result = apply_elf_relocations(format, relocs, rel_count, iter, status);
- if (format->is_32b)
- {
- result = g_binary_content_read_s32(content, &tmp, format->endian, &item->dyn32.d_tag);
- result &= g_binary_content_read_s32(content, &tmp, format->endian, &item->dyn32.d_un.d_val);
- }
- else
- {
- result = g_binary_content_read_s64(content, &tmp, format->endian, &item->dyn64.d_tag);
- result &= g_binary_content_read_s64(content, &tmp, format->endian, &item->dyn64.d_un.d_val);
- }
+ delete_symbol_iterator(iter);
}
+ rer_exit:
+
+ if (relocs != NULL)
+ free(relocs);
+
+ rer_quick_exit:
+
return result;
}
@@ -852,52 +1159,171 @@ static bool find_elf_dynamic_item(const GElfFormat *format, const elf_shdr *sect
/******************************************************************************
* *
-* Paramètres : format = informations chargées à consulter. *
-* dynamic = section de type SHT_DYNAMIC. *
+* Paramètres : loading = chargement de relocalisations en cours. *
+* format = format ELF à compléter. *
+* symbol = symbole courant issu de la liste à analyser. *
* *
-* Description : Charge tous les éléments dynamiques externes possibles. *
+* Description : Assure l'intégration d'un symbole issu des relocalisations. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Bilan de l'exécution, utile pour la poursuite du traitement. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool load_elf_external_symbols(GElfFormat *format, const elf_shdr *section)
+static bool do_elf_relocation_renaming(GElfLoading *loading, GElfFormat *format, GBinSymbol *symbol)
{
bool result; /* Bilan à retourner */
- elf_dyn item; /* Elément dynamique */
- elf_shdr relxxx; /* Section .rel.xxx trouvée */
- elf_shdr dynsym; /* Section .dynsym trouvée */
- elf_shdr dynstr; /* Section .dynstr trouvée */
+ 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
+ const char *label; /* Etiquette courante */
+#endif
- result = true;
+ result = false;
+
+ range = g_binary_symbol_get_range(symbol);
+
+ stype = g_binary_symbol_get_target_type(symbol);
- /* Section .rel.plt */
- if (find_elf_dynamic_item(format, section, DT_JMPREL, &item))
+ if (stype != STP_ROUTINE && stype != STP_CODE_LABEL && stype != STP_ENTRY_POINT)
{
- result &= find_elf_section_by_virtual_address(format, ELF_DYN(format, item, d_un.d_ptr), &relxxx);
+ g_binary_format_add_error(G_BIN_FORMAT(format), BFE_SPECIFICATION, get_mrange_addr(range),
+ _("The PLT seems to contains more than routines"));
- if (result)
- result = find_elf_section_by_index(format, ELF_SHDR(format, relxxx, sh_link), &dynsym);
+ goto derr_exit;
- if (result)
- result = find_elf_section_by_index(format, ELF_SHDR(format, dynsym, sh_link), &dynstr);
+ }
- if (result)
- switch (ELF_HDR(format, format->header, e_machine))
- {
- case EM_ARM:
- result = load_elf_arm_relocated_symbols(format, &relxxx, &dynsym, &dynstr);
- break;
+ /* Assurance du port du type adapté */
- default:
- break;
+ g_binary_symbol_set_status(symbol, SSS_IMPORTED);
- }
+ /* Détermination de la relocalisation associée */
+
+ if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
+ result = retrieve_arm_linkage_offset(format, range, &offset);
+ else
+ result = false;
+ if (!result) goto derr_exit;
+
+ result = g_elf_loading_search_for_relocation(loading, &offset, &reloc);
+ if (!result) goto derr_exit;
+
+ /* Récupération des données du symbole visé */
+
+ index = ELF_REL_SYM(format, *reloc);
+
+ name = g_elf_loading_build_plt_name(loading, index);
+
+#ifndef NDEBUG
+
+ label = g_binary_symbol_get_label(symbol);
+
+ 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"));
}
+#endif
+
+ g_binary_symbol_set_alt_label(symbol, name);
+
+ free(name);
+
+ derr_exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Applique les étiquettes issues des relocalisations. *
+* *
+* Retour : Bilan des traitements. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool apply_elf_relocations(GElfFormat *format, elf_rel *relocs, size_t rel_count, sym_iter_t *iter, GtkStatusStack *status)
+{
+ bool result; /* Bilan à retourner */
+ 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 */
+ wgroup_id_t gid; /* Identifiant pour les tâches */
+ 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(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;
+
+ /* Récupération du début des définitions de symboles */
+
+ result = find_elf_dynamic_item(format, DT_SYMTAB, &symtab);
+ if (!result) goto aer_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;
+
+ /* Détermination du nombre d'éléments */
+
+ result = count_elf_global_symbols(format, exec, &sym_count);
+ if (!result) goto aer_exit;
+
+ /* Mise en application des références externes */
+
+ msg = gtk_status_stack_add_activity(status, _("Applying relocations..."), rel_count);
+
+ queue = get_work_queue();
+ gid = g_work_queue_define_work_group(queue);
+
+ loading = g_elf_loading_new_for_applying(format, iter, str_start, relocs, rel_count,
+ sym_start, sym_count, msg, do_elf_relocation_renaming);
+
+ g_object_ref(G_OBJECT(loading));
+
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(loading), gid);
+
+ g_work_queue_wait_for_completion(queue, gid);
+
+ gtk_status_stack_remove_activity(status, msg);
+
+ /* Vérification du bon déroulement */
+
+ result = g_elf_loading_get_status(loading);
+
+ g_object_unref(G_OBJECT(loading));
+
+ aer_exit:
+
return result;
}
diff --git a/plugins/elf/symbols.h b/plugins/elf/symbols.h
index c5e150b..9e987eb 100644
--- a/plugins/elf/symbols.h
+++ b/plugins/elf/symbols.h
@@ -28,25 +28,25 @@
#include "format.h"
+#include <arch/processor.h>
#include <glibext/delayed.h>
#include <gtkext/gtkstatusstack.h>
+/* ------------------------- CHARGEMENT GLOBAL DES SYMBOLES ------------------------- */
+
+
/* Charge en mémoire la liste humaine des symboles. */
bool load_elf_symbols(GElfFormat *, GtkStatusStack *);
-/* Récupère la définition complète d'un symbole donné. */
-bool get_elf_symbol_by_index(GElfFormat *, const elf_shdr *, off_t, elf_sym *);
-/* Récupère la désignation d'un symbole donné. */
-const char *get_elf_symbol_name(GElfFormat *, const elf_shdr *, const elf_shdr *, off_t);
-/* Récupère la définition complète d'un symbole donné. */
-bool get_elf_symbol_by_index(GElfFormat *, const elf_shdr *, off_t, elf_sym *);
+/* ----------------------- PRISE EN COMPTE DE RELOCALISATIONS ----------------------- */
+
-/* Récupère la désignation d'un symbole donné. */
-const char *get_elf_symbol_name(GElfFormat *, const elf_shdr *, const elf_shdr *, off_t);
+/* Actualise la désignation des fonctions externes à reloger. */
+bool refresh_elf_relocations(GElfFormat *, GtkStatusStack *);