/* Chrysalide - Outil d'analyse de fichiers binaires * die.c - gestion des entrées renvoyant à des informations de débogage * * 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 . */ #include "die.h" #include #include #include "dwarf-int.h" /** * § 2.1 The Debugging Information Entry (DIE). */ typedef struct _dw_die { unsigned int level; /* Niveau hiérarchique */ phys_t offset; /* Position dans le flux */ const dw_abbrev *abbrev; /* Lien vers la représentation */ dw_value *values; /* Liste des valeurs associées */ bool has_children; /* Feuille ou noeud de l'arbre */ struct _dw_die **children; /* Liste d'éventuels enfants */ size_t children_count; /* Taille de cette liste */ } dw_die; /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * * pos = position de début de lecture. [OUT] * * endian = boutisme reconnu dans le format. * * header = en-tête de description de l'unité à traiter. * * die = emplacement de stockage de l'entrée ou NULL. [OUT] * * * * Description : Procède à la lecture de l'en-tête d'une unité de compilation.* * * * Retour : Bilan de l'opération. * * * * Remarques : Le format autorise à ne rien produire ici légitimement. * * * ******************************************************************************/ bool build_dwarf_die(GDwarfFormat *format, vmpa2t *pos, SourceEndian endian, const dw_compil_unit_header *header, dw_die **die) { uleb128_t code; /* Code de la description liée */ bool status; /* Bilan de la lecture */ const dw_abbrev *abbrev; /* Lien vers la représentation */ dw_value *values; /* Liste des valeurs associées */ *die = NULL; /** * § 7.5.2 Debugging Information Entry. */ status = g_binary_content_read_uleb128(G_BIN_FORMAT(format)->content, pos, &code); if (!status) return false; printf("[ok] code = 0x%llx\n", (unsigned long long)code); if (code == 0) return true; abbrev = find_dwarf_abbreviations(format, code); printf("[ok] abbrev = %p\n", abbrev); printf("----------------------\n"); values = translate_abbreviation_attributes(format, abbrev, header, pos); if (values == NULL) return false; printf("[ok] values = %p\n", values); *die = (dw_die *)calloc(1, sizeof(dw_die)); (*die)->abbrev = abbrev; (*die)->values = values; (*die)->has_children = dwarf_abbreviation_has_children(abbrev); return true; } /****************************************************************************** * * * Paramètres : die = entrée à libérer de la mémoire. * * * * Description : Supprime les éléments mis en place pour une entrée d'info. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void delete_dwarf_die(dw_die *die) { size_t i; /* Boucle de parcours */ if (die->values != NULL) free(die->values); for (i = 0; i < die->children_count; i++) delete_dwarf_die(die->children[i]); if (die->children != NULL) free(die->children); free(die); } /****************************************************************************** * * * Paramètres : die = entrée à consulter. * * * * Description : Fournit un lien vers l'abréviation de représentation. * * * * Retour : Structure de représentation en place. * * * * Remarques : - * * * ******************************************************************************/ const dw_abbrev *dw_die_get_abbrev(const dw_die *die) { return die->abbrev; } /****************************************************************************** * * * Paramètres : die = entrée à consulter. * * index = indice de cet attribut dans l'ensemble. * * * * Description : Fournit un lien vers l'abréviation de représentation. * * * * Retour : Valeur recherchée ou NULL en cas d'erreur. * * * * Remarques : - * * * ******************************************************************************/ const dw_form_value *dw_die_peek_value(const dw_die *die, size_t index) { dw_form_value *result; /* Valeur ciblée à retourner */ if (index >= dwarf_abbreviation_count_attribs(die->abbrev)) return NULL; result = &die->values[index].value; return result; } /****************************************************************************** * * * Paramètres : die = entrée d'information à consulter. * * attrib = désignation de l'attribut à retrouver. * * form = type de valeur attendu pour un attribut donné. [OUT]* * * * Description : Fournit un lien vers l'abréviation de représentation. * * * * Retour : Valeur recherchée ou NULL en cas d'erreur. * * * * Remarques : - * * * ******************************************************************************/ const dw_form_value *dw_die_peek_extended_value(const dw_die *die, DwarfAttrib attrib, DwarfForm *form) { const dw_form_value *result; /* Valeur ciblée à retourner */ size_t index; /* Indice d'élément à relire */ bool status; /* Bilan d'une récupération */ status = dwarf_abbreviation_get_attrib_index(die->abbrev, attrib, &index); if (!status) return NULL; status = dwarf_abbreviation_get_form_for_index(die->abbrev, index, form); if (!status) return NULL; result = dw_die_peek_value(die, index); return result; } /****************************************************************************** * * * Paramètres : die = entrée à consulter. * * * * Description : Indique si une entrée de débogage possède des enfants. * * * * Retour : true ou false selon la situation. * * * * Remarques : - * * * ******************************************************************************/ bool dw_die_has_children(const dw_die *die) { return die->has_children; } /****************************************************************************** * * * Paramètres : die = entrée à consulter. * * * * Description : Indique si une entrée de débogage possède des enfants. * * * * Retour : true ou false selon la situation. * * * * Remarques : - * * * ******************************************************************************/ void dw_die_append_child(dw_die *die, dw_die *child) { assert(die->has_children); die->children = (dw_die **)realloc(die->children, ++die->children_count * sizeof(dw_die *)); die->children[die->children_count - 1] = child; } /* ---------------------------------------------------------------------------------- */ /* TRAITEMENT PAR ENSEMBLES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : root = entrée première à consulter. * * visitor = intervention régulière à respecter. * * data = données quelconques à associer aux visites. * * * * Description : Entame une grande tournée de toutes les entrées présentes. * * * * Retour : true si l'opération s'est déroulée complètement, false sinon.* * * * Remarques : - * * * ******************************************************************************/ bool dw_die_visit(dw_die *root, visit_dies_fc visitor, void *data) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ result = visitor(root, data); for (i = 0; i < root->children_count && result; i++) result = dw_die_visit(root->children[i], visitor, data); return result; }