summaryrefslogtreecommitdiff
path: root/src/format/elf/symbols.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-05-19 21:21:30 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-05-19 21:21:30 (GMT)
commitf828d126a74facac145531822c6ea9c8259b50e0 (patch)
tree521bfa44de551f30934ee321339a7a87d12a3243 /src/format/elf/symbols.c
parente92c777c91612c8508d263645480c6c3889b679d (diff)
Loaded the ELF internal symbols using all the available CPUs.
Diffstat (limited to 'src/format/elf/symbols.c')
-rw-r--r--src/format/elf/symbols.c328
1 files changed, 205 insertions, 123 deletions
diff --git a/src/format/elf/symbols.c b/src/format/elf/symbols.c
index 29a8c3c..cfd0a09 100644
--- a/src/format/elf/symbols.c
+++ b/src/format/elf/symbols.c
@@ -36,6 +36,7 @@
#include "elf-int.h"
#include "helper_arm.h"
#include "helper_x86.h"
+#include "loading.h"
#include "program.h"
#include "section.h"
#include "../mangling/demangler.h"
@@ -47,6 +48,12 @@
+
+
+
+
+
+
/* Enregistre un point d'entrée au sein d'un binaire ELF. */
static void register_elf_entry_point(GElfFormat *, virt_t, phys_t, GBinRoutine *);
@@ -64,8 +71,11 @@ static bool load_all_elf_basic_entry_points(GElfFormat *);
/* -------------------------- 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 *);
+
/* Charge tous les symboles internes possibles. */
-static bool load_elf_internal_symbols(GElfFormat *);
+static bool load_elf_internal_symbols(GElfFormat *, wgroup_id_t, GtkStatusStack *);
@@ -87,9 +97,13 @@ static bool load_elf_external_symbols(GElfFormat *, const elf_shdr *);
+
+
+
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à compléter. *
+ status = barre de statut à tenir informée. *
* *
* Description : Charge en mémoire la liste humaine des symboles. *
* *
@@ -99,18 +113,21 @@ static bool load_elf_external_symbols(GElfFormat *, const elf_shdr *);
* *
******************************************************************************/
-bool load_elf_symbols(GElfFormat *format)
+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);
+ result &= load_elf_internal_symbols(format, gid, status);
@@ -150,6 +167,9 @@ bool load_elf_symbols(GElfFormat *format)
}
+
+
+
/******************************************************************************
* *
* Paramètres : format = description de l'exécutable à compléter. *
@@ -493,200 +513,262 @@ const char *get_elf_symbol_name(GElfFormat *format, const elf_shdr *sym, const e
/******************************************************************************
* *
-* Paramètres : format = description de l'exécutable à compléter. *
+* Paramètres : loading = chargement de symboles internes en cours. *
+* format = format ELF à compléter. *
+* iter = tête de lecture évoluant avec le temps. [OUT] *
* *
-* Description : Charge tous les symboles internes possibles. *
+* Description : Assure le chargement des symboles internes ELF en différé. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool load_elf_internal_symbols(GElfFormat *format)
+static bool do_elf_internal_symbol_loading(GElfLoading *loading, GElfFormat *format, phys_t *iter)
{
bool result; /* Bilan à retourner */
- bool no_name; /* Choix de construction de nom*/
- elf_shdr *sections; /* Groupe de sections trouvées */
- size_t count; /* Quantité de données */
- size_t i; /* Boucle de parcours */
+ elf_sym sym; /* Symbole aux infos visées */
+ 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 */
+ vmpa2t addr; /* Localisation d'une routine */
+ 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 = true;
+ result = read_elf_symbol(format, iter, &sym);
+ if (!result) goto geslp_done;
- /* Charge tous les symboles définis dans une section */
- bool add_all_symbols_from_section(GElfFormat *format, const elf_shdr *section, bool use_virt)
- {
- GBinFormat *base; /* Version basique du format */
- elf_shdr strtab; /* Section .strtab trouvée */
- bool has_strtab; /* Présence de cette section */
- phys_t start; /* Début de la zone à traiter */
- phys_t size; /* Taille de cette même zone */
- phys_t iter; /* Boucle de parcours */
- elf_sym sym; /* Symbole aux infos visées */
- virt_t virt; /* Adresse virtuelle */
- virt_t final_virt; /* Adresse virtuelle retenue */
- vmpa2t addr; /* Localisation d'une routine */
- mrange_t range; /* Couverture mémoire associée */
- const char *name; /* Nom du symbole trouvé */
- char alt_name[6 + VMPA_MAX_LEN]; /* Nom abstrait de substitution*/
- GBinRoutine *routine; /* Nouvelle routine trouvée */
- GBinSymbol *symbol; /* Nouveau symbole construit */
+ /* On rejette les symboles qui ne sont pas définis au sein du binaire */
- base = G_BIN_FORMAT(format);
+ if (ELF_SYM(format, sym, st_shndx) == 0) goto geslp_done;
- has_strtab = find_elf_section_by_index(format, ELF_SHDR(format, *section, sh_link), &strtab);
+ /* Résolution précise d'adresse */
- get_elf_section_content(format, section, &start, &size, NULL);
+ virt = ELF_SYM(format, sym, st_value);
+ if (virt == 0) goto geslp_done;
- for (iter = start; iter < (start + size); )
- {
- result = read_elf_symbol(format, &iter, &sym);
- if (!result) break;
- /* On rejette les symboles qui ne sont pas définis au sein du binaire */
- if (ELF_SYM(format, sym, st_shndx) == 0) continue;
+ /* TODO */
-#if 0
+ //init_vmpa(&addr, VMPA_NO_PHYSICAL, ELF_SYM(format, sym, st_value));
- Elf64_Word st_name; /* Symbol name (string tbl index) */
- unsigned char st_info; /* Symbol type and binding */
- unsigned char st_other; /* Symbol visibility */
- Elf64_Section st_shndx; /* Section index */
- Elf64_Addr st_value; /* Symbol value */
- Elf64_Xword st_size; /* Symbol size */
-#endif
+ //init_mrange(&range, &addr, 0);
- if (ELF_SYM(format, sym, st_value) == 0) continue;
+ /* Première ébauche de nom */
- /* Résolution précise d'adresse */
+ g_elf_loading_get_internal_info(loading, &section, &use_virt, &strtab, &has_strtab, &first);
+ if (!has_strtab)
+ name = NULL;
- /* TODO */
+ else
+ name = get_elf_symbol_name(format, section, strtab,
+ ((*iter - first) / ELF_SIZEOF_SYM(format)) - 1);
- //init_vmpa(&addr, VMPA_NO_PHYSICAL, ELF_SYM(format, sym, st_value));
+ /* Traitements particuliers */
- virt = ELF_SYM(format, sym, st_value);
+ base = G_BIN_FORMAT(format);
- //init_mrange(&range, &addr, 0);
+ switch (ELF_ST_TYPE(format, sym))
+ {
+ case STT_OBJECT:
+ /* Ajustement de la position */
- /* Première ébauche de nom */
+ if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), virt, &addr))
+ {
+ symbol = NULL;
+ break;
+ }
- if (!has_strtab) name = NULL;
- else name = get_elf_symbol_name(format, section, &strtab,
- ((iter - start) / ELF_SIZEOF_SYM(format)) - 1);
+ /* Création d'un nom unique ? */
- /* Traitements particuliers */
+ if (name == NULL)
+ {
+ strcpy(alt_name, "obj_");
- switch (ELF_ST_TYPE(format, sym))
+ 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;
+
+ }
+
+
+ /* TODO */
+
+ symbol = NULL;
+
+
+ break;
+
+ case STT_FUNC:
+
+ /* Ajustement de la position */
+
+ if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
+ final_virt = virt & ~0x1;
+ else
+ final_virt = virt;
+
+ if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_virt, &addr))
{
- case STT_OBJECT:
+ symbol = NULL;
+ break;
+ }
- /* Ajustement de la position */
+ init_mrange(&range, &addr, ELF_SYM(format, sym, st_size));
- if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), virt, &addr))
- {
- symbol = NULL;
- break;
- }
+ /* Création d'un nom unique ? */
- /* Création d'un nom unique ? */
+ if (name == NULL)
+ {
+ strcpy(alt_name, "func_");
- if (name != NULL)
- {
- strcpy(alt_name, "obj_");
+ 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);
- 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;
- }
+ }
+ /* Routine */
- /* TODO */
+ routine = try_to_demangle_routine(name);
- symbol = NULL;
+ g_binary_routine_set_range(routine, &range);
+ /* Symbole uniquement */
- break;
+ symbol = g_binary_symbol_new(STP_ROUTINE);
+ g_binary_symbol_attach_routine(symbol, routine);
- case STT_FUNC:
+ /* Comptabilisation pour le désassemblage brut */
- /* Ajustement de la position */
+ g_binary_format_register_code_point(G_BIN_FORMAT(format), virt, false);
- if (ELF_HDR(format, format->header, e_machine) == EM_ARM)
- final_virt = virt & ~0x1;
- else
- final_virt = virt;
+ break;
- if (!g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), final_virt, &addr))
- {
- symbol = NULL;
- break;
- }
+ default:
+ symbol = NULL;
+ break;
- init_mrange(&range, &addr, ELF_SYM(format, sym, st_size));
+ }
- /* Création d'un nom unique ? */
+ if (symbol != NULL)
+ g_binary_format_add_symbol(base, symbol);
- if (name != NULL)
- {
- strcpy(alt_name, "func_");
+ geslp_done:
- 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);
+ 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 : - *
+* *
+******************************************************************************/
- /* Routine */
+static bool load_elf_internal_symbols(GElfFormat *format, wgroup_id_t gid, GtkStatusStack *status)
+{
+ bool result; /* Bilan à retourner */
+ bool no_name; /* Choix de construction de nom*/
+ 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 */
- printf("SYM ADDING>> '%s' @ 0x%08x\n", name, (unsigned int)virt);
+ result = true;
- routine = try_to_demangle_routine(name);
+ /* 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*/
- g_binary_routine_set_range(routine, &range);
+ get_elf_section_content(format, section, &start, &size, NULL);
- /* Symbole uniquement */
+ sym_size = ELF_SIZEOF_SYM(format);
- symbol = g_binary_symbol_new(STP_ROUTINE);
- g_binary_symbol_attach_routine(symbol, routine);
+ runs_count = g_get_num_processors();
- /* Comptabilisation pour le désassemblage brut */
+ run_size = size / (sym_size * runs_count);
- g_binary_format_register_code_point(base, virt, false);
+ gtk_status_stack_extend_activity(status, id, size / sym_size);
- break;
+ for (i = 0; i < runs_count; i++)
+ {
+ begin = start + i * run_size * sym_size;
- default:
- symbol = NULL;
- break;
+ if ((i + 1) == runs_count)
+ end = start + size;
+ else
+ end = begin + run_size * sym_size;
- }
+ loading = g_elf_loading_new(format, section, use_virt, start, begin, end,
+ id, do_elf_internal_symbol_loading);
- if (symbol != NULL)
- g_binary_format_add_symbol(base, symbol);
+ g_work_queue_schedule_work(wq, G_DELAYED_WORK(loading), gid);
}
- return true;
-
}
if (!g_generic_config_get_value(get_main_configuration(), MPK_FORMAT_NO_NAME, &no_name))
return false;
- if (find_elf_sections_by_type(format, SHT_DYNSYM, &sections, &count))
- for (i = 0; i < count && result; i++)
- result = add_all_symbols_from_section(format, &sections[i], no_name);
+ msg = gtk_status_stack_add_activity(status, _("Loading internal symbols..."), 0);
+
+ queue = get_work_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);
+
+ 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);
+
+ g_work_queue_wait_for_completion(get_work_queue(), gid);
+
+ gtk_status_stack_remove_activity(status, msg);
- if (find_elf_sections_by_type(format, SHT_SYMTAB, &sections, &count))
- for (i = 0; i < count && result; i++)
- result = add_all_symbols_from_section(format, &sections[i], no_name);
+ if (dynsym_sections != NULL) free(dynsym_sections);
+ if (symtab_sections != NULL) free(symtab_sections);
return result;