diff options
Diffstat (limited to 'src/format/dwarf/symbols.c')
-rw-r--r-- | src/format/dwarf/symbols.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/format/dwarf/symbols.c b/src/format/dwarf/symbols.c new file mode 100644 index 0000000..ceaee9e --- /dev/null +++ b/src/format/dwarf/symbols.c @@ -0,0 +1,318 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * symbols.c - gestion des symboles d'un DWARF + * + * Copyright (C) 2015 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "symbols.h" + + +#include "die.h" +#include "dwarf-int.h" +#include "form.h" +#include "../mangling/demangler.h" +#include "../../core/params.h" + + + +/* Charge les informations d'une routine en tant que symbole. */ +static bool load_routine_as_symbol_from_dwarf(GDwarfFormat *, const dw_die *, const dw_abbrev *, bool); + +/* Charge les informations d'un objet en tant que symbole. */ +static bool load_object_as_symbol_from_dwarf(GDwarfFormat *, const dw_die *, const dw_abbrev *, bool); + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* die = entrée d'informations de débogage à utiliser. * +* abbrev = abréviation déjà chargée sur laquelle s'appuyer. * +* use_virt = oriente le choix de la distinction ultime. * +* * +* Description : Charge les informations d'une routine en tant que symbole. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool load_routine_as_symbol_from_dwarf(GDwarfFormat *format, const dw_die *die, const dw_abbrev *abbrev, bool use_virt) +{ + DwarfForm form; /* Type d'une valeur d'attribut*/ + const dw_form_value *value; /* Valeur concrète d'attribut */ + virt_t virt; /* Adresse virtuelle de départ */ + bool status; /* Bilan d'une récupération */ + virt_t len; /* Taille de la zone couverte */ + vmpa2t addr; /* Localisation complète */ + mrange_t range; /* Espace de couverture total */ + const char *name; /* Désignation humaine */ + char alt_name[6 + VMPA_MAX_LEN]; /* Nom abstrait de substitution*/ + GBinRoutine *routine; /* Nouvelle routine trouvée */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + + /* Surface couverte */ + + value = dw_die_peek_extended_value(die, DW_AT_low_pc, &form); + if (value == NULL) goto lrasfd_bad_start; + + status = translate_form_into_address(value, form, &virt); + if (!status) goto lrasfd_bad_start; + + value = dw_die_peek_extended_value(die, DW_AT_high_pc, &form); + if (value == NULL) goto lrasfd_bad_start; + + status &= translate_form_into_address(value, form, &len); + if (!status) goto lrasfd_bad_start; + + if (!g_exe_format_translate_address_into_vmpa(G_DBG_FORMAT(format)->executable, virt, &addr)) + init_vmpa(&addr, VMPA_NO_PHYSICAL, virt); + + init_mrange(&range, &addr, len); + + /* Désignation humaine */ + + value = dw_die_peek_extended_value(die, DW_AT_name, &form); + if (value == NULL) goto lrasfd_bad_name; + + name = translate_form_into_string(value, form); + + if (name == NULL) + { + strcpy(alt_name, "func_"); + + 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); + + name = alt_name; + + } + + /* Intégration en bonne et due forme */ + + routine = try_to_demangle_routine(name); + + g_binary_routine_set_range(routine, &range); + + symbol = g_binary_symbol_new(STP_ROUTINE); + g_binary_symbol_attach_routine(symbol, routine); + + _g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol, false); + + + + + printf(" --> [valid ?= %d] start @ 0x%08llx\n", status, virt); + printf(" --> [valid ?= %d] len = 0x%08llx\n", status, len); + printf(" --> [valid ?= %d] name = '%s'\n", status, name); + + + return true; + + lrasfd_bad_start: + lrasfd_bad_name: + + return false; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* die = entrée d'informations de débogage à utiliser. * +* abbrev = abréviation déjà chargée sur laquelle s'appuyer. * +* use_virt = oriente le choix de la distinction ultime. * +* * +* Description : Charge les informations d'un objet en tant que symbole. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool load_object_as_symbol_from_dwarf(GDwarfFormat *format, const dw_die *die, const dw_abbrev *abbrev, bool use_virt) +{ + DwarfForm form; /* Type d'une valeur d'attribut*/ + const dw_form_value *value; /* Valeur concrète d'attribut */ + virt_t virt; /* Adresse virtuelle de départ */ + bool status; /* Bilan d'une récupération */ + virt_t len; /* Taille de la zone couverte */ + vmpa2t addr; /* Localisation complète */ + mrange_t range; /* Espace de couverture total */ + const char *name; /* Désignation humaine */ + char alt_name[5 + VMPA_MAX_LEN]; /* Nom abstrait de substitution*/ + GBinRoutine *routine; /* Nouvelle routine trouvée */ + GBinSymbol *symbol; /* Nouveau symbole construit */ + + /* Surface couverte */ + + + + + + + /* + value = dw_die_peek_extended_value(die, DW_AT_low_pc, &form); + if (value == NULL) goto lrasfd_bad_start; + + status = translate_form_into_address(value, form, &virt); + if (!status) goto lrasfd_bad_start; + + value = dw_die_peek_extended_value(die, DW_AT_high_pc, &form); + if (value == NULL) goto lrasfd_bad_start; + + status &= translate_form_into_address(value, form, &len); + if (!status) goto lrasfd_bad_start; + + if (!g_exe_format_translate_address_into_vmpa(G_DBG_FORMAT(format)->executable, virt, &addr)) + init_vmpa(&addr, VMPA_NO_PHYSICAL, virt); + + init_mrange(&range, &addr, len); + */ + + + + + + /* Désignation humaine */ + + value = dw_die_peek_extended_value(die, DW_AT_name, &form); + if (value == NULL) goto lrasfd_bad_name; + + name = translate_form_into_string(value, form); + + 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); + + name = alt_name; + + } + + /* Intégration en bonne et due forme */ + + /* + routine = try_to_demangle_routine(name); + + g_binary_routine_set_range(routine, &range); + + symbol = g_binary_symbol_new(STP_OBJECT); + g_binary_symbol_attach_routine(symbol, routine); + + _g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol, false); + */ + + + + //printf(" --> [valid ?= %d] start @ 0x%08llx\n", status, virt); + //printf(" --> [valid ?= %d] len = 0x%08llx\n", status, len); + printf(" --> [valid ?= %d] name = '%s'\n", status, name); + + + return true; + + lrasfd_bad_start: + lrasfd_bad_name: + + return false; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* * +* Description : Charge en mémoire la liste humaine des symboles. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_dwarf_symbols(GDwarfFormat *format) +{ + bool result; /* Bilan à retourner */ + bool no_name; /* Choix de construction de nom*/ + + typedef struct _die_visit_info + { + GDwarfFormat *format; + bool use_virt; + + } die_visit_info; + + die_visit_info vinfo; /* Information pour visiteur */ + + + bool catch_dwarf_symbol(const dw_die *die, die_visit_info *info) + { + const dw_abbrev *abbrev; /* Lien vers la représentation */ + DwarfTag tag; /* Etiquette à analyser */ + bool status; /* Bilan d'un chargement */ + + abbrev = dw_die_get_abbrev(die); + tag = dwarf_abbreviation_get_tag(abbrev); + + switch (tag) + { + case DW_TAG_subprogram: + printf(" DIE ==> %p -> %p // tag = %x\n", die, abbrev, tag); + status = load_routine_as_symbol_from_dwarf(info->format, die, abbrev, info->use_virt); + break; + + case DW_TAG_variable: + printf(" DIE ==> %p -> %p // tag = %x\n", die, abbrev, tag); + status = load_object_as_symbol_from_dwarf(info->format, die, abbrev, info->use_virt); + break; + + default: + status = true; + break; + + } + + return status; + + } + + + if (!g_generic_config_get_value(get_main_configuration(), MPK_FORMAT_NO_NAME, &no_name)) + return false; + + vinfo.format = format; + vinfo.use_virt = no_name; + + result = dw_die_visit(format->info_die, (visit_dies_fc)catch_dwarf_symbol, &vinfo); + + return result; + +} |