summaryrefslogtreecommitdiff
path: root/src/mangling/itanium/component.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mangling/itanium/component.c')
-rw-r--r--src/mangling/itanium/component.c717
1 files changed, 717 insertions, 0 deletions
diff --git a/src/mangling/itanium/component.c b/src/mangling/itanium/component.c
new file mode 100644
index 0000000..e3f3f23
--- /dev/null
+++ b/src/mangling/itanium/component.c
@@ -0,0 +1,717 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * component.c - représentation des composants extraits de l'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 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écalage. *
+* offset = décalage 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;
+ default:
+ result = NULL;
+ 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;
+
+
+}