summaryrefslogtreecommitdiff
path: root/plugins/dwarf/symbols.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/dwarf/symbols.c')
-rw-r--r--plugins/dwarf/symbols.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/plugins/dwarf/symbols.c b/plugins/dwarf/symbols.c
new file mode 100644
index 0000000..3ddfb96
--- /dev/null
+++ b/plugins/dwarf/symbols.c
@@ -0,0 +1,316 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * symbols.c - gestion des symboles d'un DWARF
+ *
+ * Copyright (C) 2016-2017 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "symbols.h"
+
+
+#include "die.h"
+#include "dwarf-int.h"
+#include "form.h"
+#include "../../core/params.h"
+#include "../../mangling/demangler.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 = g_binary_format_decode_routine(G_BIN_FORMAT(format), name);
+ symbol = G_BIN_SYMBOL(routine);
+
+ g_binary_symbol_set_range(symbol, &range);
+
+ g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
+
+
+
+
+ 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_symbol_set_range(G_BIN_SYMBOL(routine), &range);
+
+ symbol = g_binary_symbol_new(NULL, STP_OBJECT);
+ g_binary_symbol_attach_routine(symbol, routine);
+
+ g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
+ */
+
+
+
+ //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;
+
+}