summaryrefslogtreecommitdiff
path: root/plugins/dwarf/abbrev.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/dwarf/abbrev.c')
-rw-r--r--plugins/dwarf/abbrev.c1390
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