summaryrefslogtreecommitdiff
path: root/plugins/itanium/component.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/itanium/component.c')
-rw-r--r--plugins/itanium/component.c1842
1 files changed, 1842 insertions, 0 deletions
diff --git a/plugins/itanium/component.c b/plugins/itanium/component.c
new file mode 100644
index 0000000..6e580f6
--- /dev/null
+++ b/plugins/itanium/component.c
@@ -0,0 +1,1842 @@
+
+/* 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "component.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <analysis/types/array.h>
+#include <analysis/types/cse.h>
+#include <analysis/types/expr.h>
+#include <analysis/types/override.h>
+#include <analysis/types/proto.h>
+#include <analysis/types/template.h>
+#include <common/extstr.h>
+#include <common/fnv1a.h>
+
+
+#include "component-int.h"
+
+
+
+
+/* Procédure à appliquer sur un composant visité */
+typedef void (* visit_comp_fc) (itanium_component *);
+
+
+#define reset_comp_hash(c) c->hash = 0
+
+
+/* Crée un composant de contexte Itanium complètement vierge. */
+static itanium_component *itd_alloc(void);
+
+/* Efface de la mémoire un composant de context Itanium. */
+static void itd_free(itanium_component *);
+
+/* Visite les composants en présence. */
+static void visit_comp(itanium_component *, visit_comp_fc);
+
+/* Traduit les composants de contexte Itanium en décalage. */
+static bool itd_translate_component_to_offset(const itanium_component *, call_offset_t *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un composant de contexte Itanium complètement vierge. *
+* *
+* Retour : Composant créé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static itanium_component *itd_alloc(void)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = calloc(1, sizeof(itanium_component));
+
+ result->refcount = 1;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant à supprimer. *
+* *
+* Description : Efface de la mémoire un composant de context Itanium. *
+* *
+* Retour : Composant créé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void itd_free(itanium_component *comp)
+{
+ free(comp);
+
+}
+
+
+/******************************************************************************
+* *
+* 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)
+{
+ switch (comp->type)
+ {
+ case ICT_NAME:
+ break;
+
+ case ICT_STD_UNSCOPED_NAME:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_NESTED_NAME:
+ if (comp->binary.left != NULL)
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_TEMPLATE_NAME_ARGS:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_PREFIX_BINARY:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_TPREFIX_BINARY:
+ if (comp->binary.left != NULL)
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_OPERATOR_NAME:
+ if (comp->operator.otype == IOT_CAST)
+ visit_comp(comp->operator.trans, visitor);
+ break;
+
+ case ICT_SPECIAL_NAME_VTABLE:
+ case ICT_SPECIAL_NAME_VSTRUCT:
+ visit_comp(comp->unary, visitor);
+ break;
+
+ case ICT_NON_VIRTUAL_OFFSET:
+ case ICT_VIRTUAL_OFFSET:
+ break;
+
+ case ICT_DOUBLE_OFFSET:
+ 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_CONSTRUCTOR:
+ case ICT_DESSTRUCTOR:
+ break;
+
+ case ICT_TYPE:
+ break;
+
+ case ICT_QUALIFIED_TYPE:
+ visit_comp(comp->qualified.sub, 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_TYPE:
+ visit_comp(comp->function.args, visitor);
+ break;
+
+ case ICT_FUNCTION_ENCODING:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_ARRAY:
+ if (!comp->array.numbered_dim)
+ visit_comp(comp->array.dim_expr, visitor);
+ visit_comp(comp->array.atype, visitor);
+ break;
+
+ case ICT_POINTER_TO_MEMBER:
+ visit_comp(comp->pmember.class, visitor);
+ visit_comp(comp->pmember.member, 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;
+
+ case ICT_EXPR_LIST:
+
+ visit_comp(comp->binary.left, visitor);
+
+ if (comp->binary.right != NULL)
+ visit_comp(comp->binary.right, visitor);
+
+ break;
+
+ case ICT_OPERATED_EXPRESSION:
+ visit_comp(comp->binary.left, visitor);
+ visit_comp(comp->binary.right, visitor);
+ break;
+
+ case ICT_STD_SUBST:
+ break;
+
+ case ICT_COUNT:
+ 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)
+{
+ void visit_for_unref(itanium_component *comp)
+ {
+ if (--comp->refcount == 0)
+ {
+ if (comp->type == ICT_TYPE || comp->type == ICT_STD_SUBST)
+ g_object_unref(G_OBJECT(comp->dtype));
+
+ itd_free(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, NULL);
+ comp->hash = fnv_64a_hash(desc);
+ free(desc);
+ }
+
+ return comp->hash;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type à définir pour le composant. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_with_type(ItaniumComponentType type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : 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(const char *str, size_t len)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_NAME;
+ result->s_name.str = str;
+ result->s_name.len = len;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : 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(const itanium_operator_info *info)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_OPERATOR_NAME;
+ result->operator.otype = IOT_SIMPLE;
+ result->operator.info = *info;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : 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_cast_operator(itanium_component *type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_OPERATOR_NAME;
+ result->operator.otype = IOT_CAST;
+ result->operator.trans = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium décodé à consulter. *
+* type = type d'opérateur représenté. *
+* *
+* Description : Donne des indications quant à un opérateur Itanium. *
+* *
+* Retour : Informations à interpréter selon le type transmis. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const void *itd_get_operator_info(const itanium_component *comp, ItaniumOperatorType *type)
+{
+ const void *result; /* Données à retourner */
+
+ assert(comp->type == ICT_OPERATOR_NAME);
+
+ *type = comp->operator.otype;
+
+ switch (*type)
+ {
+ case IOT_SIMPLE:
+ result = &comp->operator.info;
+ break;
+
+ case IOT_CAST:
+ result = comp->operator.trans;
+ break;
+
+ default:
+ assert(false);
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : 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(ItaniumComponentType type, ssize_t offset)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->offset = offset;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : 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(GDataType *dtype)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_TYPE;
+ result->dtype = dtype;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : sub = composant de type en place à référencer. *
+* qualifier = propriétés supplémentaires pour le type. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_qualified_type(itanium_component *sub, TypeQualifier qualifier)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ if (qualifier == TQF_NONE)
+ result = sub;
+
+ else
+ {
+ result = itd_alloc();
+
+ result->type = ICT_QUALIFIED_TYPE;
+ result->qualified.sub = sub;
+ result->qualified.qualifier = qualifier;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : sub = composant de type en place à référencer. *
+* qualifier = propriétés supplémentaires pour le type. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_function_type(bool extern_c, itanium_component *args)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_FUNCTION_TYPE;
+ result->function.extern_c = extern_c;
+ result->function.args = args;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : number = dimension du tableau. *
+* type = type des membres du même tableau. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_array_with_dim_number(ssize_t number, itanium_component *type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_ARRAY;
+ result->array.numbered_dim = true;
+ result->array.dim_number = number;
+ result->array.atype = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = dimension du tableau. *
+* type = type des membres du même tableau. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_array_with_dim_expr(itanium_component *expr, itanium_component *type)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_ARRAY;
+ result->array.numbered_dim = false;
+ result->array.dim_expr = expr;
+ result->array.atype = type;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe d'appatenance. *
+* member = membre représenté. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_pointer_to_memeber_type(itanium_component *class, itanium_component *member)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = ICT_POINTER_TO_MEMBER;
+ result->pmember.class = class;
+ result->pmember.member = member;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : 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(ItaniumComponentType type, itanium_component *unary)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->unary = unary;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : 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(ItaniumComponentType type, itanium_component *left, itanium_component *right)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->binary.left = left;
+ result->binary.right = right;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : 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(ItaniumComponentType type, itanium_component *parent, itanium_component *left)
+{
+ itanium_component *result; /* Composant à renvoyer */
+ itanium_component *iter; /* Boucle de parcours */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->binary.left = left;
+ result->binary.right = NULL;
+
+ 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 : type = type du composant à mettre en place. *
+* c0 = premier composant à associer. *
+* c1 = second composant à associer. *
+* c2 = troisième composant à associer. *
+* *
+* Description : Construit un composant dans un contexte Itanium. *
+* *
+* Retour : Composant extrait ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *itd_make_ternary(ItaniumComponentType type, itanium_component *c0, itanium_component *c1, itanium_component *c2)
+{
+ itanium_component *result; /* Composant à renvoyer */
+
+ result = itd_alloc();
+
+ result->type = type;
+ result->ternary.first = c0;
+ result->ternary.second = c1;
+ result->ternary.third = c2;
+
+ 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 : 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(const itanium_component *comp, char *base)
+{
+ char *result; /* Chaîne à retourner */
+ char *name; /* Désignation à copier */
+ const itanium_component *sub; /* Sous-partie de composant */
+ ItaniumOperatorType otype; /* Type d'opérateur */
+ const void *odata; /* Données associées */
+ const itanium_operator_info *simple; /* Données d'opérateur simple */
+ char *tmp; /* Transcription temporaire */
+
+ switch (comp->type)
+ {
+ case ICT_NAME:
+ result = strnadd(base, comp->s_name.str, comp->s_name.len);
+ break;
+
+ case ICT_STD_UNSCOPED_NAME:
+ result = stradd(base, "std::");
+ result = itd_translate_component(comp->unary, result);
+ break;
+
+ case ICT_NESTED_NAME:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ result = itd_translate_component(comp->binary.left, base);
+ result = itd_translate_component(comp->binary.right, result);
+ }
+
+ else
+ {
+ if (comp->binary.left != NULL)
+ {
+ result = itd_translate_component(comp->binary.left, base);
+ result = stradd(result, "::");
+ }
+ else
+ result = base;
+
+ result = itd_translate_component(comp->binary.right, result);
+
+ }
+
+ break;
+
+ case ICT_TEMPLATE_NAME_ARGS:
+ result = itd_translate_component(comp->binary.left, base);
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_PREFIX_BINARY:
+ result = itd_translate_component(comp->binary.left, base);
+ if (comp->binary.right->type != ICT_TEMPLATE_ARGS)
+ result = stradd(result, "::");
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_TPREFIX_BINARY:
+ if (comp->binary.left != NULL)
+ {
+ result = itd_translate_component(comp->binary.left, base);
+ if (comp->binary.right->type != ICT_TEMPLATE_ARGS)
+ result = stradd(result, "::");
+ }
+ else
+ result = base;
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_OPERATOR_NAME:
+ switch (comp->operator.otype)
+ {
+ case IOT_SIMPLE:
+ result = stradd(base, "operator");
+ result = stradd(result, comp->operator.info.name);
+ break;
+ case IOT_CAST:
+ result = stradd(base, "(");
+ sub = (const itanium_component *)odata;
+ result = itd_translate_component(comp->operator.trans, result);
+ result = stradd(result, ")");
+ break;
+ default:
+ result = NULL;
+ break;
+ }
+ break;
+
+ case ICT_SPECIAL_NAME_VTABLE:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, "::vtable");
+ break;
+
+ case ICT_SPECIAL_NAME_VSTRUCT:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, "::vstruct");
+ break;
+
+ case ICT_NON_VIRTUAL_OFFSET:
+ case ICT_VIRTUAL_OFFSET:
+ asprintf(&tmp, "%zd", comp->offset);
+ result = stradd(base, tmp);
+ free(tmp);
+ break;
+
+ case ICT_DOUBLE_OFFSET:
+ result = itd_translate_component(comp->binary.left, base);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_FUNCTION_THUNK:
+ result = itd_translate_component(comp->binary.left, base);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->binary.right, result);
+ break;
+
+ case ICT_FUNCTION_COVARIANT_THUNK:
+ result = itd_translate_component(comp->ternary.first, base);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->ternary.second, result);
+ result = stradd(result, "_");
+ result = itd_translate_component(comp->ternary.third, result);
+ 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, true);
+ result = stradd(base, name);
+ free(name);
+ break;
+
+ case ICT_QUALIFIED_TYPE:
+
+ switch (comp->qualified.qualifier)
+ {
+ case TQF_RESTRICT:
+ result = stradd(base, "restrict ");
+ break;
+ case TQF_VOLATILE:
+ result = stradd(base, "volatile ");
+ break;
+ case TQF_CONST:
+ result = stradd(base, "const ");
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ result = itd_translate_component(comp->qualified.sub, result);
+
+ break;
+
+ case ICT_POINTER_TO:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, " *");
+ break;
+
+ case ICT_REFERENCE_TO:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, " &");
+ break;
+
+ case ICT_RVALUE_REFERENCE_TO:
+ result = itd_translate_component(comp->unary, base);
+ result = stradd(result, " &");
+ break;
+
+ case ICT_COMPLEX_PAIR:
+ result = stradd(base, "<?>");
+ result = itd_translate_component(comp->unary, result);
+ break;
+
+ case ICT_IMAGINARY:
+ result = stradd(base, "<?>");
+ result = itd_translate_component(comp->unary, result);
+ break;
+
+ case ICT_FUNCTION_TYPE:
+ result = stradd(base, "(*) (");
+ result = itd_translate_component(comp->function.args, result);
+ result = stradd(result, ")");
+ break;
+
+ case ICT_FUNCTION_ENCODING:
+
+ result = stradd(base, "???");
+
+ result = stradd(result, " ");
+
+ result = itd_translate_component(comp->binary.left, result);
+
+ result = stradd(result, "(");
+
+ result = itd_translate_component(comp->binary.right, result);
+
+ result = stradd(result, ")");
+
+ break;
+
+ case ICT_ARRAY:
+
+ result = itd_translate_component(comp->array.atype, base);
+
+ result = stradd(result, "[");
+
+ if (comp->array.numbered_dim)
+ {
+ asprintf(&tmp, "%zd", comp->array.dim_number);
+ result = stradd(result, tmp);
+ free(tmp);
+ }
+
+ else
+ result = itd_translate_component(comp->array.dim_expr, result);
+
+ result = stradd(result, "]");
+
+ break;
+
+ case ICT_POINTER_TO_MEMBER:
+ result = itd_translate_component(comp->pmember.class, base);
+ result = stradd(result, "::");
+ result = itd_translate_component(comp->pmember.member, result);
+ break;
+
+ case ICT_TEMPLATE_ARGS:
+ result = stradd(base, "<");
+ result = itd_translate_component(comp->unary, result);
+ result = stradd(result, ">");
+ break;
+
+ case ICT_TYPES_LIST:
+
+ result = itd_translate_component(comp->binary.left, base);
+
+ if (comp->binary.right != NULL)
+ {
+ result = stradd(result, ", ");
+ result = itd_translate_component(comp->binary.right, result);
+ }
+
+ break;
+
+ case ICT_EXPR_LIST:
+
+ /**
+ * A priori traité en amont.
+ */
+
+ result = itd_translate_component(comp->binary.left, base);
+
+ if (comp->binary.right != NULL)
+ {
+ result = stradd(result, ", ");
+ result = itd_translate_component(comp->binary.right, result);
+ }
+
+ break;
+
+ case ICT_OPERATED_EXPRESSION:
+
+ odata = itd_get_operator_info(comp->binary.left, &otype);
+
+ sub = comp->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+
+ switch (otype)
+ {
+ case IOT_SIMPLE:
+
+ simple = (const itanium_operator_info *)odata;
+
+ switch (simple->args)
+ {
+ case 1:
+ result = stradd(base, simple->name);
+ result = itd_translate_component(sub->binary.left, result);
+ assert(sub->binary.right == NULL);
+ break;
+
+ case 2:
+
+ result = itd_translate_component(sub->binary.left, base);
+
+ result = stradd(result, simple->name);
+
+ sub = sub->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+ result = itd_translate_component(sub->binary.left, result);
+ assert(sub->binary.right == NULL);
+ break;
+
+ case 3:
+
+ result = itd_translate_component(sub->binary.left, base);
+
+ result = stradd(result, simple->name);
+
+ sub = sub->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+ result = itd_translate_component(sub->binary.left, result);
+
+ result = stradd(result, ":");
+
+ sub = sub->binary.right;
+ assert(sub->type == ICT_EXPR_LIST);
+ result = itd_translate_component(sub->binary.left, result);
+ assert(sub->binary.right == NULL);
+
+ break;
+
+ }
+
+ break;
+
+ case IOT_CAST:
+ result = stradd(base, "(");
+ sub = (const itanium_component *)odata;
+ result = itd_translate_component(sub, result);
+ result = stradd(result, ")");
+ break;
+
+ default:
+ result = NULL;
+ break;
+
+ }
+
+ break;
+
+ case ICT_STD_SUBST:
+ name = g_data_type_to_string(comp->dtype, true);
+ result = stradd(base, name);
+ free(name);
+ break;
+
+ case ICT_COUNT:
+ result = base;
+ break;
+
+ }
+
+
+
+ return result;
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium à traduire en décalage. *
+* off = réceptacle pour les informations traduites. *
+* *
+* Description : Traduit les composants de contexte Itanium en décalage. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool itd_translate_component_to_offset(const itanium_component *comp, call_offset_t *off)
+{
+ bool result; /* Bilan à retourner */
+
+ if (comp->type == ICT_DOUBLE_OFFSET)
+ {
+ result = comp->binary.left->type == ICT_NON_VIRTUAL_OFFSET
+ && comp->binary.right->type == ICT_VIRTUAL_OFFSET;
+
+ assert(result);
+
+ if (result)
+ {
+ off->values[0] = comp->binary.left->offset;
+ off->values[1] = comp->binary.right->offset;
+ off->virtual = true;
+ }
+
+ }
+
+ else if (comp->type == ICT_NON_VIRTUAL_OFFSET)
+ {
+ result = true;
+
+ off->values[0] = comp->offset;
+ off->virtual = false;
+
+ }
+
+ else
+ result = false;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium à traduire en type. *
+* *
+* Description : Traduit les composants de contexte Itanium en type. *
+* *
+* Retour : Traduction en type décodé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDataType *itd_translate_component_to_type(const itanium_component *comp)
+{
+ GDataType *result; /* Type à retourner */
+ char *name; /* Attribution finale */
+ GDataType *ns; /* Espace de noms d'un type */
+ call_offset_t off0; /* Décalage #0 */
+ call_offset_t off1; /* Décalage #1 */
+ itanium_component *iter; /* Boucle de parcours */
+ GDataType *arg; /* Argument de prototype */
+ GDataType *members; /* Type de membres de tableau */
+ GDataType *param; /* Paramètre de gabarit */
+
+ /* Pour GCC !? */
+ result = NULL;
+
+ switch (comp->type)
+ {
+ case ICT_NAME:
+ name = itd_translate_component(comp, NULL);
+ result = g_class_enum_type_new(CET_STRUCT, name);
+ break;
+
+ case ICT_STD_UNSCOPED_NAME:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ {
+ ns = g_class_enum_type_new(CET_NAMESPACE, strdup("std"));
+ g_data_type_set_namespace(result, ns, "::");
+ }
+ break;
+
+ case ICT_NESTED_NAME:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ name = itd_translate_component(comp->binary.right, name);
+
+ result = g_class_enum_type_new(CET_CLASS, name);
+
+ }
+
+ else
+ {
+ if (comp->binary.left != NULL)
+ {
+ ns = itd_translate_component_to_type(comp->binary.left);
+ if (ns == NULL)
+ {
+ result = NULL;
+ break;
+ }
+ }
+ else
+ ns = NULL;
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL && ns != NULL)
+ g_data_type_set_namespace(result, ns, "::");
+
+ }
+
+ break;
+
+ case ICT_TEMPLATE_NAME_ARGS:
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ g_template_type_set_name(G_TEMPLATE_TYPE(result), name);
+ }
+
+ break;
+
+ case ICT_PREFIX_BINARY:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ name = itd_translate_component(comp->binary.right, name);
+
+ result = g_class_enum_type_new(CET_CLASS, name);
+
+ }
+
+ else
+ {
+ ns = itd_translate_component_to_type(comp->binary.left);
+ if (ns == NULL)
+ {
+ result = NULL;
+ break;
+ }
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL)
+ g_data_type_set_namespace(result, ns, "::");
+
+ }
+
+ break;
+
+ case ICT_TPREFIX_BINARY:
+
+ if (comp->binary.right->type == ICT_TEMPLATE_ARGS)
+ {
+ name = itd_translate_component(comp->binary.left, NULL);
+ name = itd_translate_component(comp->binary.right, name);
+
+ result = g_class_enum_type_new(CET_CLASS, name);
+
+ }
+
+ else
+ {
+ if (comp->binary.left != NULL)
+ {
+ ns = itd_translate_component_to_type(comp->binary.left);
+ if (ns == NULL)
+ {
+ result = NULL;
+ break;
+ }
+
+ }
+ else
+ ns = NULL;
+
+ result = itd_translate_component_to_type(comp->binary.right);
+
+ if (result != NULL)
+ {
+ if (ns != NULL)
+ g_data_type_set_namespace(result, ns, "::");
+ }
+ else
+ {
+ if (ns != NULL)
+ g_object_unref(G_OBJECT(ns));
+ }
+
+ }
+
+ break;
+
+ case ICT_OPERATOR_NAME:
+ result = NULL;
+ break;
+
+ case ICT_SPECIAL_NAME_VTABLE:
+
+ ns = itd_translate_component_to_type(comp->unary);
+
+ if (ns == NULL)
+ result = NULL;
+
+ else
+ {
+ result = g_class_enum_type_new(CET_VIRTUAL_TABLE, NULL);
+ g_data_type_set_namespace(result, ns, "::");
+ }
+
+ break;
+
+ case ICT_SPECIAL_NAME_VSTRUCT:
+
+ ns = itd_translate_component_to_type(comp->unary);
+
+ if (ns == NULL)
+ result = NULL;
+
+ else
+ {
+ result = g_class_enum_type_new(CET_VIRTUAL_STRUCT, NULL);
+ g_data_type_set_namespace(result, ns, "::");
+ }
+
+ break;
+
+ case ICT_NON_VIRTUAL_OFFSET:
+ case ICT_VIRTUAL_OFFSET:
+ case ICT_DOUBLE_OFFSET:
+ result = NULL;
+ break;
+
+ case ICT_FUNCTION_THUNK:
+
+ if (!itd_translate_component_to_offset(comp->binary.right, &off0))
+ {
+ result = NULL;
+ break;
+ }
+
+ result = itd_translate_component_to_type(comp->binary.left);
+
+ if (result != NULL)
+ result = g_override_type_new(result, &off0);
+
+ break;
+
+ case ICT_FUNCTION_COVARIANT_THUNK:
+
+ if (!itd_translate_component_to_offset(comp->ternary.second, &off0))
+ {
+ result = NULL;
+ break;
+ }
+
+ if (!itd_translate_component_to_offset(comp->ternary.third, &off1))
+ {
+ result = NULL;
+ break;
+ }
+
+ result = itd_translate_component_to_type(comp->ternary.first);
+
+ if (result != NULL)
+ result = g_override_type_new_with_covariant(result, &off0, &off1);
+
+ break;
+
+ case ICT_CONSTRUCTOR:
+ case ICT_DESSTRUCTOR:
+ result = NULL;
+ break;
+
+ case ICT_TYPE:
+ result = g_data_type_dup(comp->dtype);
+ break;
+
+ case ICT_QUALIFIED_TYPE:
+ result = itd_translate_component_to_type(comp->qualified.sub);
+ if (result != NULL)
+ g_data_type_add_qualifier(result, comp->qualified.qualifier);
+ break;
+
+ case ICT_POINTER_TO:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL && !G_IS_PROTO_TYPE(result))
+ result = g_encapsulated_type_new(ECT_POINTER, result);
+ break;
+
+ case ICT_REFERENCE_TO:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_REFERENCE, result);
+ break;
+
+ case ICT_RVALUE_REFERENCE_TO:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_RVALUE_REF, result);
+ break;
+
+ case ICT_COMPLEX_PAIR:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_COMPLEX, result);
+ break;
+
+ case ICT_IMAGINARY:
+ result = itd_translate_component_to_type(comp->unary);
+ if (result != NULL)
+ result = g_encapsulated_type_new(ECT_IMAGINARY, result);
+ break;
+
+ case ICT_FUNCTION_TYPE:
+
+ result = g_proto_type_new();
+
+ assert(comp->function.args->type == ICT_TYPES_LIST);
+
+ for (iter = comp->function.args; iter != NULL && result != NULL; iter = iter->binary.right)
+ {
+ assert(iter->type == ICT_TYPES_LIST);
+
+ arg = itd_translate_component_to_type(iter->binary.left);
+
+ if (arg == NULL)
+ {
+ g_object_unref(G_OBJECT(result));
+ result = NULL;
+ }
+
+ else
+ {
+ if (iter == comp->function.args)
+ g_proto_type_set_return_type(G_PROTO_TYPE(result), arg);
+
+ else
+ g_proto_type_add_arg(G_PROTO_TYPE(result), arg);
+ }
+
+ }
+
+ break;
+
+ case ICT_FUNCTION_ENCODING:
+ result = NULL;
+ break;
+
+ case ICT_ARRAY:
+
+ members = itd_translate_component_to_type(comp->array.atype);
+
+ if (members == NULL)
+ result = NULL;
+
+ else
+ {
+ result = g_array_type_new(members);
+
+ if (comp->array.numbered_dim)
+ g_array_type_set_dimension_number(G_ARRAY_TYPE(result), comp->array.dim_number);
+
+ else
+ g_array_type_set_dimension_expression(G_ARRAY_TYPE(result),
+ itd_translate_component(comp, NULL));
+
+ }
+
+ break;
+
+ case ICT_POINTER_TO_MEMBER:
+
+ ns = itd_translate_component_to_type(comp->pmember.class);
+
+ if (ns == NULL)
+ result = NULL;
+
+ else
+ {
+ result = itd_translate_component_to_type(comp->pmember.member);
+
+ if (result == NULL)
+ g_object_unref(G_OBJECT(ns));
+
+ else
+ g_data_type_set_namespace(result, ns, "::");
+
+ }
+
+ break;
+
+ case ICT_TEMPLATE_ARGS:
+
+ assert(comp->unary->type == ICT_TYPES_LIST);
+
+ result = g_template_type_new();
+
+ for (iter = comp->unary; iter != NULL && result != NULL; iter = iter->binary.right)
+ {
+ assert(iter->type == ICT_TYPES_LIST);
+
+ param = itd_translate_component_to_type(iter->binary.left);
+
+ if (param == NULL)
+ {
+ g_object_unref(G_OBJECT(result));
+ result = NULL;
+ }
+ else
+ g_template_type_add_param(G_TEMPLATE_TYPE(result), param);
+
+ }
+
+ break;
+
+ case ICT_TYPES_LIST:
+
+ /**
+ * Les listes doient être rassemblées par l'appelant !
+ */
+
+ assert(false);
+ result = NULL;
+ break;
+
+ case ICT_EXPR_LIST:
+
+ /**
+ * Les listes doient être rassemblées par l'appelant !
+ */
+
+ assert(false);
+ result = NULL;
+ break;
+
+ case ICT_OPERATED_EXPRESSION:
+ result = g_expr_type_new(itd_translate_component(comp, NULL));
+ break;
+
+ case ICT_STD_SUBST:
+ result = g_data_type_dup(comp->dtype);
+ break;
+
+ case ICT_COUNT:
+ assert(false);
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comp = composant Itanium à traduire en routine. *
+* *
+* Description : Traduit les composants de contexte Itanium en routine. *
+* *
+* Retour : Traduction en routine décodée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinRoutine *itd_translate_component_to_routine(const itanium_component *comp)
+{
+ GBinRoutine *result; /* Routine à retourner */
+ bool has_ret; /* Type de retour présent ? */
+ itanium_component *name; /* Désignation de la routine */
+ char *desc; /* Description humaine */
+ GDataType *ns; /* Espace de noms de la routine*/
+ itanium_component *args; /* Liste de ses arguments */
+ itanium_component *iter; /* Boucle de parcours */
+ GDataType *type; /* Type d'un argument */
+ GBinVariable *arg; /* Argument à ajouter */
+
+ if (comp->type != ICT_FUNCTION_ENCODING)
+ goto bad_encoding;
+
+ result = g_binary_routine_new();
+
+ /* Nom de la routine */
+
+ name = comp->binary.left;
+
+ /**
+ * A la fin de § 5.1.3 ("Operator Encodings") est précisé :
+ *
+ * If the conversion operator is a member template, the result type will
+ * appear before the template parameters.
+ *
+ * On note donc cette particularité.
+ */
+
+ has_ret = (name->type == ICT_TEMPLATE_NAME_ARGS);
+
+ switch (name->type)
+ {
+ case ICT_NAME:
+ g_binary_routine_set_name(result, itd_translate_component(name, NULL));
+ break;
+
+ case ICT_NESTED_NAME:
+ case ICT_TEMPLATE_NAME_ARGS:
+
+ type = itd_translate_component_to_type(name);
+ if (type == NULL) goto unsupported_encoding;
+
+ ns = g_data_type_get_namespace(type);
+
+ g_data_type_set_namespace(type, NULL, NULL);
+
+ desc = g_data_type_to_string(type, true);
+
+ g_object_unref(G_OBJECT(type));
+
+ g_binary_routine_set_name(result, desc);
+
+ g_binary_routine_set_namespace(result, ns, "::");
+
+ break;
+
+ case ICT_OPERATOR_NAME:
+ g_binary_routine_set_name(result, itd_translate_component(name, NULL));
+ break;
+
+ default:
+ goto unsupported_encoding;
+ break;
+
+ }
+
+ /* Liste d'arguments */
+
+ args = comp->binary.right;
+
+ if (args->type != ICT_TYPES_LIST)
+ goto unsupported_encoding;
+
+ for (iter = args; iter != NULL; iter = iter->binary.right)
+ {
+ type = itd_translate_component_to_type(iter->binary.left);
+
+ if (type == NULL)
+ goto unsupported_encoding;
+
+ if (iter == args && has_ret)
+ g_binary_routine_set_return_type(result, type);
+
+ else
+ {
+ arg = g_binary_variable_new(type);
+ g_binary_routine_add_arg(result, arg);
+ }
+
+ }
+
+ return result;
+
+ unsupported_encoding:
+
+ g_object_unref(G_OBJECT(result));
+
+ bad_encoding:
+
+ return NULL;
+
+}