diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2013-12-29 14:07:38 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2013-12-29 14:07:38 (GMT) |
commit | 944461f7af1995b08783dc761772908ec7c204a6 (patch) | |
tree | 21a50208c650390e9649bb0892f94bab26d5fc8f /src/format/mangling/itanium/component.c | |
parent | 11634a93003e7b5dd339bb52f2cde04f29f4c4e4 (diff) |
Handled Itanium demangling with C code (first part).
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@361 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/format/mangling/itanium/component.c')
-rw-r--r-- | src/format/mangling/itanium/component.c | 714 |
1 files changed, 714 insertions, 0 deletions
diff --git a/src/format/mangling/itanium/component.c b/src/format/mangling/itanium/component.c new file mode 100644 index 0000000..09e13e2 --- /dev/null +++ b/src/format/mangling/itanium/component.c @@ -0,0 +1,714 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * component.c - représentation des composants extraits de l'ABI C++ Itanium + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA 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 Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "component.h" + + +#include <malloc.h> +#include <string.h> + + +#include "component-int.h" +#include "../../../common/extstr.h" +#include "../../../common/fnv1a.h" + + + + +/* Procédure à appliquer sur un composant visité */ +typedef void (* visit_comp_fc) (itanium_component *); + + + +#define reset_comp_hash(c) c->hash = 0 + +/* Visite les composants en présence. */ +static void visit_comp(itanium_component *, visit_comp_fc); + + + +/****************************************************************************** +* * +* Paramètres : comp = composant à traiter. * +* visitor = fonction à appliquer sur les composants présents. * +* * +* Description : Visite les composants en présence. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void visit_comp(itanium_component *comp, visit_comp_fc visitor) +{ + itanium_component *sub; /* Sous-partie de composant */ + + switch (comp->type) + { + case ICT_NESTED_NAME: + case ICT_TEMPLATE_NAME_ARGS: + visit_comp(comp->binary.left, visitor); + visit_comp(comp->binary.right, visitor); + break; + + case ICT_PREFIX_UNARY: + case ICT_TPREFIX_UNARY: + visit_comp(comp->unary, visitor); + break; + + case ICT_PREFIX_BINARY: + case ICT_TPREFIX_BINARY: + visit_comp(comp->binary.left, visitor); + visit_comp(comp->binary.right, visitor); + break; + + case ICT_FUNCTION_THUNK: + visit_comp(comp->binary.left, visitor); + visit_comp(comp->binary.right, visitor); + break; + + case ICT_FUNCTION_COVARIANT_THUNK: + visit_comp(comp->ternary.first, visitor); + visit_comp(comp->ternary.second, visitor); + visit_comp(comp->ternary.third, visitor); + break; + + case ICT_POINTER_TO: + visit_comp(comp->unary, visitor); + break; + + case ICT_REFERENCE_TO: + visit_comp(comp->unary, visitor); + break; + + case ICT_RVALUE_REFERENCE_TO: + visit_comp(comp->unary, visitor); + break; + + case ICT_COMPLEX_PAIR: + visit_comp(comp->unary, visitor); + break; + + case ICT_IMAGINARY: + visit_comp(comp->unary, visitor); + break; + + case ICT_FUNCTION_ENCODING: + + /* Retour ? */ + + sub = NULL;//IT_BINARY_COMP(IT_BINARY_COMP(comp).right).left; + + if (sub != NULL) + visit_comp(sub, visitor); + + /* Nom de la fonction */ + visit_comp(comp->binary.left, visitor); + + visit_comp(comp->binary.right, visitor); + + break; + + case ICT_TEMPLATE_ARGS: + visit_comp(comp->unary, visitor); + break; + + case ICT_TYPES_LIST: + + visit_comp(comp->binary.left, visitor); + + if (comp->binary.right != NULL) + visit_comp(comp->binary.right, visitor); + + break; + + default: + break; + + } + + visitor(comp); + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant à mettre à jour. * +* * +* Description : Incrémente le nombre d'utilisation du composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void itd_ref_comp(itanium_component *comp) +{ + void visit_for_ref(itanium_component *comp) + { + comp->refcount++; + + } + + visit_comp(comp, visit_for_ref); + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant à mettre à jour. * +* * +* Description : Décrémente le nombre d'utilisation du composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void itd_unref_comp(itanium_component *comp) +{ + return; + + void visit_for_unref(itanium_component *comp) + { + if (--comp->refcount == 0) + { + if (comp->type == ICT_TYPE) + g_object_unref(G_OBJECT(comp->dtype)); + + g_itanium_dcontext_mark_component_as_free(comp->context, comp); + + } + + } + + visit_comp(comp, visit_for_unref); + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant à manipuler. * +* * +* Description : Détermine ou fournit l'empreinte d'un composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +fnv64_t itd_hash_comp(itanium_component *comp) +{ + char *desc; /* Description du composant */ + + if (comp->hash == 0) + { + desc = itd_translate_component(comp->context, comp, NULL); + comp->hash = fnv_64a_hash(desc); + free(desc); + } + + return comp->hash; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_empty(GItaniumDContext *context) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = g_itanium_dcontext_get_empty_component(context); + + result->type = ICT_EMPTY; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* str = chaîne de caractères à conserver. * +* len = taille de l'identifiant à retrouver. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_name(GItaniumDContext *context, const char *str, size_t len) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = g_itanium_dcontext_get_empty_component(context); + + result->type = ICT_NAME; + result->s_name.str = str; + result->s_name.len = len; + + return result; + +} + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* info = information de base sur l'opérateur manipulé. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_operator(GItaniumDContext *context, const itanium_operator_info *info) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = g_itanium_dcontext_get_empty_component(context); + + result->type = ICT_OPERATOR_NAME; + result->operator.otype = IOT_SIMPLE; + result->operator.info = *info; + + return result; + +} + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* type = type exacte de décallage. * +* offset = décallage extrait de l'encodage. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_offset(GItaniumDContext *context, ItaniumComponentType type, ssize_t offset) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = g_itanium_dcontext_get_empty_component(context); + + result->type = type; + result->offset = offset; + + return result; + +} + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* dtype = instance de type en place à conserver. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_type(GItaniumDContext *context, GDataType *dtype) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = g_itanium_dcontext_get_empty_component(context); + + result->type = ICT_TYPE; + result->dtype = dtype; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* type = type du composant à mettre en place. * +* left = premier composant à associer. * +* right = second composant à associer. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_binary(GItaniumDContext *context, ItaniumComponentType type, itanium_component *left, itanium_component *right) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = g_itanium_dcontext_get_empty_component(context); + + result->type = type; + result->binary.left = left; + result->binary.right = right; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* type = type du composant à mettre en place. * +* left = second composant à associer. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_append_right_to_binary(GItaniumDContext *context, ItaniumComponentType type, itanium_component *parent, itanium_component *left) +{ + itanium_component *result; /* Composant à renvoyer */ + itanium_component *iter; /* Boucle de parcours */ + + result = g_itanium_dcontext_get_empty_component(context); + + result->type = type; + result->binary.left = left; + + if (parent != NULL) + { + for (iter = parent; iter->binary.right != NULL; iter = iter->binary.right) + reset_comp_hash(iter); + iter->binary.right = result; + } + + return (parent != NULL ? parent : result); + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* type = type du composant à mettre en place. * +* unary = sous-composant à associer. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_unary(GItaniumDContext *context, ItaniumComponentType type, itanium_component *unary) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = g_itanium_dcontext_get_empty_component(context); + + result->type = type; + result->unary = unary; + + return result; + +} + + + + + +/****************************************************************************** +* * +* Paramètres : comp = composant à mettre à jour. * +* type = type à redéfinir pour le composant. * +* * +* Description : Modifie légèrement le type d'un composant donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void itd_set_type(itanium_component *comp, ItaniumComponentType type) +{ + comp->type = type; + + reset_comp_hash(comp); + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant à consulter. * +* * +* Description : Fournit le type d'un composant issu d'un contexte Itanium. * +* * +* Retour : Type enregistré. * +* * +* Remarques : - * +* * +******************************************************************************/ + +ItaniumComponentType itd_get_component_type(const itanium_component *comp) +{ + return comp->type; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* comp = second composant à associer. * +* base = éventuelle base à compléter ou NULL si aucune. * +* * +* Description : Traduit les composants de contexte Itanium. * +* * +* Retour : Traduction en format humainement lisible effectuée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *itd_translate_component(GItaniumDContext *context, const itanium_component *comp, char *base) +{ + char *result; /* Chaîne à retourner */ + char *name; /* Désignation à copier */ + const itanium_component *sub; /* Sous-partie de composant */ + + //if (base != NULL) + //printf(".... %s\n", base); + + switch (comp->type) + { + case ICT_EMPTY: + result = base; + break; + + case ICT_NAME: + case ICT_STD_SUBST: + result = strnadd(base, comp->s_name.str, comp->s_name.len); + break; + + case ICT_NESTED_NAME: + result = itd_translate_component(context, comp->binary.left, base); + if (comp->binary.right->type != ICT_TEMPLATE_ARGS) + result = stradd(result, "::"); + result = itd_translate_component(context, comp->binary.right, result); + break; + + case ICT_TEMPLATE_NAME_ARGS: + result = itd_translate_component(context, comp->binary.left, base); + result = itd_translate_component(context, comp->binary.right, result); + break; + + case ICT_PREFIX_UNARY: + case ICT_TPREFIX_UNARY: + result = stradd(base, "::"); + result = itd_translate_component(context, comp->unary, result); + break; + + case ICT_PREFIX_BINARY: + case ICT_TPREFIX_BINARY: + result = itd_translate_component(context, comp->binary.left, base); + result = stradd(result, "::"); + result = itd_translate_component(context, comp->binary.right, result); + break; + + + case ICT_OPERATOR_NAME: + switch (comp->operator.otype) + { + case IOT_SIMPLE: + result = stradd(base, comp->operator.info.name); + break; + case IOT_CAST: + result = stradd(base, "TODO_CAST"); + break; + case IOT_VENDOR: + result = stradd(base, "TODO_VENDOR"); + break; + } + break; + + + case ICT_FUNCTION_THUNK: + result = itd_translate_component(context, comp->binary.right, base); + break; + + case ICT_FUNCTION_COVARIANT_THUNK: + result = itd_translate_component(context, comp->ternary.third, base); + break; + + + case ICT_CONSTRUCTOR: + result = stradd(base, "<ctor>"); + break; + + case ICT_DESSTRUCTOR: + result = stradd(base, "<dtor>"); + break; + + case ICT_TYPE: + + name = g_data_type_to_string(comp->dtype); + + result = stradd(base, name); + + free(name); + + break; + + case ICT_POINTER_TO: + result = itd_translate_component(context, comp->unary, base); + result = stradd(result, " *"); + break; + + case ICT_REFERENCE_TO: + result = itd_translate_component(context, comp->unary, base); + result = stradd(result, " &"); + break; + + case ICT_RVALUE_REFERENCE_TO: + result = itd_translate_component(context, comp->unary, base); + result = stradd(result, " &"); + break; + + case ICT_COMPLEX_PAIR: + result = stradd(base, "<?>"); + result = itd_translate_component(context, comp->unary, result); + break; + + case ICT_IMAGINARY: + result = stradd(base, "<?>"); + result = itd_translate_component(context, comp->unary, result); + break; + + + case ICT_FUNCTION_ENCODING: + + result = base; + + /* Retour ? */ + + sub = NULL;//IT_BINARY_COMP(IT_BINARY_COMP(comp).right).left; + + if (sub != NULL) + result = itd_translate_component(context, sub, result); + else + result = stradd(result, "???"); + + result = stradd(result, " "); + + /* Nom de la fonction */ + result = itd_translate_component(context, comp->binary.left, result); + + result = stradd(result, "("); + + result = itd_translate_component(context, comp->binary.right, result); + + result = stradd(result, ")"); + + + break; + + case ICT_TEMPLATE_ARGS: + result = stradd(base, "<"); + result = itd_translate_component(context, comp->unary, result); + result = stradd(result, ">"); + break; + + case ICT_TYPES_LIST: + + result = itd_translate_component(context, comp->binary.left, base); + + if (comp->binary.right != NULL) + { + result = stradd(result, ", "); + result = itd_translate_component(context, comp->binary.right, result); + } + + + //sub = IT_BINARY_COMP(IT_BINARY_COMP(comp).right).right; + + + break; + + + default: /* ICT_* */ + result = base; + break; + + } + + + + return result; + + +} |