/* Chrysalide - Outil d'analyse de fichiers binaires * context.c - contexte de décodage à la sauce ABI C++ Itanium * * Copyright (C) 2013 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 . */ #include "context.h" #include #include #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"); }