/* 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 . */ #include "context.h" #include #include #include #include #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_args(GItaniumDemangling *context, itanium_component *comp) { assert(comp != NULL); assert(itd_get_component_type(comp) == ICT_TEMPLATE_ARGS); 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 */ itanium_component *targs; /* Racine des arguments */ itanium_component *iter; /* Boucle de parcours #1 */ if (context->targs_count == 0) result = NULL; else { targs = context->template_args[context->targs_count - 1]; for (iter = targs->unary; iter != NULL; iter = iter->binary.right) { assert(itd_get_component_type(iter) == ICT_TYPES_LIST); if (index == 0) break; index--; } if (iter != NULL) { result = iter->binary.left; 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) { size_t i; /* Boucle de parcours */ assert(comp != NULL); if (itd_get_component_type(comp) == ICT_STD_SUBST) return; for (i = 0; i < context->subst_count; i++) if (comp == context->substitutions[i]) 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; }