diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-01-30 20:53:24 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-01-30 20:53:24 (GMT) |
commit | 4132223466dcabc19a1b6f0178adf1c1a35b07ad (patch) | |
tree | ad5ef2262e8e1855c9c7f23a0f11f560039d54c6 /src/mangling | |
parent | 896b31fbbef2fba442566a422fa4d409771b61dd (diff) |
Moved the mangling related code.
Diffstat (limited to 'src/mangling')
-rw-r--r-- | src/mangling/Makefile.am | 43 | ||||
-rw-r--r-- | src/mangling/context-int.h | 62 | ||||
-rw-r--r-- | src/mangling/context.c | 192 | ||||
-rw-r--r-- | src/mangling/context.h | 61 | ||||
-rw-r--r-- | src/mangling/demangler.c | 336 | ||||
-rw-r--r-- | src/mangling/demangler.h | 50 | ||||
-rw-r--r-- | src/mangling/dex/Makefile.am | 46 | ||||
-rw-r--r-- | src/mangling/dex/context.c | 154 | ||||
-rw-r--r-- | src/mangling/dex/context.h | 52 | ||||
-rw-r--r-- | src/mangling/dex/shorty_gram.y | 138 | ||||
-rw-r--r-- | src/mangling/dex/shorty_tok.l | 28 | ||||
-rw-r--r-- | src/mangling/dex/type_gram.y | 159 | ||||
-rw-r--r-- | src/mangling/dex/type_tok.l | 150 | ||||
-rwxr-xr-x | src/mangling/itanium/Makefile.am | 19 | ||||
-rw-r--r-- | src/mangling/itanium/abi.c | 2444 | ||||
-rw-r--r-- | src/mangling/itanium/abi.h | 38 | ||||
-rw-r--r-- | src/mangling/itanium/component-int.h | 79 | ||||
-rw-r--r-- | src/mangling/itanium/component.c | 717 | ||||
-rw-r--r-- | src/mangling/itanium/component.h | 213 | ||||
-rw-r--r-- | src/mangling/itanium/context.c | 571 | ||||
-rw-r--r-- | src/mangling/itanium/context.h | 117 | ||||
-rw-r--r-- | src/mangling/java.h | 59 | ||||
-rw-r--r-- | src/mangling/java_gram.y | 281 | ||||
-rw-r--r-- | src/mangling/java_tok.l | 37 |
24 files changed, 6046 insertions, 0 deletions
diff --git a/src/mangling/Makefile.am b/src/mangling/Makefile.am new file mode 100644 index 0000000..63b25c7 --- /dev/null +++ b/src/mangling/Makefile.am @@ -0,0 +1,43 @@ + +BUILT_SOURCES = libjavamangling_la-java_gram.h + +AM_YFLAGS = -d + +noinst_LTLIBRARIES = libjavamangling.la libmangling.la + +libmangling_la_SOURCES = \ + context-int.h \ + context.h context.c \ + demangler.h demangler.c + +libmangling_la_LDFLAGS = + +libmangling_la_LIBADD = \ + libjavamangling.la \ + dex/libmanglingdex.la \ + itanium/libmanglingitanium.la + + +# Partie Java + +libjavamangling_la_SOURCES = \ + java.h \ + java_gram.y \ + java_tok.l + +libjavamangling_la_YFLAGS = -d -p java_ -o y.tab.c + +libjavamangling_la_LFLAGS = -P java_ -o lex.yy.c + + + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + + +# Automake fait les choses à moitié +CLEANFILES = java_gram.h java_gram.c libjavamangling_la-java_tok.c + +SUBDIRS = dex itanium diff --git a/src/mangling/context-int.h b/src/mangling/context-int.h new file mode 100644 index 0000000..d361ff7 --- /dev/null +++ b/src/mangling/context-int.h @@ -0,0 +1,62 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * context.h - prototypes internes liés aux contextes de décodage + * + * Copyright (C) 2010-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/>. + */ + + +#ifndef _FORMAT_MANGLING_CONTEXT_INT_H +#define _FORMAT_MANGLING_CONTEXT_INT_H + + +#include "context.h" + + + +/* Procède au décodage d'une chaîne de caractères. */ +typedef bool (* demangle_fc) (GDemanglingContext *, const char *); + + +/* Contexte de décodage (instance) */ +struct _GDemanglingContext +{ + GObject parent; /* A laisser en premier */ + + union + { + GObject *gobj; /* Utile pour le nettoyage ! */ + GBinRoutine *routine; /* Routine décodée */ + GDataType *type; /* Type décodé */ + }; + +}; + +/* Contexte de décodage (classe) */ +struct _GDemanglingContextClass +{ + GObjectClass parent; /* A laisser en premier */ + + demangle_fc demangle_type; /* Décodage de type */ + demangle_fc demangle_routine; /* Décodage de routine */ + +}; + + + +#endif /* _FORMAT_MANGLING_CONTEXT_INT_H */ diff --git a/src/mangling/context.c b/src/mangling/context.c new file mode 100644 index 0000000..7a798ac --- /dev/null +++ b/src/mangling/context.c @@ -0,0 +1,192 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * context.c - fourniture de contexte aux phases de décodage + * + * Copyright (C) 2010-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 "context-int.h" + + + +/* Initialise la classe des contextes de décodage. */ +static void g_demangling_context_class_init(GDemanglingContextClass *); + +/* Initialise une instance de contexte pour décodage. */ +static void g_demangling_context_init(GDemanglingContext *); + +/* Supprime toutes les références externes. */ +static void g_demangling_context_dispose(GDemanglingContext *); + +/* Procède à la libération totale de la mémoire. */ +static void g_demangling_context_finalize(GDemanglingContext *); + + + +/* Indique le type défini pour un contexte de décodage. */ +G_DEFINE_TYPE(GDemanglingContext, g_demangling_context, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des contextes de décodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_demangling_context_class_init(GDemanglingContextClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_demangling_context_dispose; + object->finalize = (GObjectFinalizeFunc)g_demangling_context_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : context = instance à initialiser. * +* * +* Description : Initialise une instance de contexte pour décodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_demangling_context_init(GDemanglingContext *context) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_demangling_context_dispose(GDemanglingContext *context) +{ + if (context->gobj != NULL) + g_object_unref(context->gobj); + + G_OBJECT_CLASS(g_demangling_context_parent_class)->dispose(G_OBJECT(context)); + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_demangling_context_finalize(GDemanglingContext *context) +{ + G_OBJECT_CLASS(g_demangling_context_parent_class)->finalize(G_OBJECT(context)); + +} + + +/****************************************************************************** +* * +* Paramètres : context = instance à consulter. * +* desc = chaîne de caractères à décoder. * +* * +* Description : Fournit la routine créée à l'issue du codage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinRoutine *g_demangling_context_get_decoded_routine(GDemanglingContext *context, const char *desc) +{ + GBinRoutine *result; /* Construction à remonter */ + + context->routine = g_binary_routine_new(); + + if (G_DEMANGLING_CONTEXT_GET_CLASS(context)->demangle_routine(context, desc)) + { + g_object_ref(context->routine); + result = context->routine; + } + + else + result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = instance à consulter. * +* * +* Description : Fournit le type créé à l'issue du codage. * +* * +* Retour : Instance en place ou NULL en cas d'erreur fatale. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDataType *g_demangling_context_get_decoded_type(GDemanglingContext *context, const char *desc) +{ + GBinRoutine *result; /* Construction à remonter */ + + if (G_DEMANGLING_CONTEXT_GET_CLASS(context)->demangle_type(context, desc)) + { + g_object_ref(context->type); + result = context->type; + } + + else + result = NULL; + + return result; + +} diff --git a/src/mangling/context.h b/src/mangling/context.h new file mode 100644 index 0000000..705ef83 --- /dev/null +++ b/src/mangling/context.h @@ -0,0 +1,61 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * context.h - prototypes pour la fourniture de contexte aux phases de décodage + * + * Copyright (C) 2010-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/>. + */ + + +#ifndef _FORMAT_MANGLING_CONTEXT_H +#define _FORMAT_MANGLING_CONTEXT_H + + +#include <glib-object.h> + + +#include "../analysis/routine.h" + + + +#define G_TYPE_DEMANGLING_CONTEXT g_demangling_context_get_type() +#define G_DEMANGLING_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_demangling_context_get_type(), GDemanglingContext)) +#define G_IS_DEMANGLING_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_demangling_context_get_type())) +#define G_DEMANGLING_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEMANGLING_CONTEXT, GDemanglingContextClass)) +#define G_IS_DEMANGLING_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEMANGLING_CONTEXT)) +#define G_DEMANGLING_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEMANGLING_CONTEXT, GDemanglingContextClass)) + + +/* Contexte de décodage (instance) */ +typedef struct _GDemanglingContext GDemanglingContext; + +/* Contexte de décodage (classe) */ +typedef struct _GDemanglingContextClass GDemanglingContextClass; + + +/* Indique le type défini pour un contexte de décodage. */ +GType g_demangling_context_get_type(void); + +/* Fournit la routine créée à l'issue du codage. */ +GBinRoutine *g_demangling_context_get_decoded_routine(GDemanglingContext *, const char *); + +/* Fournit le type créé à l'issue du codage. */ +GDataType *g_demangling_context_get_decoded_type(GDemanglingContext *, const char *); + + + +#endif /* _FORMAT_MANGLING_CONTEXT_H */ diff --git a/src/mangling/demangler.c b/src/mangling/demangler.c new file mode 100644 index 0000000..f673a01 --- /dev/null +++ b/src/mangling/demangler.c @@ -0,0 +1,336 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * demangler.c - décodage des noms d'éléments + * + * Copyright (C) 2009-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 "demangler.h" + + +#include <malloc.h> +#include <string.h> + + +//#include "itanium.h" +#include "java.h" + + + +/* Indique si une chaîne peut être traitée par le décodeur. */ +typedef bool (* can_be_demangled_fc) (const char *); + +/* Prépare de quoi effectuer un décodage. */ +typedef GDemanglingContext * (* create_context_fc) (void); + +/* Procède au décodage d'une chaîne de caractères. */ +typedef bool (* demangle_fc) (GDemanglingContext *, const char *); + + + +/* Appels liés à un décodeur */ +typedef struct _demangling_properties +{ + can_be_demangled_fc can_demangle; /* Possibilité de traitement */ + + create_context_fc create_context; /* Création de contextes */ + + demangle_fc demangle_routine; /* Décodage d'une routine */ + demangle_fc demangle_type; /* Décodage d'un type */ + +} demangling_properties; + + +/* Liste des décodeurs */ +static demangling_properties demanglers[/*DGT_COUNT*/] = { + + /* + [DGT_ITANIUM] = { + .can_demangle = (can_be_demangled_fc)can_be_itanium_demangled, + .create_context = (create_context_fc)g_itanium_dcontext_new, + .demangle_routine = (demangle_fc)demangle_itanium_routine, + .demangle_type = (demangle_fc)NULL + }, + */ + /* + [DGT_JAVA] = { + .can_demangle = (can_be_demangled_fc)NULL, + .create_context = (create_context_fc)g_java_dcontext_new, + .demangle_routine = (demangle_fc)NULL, + .demangle_type = (demangle_fc)demangle_java_type + } + */ +}; + + + +/****************************************************************************** +* * +* Paramètres : 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 : - * +* * +******************************************************************************/ + +GBinRoutine *try_to_demangle_routine(const char *desc) +{ + GBinRoutine *result; /* Construction à remonter */ + + result = g_binary_routine_new(); + g_binary_routine_set_name(result, strdup(desc)); + + return result; + + +#if 0 + GBinRoutine *result; /* Construction à remonter */ + DemanglerType i; /* Boucle de parcours */ + + static int counter = 0; + + result = NULL; + + if (strcmp(desc, "_ZN21IUDFSettingsValidator15IdNotIllegalStdEN13UDFParameters12UDF_STANDARDES1_") == 0 + || strcmp(desc, "_ZSt12partial_sortIN9__gnu_cxx17__normal_iteratorIP28CPR_MAI_ADPTY_SectorSequenceSt6vectorIS2_SaIS2_EEEEEvT_S8_S8_") == 0 + || strcmp(desc, "_ZSt22__merge_without_bufferIN9__gnu_cxx17__normal_iteratorIP15CProfStringListSt6vectorIS2_SaIS2_EEEEiEvT_S8_S8_T0_S9_") == 0 + || strcmp(desc, "_ZSt11__push_heapIN9__gnu_cxx17__normal_iteratorIP8DRIVE_IDSt6vectorIS2_SaIS2_EEEEiS2_EvT_T0_S9_T1_") == 0 // Intéressant + //|| strcmp(desc, "") == 0 + ) + goto exit; + + for (i = 0; i < DGT_COUNT; i++) + { + if (demanglers[i].can_demangle == NULL) + continue; + + if (!demanglers[i].can_demangle(desc)) + continue; + + printf("++ [%d] routine :: %s\n", ++counter, desc); + fflush(NULL); + + result = demangle_routine(i, desc); + + /* FIXME : à supprimer quand mature */ + if (result == NULL) + { + printf("++failed :: %s\n", desc); + + if (strcmp(desc, "_ZN21IUDFSettingsValidator15IdNotIllegalStdEN13UDFParameters12UDF_STANDARDES1_") != 0 + && strcmp(desc, "_ZSt12partial_sortIN9__gnu_cxx17__normal_iteratorIP28CPR_MAI_ADPTY_SectorSequenceSt6vectorIS2_SaIS2_EEEEEvT_S8_S8_") != 0 + ) + exit(-1); + + } + else printf(" -->> '%s'\n\n", g_binary_routine_get_name(result)); + + if (result != NULL) break; + + } + + exit: + + if (result == NULL) + { + result = g_binary_routine_new(); + g_binary_routine_set_name(result, strdup(desc)); + } + + return result; +#endif + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type de décodeur à utiliser. * +* 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 : - * +* * +******************************************************************************/ + +GBinRoutine *demangle_routine(GType type, const char *desc) +{ + GBinRoutine *result; /* Construction à remonter */ + GDemanglingContext *context; /* Contexte pour le décodage */ + + context = g_object_new(type, NULL); + + result = g_demangling_context_get_decoded_routine(context, desc); + + g_object_unref(context); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type de décodeur à utiliser. * +* 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 : - * +* * +******************************************************************************/ + +GDataType *demangle_type(GType type, const char *desc) +{ + GBinRoutine *result; /* Construction à remonter */ + GDemanglingContext *context; /* Contexte pour le décodage */ + + context = g_object_new(type, NULL); + + result = g_demangling_context_get_decoded_type(context, desc); + + g_object_unref(context); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Procède au test de décodages de chaînes de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ +#if 0 +void test_itanium_demangling(void) +{ + GBinRoutine *routine; + char *human; + char stop; + +#define TEST_ITANIUM_MANGLING(name, ref) \ + do \ + { \ + printf(" >> %s\n", name); \ + routine = demangle_routine(DGT_ITANIUM, name); \ + if (routine == NULL) \ + { \ + printf("Error with %s\n", name); \ + stop = true; \ + } \ + else \ + { \ + human = g_binary_routine_to_string(routine); \ + printf(" >> %s\n", human); \ + stop = (strcmp(ref, human) != 0); \ + printf(" >> ok ? %s\n", (!stop ? "oui" : "non")); \ + if (stop) printf(" >> expected '%s'\n", ref); \ + free(human); \ + } \ + if (stop) goto end_of_test; \ + else printf("\n"); \ + } \ + while (0) + + //goto last; + + /** + * Tests de : + * http://www.codesourcery.com/public/cxx-abi/abi-examples.html#mangling + */ + + TEST_ITANIUM_MANGLING("_Z1fv", "??? f(void)"); + + TEST_ITANIUM_MANGLING("_Z1fi", "??? f(int)"); + + TEST_ITANIUM_MANGLING("_Z3foo3bar", "??? foo(bar)"); + + TEST_ITANIUM_MANGLING("_Zrm1XS_", "??? %(X, X)"); + + TEST_ITANIUM_MANGLING("_ZplR1XS0_", "??? +(X &, X &)"); + + TEST_ITANIUM_MANGLING("_ZlsRK1XS1_", "??? <<(const X &, const X &)"); + + TEST_ITANIUM_MANGLING("_Z1fIiEvi", "void f<int>(int)"); + + TEST_ITANIUM_MANGLING("_Z5firstI3DuoEvS0_", "void first<Duo>(Duo)"); + + TEST_ITANIUM_MANGLING("_Z5firstI3DuoEvT_", "void first<Duo>(Duo)"); + + TEST_ITANIUM_MANGLING("_Z3fooIiPFidEiEvv", "void foo<int, int (*)(double), int>(void)"); + + TEST_ITANIUM_MANGLING("_ZN6System5Sound4beepEv", "??? System::Sound::beep(void)"); + + TEST_ITANIUM_MANGLING("_Z1fI1XE vPV N1AIT_E1TE", "void f<X>(volatile A<X>::T *)"); + + //// TODO :: TEST_ITANIUM_MANGLING("_ZngILi42EE v N1A I XplT_Li2EE E 1TE", ""); + + TEST_ITANIUM_MANGLING("_Z4makeI7FactoryiE T_IT0_E v", "Factory<int> make<Factory, int>(void)"); + + TEST_ITANIUM_MANGLING("_ZlsRSoRKSs", "??? <<(std::ostream &, const std::string &)"); + + //TEST_ITANIUM_MANGLING("", ""); + + /** + * Tests de : + * http://www.codesourcery.com/public/cxx-abi/abi.html#mangling + */ + + TEST_ITANIUM_MANGLING("_ZN1N1TIiiE2mfES0_IddE", "??? N::T<int, int>::mf(N::T<double, double>)"); + + /** + * Tests de : + * (nero.so). + */ + + TEST_ITANIUM_MANGLING("_ZNSt6vectorItSaItEE6insertEN9__gnu_cxx17__normal_iteratorIPtS1_EERKt", "??? std::vector<unsigned short, std::allocator<unsigned short>>::insert(__gnu_cxx::__normal_iterator<unsigned short *, std::vector<unsigned short, std::allocator<unsigned short>>>, const unsigned short &)"); + + TEST_ITANIUM_MANGLING("_ZSt26__uninitialized_fill_n_auxIP15CProfStringListiS0_ET_S2_T0_RKT1_12__false_type", "CProfStringList *std::__uninitialized_fill_n_aux<CProfStringList *, int, CProfStringList>(CProfStringList *, int, const CProfStringList &, __false_type)"); + + // TODO TEST_ITANIUM_MANGLING("_ZN21IUDFSettingsValidator15IdNotIllegalStdEN13UDFParameters12UDF_STANDARDES1_", ""); + + TEST_ITANIUM_MANGLING("_ZNSbI26NeroMediumFeatureSpecifierSt11char_traitsIS_ESaIS_EE4_Rep10_M_destroyERKS2_", "??? std::basic_string<NeroMediumFeatureSpecifier, std::char_traits<NeroMediumFeatureSpecifier>, std::allocator<NeroMediumFeatureSpecifier>>::_Rep::_M_destroy(const std::allocator<NeroMediumFeatureSpecifier> &)"); + + last: + + /* 80 */ + TEST_ITANIUM_MANGLING("_ZNSt6vectorIlSaIlEE6insertEN9__gnu_cxx17__normal_iteratorIPlS1_EERKl", "??? std::vector<long, std::allocator<long>>::insert(__gnu_cxx::__normal_iterator<long *, std::vector<long, std::allocator<long>>>, const long &)"); + + end_of_test: + + ; + +} +#endif diff --git a/src/mangling/demangler.h b/src/mangling/demangler.h new file mode 100644 index 0000000..00218e4 --- /dev/null +++ b/src/mangling/demangler.h @@ -0,0 +1,50 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * demangler.h - prototypes pour le décodage des noms d'éléments + * + * Copyright (C) 2009-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/>. + */ + + +#ifndef _FORMAT_MANGLING_DEMANGLER_H +#define _FORMAT_MANGLING_DEMANGLER_H + + +#include "../analysis/routine.h" + + + +/* Tente de décoder une chaîne de caractères donnée. */ +GBinRoutine *try_to_demangle_routine(const char *); + +/* Tente de décoder une chaîne de caractères donnée. */ +GBinRoutine *demangle_routine(GType, const char *); + +/* Tente de décoder une chaîne de caractères donnée. */ +GDataType *demangle_type(GType, const char *); + + + +/* Procède au test de décodages de chaînes de caractères. */ +#ifdef DEBUG +void test_itanium_demangling(void); +#endif + + + +#endif /* _FORMAT_MANGLING_DEMANGLER_H */ diff --git a/src/mangling/dex/Makefile.am b/src/mangling/dex/Makefile.am new file mode 100644 index 0000000..547d686 --- /dev/null +++ b/src/mangling/dex/Makefile.am @@ -0,0 +1,46 @@ + +BUILT_SOURCES = libmanglingdexshorty_la-shorty_gram.h libmanglingdextype_la-type_gram.h + +AM_YFLAGS = -d + +noinst_LTLIBRARIES = libmanglingdex.la libmanglingdexshorty.la libmanglingdextype.la + +libmanglingdex_la_SOURCES = \ + context.h context.c + +libmanglingdex_la_LDFLAGS = + +libmanglingdex_la_LIBADD = \ + libmanglingdexshorty.la \ + libmanglingdextype.la + + +libmanglingdexshorty_la_SOURCES = \ + shorty_gram.y \ + shorty_tok.l + +libmanglingdexshorty_la_YFLAGS = -d -p shorty_ -o y.tab.c + +libmanglingdexshorty_la_LFLAGS = -P shorty_ -o lex.yy.c + + +libmanglingdextype_la_SOURCES = \ + type_gram.y \ + type_tok.l + +libmanglingdextype_la_YFLAGS = -d -p type_ -o y.tab.c + +libmanglingdextype_la_LFLAGS = -P type_ -o lex.yy.c + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + + +# Automake fait les choses à moitié +CLEANFILES = \ + libmanglingdexshorty_la-shorty_gram.h libmanglingdexshorty_la-shorty_gram.c \ + libmanglingdexshorty_la-shorty_tok.c \ + libmanglingdextype_la-type_gram.h libmanglingdextype_la-type_gram.c \ + libmanglingdextype_la-type_tok.c diff --git a/src/mangling/dex/context.c b/src/mangling/dex/context.c new file mode 100644 index 0000000..9dd9b9c --- /dev/null +++ b/src/mangling/dex/context.c @@ -0,0 +1,154 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * context.c - contextes de décodage DEX + * + * Copyright (C) 2015-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 "../context-int.h" + + + +/* Contexte de décodage DEX (instance) */ +struct _GDexDemangler +{ + GDemanglingContext parent; /* A laisser en premier */ + +}; + +/* Contexte de décodage DEX (classe) */ +struct _GDexDemanglerClass +{ + GDemanglingContextClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des contextes de décodage DEX. */ +static void g_dex_demangler_class_init(GDexDemanglerClass *); + +/* Initialise une instance de contexte pour décodage DEX. */ +static void g_dex_demangler_init(GDexDemangler *); + +/* Supprime toutes les références externes. */ +static void g_dex_demangler_dispose(GDexDemangler *); + +/* Procède à la libération totale de la mémoire. */ +static void g_dex_demangler_finalize(GDexDemangler *); + + +/* Procède au décodage d'une chaîne de caractères. */ +extern bool demangle_dex_routine(GDexDemangler *, const char *); + +/* Procède au décodage d'une chaîne de caractères. */ +extern bool demangle_dex_type(GDexDemangler *, const char *); + + + +/* Indique le type défini pour un contexte de décodage DEX. */ +G_DEFINE_TYPE(GDexDemangler, g_dex_demangler, G_TYPE_DEMANGLING_CONTEXT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des contextes de décodage DEX. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_demangler_class_init(GDexDemanglerClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDemanglingContextClass *context; /* Version parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_dex_demangler_dispose; + object->finalize = (GObjectFinalizeFunc)g_dex_demangler_finalize; + + context = G_DEMANGLING_CONTEXT_CLASS(klass); + + context->demangle_type = (demangle_fc)demangle_dex_type; + context->demangle_routine = (demangle_fc)demangle_dex_routine; + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = instance à initialiser. * +* * +* Description : Initialise une instance de contexte pour décodage DEX. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_demangler_init(GDexDemangler *demangler) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_demangler_dispose(GDexDemangler *demangler) +{ + G_OBJECT_CLASS(g_dex_demangler_parent_class)->dispose(G_OBJECT(demangler)); + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dex_demangler_finalize(GDexDemangler *demangler) +{ + G_OBJECT_CLASS(g_dex_demangler_parent_class)->finalize(G_OBJECT(demangler)); + +} diff --git a/src/mangling/dex/context.h b/src/mangling/dex/context.h new file mode 100644 index 0000000..1af7a9d --- /dev/null +++ b/src/mangling/dex/context.h @@ -0,0 +1,52 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * context.h - prototypes internes liés aux contextes de décodage DEX + * + * Copyright (C) 2015-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/>. + */ + + +#ifndef _FORMAT_MANGLING_DEX_CONTEXT_H +#define _FORMAT_MANGLING_DEX_CONTEXT_H + + +#include <glib-object.h> + + + +#define G_TYPE_DEX_DEMANGLER g_dex_demangler_get_type() +#define G_DEX_DEMANGLER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dex_demangler_get_type(), GDexDemangler)) +#define G_IS_DEX_DEMANGLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dex_demangler_get_type())) +#define G_DEX_DEMANGLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DEX_DEMANGLER, GDexDemanglerClass)) +#define G_IS_DEX_DEMANGLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DEX_DEMANGLER)) +#define G_DEX_DEMANGLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DEX_DEMANGLER, GDexDemanglerClass)) + + +/* Contexte de décodage DEX (instance) */ +typedef struct _GDexDemangler GDexDemangler; + +/* Contexte de décodage DEX (classe) */ +typedef struct _GDexDemanglerClass GDexDemanglerClass; + + +/* Indique le type défini pour un contexte de décodage DEX. */ +GType g_dex_demangler_get_type(void); + + + +#endif /* _FORMAT_MANGLING_DEX_CONTEXT_H */ diff --git a/src/mangling/dex/shorty_gram.y b/src/mangling/dex/shorty_gram.y new file mode 100644 index 0000000..b688896 --- /dev/null +++ b/src/mangling/dex/shorty_gram.y @@ -0,0 +1,138 @@ + +%{ + +#include <stdbool.h> + + +#include "context.h" +#include "../context-int.h" + + + +/* Affiche un message d'erreur concernant l'analyse. */ +static int shorty_error(GDexDemangler *, char *); + +/* Procède au décodage d'une chaîne de caractères. */ +bool demangle_dex_routine(GDexDemangler *, const char *); + + +%} + + +%code requires { + +#include "../../analysis/types/basic.h" +#include "../../analysis/types/cse.h" + +} + +%union { + + GDataType *type; /* Type reconstruit */ + +} + + +%parse-param { GDexDemangler *demangler } + +%token V Z B S C I J F D L + +%type <type> shorty_return_type shorty_field_type + + +%{ + +/* Déclarations issues de l'analyseur syntaxique... */ + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern YY_BUFFER_STATE shorty__scan_string(const char *); +extern void shorty__delete_buffer(YY_BUFFER_STATE); +extern int shorty_lex(void); + +%} + + +%% + + +shorty_descriptor: + shorty_return_type shorty_field_type_list { + GBinRoutine *routine; + routine = G_DEMANGLING_CONTEXT(demangler)->routine; + g_binary_routine_set_return_type(routine, $1); + } + +shorty_field_type_list: + /* empty */ + | shorty_field_type shorty_field_type_list { + GBinRoutine *routine; + GBinVariable *var; + routine = G_DEMANGLING_CONTEXT(demangler)->routine; + var = g_binary_variable_new($1); + g_binary_routine_add_arg(routine, var); + } + +shorty_return_type: + V { $$ = g_basic_type_new(BTP_VOID); } + | shorty_field_type { $$ = $1; } + +shorty_field_type: + Z { $$ = g_basic_type_new(BTP_BOOL); } + | B { $$ = g_basic_type_new(BTP_UCHAR); } + | S { $$ = g_basic_type_new(BTP_SHORT); } + | C { $$ = g_basic_type_new(BTP_CHAR); } + | I { $$ = g_basic_type_new(BTP_INT); } + | J { $$ = g_basic_type_new(BTP_LONG); } + | F { $$ = g_basic_type_new(BTP_FLOAT); } + | D { $$ = g_basic_type_new(BTP_DOUBLE); } + | L { $$ = g_class_enum_type_new(CET_CLASS, ""); } + + +%% + + +/****************************************************************************** +* * +* Paramètres : demangler = contexte associé à la procédure de décodage. * +* msg = indications humaines sur l'événement. * +* * +* Description : Affiche un message d'erreur concernant l'analyse. * +* * +* Retour : Valeur historique, ignorée. * +* * +* Remarques : - * +* * +******************************************************************************/ +static int shorty_error(GDexDemangler *demangler, char *msg) +{ + return -1; + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = contexte de décodage à utiliser. * +* desc = chaîne de caractères à décoder. * +* * +* Description : Procède au décodage d'une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool demangle_dex_routine(GDexDemangler *demangler, const char *desc) +{ + YY_BUFFER_STATE buffer; /* Tampon pour bison */ + int ret; /* Bilan de l'appel */ + + buffer = shorty__scan_string(desc); + ret = yyparse(demangler); + shorty__delete_buffer(buffer); + + return (ret == 0); + +} diff --git a/src/mangling/dex/shorty_tok.l b/src/mangling/dex/shorty_tok.l new file mode 100644 index 0000000..92c264a --- /dev/null +++ b/src/mangling/dex/shorty_tok.l @@ -0,0 +1,28 @@ + +%{ + +#include "context.h" +#include "libformatmanglingdexshorty_la-shorty_gram.h" + +%} + + +%option noyywrap +%option yylineno +%option nounput +%option noinput + +%% + +"V" { return V; } +"Z" { return Z; } +"B" { return B; } +"S" { return S; } +"C" { return C; } +"I" { return I; } +"J" { return J; } +"F" { return F; } +"D" { return D; } +"L" { return L; } + +%% diff --git a/src/mangling/dex/type_gram.y b/src/mangling/dex/type_gram.y new file mode 100644 index 0000000..79c9320 --- /dev/null +++ b/src/mangling/dex/type_gram.y @@ -0,0 +1,159 @@ + +%{ + +#include <stdbool.h> + + +#include "context.h" +#include "../context-int.h" + +typedef void *yyscan_t; + +/* Affiche un message d'erreur concernant l'analyse. */ +static int type_error(GDexDemangler *, yyscan_t, char *); + +/* Procède au décodage d'une chaîne de caractères. */ +bool demangle_dex_type(GDexDemangler *, const char *); + + +%} + + +%code requires { + +#include "../../analysis/types/basic.h" +#include "../../analysis/types/cse.h" +#include "../../common/extstr.h" + +} + +%union { + + GDataType *type; /* Type reconstruit */ + size_t adeep; /* Dimension d'un tableau */ + char *text; /* Chaîne de caractères */ + +} + + + +%define api.pure full +%parse-param { GDexDemangler *demangler } { yyscan_t scanner } +%lex-param { yyscan_t scanner } + + +%token V Z B S C I J F D +%token ARRAY +%token L SEMICOLON +%token SLASH DOLLAR +%token TEXT + +%type <type> type_descriptor field_type_descriptor non_array_field_type_descriptor full_class_name + +%type <text> TEXT simple_name + + +%{ + +/* Déclarations issues de l'analyseur syntaxique... */ + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int type_lex_init(yyscan_t *scanner); +extern YY_BUFFER_STATE type__scan_string(const char *, yyscan_t); +extern void type__delete_buffer(YY_BUFFER_STATE, yyscan_t); +extern int type_lex(YYSTYPE *, yyscan_t); +extern int type_lex_destroy(yyscan_t); + +%} + + +%% + + +input: + type_descriptor { G_DEMANGLING_CONTEXT(demangler)->type = $1; } + +type_descriptor: + V { $$ = g_basic_type_new(BTP_VOID); } + | field_type_descriptor { $$ = $1; } + +field_type_descriptor: + non_array_field_type_descriptor { $$ = $1; } + | ARRAY non_array_field_type_descriptor { $$ = $2; } + +non_array_field_type_descriptor: + Z { $$ = g_basic_type_new(BTP_BOOL); } + | B { $$ = g_basic_type_new(BTP_UCHAR); } + | S { $$ = g_basic_type_new(BTP_SHORT); } + | C { $$ = g_basic_type_new(BTP_CHAR); } + | I { $$ = g_basic_type_new(BTP_INT); } + | J { $$ = g_basic_type_new(BTP_LONG); } + | F { $$ = g_basic_type_new(BTP_FLOAT); } + | D { $$ = g_basic_type_new(BTP_DOUBLE); } + | L full_class_name SEMICOLON { $$ = $2; } + +full_class_name: + simple_name { $$ = g_class_enum_type_new(CET_CLASS, $1); } + | full_class_name SLASH simple_name { + $$ = g_class_enum_type_new(CET_CLASS, $3); + g_data_type_set_namespace($$, $1); + g_object_unref($1); + } +simple_name: + TEXT { $$ = strdup($1); } + | simple_name TEXT { $$ = stradd($1, $2); } + +%% + + +/****************************************************************************** +* * +* Paramètres : demangler = contexte associé à la procédure de décodage. * +* scanner = données internes aux analyseurs. * +* msg = indications humaines sur l'événement. * +* * +* Description : Affiche un message d'erreur concernant l'analyse. * +* * +* Retour : Valeur historique, ignorée. * +* * +* Remarques : - * +* * +******************************************************************************/ +static int type_error(GDexDemangler *demangler, yyscan_t scanner, char *msg) +{ + return -1; + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = contexte de décodage à utiliser. * +* desc = chaîne de caractères à décoder. * +* * +* Description : Procède au décodage d'une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool demangle_dex_type(GDexDemangler *demangler, const char *desc) +{ + yyscan_t scanner; /* Données internes */ + YY_BUFFER_STATE buffer; /* Tampon pour bison */ + int ret; /* Bilan de l'appel */ + + type_lex_init(&scanner); + + buffer = type__scan_string(desc, scanner); + ret = yyparse(demangler, scanner); + type__delete_buffer(buffer, scanner); + + type_lex_destroy(scanner); + + return (ret == 0); + +} diff --git a/src/mangling/dex/type_tok.l b/src/mangling/dex/type_tok.l new file mode 100644 index 0000000..918846a --- /dev/null +++ b/src/mangling/dex/type_tok.l @@ -0,0 +1,150 @@ + +%{ + +#include "context.h" +#include "libformatmanglingdextype_la-type_gram.h" + +/* See lemoda.net/c/reentrant-parser */ + +%} + + +%option noyywrap +%option yylineno +%option nounput +/*%option noinput*/ +%option reentrant +%option bison-bridge + +%x string + +ASCII [A-Za-z0-9] +SIMPLE {ASCII}|"$"|"-"|"_" + +%% + +"V" { return V; } +"Z" { return Z; } +"B" { return B; } +"S" { return S; } +"C" { return C; } +"I" { return I; } +"J" { return J; } +"F" { return F; } +"D" { return D; } +"L" { BEGIN(string); return L; } +"["* { yylval->adeep = strlen(yytext); return ARRAY; } +<string>"/" { return SLASH; } +<string>";" { BEGIN(INITIAL); return SEMICOLON; } + +<string>{SIMPLE}* { yylval->text = yytext; return TEXT; } + +<string>. { + unsigned char next; + char mutf8[4]; + + switch ((unsigned char)yytext[0]) + { + /* U+00a1 ... U+1fff */ + case 0x00 ... 0x1f: + + next = input(yyscanner); + + if (yytext[0] == 0x00 && next < 0xa1) + { + REJECT; + } + + else + { + mutf8[0] = yytext[0]; + mutf8[1] = next; + mutf8[2] = '\0'; + + strcpy(yylval->text, mutf8); return TEXT; + + } + + break; + + /* U+2010 ... U+2027 / U+2030 ... U+d7ff */ + case 0x20: + + next = input(yyscanner); + + switch (next) + { + case 0x10 ... 0x27: + case 0x30 ... 0xff: + + mutf8[0] = yytext[0]; + mutf8[1] = next; + mutf8[2] = '\0'; + + strcpy(yylval->text, mutf8); return TEXT; + break; + + default: + REJECT; + break; + + } + + break; + + /* ~ U+2030 ... U+d7ff */ + case 0x21 ... 0xd7: + + next = input(yyscanner); + + mutf8[0] = yytext[0]; + mutf8[1] = next; + mutf8[2] = '\0'; + + strcpy(yylval->text, mutf8); return TEXT; + break; + + /* U+e000 ... U+ffef */ + case 0xe0 ... 0xff: + + next = input(yyscanner); + + if (yytext[0] == 0xff && next > 0xef) + { + REJECT; + } + + else + { + mutf8[0] = yytext[0]; + mutf8[1] = next; + mutf8[2] = '\0'; + + strcpy(yylval->text, mutf8); return TEXT; + + } + + break; + + /* U+10000 ... U+10ffff */ + /* + case 0x10: + + mutf8[0] = yytext[0]; + mutf8[1] = input(yyscanner); + mutf8[2] = input(yyscanner); + mutf8[3] = '\0'; + + strcpy(yylval->text, mutf8); return TEXT; + break; + */ + + default: + REJECT; + break; + + } + + } + +%% diff --git a/src/mangling/itanium/Makefile.am b/src/mangling/itanium/Makefile.am new file mode 100755 index 0000000..216788b --- /dev/null +++ b/src/mangling/itanium/Makefile.am @@ -0,0 +1,19 @@ + +noinst_LTLIBRARIES = libmanglingitanium.la + +libmanglingitanium_la_SOURCES = \ + abi.h abi.c \ + component-int.h \ + component.h component.c \ + context.h context.c + +libmanglingitanium_la_LIBADD = + +libmanglingitanium_la_LDFLAGS = + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = diff --git a/src/mangling/itanium/abi.c b/src/mangling/itanium/abi.c new file mode 100644 index 0000000..3970482 --- /dev/null +++ b/src/mangling/itanium/abi.c @@ -0,0 +1,2444 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * abi.c - décodage des noms d'éléments selon 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 "abi.h" + + +#include <ctype.h> +#include <stdlib.h> + + + +#include "../../analysis/types/basic.h" +#include "../../common/cpp.h" + + + +/* Liste des opérateurs reconnus */ + +#define IDT_NL(s) s, sizeof(s) - 1 + +const itanium_operator_info itanium_demangle_operators[] = { + + { "aN", IDT_NL("&="), 2 }, + { "aS", IDT_NL("="), 2 }, + { "aa", IDT_NL("&&"), 2 }, + { "ad", IDT_NL("&"), 1 }, + { "an", IDT_NL("&"), 2 }, + { "at", IDT_NL("alignof "), 1 }, + { "az", IDT_NL("alignof "), 1 }, + { "cc", IDT_NL("const_cast"), 2 }, + { "cl", IDT_NL("()"), 2 }, + { "cm", IDT_NL(","), 2 }, + { "co", IDT_NL("~"), 1 }, + { "dV", IDT_NL("/="), 2 }, + { "da", IDT_NL("delete[] "), 1 }, + { "dc", IDT_NL("dynamic_cast"), 2 }, + { "de", IDT_NL("*"), 1 }, + { "dl", IDT_NL("delete "), 1 }, + { "ds", IDT_NL(".*"), 2 }, + { "dt", IDT_NL("."), 2 }, + { "dv", IDT_NL("/"), 2 }, + { "eO", IDT_NL("^="), 2 }, + { "eo", IDT_NL("^"), 2 }, + { "eq", IDT_NL("=="), 2 }, + { "ge", IDT_NL(">="), 2 }, + { "gs", IDT_NL("::"), 1 }, + { "gt", IDT_NL(">"), 2 }, + { "ix", IDT_NL("[]"), 2 }, + { "lS", IDT_NL("<<="), 2 }, + { "le", IDT_NL("<="), 2 }, + { "li", IDT_NL("operator\"\" "), 1 }, + { "ls", IDT_NL("<<"), 2 }, + { "lt", IDT_NL("<"), 2 }, + { "mI", IDT_NL("-="), 2 }, + { "mL", IDT_NL("*="), 2 }, + { "mi", IDT_NL("-"), 2 }, + { "ml", IDT_NL("*"), 2 }, + { "mm", IDT_NL("--"), 1 }, + { "na", IDT_NL("new[]"), 3 }, + { "ne", IDT_NL("!="), 2 }, + { "ng", IDT_NL("-"), 1 }, + { "nt", IDT_NL("!"), 1 }, + { "nw", IDT_NL("new"), 3 }, + { "oR", IDT_NL("|="), 2 }, + { "oo", IDT_NL("||"), 2 }, + { "or", IDT_NL("|"), 2 }, + { "pL", IDT_NL("+="), 2 }, + { "pl", IDT_NL("+"), 2 }, + { "pm", IDT_NL("->*"), 2 }, + { "pp", IDT_NL("++"), 1 }, + { "ps", IDT_NL("+"), 1 }, + { "pt", IDT_NL("->"), 2 }, + { "qu", IDT_NL("?"), 3 }, + { "rM", IDT_NL("%="), 2 }, + { "rS", IDT_NL(">>="), 2 }, + { "rc", IDT_NL("reinterpret_cast"), 2 }, + { "rm", IDT_NL("%"), 2 }, + { "rs", IDT_NL(">>"), 2 }, + { "sc", IDT_NL("static_cast"), 2 }, + { "st", IDT_NL("sizeof "), 1 }, + { "sz", IDT_NL("sizeof "), 1 }, + { "tr", IDT_NL("throw"), 0 }, + { "tw", IDT_NL("throw "), 1 } +}; + +/* Substitutions standards */ + +typedef struct _itanium_std_subst_info +{ + char code; /* Identifiant associé */ + + const char *simple; /* Représentation simple */ + size_t simple_len; /* Taille de cette représentat°*/ + + const char *full; /* Représentation complète */ + size_t full_len; /* Taille de cette représentat°*/ + + const char *last_name; /* Pour les (con|de)structeurs */ + size_t last_name_len; /* Taille de cette indication */ + +} itanium_std_subst_info; + +const itanium_std_subst_info itanium_standard_substitutions[] = { + + { + 't', + IDT_NL("std"), + IDT_NL("std"), + NULL, + 0 + }, + { + 'a', + IDT_NL("std::allocator"), + IDT_NL("std::allocator"), + IDT_NL("allocator") + }, + { + 'b', + IDT_NL("std::basic_string"), + IDT_NL("std::basic_string"), + IDT_NL("basic_string") + }, + { + 's', + IDT_NL("std::string"), + IDT_NL("std::basic_string<char, std::char_traits<char>, std::allocator<char>>"), + IDT_NL("basic_string") + }, + { + 'i', + IDT_NL("std::istream"), + IDT_NL("std::basic_istream<char, std::char_traits<char>>"), + IDT_NL("basic_istream") + }, + { + 'o', + IDT_NL("std::ostream"), + IDT_NL("std::basic_ostream<char, std::char_traits<char>>"), + IDT_NL("basic_ostream") + }, + { + 'd', + IDT_NL("std::iostream"), + IDT_NL("std::basic_iostream<char, std::char_traits<char>>"), + IDT_NL("basic_iostream") + } + +}; + + + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_encoding(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_unscoped_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_unscoped_template_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_nested_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_prefix(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_prefix(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_unqualified_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_source_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static bool itd_number(GItaniumDContext *, ssize_t *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_identifier(GItaniumDContext *, size_t); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_operator_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_special_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_call_offset(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_nv_offset(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_v_offset(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_ctor_dtor_name(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_type(GItaniumDContext *); + +/* Extrait une propriété de composant pour un contexte Itanium. */ +static TypeQualifier itd_cv_qualifiers(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_builtin_type(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_bare_function_type(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_class_enum_type(GItaniumDContext *); + + + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_args(GItaniumDContext *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_arg(GItaniumDContext *); + + + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_value_to_string(GItaniumDContext *, bool); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_expr_primary(GItaniumDContext *); + + + + +/* Extrait un composant dans un contexte Itanium. */ +static bool itd_seq_id(GItaniumDContext *, char, size_t *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_substitution(GItaniumDContext *); + + + + + + +#define itd_template_param(ctx) NULL + + +#define itd_local_name(ctx) NULL + + + + +#define itd_expression(ctx) NULL + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_mangled_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + + /** + * La règle traitée ici est la suivante : + * + * <mangled-name> ::= _Z <encoding> + * + */ + + if (!g_itanium_dcontext_check_char(context, '_')) + return NULL; + + if (!g_itanium_dcontext_check_char(context, 'Z')) + return NULL; + + result = itd_encoding(context); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_encoding(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *func; /* Composant 'function name' */ + itanium_component *types; /* Composant 'bare-function...'*/ + + /** + * La règle traitée ici est la suivante : + * + * <encoding> ::= <function name> <bare-function-type> + * ::= <data name> + * ::= <special-name> + * + */ + + result = NULL; + g_itanium_dcontext_push_state(context, &saved); + + func = itd_name(context); + + if (func != NULL) + { + types = itd_bare_function_type(context); + + if (types != NULL) + result = itd_make_binary(context, ICT_FUNCTION_ENCODING, func, types); + else + itd_unref_comp(func); + + } + /* + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_name(context); + } + */ + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_special_name(context); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *tname; /* Composant '...template-name'*/ + itanium_component *targs; /* Composant 'template-args' */ + + /** + * La règle traitée ici est la suivante : + * + * <name> ::= <nested-name> + * ::= <unscoped-name> + * ::= <unscoped-template-name> <template-args> + * ::= <local-name> + * + */ + + g_itanium_dcontext_push_state(context, &saved); + + result = itd_nested_name(context); + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + + tname = itd_unscoped_template_name(context); + + if (tname != NULL) + { + targs = itd_template_args(context); + + if (targs != NULL) + { + g_itanium_dcontext_add_substitution(context, tname); + result = itd_make_binary(context, ICT_TEMPLATE_NAME_ARGS, tname, targs); + } + + else + itd_unref_comp(tname); + + } + + } + + /** + * La règle <unscoped-name> doit être traitée après <unscoped-template-name>, + * car ces deux dernières ont une base commune et la seconde peut avoir besoin + * d'aller plus loin avec la règle <template-args>. + * + * On termine donc par moins gourmand si la règle la plus complexe n'a pas abouti. + */ + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_unscoped_name(context); + } + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_local_name(context); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_unscoped_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + + /** + * La règle traitée ici est la suivante : + * + * <unscoped-name> ::= <unqualified-name> + * ::= St <unqualified-name> # ::std:: + * + */ + + + /* TODO : 'St' */ + + + result = itd_unqualified_name(context); + + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_unscoped_template_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itd_state saved; /* Position d'analyse courante */ + + /** + * La règle traitée ici est la suivante : + * + * <unscoped-template-name> ::= <unscoped-name> + * ::= <substitution> + * + */ + + g_itanium_dcontext_push_state(context, &saved); + + result = itd_unscoped_name(context); + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_substitution(context); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_nested_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + TypeQualifier qualifier; /* Propriétés supplémentaires */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *left; /* Première partie */ + itanium_component *right; /* Seconde partie */ + + static int inner = 0; + + int val = inner++; + + printf("\n ### (%d) NESTED>> '%s'\n", val, + g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + + /** + * La règle traitée ici est la suivante : + * + * <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E + * ::= N [<CV-qualifiers>] <template-prefix> <template-args> E + * + */ + + if (!g_itanium_dcontext_check_char(context, 'N')) + return NULL; + + qualifier = itd_cv_qualifiers(context); + + result = NULL; + + g_itanium_dcontext_push_state(context, &saved); + + + printf("\n ----- (%d) nested prefix '%s'\n", val, g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + + + + left = itd_prefix(context); + + if (left != NULL) + { + if (itd_get_component_type(left) != ICT_EMPTY) + g_itanium_dcontext_add_substitution(context, left); + + right = itd_unqualified_name(context); + + if (right != NULL) + { + if (g_itanium_dcontext_check_char(context, 'E')) + result = itd_make_binary(context, ICT_NESTED_NAME, left, right); + else + printf("=== (%d) nested/prefix : BAD E\n\n", val); + + //result = itd_make_binary(context, ICT_NESTED_NAME, left, right); + + } + else + itd_unref_comp(left); + + printf(" ---- (%d) nested prefix --> %p\n\n", val, result); + + } + + + if (result == NULL) + { + printf("\n ----- (%d) nested template_arg '%s'\n", val, g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + + g_itanium_dcontext_pop_state(context, &saved); + + left = itd_template_prefix(context); + + if (left != NULL) + { + g_itanium_dcontext_add_substitution(context, left); + + right = itd_template_args(context); + + if (right != NULL) + { + if (g_itanium_dcontext_check_char(context, 'E')) + result = itd_make_binary(context, ICT_NESTED_NAME, left, right); + else + printf("=== (%d) nested/prefix : BAD E\n\n", val); + } + else + itd_unref_comp(left); + + } + + printf(" ---- (%d) nested template_arg --> %p\n\n", val, result); + + } + + + + printf("(%d) nested/E >> '%s'\n", val, g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + + /* + if (!g_itanium_dcontext_check_char(context, 'E')) + { + printf("=== (%d) NESTED : BAD E\n\n", val); + + if (result != NULL) + itd_unref_comp(result); + return NULL; + } + */ + + if (result != NULL) + printf("=== (%d) NESTED OK (%p)\n\n", val, result); + + inner--; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_prefix(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itanium_component *looping_rule; /* Extraction d'une boucle */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *left; /* Première partie */ + itanium_component *right; /* Seconde partie */ + + itd_state next_name_saved; /* Position d'analyse courante */ + itanium_component *next_name; /* Eventuel complément #1 */ + itd_state next_targs_saved; /* Position d'analyse courante */ + itanium_component *next_targs; /* Eventuel complément #2 */ + + + + itd_state expected_saved; /* Position d'analyse suivante */ + itanium_component *expected; /* Nom non-qualifié en réserve */ + + + + /** + * Les deux règles traitées ici sont les suivantes : + * + * <prefix> ::= <prefix> <unqualified-name> + * ::= <template-prefix> <template-args> + * ::= <template-param> + * ::= # empty + * ::= <substitution> + * + * <template-prefix> ::= <prefix> <template unqualified-name> + * ::= <template-param> + * ::= <substitution> + * + * Pour éviter une récursivité qui ferait exploser la pile, on les fusionne + * en une nouvelle règle <prefix> étendue : + * + * <prefix> ::= <prefix> <unqualified-name> + * ::= <prefix> <unqualified-name> <template-args> + * ::= <template-param> <template-args> + * ::= <substitution> <template-args> + * ::= <template-param> + * ::= # empty + * ::= <substitution> + * + * On découpe ainsi les traitements en deux parties : + * - extraction du socle non récursif. + * - extraction éventuelle d'un complément <unqualified-name> [<template-args>] + */ + + result = NULL; + + while (1) + { + printf("loop....\n"); + + looping_rule = NULL; + + /** + * Première partie. + */ + + g_itanium_dcontext_push_state(context, &saved); + + /* <template-param> <template-args> */ + + left = itd_template_param(context); + + if (left != NULL) + { + g_itanium_dcontext_add_substitution(context, left); + + right = itd_template_args(context); + + if (right != NULL) + looping_rule = itd_make_binary(context, ICT_PREFIX_BINARY, left, right); + else + itd_unref_comp(left); + + } + + /* <substitution> <template-args> */ + + if (looping_rule != NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + + left = itd_substitution(context); + + if (left != NULL) + { + right = itd_template_args(context); + + if (right != NULL) + looping_rule = itd_make_binary(context, ICT_PREFIX_BINARY, left, right); + else + itd_unref_comp(left); + + } + + } + + /* <template-param> */ + + if (looping_rule == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + looping_rule = itd_template_param(context); + } + + /* <substitution> */ + + if (looping_rule == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + looping_rule = itd_substitution(context); + } + + printf("looping_rule = %p\n", looping_rule); + + if (looping_rule != NULL) + { + if (result == NULL) + result = looping_rule; + else + result = itd_make_binary(context, ICT_PREFIX_BINARY, result, looping_rule); + } + + /** + * Seconde partie (1/3) : recherche d'un éventuel complément. + */ + + if (looping_rule == NULL) + g_itanium_dcontext_pop_state(context, &saved); + + /* <unqualified-name> */ + + g_itanium_dcontext_push_state(context, &next_name_saved); + + next_name = itd_unqualified_name(context); + + if (next_name == NULL) + { + /** + * Si on n'obtient pas de <unqualified-name> ici, rien ne sert de + * continuer. On se dirige donc vers la sortie avec ce que l'on a. + */ + + return NULL; + + break; + + } + + /* <template-args> */ + + g_itanium_dcontext_push_state(context, &next_targs_saved); + + next_targs = itd_template_args(context); + + g_itanium_dcontext_pop_state(context, &next_targs_saved); + + /** + * Seconde partie (2/3) : validation de la présence d'un jeton + * <unqualified-name> en réserve pour la règle <nested-name> parente. + */ + + g_itanium_dcontext_push_state(context, &expected_saved); + + expected = itd_unqualified_name(context); + + if (expected == NULL) + { + /** + * La lecture a été trop loin ici. + * + * Le dernier <unqualified-name> valide pour la règle parente est + * donc celui lu à une fin de recherche de complément. + * + * On revient donc à ce stade avant de se diriger vers la sortie. + */ + + itd_unref_comp(next_name); + + if (next_targs != NULL) + itd_unref_comp(next_targs); + + g_itanium_dcontext_pop_state(context, &next_name_saved); + + break; + + } + + g_itanium_dcontext_pop_state(context, &expected_saved); + + /** + * Seconde partie (3/3) : pleine inscription des composants extraits. + * + * On s'est manifestement retrouvé dans un des deux cas suivants : + * - <prefix> ::= <prefix> <unqualified-name> + * - <prefix> ::= <prefix> <template unqualified-name> <template-args> + * + * Or <prefix> est un candidat pour des substitutions futures, donc on + * procède à son enregistrement, s'il n'est pas nul. + */ + + if (result != NULL) + g_itanium_dcontext_add_substitution(context, result); + + printf("result = %p - next_name = %p\n", result, next_name); + + + if (result == NULL) + result = next_name; + else + result = itd_make_binary(context, ICT_PREFIX_BINARY, result, next_name); + + if (next_targs != NULL) + result = itd_make_binary(context, ICT_PREFIX_BINARY, result, next_targs); + + + printf(" > result = %p\n", result); + + } + + if (result == NULL) + result = itd_make_empty(context); + /* + if (itd_get_component_type(result) != ICT_PREFIX_BINARY) + result = itd_make_unary(context, ICT_PREFIX_UNARY, result); + */ + //printf("<prefix> : %p\n", result); + + printf("### FIN DE PREFIX ### '%s'\n", + g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_template_prefix(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *prefix; /* Premier d'un couple de comp.*/ + itanium_component *name; /* Second d'un couple de comp. */ + + /** + * La règle traitée ici est la suivante : + * + * <template-prefix> ::= <prefix> <template unqualified-name> + * ::= <template-param> + * ::= <substitution> + * + */ + + result = NULL; + g_itanium_dcontext_push_state(context, &saved); + + prefix = itd_prefix(context); + + if (prefix != NULL) + { + name = itd_unqualified_name(context); + + if (name != NULL) + result = itd_make_binary(context, ICT_TPREFIX_BINARY, prefix, name); + else + itd_unref_comp(prefix); + + } + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_template_param(context); + } + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_substitution(context); + } + + if (result != NULL && itd_get_component_type(result) != ICT_TPREFIX_BINARY) + result = itd_make_unary(context, ICT_TPREFIX_UNARY, result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_unqualified_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itd_state saved; /* Position d'analyse courante */ + + /** + * La règle traitée ici est la suivante : + * + * <unqualified-name> ::= <operator-name> + * ::= <ctor-dtor-name> + * ::= <source-name> + * + */ + + g_itanium_dcontext_push_state(context, &saved); + + result = itd_operator_name(context); + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_ctor_dtor_name(context); + } + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_source_name(context); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_source_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + ssize_t number; /* Taille positive */ + + /** + * La règle traitée ici est la suivante : + * + * <source-name> ::= <positive length number> <identifier> + * + */ + + if (!itd_number(context, &number)) + return NULL; + + if (number <= 0) + return NULL; + + result = itd_identifier(context, number); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* size = taille positive ou non lue. [OUT] * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Bilan de l'opération (un chifre lu au moins). * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool itd_number(GItaniumDContext *context, ssize_t *size) +{ + bool result; /* Validité à renvoyer */ + bool negative; /* Taille négative ? */ + char peek; /* Prochain caractère lu */ + + /** + * La règle traitée ici est la suivante : + * + * <number> ::= [n] <non-negative decimal integer> + * + */ + + result = false; + + negative = false; + + peek = g_itanium_dcontext_peek_char(context); + + if (peek == 'n') + { + negative = true; + g_itanium_dcontext_advance(context, 1); + peek = g_itanium_dcontext_peek_char(context); + } + + *size = 0; + + while (isdigit(peek)) + { + result = true; + *size = *size * 10 + peek - '0'; + g_itanium_dcontext_advance(context, 1); + peek = g_itanium_dcontext_peek_char(context); + } + + if (negative) + *size *= -1; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* length = taille de l'identifiant à retrouver. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_identifier(GItaniumDContext *context, size_t length) +{ + itanium_component *result; /* Construction à retourner */ + const char *data; /* Données restantes */ + size_t remaining; /* Quantité d'octets */ + + /** + * La règle traitée ici est la suivante : + * + * <identifier> ::= <unqualified source code identifier> + * + */ + + data = g_itanium_dcontext_get_string(context, &remaining); + + if (length > remaining) + return NULL; + + result = itd_make_name(context, data, length); + + if (result != NULL) + g_itanium_dcontext_advance(context, length); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_operator_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + char code[2]; /* Code à venir lire */ + itanium_operator_info info; /* Clef des informations */ + itanium_operator_info *found; /* Informations complètes */ + + /** + * La règle traitée ici est la suivante : + * + * <operator-name> ::= nw # new + * ::= na # new[] + * ::= dl # delete + * ::= da # delete[] + * ::= ps # + (unary) + * ::= ng # - (unary) + * ::= ad # & (unary) + * ::= de # * (unary) + * ::= co # ~ + * ::= pl # + + * ::= mi # - + * ::= ml # * + * ::= dv # / + * ::= rm # % + * ::= an # & + * ::= or # | + * ::= eo # ^ + * ::= aS # = + * ::= pL # += + * ::= mI # -= + * ::= mL # *= + * ::= dV # /= + * ::= rM # %= + * ::= aN # &= + * ::= oR # |= + * ::= eO # ^= + * ::= ls # << + * ::= rs # >> + * ::= lS # <<= + * ::= rS # >>= + * ::= eq # == + * ::= ne # != + * ::= lt # < + * ::= gt # > + * ::= le # <= + * ::= ge # >= + * ::= nt # ! + * ::= aa # && + * ::= oo # || + * ::= pp # ++ + * ::= mm # -- + * ::= cm # , + * ::= pm # ->* + * ::= pt # -> + * ::= cl # () + * ::= ix # [] + * ::= qu # ? + * ::= st # sizeof (a type) + * ::= sz # sizeof (an expression) + * ::= cv <type> # (cast) + * ::= v <digit> <source-name> # vendor extended operator + * + */ + + result = NULL; + + code[0] = g_itanium_dcontext_next_char(context); + + if (code[0] == 'v') + { + + result = NULL; /* TODO */ + + goto itd_operator_name_exit; + + + } + + code[1] = g_itanium_dcontext_next_char(context); + + if (code[0] == 'c' && code[1] == 'v') + { + + result = NULL; /* TODO */ + + goto itd_operator_name_exit; + + + } + + /* Recherche dans la liste des opérateurs reconnus */ + + info.code = code; + + int comp_itanium_operators(const itanium_operator_info *a, const itanium_operator_info *b) + { + int result; /* Bilan à renvoyer */ + + if (a->code[0] < b->code[0]) + result = -1; + else if (a->code[0] > b->code[0]) + result = 1; + else + { + if (a->code[1] < b->code[1]) + result = -1; + else if (a->code[1] > b->code[1]) + result = 1; + else + result = 0; + } + + return result; + + } + + found = bsearch(&info, itanium_demangle_operators, + ARRAY_SIZE(itanium_demangle_operators), + sizeof(itanium_operator_info), (__compar_fn_t)comp_itanium_operators); + + if (found != NULL) + result = itd_make_operator(context, found); + + itd_operator_name_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_special_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + char next; /* Caractère suivant */ + char peek; /* Prochain caractère lu */ + itanium_component *offset1; /* Décalage extrait #1 */ + itanium_component *encoding; /* Encodage suivant */ + + /** + * La règle traitée ici est la suivante : + * + * <special-name> ::= T <call-offset> <base encoding> + * # base is the nominal target function of thunk + */ + + result = NULL; + + next = g_itanium_dcontext_next_char(context); + + if (next == 'T') + { + peek = g_itanium_dcontext_peek_char(context); + + switch (peek) + { + case 'V': + result = NULL; /* TODO */ + break; + + case 'T': + result = NULL; /* TODO */ + break; + + case 'I': + result = NULL; /* TODO */ + break; + + case 'S': + result = NULL; /* TODO */ + break; + + case 'c': + result = NULL; /* TODO */ + break; + + + default: + + offset1 = itd_call_offset(context); + if (offset1 == NULL) break; + + encoding = itd_encoding(context); + + if (encoding == NULL) + itd_unref_comp(offset1); + else + result = itd_make_binary(context, ICT_FUNCTION_THUNK, offset1, encoding); + + break; + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_call_offset(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + char next; /* Caractère suivant */ + + /** + * La règle traitée ici est la suivante : + * + * <call-offset> ::= h <nv-offset> _ + * ::= v <v-offset> _ + */ + + next = g_itanium_dcontext_next_char(context); + + switch (next) + { + case 'h': + result = itd_nv_offset(context); + break; + + case 'v': + result = itd_v_offset(context); + break; + + default: + result = NULL; + break; + + } + + if (result != NULL && !g_itanium_dcontext_check_char(context, '_')) + { + itd_unref_comp(result); + result = NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_nv_offset(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + ssize_t offset; /* Décalage obtenu */ + + /** + * La règle traitée ici est la suivante : + * + * <nv-offset> ::= <offset number> + * # non-virtual base override + */ + + if (!itd_number(context, &offset)) + return NULL; + + result = itd_make_offset(context, ICT_NON_VIRTUAL_OFFSET, offset); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_v_offset(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + ssize_t offset; /* Décalage obtenu #1 */ + ssize_t voffset; /* Décalage obtenu #2 */ + + /** + * La règle traitée ici est la suivante : + * + * <v-offset> ::= <offset number> _ <virtual offset number> + * # virtual base override, with vcall offset + */ + + if (!itd_number(context, &offset)) + return NULL; + + if (!g_itanium_dcontext_check_char(context, '_')) + return NULL; + + if (!itd_number(context, &voffset)) + return NULL; + + result = itd_make_binary(context, ICT_VIRTUAL_OFFSET, + itd_make_offset(context, ICT_NON_VIRTUAL_OFFSET, offset), + itd_make_offset(context, ICT_VIRTUAL_OFFSET, voffset)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_ctor_dtor_name(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + char next; /* Caractère suivant */ + ItaniumComponentType type; /* Type de composant */ + + /** + * La règle traitée ici est la suivante : + * + * <ctor-dtor-name> ::= C1 # complete object constructor + * ::= C2 # base object constructor + * ::= C3 # complete object allocating constructor + * ::= D0 # deleting destructor + * ::= D1 # complete object destructor + * ::= D2 # base object destructor + */ + + next = g_itanium_dcontext_peek_char(context); + + if (next == 'C') + type = ICT_CONSTRUCTOR; + else if (next == 'D') + type = ICT_DESSTRUCTOR; + else + return NULL; + + g_itanium_dcontext_advance(context, 1); + + next = g_itanium_dcontext_peek_char(context); + + if (next != '0' && next != '1' && next != '2') + return NULL; + + g_itanium_dcontext_advance(context, 1); + + result = itd_make_empty(context); + itd_set_type(result, type); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_type(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + TypeQualifier qualifier; /* Propriétés supplémentaires */ + itanium_component *sub; /* Sous-type lié à associer */ + itd_state saved; /* Position d'analyse courante */ + + /** + * La règle traitée ici est la suivante : + * + * <type> ::= <builtin-type> + * ::= <function-type> + * ::= <class-enum-type> + * ::= <array-type> + * ::= <pointer-to-member-type> + * ::= <template-param> + * ::= <template-template-param> <template-args> + * ::= <substitution> # See Compression below + * ::= <CV-qualifiers> <type> + * ::= P <type> # pointer-to + * ::= R <type> # reference-to + * ::= O <type> # rvalue reference-to (C++0x) + * ::= C <type> # complex pair (C 2000) + * ::= G <type> # imaginary (C 2000) + * ::= U <source-name> <type> # vendor extended type qualifier + * + */ + + result = NULL; + + qualifier = itd_cv_qualifiers(context); + + switch (g_itanium_dcontext_peek_char(context)) + { + case 'P': + + g_itanium_dcontext_advance(context, 1); + + sub = itd_type(context); + if (sub == NULL) return NULL; + + result = itd_make_unary(context, ICT_POINTER_TO, sub); + break; + + case 'R': + + g_itanium_dcontext_advance(context, 1); + + sub = itd_type(context); + if (sub == NULL) return NULL; + + result = itd_make_unary(context, ICT_REFERENCE_TO, sub); + break; + + case 'O': + + g_itanium_dcontext_advance(context, 1); + + sub = itd_type(context); + if (sub == NULL) return NULL; + + result = itd_make_unary(context, ICT_RVALUE_REFERENCE_TO, sub); + break; + + case 'C': + + g_itanium_dcontext_advance(context, 1); + + sub = itd_type(context); + if (sub == NULL) return NULL; + + result = itd_make_unary(context, ICT_COMPLEX_PAIR, sub); + break; + + case 'G': + + g_itanium_dcontext_advance(context, 1); + + sub = itd_type(context); + if (sub == NULL) return NULL; + + result = itd_make_unary(context, ICT_IMAGINARY, sub); + break; + + case 'U': + + g_itanium_dcontext_advance(context, 1); + /* TODO */ + return NULL; + break; + + } + + if (result != NULL) goto itd_type_end; + + g_itanium_dcontext_push_state(context, &saved); + + result = itd_builtin_type(context); + if (result != NULL) goto itd_type_end; + + g_itanium_dcontext_pop_state(context, &saved); + + result = itd_class_enum_type(context); + if (result != NULL) goto itd_type_end; + + + g_itanium_dcontext_pop_state(context, &saved); + + result = itd_substitution(context); + if (result != NULL) goto itd_type_end; + + + + + itd_type_end: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait une propriété de composant pour un contexte Itanium. * +* * +* Retour : Indication extraite. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static TypeQualifier itd_cv_qualifiers(GItaniumDContext *context) +{ + TypeQualifier result; /* Valeur à remonter */ + + /** + * La règle traitée ici est la suivante : + * + * <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const + * + */ + + result = TQF_NONE; + + while (1) + switch (g_itanium_dcontext_peek_char(context)) + { + case 'r': + result = TQF_RESTRICT; + g_itanium_dcontext_advance(context, 1); + break; + + case 'V': + result = TQF_VOLATILE; + g_itanium_dcontext_advance(context, 1); + break; + + case 'K': + result = TQF_CONST; + g_itanium_dcontext_advance(context, 1); + break; + + default: + goto itd_cv_qualifiers_exit; + break; + + } + + itd_cv_qualifiers_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_builtin_type(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + BaseType type; /* Type reconnu ou BTP_INVALID */ + GDataType *builtin; /* Type construit */ + + /** + * La règle traitée ici est la suivante : + * + * <builtin-type> ::= v # void + * ::= w # wchar_t + * ::= b # bool + * ::= c # char + * ::= a # signed char + * ::= h # unsigned char + * ::= s # short + * ::= t # unsigned short + * ::= i # int + * ::= j # unsigned int + * ::= l # long + * ::= m # unsigned long + * ::= x # long long, __int64 + * ::= y # unsigned long long, __int64 + * ::= n # __int128 + * ::= o # unsigned __int128 + * ::= f # float + * ::= d # double + * ::= e # long double, __float80 + * ::= g # __float128 + * ::= z # ellipsis + * ::= u <source-name> # vendor extended type + * + */ + + switch (g_itanium_dcontext_peek_char(context)) + { + case 'v': + type = BTP_VOID; + break; + case 'w': + type = BTP_WCHAR_T; + break; + case 'b': + type = BTP_BOOL; + break; + case 'c': + type = BTP_CHAR; + break; + case 'a': + type = BTP_SCHAR; + break; + case 'h': + type = BTP_UCHAR; + break; + case 's': + type = BTP_SHORT; + break; + case 't': + type = BTP_USHORT; + break; + case 'i': + type = BTP_INT; + break; + case 'j': + type = BTP_UINT; + break; + case 'l': + type = BTP_LONG; + break; + case 'm': + type = BTP_ULONG; + break; + case 'x': + type = BTP_LONG_LONG; + break; + case 'y': + type = BTP_ULONG_LONG; + break; + case 'n': + type = BTP_INT128; + break; + case 'o': + type = BTP_UINT128; + break; + case 'f': + type = BTP_FLOAT; + break; + case 'd': + type = BTP_DOUBLE; + break; + case 'e': + type = BTP_LONG_DOUBLE; + break; + case 'g': + type = BTP_FLOAT128; + break; + case 'z': + type = BTP_ELLIPSIS; + break; + case 'u': + type = BTP_OTHER; + /* FIXME */ + /* <source-name> # vendor extended type */ + break; + default: + type = BTP_INVALID; + break; + } + + if (type != BTP_INVALID) + { + builtin = g_basic_type_new(type); + result = itd_make_type(context, builtin); + g_itanium_dcontext_advance(context, 1); + } + else + result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_bare_function_type(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itanium_component *type; /* Nouvel élément à intégrer */ + itd_state saved; /* Position d'analyse courante */ + + /** + * La règle traitée ici est la suivante : + * + * <bare-function-type> ::= <signature type>+ + * # types are possible return type, then parameter types + * + */ + + type = itd_type(context); + if (type == NULL) return NULL; + + result = itd_append_right_to_binary(context, ICT_TYPES_LIST, NULL, type); + + while (1) + { + g_itanium_dcontext_push_state(context, &saved); + + type = itd_type(context); + if (type == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + break; + } + + result = itd_append_right_to_binary(context, ICT_TYPES_LIST, result, type); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_class_enum_type(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + + /** + * La règle traitée ici est la suivante : + * + * <class-enum-type> ::= <name> + * + */ + + result = itd_name(context); + + return result; + +} + + + + + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_template_args(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itanium_component *arg; /* Nouvel argument extrait */ + itd_state saved; /* Position d'analyse courante */ + + printf(">>> TA>> '%s'\n", g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + + /** + * La règle traitée ici est la suivante : + * + * <template-args> ::= I <template-arg>+ E + * + */ + + if (!g_itanium_dcontext_check_char(context, 'I')) + return NULL; + + arg = itd_template_arg(context); + if (arg == NULL) return NULL; + + result = itd_append_right_to_binary(context, ICT_TYPES_LIST, NULL, arg); + + while (1) + { + g_itanium_dcontext_push_state(context, &saved); + + arg = itd_template_arg(context); + if (arg == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + break; + } + + result = itd_append_right_to_binary(context, ICT_TYPES_LIST, result, arg); + + } + + //printf(" ta/E >> '%s'\n", g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + + if (!g_itanium_dcontext_check_char(context, 'E')) + { + //printf("=== TA : BAD E\n\n"); + + if (result != NULL) + itd_unref_comp(result); + return NULL; + } + + //printf("=== TA >> %p\n\n", result); + + result = itd_make_unary(context, ICT_TEMPLATE_ARGS, result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_template_arg(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itd_state saved; /* Position d'analyse courante */ + + /** + * La règle traitée ici est la suivante : + * + * <template-arg> ::= <type> # type or template + * ::= X <expression> E # expression + * ::= <expr-primary> # simple expressions + * + */ + + g_itanium_dcontext_push_state(context, &saved); + + result = itd_type(context); + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + + if (g_itanium_dcontext_check_char(context, 'X')) + { + result = itd_expression(context); + + if (result != NULL && !g_itanium_dcontext_check_char(context, 'E')) + { + itd_unref_comp(result); + result = NULL; + } + + } + + } + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_expr_primary(context); + } + + return result; + +} + + + + + + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* hex = prise en compte des caractères hexadécimaux ? * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_value_to_string(GItaniumDContext *context, bool hex) +{ + itanium_component *result; /* Construction à retourner */ + const char *data; /* Données restantes */ + itd_state saved; /* Position d'analyse initiale */ + itd_state cur; /* Position d'analyse courante */ + char peek; /* Prochain caractère lu */ + + /** + * Les règles traitées ici sont les suivantes : + * + * <value number> # integer literal + * <value float> # floating literal + * + */ + + result = NULL; + + data = g_itanium_dcontext_get_string(context, (size_t []) { 0 }); + + g_itanium_dcontext_push_state(context, &saved); + + while (1) + { + peek = g_itanium_dcontext_peek_char(context); + + switch (peek) + { + case '0' ... '9': + g_itanium_dcontext_advance(context, 1); + break; + + case 'a' ... 'f': + if (hex) + g_itanium_dcontext_advance(context, 1); + else + goto exit_iits; + break; + + case 'E': + goto exit_loop; + break; + + default: + goto exit_iits; + + } + + } + + exit_loop: + + g_itanium_dcontext_push_state(context, &cur); + + if ((cur.pos - saved.pos) > 0) + result = itd_make_name(context, data, cur.pos - saved.pos); + + exit_iits: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_expr_primary(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *type; /* Type de valeur extrait */ + itd_state saved_value; /* Position d'analyse courante */ + + /** + * La règle traitée ici est la suivante : + * + * <expr-primary> ::= L <type> <value number> E # integer literal + * ::= L <type> <value float> E # floating literal + * ::= L <mangled-name> E # external name + * + */ + + printf("PRIMARY :: no L\n"); + + if (!g_itanium_dcontext_check_char(context, 'L')) + return NULL; + + g_itanium_dcontext_push_state(context, &saved); + + type = itd_type(context); + + if (type != NULL) + { + g_itanium_dcontext_push_state(context, &saved_value); + + /* Règle <type> <value number> */ + + result = itd_value_to_string(context, false); + + if (result != NULL && !g_itanium_dcontext_check_char(context, 'E')) + { + itd_unref_comp(result); + result = NULL; + } + + /* Règle <type> <value float> */ + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved_value); + + result = itd_value_to_string(context, true); + + if (result != NULL && !g_itanium_dcontext_check_char(context, 'E')) + { + itd_unref_comp(result); + result = NULL; + } + + } + + itd_unref_comp(type); + + } + else + result = NULL; + + /* Règle <mangled-name> */ + + if (result == NULL) + { + g_itanium_dcontext_pop_state(context, &saved); + result = itd_mangled_name(context); + + if (result != NULL && !g_itanium_dcontext_check_char(context, 'E')) + { + itd_unref_comp(result); + result = NULL; + } + + } + + printf("PRIMARY :: %p\n", result); + + return result; + +} + + + + + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* cur = caractère courant. * +* id = identifiant lu en cas de succès. [OUT] * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool itd_seq_id(GItaniumDContext *context, char cur, size_t *id) +{ + /** + * La règle traitée ici est la suivante : + * + * <seq-id> + * + */ + + *id = 0; + + /** + * La fonction n'est appelée que si un début de séquence est détecté. + * (ie, cur == '_' || isdigit(cur) || isupper(cur)). + */ + + if (cur != '_') + { + do + { + if (isdigit(cur)) + *id = *id * 36 + cur - '0'; + else if (isupper(cur)) + *id = *id * 36 + cur - 'A' + 10; + else + return false; + + cur = g_itanium_dcontext_next_char(context); + + } + while (cur != '_'); + + (*id)++; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_substitution(GItaniumDContext *context) +{ + itanium_component *result; /* Construction à retourner */ + char cur; /* Caractère analysé */ + size_t id; /* Identifiant de substitution */ + char peek; /* Prochain caractère lu */ + bool verbose; /* Sélection du rendu idéal */ + size_t i; /* Boucle de parcours */ + + /** + * La règle traitée ici est la suivante : + * + * <substitution> ::= S <seq-id> _ + * ::= S_ + * ::= St # ::std:: + * ::= Sa # ::std::allocator + * ::= Sb # ::std::basic_string + * ::= Ss # ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>> + * ::= Si # ::std::basic_istream<char, std::char_traits<char>> + * ::= So # ::std::basic_ostream<char, std::char_traits<char>> + * ::= Sd # ::std::basic_iostream<char, std::char_traits<char>> + * + */ + + peek = g_itanium_dcontext_peek_char(context); + + if (!g_itanium_dcontext_check_char(context, 'S')) + return NULL; + + cur = g_itanium_dcontext_next_char(context); + + if (cur == '_' || isdigit(cur) || isupper(cur)) + { + if (!itd_seq_id(context, cur, &id)) + return NULL; + + printf("requesting... %zu\n", id); + + result = g_itanium_dcontext_get_substitution(context, id); + + } + else + { + result = NULL; + + peek = g_itanium_dcontext_peek_char(context); + verbose = (peek == 'C' || peek == 'D'); /* TODO : prefixe ? */ + + for (i = 0; i < ARRAY_SIZE(itanium_standard_substitutions); i++) + if (itanium_standard_substitutions[i].code == cur) + { + /* TODO : constructeur... */ + + if (verbose) + result = itd_make_name(context, + itanium_standard_substitutions[i].full, + itanium_standard_substitutions[i].full_len); + else + result = itd_make_name(context, + itanium_standard_substitutions[i].simple, + itanium_standard_substitutions[i].simple_len); + + itd_set_type(result, ICT_STD_SUBST); + + break; + + } + + } + + return result; + +} diff --git a/src/mangling/itanium/abi.h b/src/mangling/itanium/abi.h new file mode 100644 index 0000000..1ed21f3 --- /dev/null +++ b/src/mangling/itanium/abi.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * abi.h - prototypes pour le décodage des noms d'éléments selon 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/>. + */ + + +#ifndef _FORMAT_MANGLING_ITANIUM_ABI_H +#define _FORMAT_MANGLING_ITANIUM_ABI_H + + +#include "component.h" +#include "context.h" + + + +/* Extrait un composant dans un contexte Itanium. */ +itanium_component *itd_mangled_name(GItaniumDContext *); + + + +#endif /* _FORMAT_MANGLING_ITANIUM_ABI_H */ diff --git a/src/mangling/itanium/component-int.h b/src/mangling/itanium/component-int.h new file mode 100644 index 0000000..3d4c1d0 --- /dev/null +++ b/src/mangling/itanium/component-int.h @@ -0,0 +1,79 @@ + + +#ifndef _FORMAT_MANGLING_ITANIUM_ABI2_H +#define _FORMAT_MANGLING_ITANIUM_ABI2_H + + +#include "component.h" + + + +/* Composant extrait de l'encodage */ +struct _itanium_component +{ + ItaniumComponentType type; /* Type de composant */ + + GItaniumDContext *context; /* Regroupement de composants */ + unsigned int refcount; /* Compteur de références */ + + fnv64_t hash; /* Empreinte en cache */ + + union + { + /* ICT_NAME */ + struct + { + const char *str; + size_t len; + + } s_name; + + /* ICT_OPERATOR_NAME */ + struct + { + ItaniumOperatorType otype; /* Sélection dans l'union */ + + union + { + itanium_operator_info info; /* Opérateur simple */ + + + }; + + } operator; + + /* ICT_NON_VIRTUAL_OFFSET */ + /* ICT_VIRTUAL_OFFSET */ + ssize_t offset; /* Décalage de fonction */ + + /* ICT_TYPE */ + GDataType *dtype; /* Type instancié */ + + + /* ICT_* */ + struct + { + itanium_component *left; /* Elément premier */ + itanium_component *right; /* Elément second */ + + } binary; + + /* ICT_* */ + struct + { + itanium_component *first; /* Elément premier */ + itanium_component *second; /* Elément second */ + itanium_component *third; /* Elément troisième */ + + } ternary; + + /* ICT_* */ + itanium_component *unary; /* Sous-élément */ + + }; + +}; + + + +#endif /* _FORMAT_MANGLING_ITANIUM_ABI2_H */ 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; + + +} diff --git a/src/mangling/itanium/component.h b/src/mangling/itanium/component.h new file mode 100644 index 0000000..7ab2521 --- /dev/null +++ b/src/mangling/itanium/component.h @@ -0,0 +1,213 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * component.h - prototypes pour la 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/>. + */ + + +#ifndef _FORMAT_MANGLING_ITANIUM_COMPONENT_H +#define _FORMAT_MANGLING_ITANIUM_COMPONENT_H + + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <malloc.h> +#include <sys/types.h> + + +#include "context.h" +#include "../../analysis/type.h" +#include "../../common/fnv1a.h" + + + +/* Type de composants */ +typedef enum _ItaniumComponentType +{ + /** + * Représentation d'une règle vide. + */ + ICT_EMPTY, + + /** + * Chaîne de caractère, terminée par un octet nul. + */ + ICT_NAME, + ICT_STD_SUBST, + + /** + * Noms imbriqués, en deux parties : 'binary'. + */ + ICT_NESTED_NAME, + ICT_TEMPLATE_NAME_ARGS, + + /** + * Deux types de préfixes : un ou deux éléments. + * -> 'unary' ou 'binary' + */ + ICT_PREFIX_UNARY, + ICT_PREFIX_BINARY, + ICT_TPREFIX_UNARY, + ICT_TPREFIX_BINARY, + + /** + * Encodage d'un nom d'opérateur, consigné dans 'operator'. + */ + ICT_OPERATOR_NAME, + + + /** + * Fonctions virtuelles. + * -> décalage : 'offset'. + * -> fonctions simples : 'binary'. + * -> fonctions complexes : 'ternary'. + */ + ICT_NON_VIRTUAL_OFFSET, + ICT_VIRTUAL_OFFSET, + ICT_FUNCTION_THUNK, + ICT_FUNCTION_COVARIANT_THUNK, + + /** + * Constructeur ou destructeur, sans plus de détail. + */ + ICT_CONSTRUCTOR, + ICT_DESSTRUCTOR, + + /** + * Type instanciable dans le programme. + */ + ICT_TYPE, + + /** + * Différentes références vers un sous-type. + * Le champ impacté est 'unary'. + */ + ICT_POINTER_TO, + ICT_REFERENCE_TO, + ICT_RVALUE_REFERENCE_TO, + ICT_COMPLEX_PAIR, + ICT_IMAGINARY, + + /** + * Fonction (nom + retour/paramètres), sous forme binaire : + * -> left = function name + * -> right = bare-function-type + */ + ICT_FUNCTION_ENCODING, + + /** + * Liste d'arguments pour templates, à encadrer par des chevrons. + * 'unary' pointe vers la liste des éléments. + */ + ICT_TEMPLATE_ARGS, + + /** + * Liste de types, sous forme binaire : + * -> left = élément de la liste de types. + * -> right = reste de la liste de types. + */ + ICT_TYPES_LIST, + + ICT_COUNT + +} ItaniumComponentType; + + +/* Catégories d'opérateurs */ +typedef enum _ItaniumOperatorType +{ + IOT_SIMPLE, /* Présent dans la liste */ + IOT_CAST, /* Conversion forcée */ + IOT_VENDOR /* Défini par un vendeur */ + +} ItaniumOperatorType; + + +/* Enregistrement des opérateurs */ +typedef struct _itanium_operator_info +{ + const char *code; /* Nom encodé */ + const char *name; /* Désignation humaine */ + size_t name_len; /* Taille du nom humain */ + int args; /* Nombre d'arguments */ + +} itanium_operator_info; + + +/* Composant extrait de l'encodage */ +typedef struct _itanium_component itanium_component; + + + +/* Incrémente le nombre d'utilisation du composant. */ +void itd_ref_comp(itanium_component *); + +/* Décrémente le nombre d'utilisation du composant. */ +void itd_unref_comp(itanium_component *); + +/* Détermine ou fournit l'empreinte d'un composant. */ +fnv64_t itd_hash_comp(itanium_component *); + + + +/* Marque un composant comme étant disponible pour un usage. */ +void itd_free_comp(GItaniumDContext *, itanium_component *); + +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_empty(GItaniumDContext *); + +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_name(GItaniumDContext *, const char *, size_t); + + +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_operator(GItaniumDContext *, const itanium_operator_info *); + + +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_offset(GItaniumDContext *, ItaniumComponentType, ssize_t); + + +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_type(GItaniumDContext *, GDataType *); + +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_binary(GItaniumDContext *, ItaniumComponentType, itanium_component *, itanium_component *); + +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_append_right_to_binary(GItaniumDContext *, ItaniumComponentType, itanium_component *, itanium_component *); + +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_unary(GItaniumDContext *, ItaniumComponentType, itanium_component *); + + + +/* Modifie légèrement le type d'un composant donné. */ +void itd_set_type(itanium_component *, ItaniumComponentType); + +/* Fournit le type d'un composant issu d'un contexte Itanium. */ +ItaniumComponentType itd_get_component_type(const itanium_component *); + +/* Traduit les composants de contexte Itanium. */ +char *itd_translate_component(GItaniumDContext *, const itanium_component *, char *); + + + +#endif /* _FORMAT_MANGLING_ITANIUM_COMPONENT_H */ 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"); + + +} diff --git a/src/mangling/itanium/context.h b/src/mangling/itanium/context.h new file mode 100644 index 0000000..13ec1f4 --- /dev/null +++ b/src/mangling/itanium/context.h @@ -0,0 +1,117 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * context.h - prototypes pour le 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/>. + */ + + +#ifndef _FORMAT_MANGLING_ITANIUM_CONTEXT_H +#define _FORMAT_MANGLING_ITANIUM_CONTEXT_H + + +#include <glib-object.h> +#include <stdbool.h> + +#include "../context.h" + + + +#define G_TYPE_ITANIUM_DCONTEXT g_itanium_dcontext_get_type() +#define G_ITANIUM_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_itanium_dcontext_get_type(), GItaniumDContext)) +#define G_IS_ITANIUM_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_itanium_dcontext_get_type())) +#define G_ITANIUM_DCONTEXT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_itanium_dcontext_get_type(), GItaniumDContextIface)) +#define G_ITANIUM_DCONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ITANIUM_DCONTEXT, GItaniumDContextClass)) + + +/* Contexte de décodage Itanium (instance) */ +typedef struct _GItaniumDContext GItaniumDContext; + +/* Contexte de décodage Itanium (classe) */ +typedef struct _GItaniumDContextClass GItaniumDContextClass; + + +/* Indique le type défini pour un contexte de décodage. */ +GType g_itanium_dcontext_get_type(void); + +/* Prépare de quoi effectuer un décodage Itanium. */ +GDemanglingContext *g_itanium_dcontext_new(void); + +/* Tente de décoder une chaîne de caractères donnée. */ +void /*GBinRoutine **/g_itanium_dcontext_demangle_routine(GItaniumDContext *, const char *); + +/* Sauvegarde d'un état courant */ +typedef struct _itd_state +{ + size_t pos; /* Position courante */ + size_t subst_count; /* Nombre de substitutions */ + +} itd_state; + +/* Fournit l'état courant à une fin de retour en arrière. */ +void g_itanium_dcontext_push_state(const GItaniumDContext *, itd_state *); + +/* Définit l'état courant suite à un retour en arrière. */ +void g_itanium_dcontext_pop_state(GItaniumDContext *, const itd_state *); + +/* Fournit la valeur du caractère courant. */ +char g_itanium_dcontext_peek_char(const GItaniumDContext *); + +/* Avance la tête de lecture courante. */ +void g_itanium_dcontext_advance(GItaniumDContext *, size_t); + +/* Fournit et avance la tête de lecture courante. */ +char g_itanium_dcontext_next_char(GItaniumDContext *); + +/* Vérifie la nature du caractère courant. */ +bool g_itanium_dcontext_check_char(GItaniumDContext *, char); + +/* Fournit la chaîne de caractère restant à traiter. */ +const char *g_itanium_dcontext_get_string(const GItaniumDContext *, size_t *); + + + + +/* Composant extrait de l'encodage */ +typedef struct _itanium_component itanium_component; + + +/* Fournit un nouveau composant vierge. */ +itanium_component *g_itanium_dcontext_get_empty_component(GItaniumDContext *); + +/* Marque un composant comme étant disponible pour un usage. */ +void g_itanium_dcontext_mark_component_as_free(GItaniumDContext *, itanium_component *); + +/* Indexe un composant comme future substitution potentielle. */ +void g_itanium_dcontext_add_substitution(GItaniumDContext *, itanium_component *); + +/* Fournit un composant en place pour une substitution. */ +itanium_component *g_itanium_dcontext_get_substitution(GItaniumDContext *, size_t); + + + + + + +void test_itanium(void); + + + + + +#endif /* _FORMAT_MANGLING_ITANIUM_CONTEXT_H */ diff --git a/src/mangling/java.h b/src/mangling/java.h new file mode 100644 index 0000000..ee7f21d --- /dev/null +++ b/src/mangling/java.h @@ -0,0 +1,59 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * java.h - prototypes pour le décodage des noms d'éléments selon Java + * + * Copyright (C) 2010-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/>. + */ + + +#ifndef _FORMAT_MANGLING_JAVA_H +#define _FORMAT_MANGLING_JAVA_H + + +#include <stdbool.h> + + +#include "context.h" +#include "demangler.h" + + + +/* ------------------------- CONTEXTE POUR LE DECODAGE JAVA ------------------------- */ + + +/* Contexte de décodage Java (instance) */ +typedef struct _GJavaDContext GJavaDContext; + +/* Contexte de décodage Java (classe) */ +typedef struct _GJavaDContextClass GJavaDContextClass; + + +/* Prépare de quoi effectuer un décodage Java. */ +GDemanglingContext *g_java_dcontext_new(void); + + + +/* ----------------------- TRAITEMENT DE L'ENCODAGE TYPE JAVA ----------------------- */ + + +/* Procède au décodage d'une chaîne de caractères. */ +bool demangle_java_type(GJavaDContext *, const char *); + + + +#endif /* _FORMAT_MANGLING_JAVA_H */ diff --git a/src/mangling/java_gram.y b/src/mangling/java_gram.y new file mode 100644 index 0000000..cb60d82 --- /dev/null +++ b/src/mangling/java_gram.y @@ -0,0 +1,281 @@ + +%{ + + + +#include "context-int.h" +#include "java.h" +#include "../analysis/types/cse.h" + + + +/* ------------------------- CONTEXTE POUR LE DECODAGE JAVA ------------------------- */ + + +#define G_TYPE_JAVA_DCONTEXT g_java_dcontext_get_type() +#define G_JAVA_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_java_dcontext_get_type(), GJavaDContext)) +#define G_IS_JAVA_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_java_dcontext_get_type())) +#define G_JAVA_DCONTEXT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_java_dcontext_get_type(), GJavaDContextIface)) +#define G_JAVA_DCONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_JAVA_DCONTEXT, GJavaDContextClass)) + + +/* Contexte de décodage Java (instance) */ +struct _GJavaDContext +{ + GDemanglingContext parent; /* A laisser en premier */ + +}; + +/* Contexte de décodage Java (classe) */ +struct _GJavaDContextClass +{ + GDemanglingContextClass parent; /* A laisser en premier */ + +}; + + +/* Indique le type défini pour un contexte de décodage. */ +static GType g_java_dcontext_get_type(void); + +/* Initialise la classe des contextes de décodage. */ +static void g_java_dcontext_class_init(GJavaDContextClass *); + +/* Initialise une instance de contexte pour décodage. */ +static void g_java_dcontext_init(GJavaDContext *); + +/* Affiche un message d'erreur concernant l'analyse. */ +static int java_error(/*const YYLTYPE *yyloc, bool hunt, char **ucode, unsigned char *index, */GJavaDContext *, char *); + + + + + + +%} + + +%union { + + void /*GDataType*/ *type; + + size_t adeep; /* Dimension d'un tableau */ + + char *text; /* Chaîne de caractères */ + +} + +%parse-param { GJavaDContext *context } + +%token V Z B S C I J F D +%token ARRAY +%token L SEMICOLON +%token SLASH DOLLAR +%token TEXT + +%type <type> type_descriptor field_type_descriptor non_array_field_type_descriptor full_class_name + +%type <text> TEXT + + +%{ + +/* De lexi.c... */ +/*int yylex(YYSTYPE *, YYLTYPE *);*/ +void java_restart(FILE *); +typedef struct yy_buffer_state *YY_BUFFER_STATE; +extern YY_BUFFER_STATE java__scan_string(const char *); +extern void java__delete_buffer(YY_BUFFER_STATE); + + extern int java_lex (void); + + +/* Affiche un message d'erreur concernant l'analyse. */ +/*int yyerror(const YYLTYPE *, bool, char **, unsigned char *, char *);*/ + +%} + + +%% + + +input: + type_descriptor { G_DEMANGLING_CONTEXT(context)->type = $1; } + ; + +type_descriptor: + V { $$ = g_basic_type_new(BTP_VOID); } + | field_type_descriptor { $$ = $1; } + ; + +field_type_descriptor: + non_array_field_type_descriptor { $$ = $1; } + | ARRAY non_array_field_type_descriptor { $$ = $2; } + ; + +non_array_field_type_descriptor: + Z { $$ = g_basic_type_new(BTP_BOOL); } + | B { $$ = g_basic_type_new(BTP_UCHAR); } + | S { $$ = g_basic_type_new(BTP_SHORT); } + | C { $$ = g_basic_type_new(BTP_CHAR); } + | I { $$ = g_basic_type_new(BTP_INT); } + | J { $$ = g_basic_type_new(BTP_LONG); } + | F { $$ = g_basic_type_new(BTP_FLOAT); } + | D { $$ = g_basic_type_new(BTP_DOUBLE); } + | L full_class_name SEMICOLON { $$ = $2; } + ; + +full_class_name: + TEXT { $$ = g_class_enum_type_new(CET_CLASS, $1); } + | full_class_name SLASH TEXT { + $$ = g_class_enum_type_new(CET_CLASS, $3); + g_data_type_set_namespace($$, $1); + g_object_unref($1); + } + | full_class_name DOLLAR TEXT { + $$ = g_class_enum_type_new(CET_CLASS, $3); + g_data_type_set_namespace($$, $1); + g_object_unref($1); + } + ; + + +%% + + + +/* ---------------------------------------------------------------------------------- */ +/* CONTEXTE POUR LE DECODAGE JAVA */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un contexte de décodage. */ +G_DEFINE_TYPE(GJavaDContext, g_java_dcontext, G_TYPE_DEMANGLING_CONTEXT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des contextes de décodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_dcontext_class_init(GJavaDContextClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : context = instance à initialiser. * +* * +* Description : Initialise une instance de contexte pour décodage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_java_dcontext_init(GJavaDContext *context) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Prépare de quoi effectuer un décodage Java. * +* * +* Retour : Instance du contexte mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDemanglingContext *g_java_dcontext_new(void) +{ + GDemanglingContext *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_JAVA_DCONTEXT, NULL); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TRAITEMENT DE L'ENCODAGE TYPE JAVA */ +/* ---------------------------------------------------------------------------------- */ + + + + + + + + + + + + + +/** + * Affiche un message d'erreur concernant l'analyse. + * @param yyloc informations concernant les coordonnées du soucis. + * @param hunt indique le type de passe réalisée. + * @param ucode code résultant compilé. + * @param index indice de commande à mettre à jour. + * @param msg indications humaines sur l'événement. + * @return 0. + */ +static int java_error(/*const YYLTYPE *yyloc, bool hunt, char **ucode, unsigned char *index, */GJavaDContext *context, char *msg) +{ + + + + fprintf(stderr, "ERREUR !\n"); + fprintf(stderr, "%s\n", msg); + + return -1; + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* desc = chaîne de caractères à décoder. * +* * +* Description : Procède au décodage d'une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool demangle_java_type(GJavaDContext *context, const char *desc) +{ + YY_BUFFER_STATE buffer; /* Tampon pour bison */ + int ret; /* Bilan de l'appel */ + + buffer = java__scan_string(desc); + ret = yyparse(context); + java__delete_buffer(buffer); + + return (ret == 0); + +} diff --git a/src/mangling/java_tok.l b/src/mangling/java_tok.l new file mode 100644 index 0000000..4adf623 --- /dev/null +++ b/src/mangling/java_tok.l @@ -0,0 +1,37 @@ + +%{ + +#include "java.h" +#include "libjavamangling_la-java_gram.h" + +%} + + +%option noyywrap +%option yylineno +%option nounput +%option noinput + +%x string + + +%% + +V { return V; } +Z { return Z; } +B { return B; } +S { return S; } +C { return C; } +I { return I; } +J { return J; } +F { return F; } +D { return D; } +L { BEGIN(string); return L; } +[[]* { java_lval.adeep = strlen(yytext); return ARRAY; } +<string>[/] { return SLASH; } +<string>[$] { return DOLLAR; } +<string>[;] { BEGIN(INITIAL); return SEMICOLON; } + +<string>[A-Za-z0-9]* { java_lval.text = yytext; return TEXT; } + +%% |