/* 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 . */ #include "abbrev.h" #include #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 #include #include #include "utils.h" #include /* 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