summaryrefslogtreecommitdiff
path: root/src/mangling/itanium/context.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mangling/itanium/context.c')
-rw-r--r--src/mangling/itanium/context.c571
1 files changed, 571 insertions, 0 deletions
diff --git a/src/mangling/itanium/context.c b/src/mangling/itanium/context.c
new file mode 100644
index 0000000..d0a0664
--- /dev/null
+++ b/src/mangling/itanium/context.c
@@ -0,0 +1,571 @@
+
+/* 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "context.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "abi.h"
+#include "component-int.h"
+#include "../context-int.h"
+
+
+
+/* Taille des extensions d'allocation */
+#define ITCOMP_ALLOC_BULK 200
+
+/* Marqueur de fin pour les disponibilités */
+#define ITCOMP_INVALID ((size_t)-1)
+
+
+/* Contexte de décodage Itanium (instance) */
+struct _GItaniumDContext
+{
+ GDemanglingContext parent; /* A laisser en premier */
+
+ char *mangled; /* Caractères à traiter */
+ size_t len; /* Quantité de caractères */
+ size_t pos; /* Position d'analyse */
+
+ itanium_component *components; /* Tableaux des composants */
+ size_t *next_links; /* Chemins d'allocation */
+ size_t length; /* Taille allouée */
+ size_t last_used; /* Lien vers la disponibilité */
+
+ itanium_component **substitutions; /* Table de substitutions */
+ size_t subst_count; /* Quantité utilisée */
+
+};
+
+/* Contexte de décodage Itanium (classe) */
+struct _GItaniumDContextClass
+{
+ GDemanglingContextClass parent; /* A laisser en premier */
+
+};
+
+
+
+/* Indique le type défini pour un contexte de décodage. */
+G_DEFINE_TYPE(GItaniumDContext, g_itanium_dcontext, G_TYPE_DEMANGLING_CONTEXT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des contextes de décodage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_dcontext_class_init(GItaniumDContextClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = instance à initialiser. *
+* *
+* Description : Initialise une instance de contexte pour décodage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_itanium_dcontext_init(GItaniumDContext *context)
+{
+ context->last_used = ITCOMP_INVALID;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Prépare de quoi effectuer un décodage Itanium. *
+* *
+* Retour : Instance du contexte mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDemanglingContext *g_itanium_dcontext_new(void)
+{
+ GDemanglingContext *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_ITANIUM_DCONTEXT, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage sur lequel s'appuyer. *
+* desc = chaîne de caractères à décoder. *
+* *
+* Description : Tente de décoder une chaîne de caractères donnée. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void /*GBinRoutine **/g_itanium_dcontext_demangle_routine(GItaniumDContext *context, const char *desc)
+{
+ itanium_component *comp;
+
+ char *str;
+
+ printf("<<== %s\n", desc);
+
+ context->mangled = strdup(desc);
+ context->len = strlen(desc);
+ context->pos = 0;
+
+
+ /**
+ * On part du principe qu'il n'y aura jamais plus de substitutions
+ * à enregistrer que de caractères dans la chaîne à traiter.
+ * Du coup, on peut tout allouer d'un coup !
+ */
+ context->substitutions = (itanium_component **)calloc(context->len, sizeof(itanium_component *));
+
+
+ comp = itd_mangled_name(context);
+
+
+ printf("Got :: %p\n", comp);
+
+ str = itd_translate_component(context, comp, NULL);
+
+ printf("==>> %s\n", str);
+
+}
+
+
+/******************************************************************************
+* *
+* 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_dcontext_push_state(const GItaniumDContext *context, itd_state *state)
+{
+ state->pos = context->pos;
+ 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_dcontext_pop_state(GItaniumDContext *context, const itd_state *state)
+{
+ size_t i; /* Boucle de parcours */
+
+ /*
+ printf("--deleting subst-- from %zu to %zu\n",
+ state->subst_count, context->subst_count);
+ */
+
+ for (i = state->subst_count; i < context->subst_count; i++)
+ itd_unref_comp(context->substitutions[i]);
+
+ context->pos = state->pos;
+ context->subst_count = state->subst_count;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Fournit la valeur du caractère courant. *
+* *
+* Retour : Caractère courant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char g_itanium_dcontext_peek_char(const GItaniumDContext *context)
+{
+ return *(context->mangled + context->pos);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* quantity = quantié de caractères à marquer comme traités. *
+* *
+* Description : Avance la tête de lecture courante. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_itanium_dcontext_advance(GItaniumDContext *context, size_t quantity)
+{
+ context->pos += quantity;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* *
+* Description : Fournit et avance la tête de lecture courante. *
+* *
+* Retour : Caractère courant. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char g_itanium_dcontext_next_char(GItaniumDContext *context)
+{
+ return *(context->mangled + context->pos++);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* c = caractère à retrouver. *
+* *
+* Description : Vérifie la nature du caractère courant. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_itanium_dcontext_check_char(GItaniumDContext *context, char c)
+{
+ bool result; /* Validation à retourner */
+
+ if (g_itanium_dcontext_peek_char(context) == c)
+ {
+ result = true;
+ g_itanium_dcontext_advance(context, 1);
+ }
+ else
+ result = false;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à utiliser. *
+* remaining = taille de la chaîne retournée. [OUT] *
+* *
+* Description : Fournit la chaîne de caractère restant à traiter. *
+* *
+* Retour : Pointeur vers les données courantes. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_itanium_dcontext_get_string(const GItaniumDContext *context, size_t *remaining)
+{
+ const char *result; /* Données à renvoyer */
+
+ *remaining = context->len - context->pos;
+
+ result = &context->mangled[context->pos];
+
+ return result;
+
+}
+
+
+
+
+
+/*
+
+################define d_peek_char(di) (*((di)->n))
+#define d_peek_next_char(di) ((di)->n[1])
+################define d_advance(di, i) ((di)->n += (i))
+################define d_check_char(di, c) (d_peek_char(di) == c ? ((di)->n++, 1) : 0)
+#define d_next_char(di) (d_peek_char(di) == '\0' ? '\0' : *((di)->n++))
+################define d_str(di) ((di)->n)
+
+
+*/
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à manipuler. *
+* *
+* Description : Fournit un nouveau composant vierge. *
+* *
+* Retour : Composant prêt à être défini. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+itanium_component *g_itanium_dcontext_get_empty_component(GItaniumDContext *context)
+{
+ itanium_component *result; /* Disponibilité à retourner */
+ size_t i; /* Boucle de parcours */
+ size_t next; /* Indice de disponibilité */
+
+ if (context->last_used == ITCOMP_INVALID
+ || context->next_links[context->last_used] == ITCOMP_INVALID)
+ {
+ /* Création d'extensions */
+
+ context->components = (itanium_component *)
+ realloc(context->components,
+ (context->length + ITCOMP_ALLOC_BULK) * sizeof(itanium_component));
+
+ context->next_links = (size_t *)
+ realloc(context->next_links, (context->length + ITCOMP_ALLOC_BULK) * sizeof(size_t));
+
+ /* Inscription des liens d'allocation */
+
+ for (i = context->length; i < (context->length + ITCOMP_ALLOC_BULK - 1); i++)
+ context->next_links[i] = i + 1;
+
+ context->next_links[context->length + ITCOMP_ALLOC_BULK - 1] = ITCOMP_INVALID;
+
+ if (context->last_used != ITCOMP_INVALID)
+ context->next_links[context->last_used] = context->length;
+
+ /* Mise à jour globale */
+
+ context->length += ITCOMP_ALLOC_BULK;
+
+ }
+
+ /* Extraction d'un composant disponible */
+
+ if (context->last_used == ITCOMP_INVALID)
+ next = 0;
+ else
+ next = context->next_links[context->last_used];
+
+ result = &context->components[next];
+ context->last_used = next;
+
+ memset(result, 0, sizeof(itanium_component));
+
+ result->context = context;
+ g_object_ref(G_OBJECT(result->context));
+ result->refcount = 1;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : context = contexte de décodage à manipuler. *
+* comp = composant à libérer. *
+* *
+* Description : Marque un composant comme étant disponible pour un usage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_itanium_dcontext_mark_component_as_free(GItaniumDContext *context, itanium_component *comp)
+{
+ size_t index; /* Indice du composant concerné*/
+
+ /*BUG_ON(comp->refcount != 0);*/
+
+ g_object_unref(G_OBJECT(comp->context));
+
+ index = comp - context->components;
+
+ context->next_links[index] = context->next_links[context->last_used];
+ context->next_links[context->last_used] = index;
+
+}
+
+
+/******************************************************************************
+* *
+* 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_dcontext_add_substitution(GItaniumDContext *context, itanium_component *comp)
+{
+ fnv64_t hash; /* Empreinte du candidat */
+ size_t i; /* Boucle de parcours */
+
+ hash = itd_hash_comp(comp);
+
+ for (i = 0; i < context->subst_count; i++)
+ if (cmp_fnv_64a(itd_hash_comp(context->substitutions[i]), hash) == 0)
+ break;
+
+ if (i == context->subst_count)
+ {
+
+ printf("[ADDING SUBST] [%zu] '%s'\n",
+ context->subst_count,
+ itd_translate_component(context, comp, NULL));
+
+
+ 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_dcontext_get_substitution(GItaniumDContext *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;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+void test_itanium(void)
+{
+
+
+
+
+#define TEST_DEMANG(v) \
+ do \
+ { \
+ GDemanglingContext *ctx; \
+ /*char *str;*/ \
+ ctx = g_itanium_dcontext_new(); \
+ /*str = */g_itanium_dcontext_demangle_routine(G_ITANIUM_DCONTEXT(ctx), v); \
+ /*printf("==> %s\n", str);*/ \
+ } \
+ while (0)
+
+
+ TEST_DEMANG("_Z3fooILi2EEvRAplT_Li1E_i");
+
+ exit(0);
+
+ TEST_DEMANG("_Z1fv");
+ TEST_DEMANG("_Z3foo3bar");
+
+
+}