/* Chrysalide - Outil d'analyse de fichiers binaires * dwarf.c - support du format Dwarf * * Copyright (C) 2009-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 . */ #include "dwarf.h" #include "abbrev.h" #include "dwarf-int.h" #include "info.h" #include "symbols.h" #include "../../common/cpp.h" /* Initialise la classe des formats de débogage DWARF. */ static void g_dwarf_format_class_init(GDwarfFormatClass *); /* Initialise une instance de format de débogage DWARF. */ static void g_dwarf_format_init(GDwarfFormat *); /* Supprime toutes les références externes. */ static void g_dwarf_format_dispose(GDwarfFormat *); /* Procède à la libération totale de la mémoire. */ static void g_dwarf_format_finalize(GDwarfFormat *); /****************************************************************************** * * * Paramètres : content = contenu binaire à parcourir. * * parent = éventuel format exécutable déjà chargé. * * unused = adresse non utilisée ici. * * key = identifiant de format trouvé ou NULL. [OUT] * * * * Description : Indique si le format peut être pris en charge ici. * * * * Retour : Conclusion de haut niveau sur la reconnaissance effectuée. * * * * Remarques : - * * * ******************************************************************************/ FormatMatchStatus dwarf_is_matching(GBinContent *content, GExeFormat *parent, void *unused, char **key) { FormatMatchStatus result; /* Bilan à renvoyer */ size_t i; /* Boucle de parcours */ mrange_t range; /* Couverture d'une section */ dw_section_header header; /* En-tête DWARF de section */ bool found; /* Bilan d'une comparaison */ static const char *section_names[] = { ".debug_aranges", ".debug_frame", ".debug_info", ".debug_line", ".debug_pubnames", ".debug_pubtypes", ".debug_types" }; static const uint16_t dwarf_v2_versions[] = { 2, /* .debug_aranges */ 1, /* .debug_frame */ 2, /* .debug_info */ 2, /* .debug_line */ 2, /* .debug_pubnames */ 0, /* .debug_pubtypes */ 0 /* .debug_types */ }; static const uint16_t dwarf_v3_versions[] = { 2, /* .debug_aranges */ 3, /* .debug_frame */ 3, /* .debug_info */ 3, /* .debug_line */ 2, /* .debug_pubnames */ 2, /* .debug_pubtypes */ 0 /* .debug_types */ }; static const uint16_t dwarf_v4_versions[] = { 2, /* .debug_aranges */ 4, /* .debug_frame */ 4, /* .debug_info */ 4, /* .debug_line */ 2, /* .debug_pubnames */ 2, /* .debug_pubtypes */ 4 /* .debug_types */ }; uint16_t current_versions[] = { 0, /* .debug_aranges */ 0, /* .debug_frame */ 0, /* .debug_info */ 0, /* .debug_line */ 0, /* .debug_pubnames */ 0, /* .debug_pubtypes */ 0 /* .debug_types */ }; result = FMS_UNKNOWN; if (parent == NULL) return FMS_UNKNOWN; return FMS_UNKNOWN; *key = strdup("dwarf_v4"); return FMS_MATCHED; /* Lecture des indices présents */ for (i = 0; i < ARRAY_SIZE(section_names); i++) { if (!g_exe_format_get_section_range_by_name(parent, section_names[i], &range)) continue; if (!read_dwarf_section_header(content, get_mrange_addr(&range), SRE_LITTLE /* FIXME */, &header)) continue; current_versions[i] = header.version; } /* Détermination d'une version bien identifiée */ bool check_dwarf_version(const uint16_t *ref, const uint16_t *cur, size_t count) { bool equal; size_t k; equal = true; for (k = 0; k < count && equal; k++) printf(" -> %hhu vs %hhu\n", ref[k], cur[k]); for (k = 0; k < count && equal; k++) equal = (cur[k] == 0) || (ref[k] == cur[k]); return equal; } /** * Un fichier DWARF sans section sera vu comme un fichier DWARF de * dernière génération. * Ce qui n'est pas très grave car rien ne sera chargé par la suite, * du fait de l'absence de section, donc il n'y aura pas d'incompatibilité. */ printf("---dwarf v4\n"); found = check_dwarf_version(dwarf_v4_versions, current_versions, ARRAY_SIZE(section_names)); if (found) { result = FMS_MATCHED; *key = strdup("dwarf_v4"); } if (result == FMS_UNKNOWN) { printf("---dwarf v3\n"); found = check_dwarf_version(dwarf_v3_versions, current_versions, ARRAY_SIZE(section_names)); if (found) { result = FMS_MATCHED; *key = strdup("dwarf_v3"); } } if (result == FMS_UNKNOWN) { printf("---dwarf v2\n"); found = check_dwarf_version(dwarf_v2_versions, current_versions, ARRAY_SIZE(section_names)); if (found) { result = FMS_MATCHED; *key = strdup("dwarf_v2"); } } return result; } /* Indique le type défini pour un format de débogage générique. */ G_DEFINE_TYPE(GDwarfFormat, g_dwarf_format, G_TYPE_DBG_FORMAT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des formats de débogage DWARF. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_dwarf_format_class_init(GDwarfFormatClass *klass) { GObjectClass *object; /* Autre version de la classe */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_dwarf_format_dispose; object->finalize = (GObjectFinalizeFunc)g_dwarf_format_finalize; } /****************************************************************************** * * * Paramètres : format = instance à initialiser. * * * * Description : Initialise une instance de format de débogage DWARF. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_dwarf_format_init(GDwarfFormat *format) { } /****************************************************************************** * * * Paramètres : format = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_dwarf_format_dispose(GDwarfFormat *format) { G_OBJECT_CLASS(g_dwarf_format_parent_class)->dispose(G_OBJECT(format)); } /****************************************************************************** * * * Paramètres : format = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_dwarf_format_finalize(GDwarfFormat *format) { G_OBJECT_CLASS(g_dwarf_format_parent_class)->finalize(G_OBJECT(format)); } /****************************************************************************** * * * Paramètres : format = description du binaire de débogage à compléter. * * executable = référence vers le binaire exécutable à lier. * * * * Description : Charge de façon générique toutes les informations DWARF. * * * * Retour : Bilan du chargement : réussi ou non ? * * * * Remarques : - * * * ******************************************************************************/ bool g_dwarf_format_load(GDwarfFormat *format, GExeFormat *executable) { bool result; /* Bilan à faire remonter */ result = true; g_debuggable_format_attach_executable(G_DBG_FORMAT(format), executable); printf("Loading abbrev...\n"); result &= load_all_dwarf_abbreviations(format); printf("Loading debug info...\n"); result &= load_dwarf_debug_information(format); printf("Done!\n"); result &= load_dwarf_symbols(format); printf("Got symbols...\n"); exit(0); return result; }