diff options
Diffstat (limited to 'plugins/dwarf/abbrev.c')
-rw-r--r-- | plugins/dwarf/abbrev.c | 1390 |
1 files changed, 1390 insertions, 0 deletions
diff --git a/plugins/dwarf/abbrev.c b/plugins/dwarf/abbrev.c new file mode 100644 index 0000000..f214430 --- /dev/null +++ b/plugins/dwarf/abbrev.c @@ -0,0 +1,1390 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * abbrev.c - manipulation des abréviation DWARF + * + * Copyright (C) 2008-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 "abbrev.h" + + +#include <malloc.h> + + +#include "dwarf-int.h" + + + + + +/* Description d'un attribut d'une abréviation */ +typedef struct _dw_abbrev_attr +{ + DwarfAttrib name; /* Sujet de l'élément */ + DwarfForm form; /* Représentation */ + +} dw_abbrev_attr; + + +/* Description d'une abréviation */ +struct _dw_abbrev +{ + uleb128_t code; /* Identifiant attribué */ + DwarfTag tag; /* Sujet de l'élément */ + + dw_abbrev_attr *attribs; /* Liste des attributs */ + size_t attribs_count; /* Nombre de ces attributs */ + + struct _dw_abbrev **children; /* Liste des sous-éléments */ + size_t children_count; /* Nombre de ces enfants */ + +}; + + + + + +/* Procède à la conversion de base d'une abréviation DWARF. */ +static bool check_abbreviation_decl(const GDwarfFormat *, const dw_abbrev_decl *, dw_abbrev *); + +/* Procède à la conversion d'un attribut d'abréviation DWARF. */ +static bool check_abbreviation_attrib(const GDwarfFormat *, const dw_abbrev_raw_attr *, dw_abbrev_attr *); + + + + + +/****************************************************************************** +* * +* Paramètres : format = informations de débogage à constituer. * +* * +* Description : Charge toutes les abbréviations présentes dans un DWARF. * +* * +* Retour : Bilan de l'opération, potentiellement un succès sans sortie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_all_dwarf_abbreviations(GDwarfFormat *format) +{ + bool result; /* Bilan à faire remonter */ + mrange_t range; /* Couverture d'une section */ + vmpa2t *pos; /* Position de tête de lecture */ + + result = g_exe_format_get_section_range_by_name(G_DBG_FORMAT(format)->executable, ".debug_abbrev", &range); + + pos = get_mrange_addr(&range); + + printf("start :: 0x%08x\n", (unsigned int)pos->physical); + + result &= load_dwarf_abbreviation(format, pos, &format->abbreviations); + + printf("abbrevs :: %p\n", format->abbreviations); + + if (format->abbreviations != NULL) + printf(" -> children : %zu\n", format->abbreviations->children_count); + else + printf(" -> (nothing)\n"); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations de débogage à consulter. * +* pos = tête de lecture à faire évoluer. * +* abbrev = abréviation lue et complète, NULL si aucune. [OUT] * +* * +* Description : Charge une abréviation valide pour un DWARF en mémoire. * +* * +* Retour : Bilan de l'opération, potentiellement un succès sans sortie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_dwarf_abbreviation(const GDwarfFormat *format, vmpa2t *pos, dw_abbrev **abbrev) +{ + dw_abbrev_decl decl; /* En-tête d'abréviation */ + bool status; /* Bilan d'une lecture */ + dw_abbrev_raw_attr attr; /* Attribut de l'abréviation */ + dw_abbrev *child; /* Rejeton à intégrer */ + + *abbrev = NULL; + + /** + * Cette routine est la transcription du paragraphe 7.5.3 ("Abbreviations Tables"), + * de la quatrième version de la définition du format DWARF. + * + * La spécification précise : + * + * As mentioned in Section 2.3, each chain of sibling entries is terminated by a null entry. + * + * Cependant, ce formalisme n'est pas constaté dans la pratique. D'ailleurs, readelf + * comporte le commentaire suivant dans le fichier 'dwarf_reader.cc' : + * + * Read the abbrev code. A zero here indicates the end of the abbrev table. + * + */ + + if (!read_dwarf_abbrev_decl(format, pos, &decl)) + goto lda_bad_exit; + + if (decl.code == 0) + goto lda_exit; + + *abbrev = (dw_abbrev *)calloc(1, sizeof(dw_abbrev)); + + if (!check_abbreviation_decl(format, &decl, *abbrev)) + goto lda_bad_exit; + + /* Chargement des attributs */ + + for (;;) + { + status = read_dwarf_abbrev_attr(format, pos, &attr); + if (!status) goto lda_bad_exit; + + printf(" -- [0x%llx] [0x%llx] name = %u\tform = %u\n", + (unsigned long long)pos->physical, + (unsigned long long)decl.code, + (unsigned int)attr.name, (unsigned int)attr.form); + + if (attr.name == DW_ATTR_invalid && attr.form == DW_FORM_invalid) + break; + + (*abbrev)->attribs_count++; + (*abbrev)->attribs = (dw_abbrev_attr *)realloc((*abbrev)->attribs, + (*abbrev)->attribs_count * sizeof(dw_abbrev_attr)); + + status = check_abbreviation_attrib(format, &attr, + &(*abbrev)->attribs[(*abbrev)->attribs_count - 1]); + if (!status) goto lda_bad_exit; + + } + + /* Chargement des enfants */ + + printf(" || children ? %d vs %d\n", (int)decl.has_children, (int)DW_CHILDREN_yes); + + if (decl.has_children == DW_CHILDREN_yes) + for (;;) + { + status = load_dwarf_abbreviation(format, pos, &child); + if (!status) goto lda_bad_exit; + + if (child == NULL) + break; + + (*abbrev)->children_count++; + (*abbrev)->children = (dw_abbrev **)realloc((*abbrev)->children, + (*abbrev)->children_count * sizeof(dw_abbrev)); + + (*abbrev)->children[(*abbrev)->children_count - 1] = child; + + } + + lda_exit: + + return true; + + lda_bad_exit: + + free_dwarf_abbreviation(*abbrev); + + return false; + +} + + +/****************************************************************************** +* * +* Paramètres : abbrev = abréviation chargée en mémoire à traiter. * +* * +* Description : Supprime de la mémoire toute trace d'une abréviation DWARF. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void free_dwarf_abbreviation(dw_abbrev *abbrev) +{ + size_t i; /* Boucle de parcours */ + + if (abbrev->attribs != NULL) + free(abbrev->attribs); + + if (abbrev->children != NULL) + { + for (i = 0; i < abbrev->children_count; i++) + free_dwarf_abbreviation(abbrev->children[i]); + + free(abbrev->attribs); + + } + + free(abbrev); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* decl = structure brute dont le contenu est à valider. * +* abbrev = abréviation à constituer à partir du brut. [OUT] * +* * +* Description : Procède à la conversion de base d'une abréviation DWARF. * +* * +* Retour : Validité confirmée ou non. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool check_abbreviation_decl(const GDwarfFormat *format, const dw_abbrev_decl *decl, dw_abbrev *abbrev) +{ + bool result; /* Validité à retourner */ + + result = (decl->has_children == DW_CHILDREN_no + || decl->has_children == DW_CHILDREN_yes); + + + /* TODO : vérifier les bornes de 'tag' */ + + + if (result) + { + abbrev->code = decl->code; + abbrev->tag = decl->tag; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations chargées à consulter. * +* decl = structure brute dont le contenu est à valider. * +* abbrev = abréviation à constituer à partir du brut. [OUT] * +* * +* Description : Procède à la conversion d'un attribut d'abréviation DWARF. * +* * +* Retour : Validité confirmée ou non. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool check_abbreviation_attrib(const GDwarfFormat *format, const dw_abbrev_raw_attr *attr, dw_abbrev_attr *attrib) +{ + bool result; /* Validité à retourner */ + + result = true; + + + /* TODO : vérifier les bornes de 'name' et 'form' */ + + + if (result) + { + attrib->name = attr->name; + attrib->form = attr->form; + + + + } + + return result; + +} + + + + + + + + +/****************************************************************************** +* * +* Paramètres : abbrev = abréviation chargée en mémoire à consulter. * +* * +* Description : Fournit l'étiquette associée à l'ensemble des attributs. * +* * +* Retour : Etiquette officielle de l'ensemble représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +DwarfTag dwarf_abbreviation_get_tag(const dw_abbrev *abbrev) +{ + return abbrev->tag; + +} + + +/****************************************************************************** +* * +* Paramètres : abbrev = abréviation chargée en mémoire à consulter. * +* * +* Description : Compte le nombre d'attributs présents dans une abréviation. * +* * +* Retour : Quantité d'attributs pris en compte dans l'abréviation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t dwarf_abbreviation_count_attribs(const dw_abbrev *abbrev) +{ + return abbrev->attribs_count; + +} + + +/****************************************************************************** +* * +* Paramètres : abbrev = abréviation chargée en mémoire à consulter. * +* attrib = désignation de l'attribut à retrouver. * +* index = indice de cet attribut dans l'ensemble. [OUT] * +* * +* Description : Recherche un attribut dans une abréviation. * +* * +* Retour : Indication sur le bilan des recherches. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool dwarf_abbreviation_get_attrib_index(const dw_abbrev *abbrev, DwarfAttrib attrib, size_t *index) +{ + bool result; /* Etat de validité à renvoyer */ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < abbrev->attribs_count; i++) + if (abbrev->attribs[i].name == attrib) + break; + + if (i < abbrev->attribs_count) + { + result = true; + *index = i; + } + else + result = false; + + return result; + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : abbrev = abréviation chargée en mémoire à consulter. * +* attrib = désignation de l'attribut à retrouver. * +* index = indice de cet attribut dans l'ensemble. * +* form = type de valeur attendu pour un attribut donné. [OUT]* +* * +* Description : Détermine le type d'un attribut dans une abréviation. * +* * +* Retour : Indication sur le bilan des accès. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool dwarf_abbreviation_get_form_for_index(const dw_abbrev *abbrev, size_t index, DwarfForm *form) +{ + if (index >= abbrev->attribs_count) + return false; + + *form = abbrev->attribs[index].form; + + return true; + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : abbrev = abréviation chargée en mémoire à consulter. * +* * +* Description : Indique si une abbréviation comporte des sous-définitions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool dwarf_abbreviation_has_children(const dw_abbrev *abbrev) +{ + return (abbrev->children_count > 0); + +} + + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : format = informations de débogage à consulter. * +* code = identifiant de l'abbréviation recherchée. * +* * +* Description : Recherche une abréviation DWARF donnée. * +* * +* Retour : Adresse d'une abréviation ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const dw_abbrev *find_dwarf_abbreviations(const GDwarfFormat *format, uleb128_t code) +{ + const dw_abbrev *result; /* Trouvaille à retourner */ + + if (format->abbreviations->code == code) + result = format->abbreviations; + + else + { + const dw_abbrev *_find_dwarf_abbreviations(const dw_abbrev *abbrev, uleb128_t c) + { + const dw_abbrev *found; /* Trouvaille à retourner */ + size_t i; /* Boucle de parcours */ + + if (abbrev->code == c) + found = abbrev; + else + { + found = NULL; + + for (i = 0; i < abbrev->children_count && found == NULL; i++) + found = _find_dwarf_abbreviations(abbrev->children[i], c); + + } + + return found; + + } + + result = _find_dwarf_abbreviations(format->abbreviations, code); + + } + + return result; + +} + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : format = contenu binaire de débogage à parcourir. * +* cu = unité de compilation parente. * +* form = nature de la valeur à lire. * +* pos = tête de lecture au sein des données. [OUT] * +* value = valeur au format donné lue. [OUT] * +* * +* Description : Lit la valeur correspondant à un type donné. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +dw_value *translate_abbreviation_attributes(const GDwarfFormat *format, const dw_abbrev *abbrev, const dw_compil_unit_header *cu, vmpa2t *pos) +{ + dw_value *result; /* Valeurs lues retournées */ + size_t i; /* Boucle de parcours */ + bool status; /* Bilan d'une lecture */ + + result = (dw_value *)calloc(abbrev->attribs_count, sizeof(dw_value)); + + for (i = 0; i < abbrev->attribs_count; i++) + { + result[i].attrib = abbrev->attribs[i].name; + + printf("-- loading attrib %x (%u) -- form = %x (%u) -- pos = %llx --\n", + (unsigned int)abbrev->attribs[i].name, + (unsigned int)abbrev->attribs[i].name, + (unsigned int)abbrev->attribs[i].form, + (unsigned int)abbrev->attribs[i].form, + (unsigned long long)(pos->physical - 0x1039)); + + status = G_DWARF_FORMAT_GET_CLASS(format)->read_form(format, cu, + abbrev->attribs[i].form, pos, &result[i].value); + if (!status) printf("[%zu] failed for %x\n", i, abbrev->attribs[i].form); + if (status) printf("[%zu] success for %x\n", i, abbrev->attribs[i].form); + printf(" current pos :: %llx\n", (unsigned long long)(pos->physical - 0x1039)); + if (!status) break; + + } + + if (i != abbrev->attribs_count) + { + free(result); + result = NULL; + } + + return result; + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#if 0 + +#include <malloc.h> +#include <stdarg.h> +#include <string.h> + + +#include "utils.h" + + + +#include <ctype.h> + + + +/* Libère de la mémoire une abréviation DWARF. */ +void free_dwarf_abbrev(dw_abbrev *); + +/* Charge une abréviations DWARF. */ +dw_abbrev *read_dwarf_abbreviations(dwarf_format *, off_t *, uint64_t *); + +/* Recherche une abréviation DWARF donnée. */ +const dw_abbrev *_find_dwarf_abbreviations(const dw_abbrev *, uint8_t *); + +/* Lit la valeur d'un attribut DWARF. */ +bool _read_dwarf_abbrev_attribute(dwarf_format *, off_t *, DwarfForm, ...); + + + +/****************************************************************************** +* * +* Paramètres : format = informations de débogage à compléter. * +* * +* Description : Charge les abréviations trouvées pour un DWARF. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_dwarf_abbreviations(dwarf_format *format) +{ + bool result; /* Bilan à renvoyer */ + + + + + off_t offset; + off_t start; + off_t size; + + bool test; + + int i; + + + dw_abbrev *abbrev; + uint64_t index; + + printf("Searching...\n"); + + + result = true; + + test = find_exe_section(DBG_FORMAT(format)->e_format, ".debug_abbrev", &start, &size, NULL); + + offset = start; + + + printf(" -> offset=%d size=%d\n", offset, size); + + + + for (i = 0; i < size; i++) + { + if (i % 10 == 0) printf("\n"); + printf("0x%02hhx ", DBG_FORMAT(format)->content[offset + i]); + } + + printf("\n"); + + + + + while (offset < (start + size)) + { + abbrev = read_dwarf_abbreviations(format, &offset, &index); + + offset++; /* 0x00 */ + + printf("abbrev :: %p\n", abbrev); + + if (abbrev != NULL) + { + abbrev->offset -= start; + + format->abbrevs = (dw_abbrev **)realloc(format->abbrevs, ++format->abbrevs_count * sizeof(dw_abbrev *)); + format->abbrevs[format->abbrevs_count - 1] = abbrev; + + printf(" %d attribs, %d children\n", abbrev->attribs_count, abbrev->children_count); + + } + else + { + unload_dwarf_abbreviations(format); + result = false; + break; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations de débogage à effacer. * +* * +* Description : Décharge les abréviations trouvées pour un DWARF. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_dwarf_abbreviations(dwarf_format *format) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < format->abbrevs_count; i++) + free_dwarf_abbrev(format->abbrevs[i]); + +} + + +/****************************************************************************** +* * +* Paramètres : abbrev = élément à supprimer de la mémoire. * +* * +* Description : Libère de la mémoire une abréviation DWARF. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void free_dwarf_abbrev(dw_abbrev *abbrev) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < abbrev->children_count; i++) + free_dwarf_abbrev(abbrev->children[i]); + + free(abbrev->attribs); + free(abbrev->children); + + free(abbrev); + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations de débogage à compléter. * +* pos = tête de lecture à mettre à jour. [OUT] * +* index = code de l'abréviation. [OUT] * +* * +* Description : Charge une abréviation DWARF. * +* * +* Retour : Adresse d'une abréviation ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +dw_abbrev *read_dwarf_abbreviations(dwarf_format *format, off_t *pos, uint64_t *index) +{ + dw_abbrev *result; /* Abréviation à retourner */ + bool has_children; /* Indique la présence de fils */ + uint64_t value1; /* Valeur quelconque lue #1 */ + uint64_t value2; /* Valeur quelconque lue #2 */ + uint64_t sub_index; /* Indice d'un sous-élément */ + dw_abbrev *child; /* Sous-élément à intégrer */ + + result = (dw_abbrev *)calloc(1, sizeof(dw_abbrev)); + + result->offset = *pos; + + /* Code de l'élément */ + if (!read_uleb128(format, pos, index, true)) goto rda_error; + + if (!read_uleb128(format, pos, &value1, true)) goto rda_error; + result->tag = value1; + + printf(" --ta :: 0x%02llx\n", value1); + + if (*pos >= DBG_FORMAT(format)->length) goto rda_error; + has_children = (DBG_FORMAT(format)->content[(*pos)++] == DW_CHILDREN_YES); + + printf(" --ch ? %d\n", has_children); + + /* Liste des attributs */ + + while (DBG_FORMAT(format)->content[*pos] != 0x00) + { + if (!read_uleb128(format, pos, &value1, true)) goto rda_error; + if (!read_uleb128(format, pos, &value2, true)) goto rda_error; + + result->attribs = (dw_abbrev_attr *)realloc(result->attribs, ++result->attribs_count * sizeof(dw_abbrev_attr)); + + result->attribs[result->attribs_count - 1].attrib = value1; + result->attribs[result->attribs_count - 1].form = value2; + + } + + (*pos) += 2; /* 0x00 0x00 */ + + /* Chargement des sous-éléments */ + + if (has_children) + while (DBG_FORMAT(format)->content[*pos] != 0x00) + { + child = read_dwarf_abbreviations(format, pos, &sub_index); + + if (child == NULL) goto rda_error; + + if ((sub_index - *index - 1) != result->children_count) goto rda_error; + + result->children = (dw_abbrev **)realloc(result->children, ++result->children_count * sizeof(dw_abbrev *)); + + result->children[result->children_count - 1] = child; + + } + + return result; + + rda_error: + + free_dwarf_abbrev(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : abbrev = abréviation racine à parcourir. * +* index = code de l'abréviation. [OUT] * +* * +* Description : Recherche une abréviation DWARF donnée. * +* * +* Retour : Adresse d'une abréviation ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const dw_abbrev *_find_dwarf_abbreviations(const dw_abbrev *abbrev, uint8_t *index) +{ + const dw_abbrev *result; /* Structure à retourner */ + size_t i; /* Boucle de parcours */ + + result = NULL; + + if (*index == 0) result = abbrev; + else + for (i = 0; i < abbrev->children_count && result == NULL; i++) + { + (*index)--; + result = _find_dwarf_abbreviations(abbrev->children[i], index); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations de débogage à consulter. * +* offset = position dans les abréviations. * +* pos = position dans le flux binaire courant. [OUT] * +* * +* Description : Recherche une abréviation DWARF donnée. * +* * +* Retour : Adresse d'une abréviation ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const dw_abbrev *find_dwarf_abbreviations(dwarf_format *format, const off_t *offset, off_t *pos) +{ + const dw_abbrev *result; /* Structure à retourner */ + uint64_t index; /* Code de l'abréviation */ + size_t i; /* Boucle de parcours */ + + result = NULL; + + do + { + if (!read_uleb128(format, pos, &index, true)) + { + printf("error skipping padding...\n"); + return NULL; + } + } + while (index == 0); + + for (i = 0; i < format->abbrevs_count; i++) + if (format->abbrevs[i]->offset == *offset) break; + + if (i < format->abbrevs_count) + { + index--; + result = _find_dwarf_abbreviations(format->abbrevs[i], &index); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : abbrev = informations à parcourir. * +* attrib = attribut visé par la lecture. * +* * +* Description : Indique la présence ou l'absence d'un attribut donné. * +* * +* Retour : true si l'attribut est présent, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool test_dwarf_abbrev_attribute(const dw_abbrev *abbrev, DwarfAttrib attrib) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + + result = false; + + for (i = 0; i < abbrev->attribs_count && !result; i++) + result = (abbrev->attribs[i].attrib == attrib); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations de débogage à compléter. * +* pos = tête de lecture à mettre à jour. [OUT] * +* form = format des données à lire. * +* ... = lieu d'enregistrement ou NULL. [OUT] * +* * +* Description : Lit la valeur d'un attribut DWARF. * +* * +* Retour : true si la lecture est un succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _read_dwarf_abbrev_attribute(dwarf_format *format, off_t *pos, DwarfForm form, ...) +{ + bool result; /* Bilan à revoyer */ + va_list ap; /* Adresse fournie en dernier */ + uint8_t *val8; /* Données sur 8 bits */ + uint16_t *val16; /* Données sur 16 bits */ + uint32_t *val32; /* Données sur 32 bits */ + uint64_t *val64; /* Données sur 64 bits */ + uint64_t *sval64; /* Données sur 64 bits (signée)*/ + bool *boolval; /* Valeur booléenne */ + uint8_t tmp8; /* Données sur 8 bits */ + uint16_t tmp16; /* Données sur 16 bits */ + uint32_t tmp32; /* Données sur 32 bits */ + uint64_t tmp64; /* Données sur 64 bits */ + uint64_t stmp64; /* Données sur 64 bits (signée)*/ + uint64_t size_to_read; /* Nombre d'octets à lire */ + off_t offset; /* Décalage dans une zone */ + char **strval; /* Chaîne de caractères */ + size_t length; /* Taille d'une chaîne */ + + va_start(ap, form); + + switch (form) + { + case DWF_ADDR: + result = ((*pos + (format->format == DWF_32_BITS ? 4 : 8)) <= DBG_FORMAT(format)->length); + if (result) + { + val64 = va_arg(ap, uint64_t *); + if (val64 != NULL) + { + if (format->format == DWF_32_BITS) + { + memcpy(&tmp32, &DBG_FORMAT(format)->content[*pos], 4); + *val64 = tmp32; + } + else memcpy(val64, &DBG_FORMAT(format)->content[*pos], 8); + } + *pos += (format->format == DWF_32_BITS ? 4 : 8); + } + break; + + case DWF_BLOCK2: + result = ((*pos + 2) <= DBG_FORMAT(format)->length); + if (result) + { + memcpy(&tmp16, &DBG_FORMAT(format)->content[*pos], 2); + size_to_read = tmp16; + /* ... */ + *pos += 2 + size_to_read; + } + break; + + case DWF_BLOCK4: + result = ((*pos + 4) <= DBG_FORMAT(format)->length); + if (result) + { + memcpy(&tmp32, &DBG_FORMAT(format)->content[*pos], 4); + size_to_read = tmp32; + /* ... */ + *pos += 4 + size_to_read; + } + break; + + case DWF_DATA2: + result = ((*pos + 2) <= DBG_FORMAT(format)->length); + if (result) + { + val16 = va_arg(ap, uint16_t *); + if (val16 != NULL) memcpy(val16, &DBG_FORMAT(format)->content[*pos], 2); + *pos += 2; + } + break; + + case DWF_DATA4: + result = ((*pos + 4) <= DBG_FORMAT(format)->length); + if (result) + { + val32 = va_arg(ap, uint32_t *); + if (val32 != NULL) memcpy(val32, &DBG_FORMAT(format)->content[*pos], 4); + *pos += 4; + } + break; + + case DWF_DATA8: + result = ((*pos + 8) <= DBG_FORMAT(format)->length); + if (result) + { + val64 = va_arg(ap, uint64_t *); + if (val64 != NULL) memcpy(val64, &DBG_FORMAT(format)->content[*pos], 8); + *pos += 8; + } + break; + + case DWF_STRING: + result = ((*pos + 1) <= DBG_FORMAT(format)->length); + if (result) + { + strval = va_arg(ap, char **); + if (strval != NULL) *strval = (char *)calloc(1, sizeof(char)); + length = 0; + + while (result) + { + if (DBG_FORMAT(format)->content[*pos] == '\0') break; + + length++; + + if (strval != NULL) + { + *strval = (char *)realloc(*strval, (length + 1) * sizeof(char)); + (*strval)[length - 1] = DBG_FORMAT(format)->content[*pos]; + } + + result = ((*pos + 1) <= DBG_FORMAT(format)->length); + if (!result) break; + + (*pos)++; + + } + + result = ((*pos + 1) <= DBG_FORMAT(format)->length); + + if (result) + { + (*pos)++; + + if (strval != NULL) + (*strval)[length] = 0; + + } + else if (strval != NULL) + { + free(*strval); + *strval = NULL; + } + + } + + break; + + case DWF_BLOCK: + result = read_uleb128(format, pos, &size_to_read, true); + result &= ((*pos + size_to_read) <= DBG_FORMAT(format)->length); + if (result) + { + /* ... */ + *pos += size_to_read; + } + break; + + case DWF_BLOCK1: + result = ((*pos + 1) <= DBG_FORMAT(format)->length); + if (result) + { + memcpy(&tmp8, &DBG_FORMAT(format)->content[*pos], 1); + size_to_read = tmp8; + /* ... */ + *pos += 1 + size_to_read; + } + break; + + case DWF_DATA1: + result = ((*pos + 1) <= DBG_FORMAT(format)->length); + if (result) + { + val8 = va_arg(ap, uint8_t *); + if (val8 != NULL) memcpy(val8, &DBG_FORMAT(format)->content[*pos], 1); + *pos += 1; + } + break; + + case DWF_FLAG: + result = ((*pos + 1) <= DBG_FORMAT(format)->length); + if (result) + { + boolval = va_arg(ap, bool *); + if (boolval != NULL) *boolval = (DBG_FORMAT(format)->content[*pos] != 0x00); + *pos += 1; + } + break; + + case DWF_SDATA: + sval64 = va_arg(ap, int64_t *); + if (sval64 == NULL) sval64 = &stmp64; + result = read_uleb128(format, pos, sval64, true); + break; + + case DWF_STRP: + result = read_abbrev_offset(format, pos, &offset); + if (result) + { + if (va_arg(ap, bool *) != NULL) + { + printf("TODO\n"); + exit(0); + } + /* + boolval = va_arg(ap, bool *); + if (boolval != NULL) *boolval = (DBG_FORMAT(format)->content[*pos] != 0x00); + */ + } + break; + + case DWF_UDATA: + val64 = va_arg(ap, uint64_t *); + if (val64 == NULL) val64 = &tmp64; + result = read_uleb128(format, pos, val64, true); + break; + + case DWF_REF_ADDR: + result = ((*pos + 4) <= DBG_FORMAT(format)->length); + + printf("bad at %d\n", __LINE__); exit(0); + + break; + + + case DWF_REF1: + result = ((*pos + 1) <= DBG_FORMAT(format)->length); + if (result) + { + val8 = va_arg(ap, uint8_t *); + if (val8 != NULL) memcpy(val8, &DBG_FORMAT(format)->content[*pos], 1); + *pos += 1; + } + break; + + case DWF_REF2: + result = ((*pos + 2) <= DBG_FORMAT(format)->length); + if (result) + { + val16 = va_arg(ap, uint16_t *); + if (val16 != NULL) memcpy(val16, &DBG_FORMAT(format)->content[*pos], 2); + *pos += 2; + } + break; + + case DWF_REF4: + result = ((*pos + 4) <= DBG_FORMAT(format)->length); + if (result) + { + val32 = va_arg(ap, uint32_t *); + if (val32 != NULL) memcpy(val32, &DBG_FORMAT(format)->content[*pos], 4); + *pos += 4; + } + break; + + case DWF_REF8: + result = ((*pos + 8) <= DBG_FORMAT(format)->length); + if (result) + { + val64 = va_arg(ap, uint64_t *); + if (val64 != NULL) memcpy(val64, &DBG_FORMAT(format)->content[*pos], 8); + *pos += 8; + } + break; + + case DWF_REF_UDATA: + result = ((*pos + 4) <= DBG_FORMAT(format)->length); + + printf("bad at %d\n", __LINE__); exit(0); + + break; + + + case DWF_INDIRECT: + result = ((*pos + 4) <= DBG_FORMAT(format)->length); + + printf("bad at %d\n", __LINE__); exit(0); + + break; + + + + + default: + result = false; + break; + + } + + va_end(ap); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations de débogage à compléter. * +* pos = tête de lecture à mettre à jour. [OUT] * +* update = indique si la position est à mettre à jour. * +* abbrev = informations à parcourir. * +* attrib = attribut visé par la lecture. * +* ... = lieu d'enregistrement ou NULL. [OUT] * +* * +* Description : Lit la valeur d'un attribut DWARF. * +* * +* Retour : true si la lecture est un succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool read_dwarf_abbrev_attribute(dwarf_format *format, off_t *pos, bool update, const dw_abbrev *abbrev, DwarfAttrib attrib, ...) +{ + bool result; /* Bilan à retourner */ + off_t curpos; /* Tête de lecture effective */ + size_t i; /* Boucle de parcours */ + va_list ap; /* Adresse fournie en dernier */ + + result = true; + + curpos = *pos; + + for (i = 0; i < abbrev->attribs_count && result; i++) + if (abbrev->attribs[i].attrib == attrib) break; + else result = _read_dwarf_abbrev_attribute(format, &curpos, abbrev->attribs[i].form, NULL); + + if (result) + { + va_start(ap, attrib); + + if (i < abbrev->attribs_count) + result = _read_dwarf_abbrev_attribute(format, &curpos, abbrev->attribs[i].form, va_arg(ap, void *)); + else + result = false; + + va_end(ap); + + } + + if (result && update) *pos = curpos; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = informations de débogage à compléter. * +* pos = tête de lecture à mettre à jour. [OUT] * +* abbrev = informations à survoler. * +* * +* Description : Fait avancer la tête de lecture d'une seule abréviation. * +* * +* Retour : true si l'opération est un succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool skip_dwarf_abbrev(dwarf_format *format, off_t *pos, const dw_abbrev *abbrev) +{ + bool result; /* Bilan à revoyer */ + size_t i; /* Boucle de parcours */ + uint64_t index; /* Code de padding */ + + result = true; + + /* Ecartement du corps */ + + for (i = 0; i < abbrev->attribs_count && result; i++) + result = _read_dwarf_abbrev_attribute(format, pos, abbrev->attribs[i].form, NULL); + + /* Ecartement du padding */ + + do + { + if (!read_uleb128(format, pos, &index, false)) + { + printf("error skipping padding...\n"); + return false; + } + + if (index == 0) + read_uleb128(format, pos, &index, true); + + } + while (index == 0); + + return result; + +} + +#endif |