diff options
Diffstat (limited to 'plugins/itanium/context.c')
-rw-r--r-- | plugins/itanium/context.c | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/plugins/itanium/context.c b/plugins/itanium/context.c new file mode 100644 index 0000000..1d2c365 --- /dev/null +++ b/plugins/itanium/context.c @@ -0,0 +1,516 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * context.c - contexte de décodage à la sauce ABI C++ Itanium + * + * Copyright (C) 2013-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 "context.h" + + +#include <assert.h> +#include <malloc.h> +#include <string.h> + + +#include <mangling/context-int.h> + + +#include "abi.h" +#include "component-int.h" + + + +/* Contexte de décodage Itanium (instance) */ +struct _GItaniumDemangling +{ + GDemanglingContext parent; /* A laisser en premier */ + + itanium_component **template_args; /* Paramètres de modèle */ + size_t targs_count; /* Quantité utilisée */ + + itanium_component **substitutions; /* Table de substitutions */ + size_t subst_count; /* Quantité utilisée */ + +}; + +/* Contexte de décodage Itanium (classe) */ +struct _GItaniumDemanglingClass +{ + GDemanglingContextClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des contextes de décodage. */ +static void g_itanium_demangling_class_init(GItaniumDemanglingClass *); + +/* Initialise une instance de contexte pour décodage. */ +static void g_itanium_demangling_init(GItaniumDemangling *); + +/* Supprime toutes les références externes. */ +static void g_itanium_demangling_dispose(GItaniumDemangling *); + +/* Procède à la libération totale de la mémoire. */ +static void g_itanium_demangling_finalize(GItaniumDemangling *); + +/* Prépare l'environnement de contexte pour un décodage Itanium. */ +static void g_itanium_demangling_prepare(GItaniumDemangling *); + +/* Valide un composant final issu d'un décodage Itanium. */ +static void g_itanium_demangling_check(GItaniumDemangling *, itanium_component **); + +/* Décode une définition de type pour Itanium. */ +static GDataType *g_itanium_demangling_decode_type(GItaniumDemangling *); + +/* Décode une définition de routine pour Itanium. */ +static GBinRoutine *g_itanium_demangling_decode_routine(GItaniumDemangling *); + + + +/* Indique le type défini pour un contexte de décodage. */ +G_DEFINE_TYPE(GItaniumDemangling, g_itanium_demangling, G_TYPE_DEMANGLING_CONTEXT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des contextes de décodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_itanium_demangling_class_init(GItaniumDemanglingClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDemanglingContextClass *context; /* Version de base du contexte */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_itanium_demangling_dispose; + object->finalize = (GObjectFinalizeFunc)g_itanium_demangling_finalize; + + context = G_DEMANGLING_CONTEXT_CLASS(klass); + + context->decode_type = (decode_type_fc)g_itanium_demangling_decode_type; + context->decode_routine = (decode_routine_fc)g_itanium_demangling_decode_routine; + +} + + +/****************************************************************************** +* * +* Paramètres : context = instance à initialiser. * +* * +* Description : Initialise une instance de contexte pour décodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_itanium_demangling_init(GItaniumDemangling *context) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : context = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_itanium_demangling_dispose(GItaniumDemangling *context) +{ + G_OBJECT_CLASS(g_itanium_demangling_parent_class)->dispose(G_OBJECT(context)); + +} + + +/****************************************************************************** +* * +* Paramètres : context = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_itanium_demangling_finalize(GItaniumDemangling *context) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < context->targs_count; i++) + itd_unref_comp(context->template_args[i]); + + if (context->template_args != NULL) + free(context->template_args); + + for (i = 0; i < context->subst_count; i++) + itd_unref_comp(context->substitutions[i]); + + if (context->substitutions != NULL) + free(context->substitutions); + + G_OBJECT_CLASS(g_itanium_demangling_parent_class)->finalize(G_OBJECT(context)); + +} + + +/****************************************************************************** +* * +* Paramètres : context = environnement de décodage à manipuler. * +* * +* Description : Prépare l'environnement de contexte pour un décodage Itanium.* +* * +* Retour : - . * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_itanium_demangling_prepare(GItaniumDemangling *context) +{ + input_buffer *ibuf; /* Tampon de texte manipulé */ + size_t len; /* Taille de chaîne à traiter */ + + /** + * On part du principe qu'il n'y aura jamais plus de paramètres de modèle + * ou de substitutions à enregistrer que de caractères dans la chaîne à traiter. + * Du coup, on peut tout allouer d'un coup ! + */ + + assert(context->template_args == NULL); + + assert(context->substitutions == NULL); + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + len = get_input_buffer_size(ibuf); + + context->template_args = (itanium_component **)malloc(len * sizeof(itanium_component *)); + + context->substitutions = (itanium_component **)malloc(len * sizeof(itanium_component *)); + +} + + +/****************************************************************************** +* * +* Paramètres : context = environnement de décodage à manipuler. * +* comp = composant final à valider. [OUT] * +* * +* Description : Valide un composant final issu d'un décodage Itanium. * +* * +* Retour : - . * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_itanium_demangling_check(GItaniumDemangling *context, itanium_component **comp) +{ + input_buffer *ibuf; /* Tampon de texte manipulé */ + size_t remaining; /* Données restant à consommer */ + + if (*comp != NULL) + { + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + remaining = count_input_buffer_remaining(ibuf); + + if (remaining > 0) + { + itd_unref_comp(*comp); + *comp = NULL; + } + + } + +} + + +/****************************************************************************** +* * +* Paramètres : context = environnement de décodage à manipuler. * +* * +* Description : Décode une définition de type pour Itanium. * +* * +* Retour : Nouvelle instance créée ou NULL en cas d'erreur fatale. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GDataType *g_itanium_demangling_decode_type(GItaniumDemangling *context) +{ + GDataType *result; /* Type construit à retourner */ + itanium_component *comp; /* Composants décodés */ + + g_itanium_demangling_prepare(context); + + comp = itd_mangled_name(context); + + g_itanium_demangling_check(context, &comp); + + if (comp == NULL) + result = NULL; + + else + { + result = itd_translate_component_to_type(comp); + + itd_unref_comp(comp); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = environnement de décodage à manipuler. * +* * +* Description : Décode une définition de routine pour Itanium. * +* * +* Retour : Nouvelle instance créée ou NULL en cas d'erreur fatale. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBinRoutine *g_itanium_demangling_decode_routine(GItaniumDemangling *context) +{ + GBinRoutine *result; /* Routine en place à retourner*/ + itanium_component *comp; /* Composants décodés */ + + g_itanium_demangling_prepare(context); + + comp = itd_mangled_name(context); + + g_itanium_demangling_check(context, &comp); + + if (comp == NULL) + result = NULL; + + else + { + result = itd_translate_component_to_routine(comp); + + itd_unref_comp(comp); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à manipuler. * +* state = état courant à sauvegarder. [OUT] * +* * +* Description : Fournit l'état courant à une fin de retour en arrière. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_itanium_demangling_push_state(const GItaniumDemangling *context, itd_state *state) +{ + input_buffer *ibuf; /* Tampon de texte manipulé */ + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + save_input_buffer_pos(ibuf, &state->pos); + state->targs_count = context->targs_count; + state->subst_count = context->subst_count; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à manipuler. * +* state = état courant à restaurer. * +* * +* Description : Définit l'état courant suite à un retour en arrière. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_itanium_demangling_pop_state(GItaniumDemangling *context, const itd_state *state) +{ + size_t i; /* Boucle de parcours */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + + for (i = state->targs_count; i < context->targs_count; i++) + itd_unref_comp(context->template_args[i]); + + for (i = state->subst_count; i < context->subst_count; i++) + itd_unref_comp(context->substitutions[i]); + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + restore_input_buffer_pos(ibuf, state->pos); + context->targs_count = state->targs_count; + context->subst_count = state->subst_count; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à manipuler. * +* comp = composant à conserver en mémoire. * +* * +* Description : Indexe un composant représentant un argument de modèle. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_itanium_demangling_add_template_arg(GItaniumDemangling *context, itanium_component *comp) +{ + assert(comp != NULL); + + context->template_args[context->targs_count++] = comp; + itd_ref_comp(comp); + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à manipuler. * +* index = indice de l'argument visé. * +* * +* Description : Fournit un composant représentant un argument de modèle. * +* * +* Retour : Composant déjà extrait et conservé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *g_itanium_demangling_get_template_arg(GItaniumDemangling *context, size_t index) +{ + itanium_component *result; /* Composant à retourner */ + + if (index < context->targs_count) + { + result = context->template_args[index]; + itd_ref_comp(result); + } + else + result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à manipuler. * +* comp = composant à conserver en mémoire. * +* * +* Description : Indexe un composant comme future substitution potentielle. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_itanium_demangling_add_substitution(GItaniumDemangling *context, itanium_component *comp) +{ + fnv64_t hash; /* Empreinte du candidat */ + size_t i; /* Boucle de parcours */ + + assert(comp != NULL); + + hash = itd_hash_comp(comp); + + for (i = 0; i < context->subst_count; i++) + if (cmp_fnv_64a(itd_hash_comp(context->substitutions[i]), hash) == 0) + break; + + if (i == context->subst_count) + { + context->substitutions[context->subst_count++] = comp; + itd_ref_comp(comp); + } + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à manipuler. * +* index = indice de la substitution visée. * +* * +* Description : Fournit un composant en place pour une substitution. * +* * +* Retour : Composant déjà extrait et conservé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *g_itanium_demangling_get_substitution(GItaniumDemangling *context, size_t index) +{ + itanium_component *result; /* Composant à retourner */ + + if (index < context->subst_count) + { + result = context->substitutions[index]; + itd_ref_comp(result); + } + else + result = NULL; + + return result; + +} |