diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2016-05-19 21:21:30 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2016-05-19 21:21:30 (GMT) |
commit | f828d126a74facac145531822c6ea9c8259b50e0 (patch) | |
tree | 521bfa44de551f30934ee321339a7a87d12a3243 /src/format/elf/symbols.c | |
parent | e92c777c91612c8508d263645480c6c3889b679d (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.c | 328 |
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, §ion, &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, §ions, &count)) - for (i = 0; i < count && result; i++) - result = add_all_symbols_from_section(format, §ions[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, §ions, &count)) - for (i = 0; i < count && result; i++) - result = add_all_symbols_from_section(format, §ions[i], no_name); + if (dynsym_sections != NULL) free(dynsym_sections); + if (symtab_sections != NULL) free(symtab_sections); return result; |