diff options
34 files changed, 5011 insertions, 1841 deletions
diff --git a/configure.ac b/configure.ac index 400818b..fb16dcc 100644 --- a/configure.ac +++ b/configure.ac @@ -353,6 +353,8 @@ AC_CONFIG_FILES([Makefile plugins/elf/Makefile plugins/elf/python/Makefile plugins/fmtp/Makefile + plugins/itanium/Makefile + plugins/itanium/python/Makefile plugins/libcsem/Makefile plugins/lnxsyscalls/Makefile plugins/mobicore/Makefile @@ -414,7 +416,6 @@ AC_CONFIG_FILES([Makefile src/gui/panels/Makefile src/gui/tb/Makefile src/mangling/Makefile - src/mangling/itanium/Makefile src/plugins/Makefile tools/Makefile tools/d2c/Makefile diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 257e0d5..6b0c295 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -4,4 +4,4 @@ if HAVE_PYTHON3_CONFIG endif # androhelpers -SUBDIRS = $(PYTHON3_SUBDIRS) arm dex dalvik devdbg dexbnf elf fmtp libcsem lnxsyscalls mobicore readdex readelf readmc ropgadgets +SUBDIRS = $(PYTHON3_SUBDIRS) arm dex dalvik devdbg dexbnf elf fmtp itanium libcsem lnxsyscalls mobicore readdex readelf readmc ropgadgets diff --git a/plugins/dexbnf/context.c b/plugins/dexbnf/context.c index ebf7c0d..2daeb52 100644 --- a/plugins/dexbnf/context.c +++ b/plugins/dexbnf/context.c @@ -121,7 +121,7 @@ static void g_dex_demangling_init(GDexDemangling *context) /****************************************************************************** * * -* Paramètres : demangler = instance d'objet GLib à traiter. * +* Paramètres : context = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -140,7 +140,7 @@ static void g_dex_demangling_dispose(GDexDemangling *context) /****************************************************************************** * * -* Paramètres : demangler = instance d'objet GLib à traiter. * +* Paramètres : context = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -197,7 +197,7 @@ static GDataType *g_dex_demangling_decode_type(GDexDemangling *context) static GBinRoutine *g_dex_demangling_decode_routine(GDexDemangling *context) { - GBinRoutine *result; /* Routine en place à retourner */ + GBinRoutine *result; /* Routine en place à retourner*/ GDemanglingContext *base; /* Autre version du contexte */ base = G_DEMANGLING_CONTEXT(context); diff --git a/plugins/dexbnf/demangler.c b/plugins/dexbnf/demangler.c index 32aa36f..3489f15 100644 --- a/plugins/dexbnf/demangler.c +++ b/plugins/dexbnf/demangler.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * demangler.c - décodage des noms d'éléments + * demangler.c - décodage des noms d'éléments Dex * * Copyright (C) 2018 Cyrille Bagard * diff --git a/plugins/dexbnf/python/demangler.c b/plugins/dexbnf/python/demangler.c index f47eefe..e9dba41 100644 --- a/plugins/dexbnf/python/demangler.c +++ b/plugins/dexbnf/python/demangler.c @@ -129,7 +129,7 @@ PyTypeObject *get_python_dex_demangler_type(void) bool register_python_dex_demangler(PyObject *module) { - PyTypeObject *py_dex_demangler_type; /* Type Python 'ElfFormat' */ + PyTypeObject *py_dex_demangler_type; /* Type Python 'DexDemangler' */ PyObject *dict; /* Dictionnaire du module */ py_dex_demangler_type = get_python_dex_demangler_type(); diff --git a/plugins/dexbnf/python/demangler.h b/plugins/dexbnf/python/demangler.h index af56289..f2cd964 100644 --- a/plugins/dexbnf/python/demangler.h +++ b/plugins/dexbnf/python/demangler.h @@ -34,7 +34,7 @@ /* Fournit un accès à une définition de type à diffuser. */ PyTypeObject *get_python_dex_demangler_type(void); -/* Prend en charge l'objet 'pychrysalide.format.elf.ElfFormat'. */ +/* Prend en charge l'objet 'pychrysalide.format.mangling.DexDemangler'. */ bool register_python_dex_demangler(PyObject *); diff --git a/plugins/itanium/Makefile.am b/plugins/itanium/Makefile.am new file mode 100644 index 0000000..b4a9cb7 --- /dev/null +++ b/plugins/itanium/Makefile.am @@ -0,0 +1,32 @@ + +lib_LTLIBRARIES = libitanium.la + +libdir = $(pluginsdir) + +libitanium_la_SOURCES = \ + abi.h abi.c \ + component-int.h \ + component.h component.c \ + context.h context.c \ + core.h core.c \ + demangler.h demangler.c + +libitanium_la_LIBADD = \ + python/libitaniumpython.la + +libitanium_la_LDFLAGS = \ + -L$(top_srcdir)/src/.libs -lchrysacore \ + -Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs \ + -L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libitanium_la_SOURCES:%c=) + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = python diff --git a/src/mangling/itanium/abi.c b/plugins/itanium/abi.c index 8d15ad4..5f76342 100644 --- a/src/mangling/itanium/abi.c +++ b/plugins/itanium/abi.c @@ -24,13 +24,15 @@ #include "abi.h" +#include <assert.h> #include <ctype.h> #include <stdlib.h> - -#include "../../analysis/types/basic.h" -#include "../../common/cpp.h" +#include <analysis/types/basic.h> +#include <analysis/types/cse.h> +#include <common/cpp.h> +#include <mangling/context-int.h> @@ -63,7 +65,7 @@ const itanium_operator_info itanium_demangle_operators[] = { { "eo", IDT_NL("^"), 2 }, { "eq", IDT_NL("=="), 2 }, { "ge", IDT_NL(">="), 2 }, - { "gs", IDT_NL("::"), 1 }, + { "gs", IDT_NL("::"), 1 }, { "gt", IDT_NL(">"), 2 }, { "ix", IDT_NL("[]"), 2 }, { "lS", IDT_NL("<<="), 2 }, @@ -98,9 +100,7 @@ const itanium_operator_info itanium_demangle_operators[] = { { "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 } + { "sz", IDT_NL("sizeof "), 1 } }; /* Substitutions standards */ @@ -108,165 +108,140 @@ const itanium_operator_info itanium_demangle_operators[] = { 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 */ + const char *class; /* Classe visée dans l'espace */ } 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") - } + { 't', NULL }, + { 'a', "allocator" }, + { 'b', "basic_string" }, + { 's', "string" }, + { 'i', "istream" }, + { 'o', "ostream" }, + { 'd', "iostream" } }; +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_encoding(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_encoding(GItaniumDContext *); +static itanium_component *itd_name(GItaniumDemangling *); + +/* Détermine si le composant suivant correspond à un type donné. */ +static bool is_itd_unscoped_name(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_name(GItaniumDContext *); +static itanium_component *itd_unscoped_name(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_unscoped_name(GItaniumDContext *); +static itanium_component *itd_unscoped_template_name(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_unscoped_template_name(GItaniumDContext *); +static itanium_component *itd_nested_name(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_nested_name(GItaniumDContext *); +static itanium_component *itd_prefix(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_prefix(GItaniumDContext *); +static itanium_component *itd_prefix_rec(GItaniumDemangling *, itanium_component *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_template_prefix(GItaniumDContext *); +static itanium_component *itd_template_prefix(GItaniumDemangling *); + +/* Détermine si le composant suivant correspond à un type donné. */ +static bool is_itd_unqualified_name(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_unqualified_name(GItaniumDContext *); +static itanium_component *itd_unqualified_name(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_source_name(GItaniumDContext *); +static itanium_component *itd_source_name(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static bool itd_number(GItaniumDContext *, ssize_t *); +static bool itd_number(GItaniumDemangling *, ssize_t *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_identifier(GItaniumDContext *, size_t); +static itanium_component *itd_identifier(GItaniumDemangling *, size_t); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_operator_name(GItaniumDContext *); +static itanium_component *itd_operator_name(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_special_name(GItaniumDContext *); +static itanium_component *itd_special_name(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_call_offset(GItaniumDContext *); +static itanium_component *itd_call_offset(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_nv_offset(GItaniumDContext *); +static itanium_component *itd_nv_offset(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_v_offset(GItaniumDContext *); +static itanium_component *itd_v_offset(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_ctor_dtor_name(GItaniumDContext *); +static itanium_component *itd_ctor_dtor_name(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_type(GItaniumDContext *); +static itanium_component *itd_type(GItaniumDemangling *); /* Extrait une propriété de composant pour un contexte Itanium. */ -static TypeQualifier itd_cv_qualifiers(GItaniumDContext *); +static TypeQualifier itd_cv_qualifiers(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_builtin_type(GItaniumDContext *); +static itanium_component *itd_builtin_type(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_bare_function_type(GItaniumDContext *); +static itanium_component *itd_function_type(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_class_enum_type(GItaniumDContext *); +static itanium_component *itd_bare_function_type(GItaniumDemangling *); +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_class_enum_type(GItaniumDemangling *); +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_array_type(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_template_args(GItaniumDContext *); +static itanium_component *itd_pointer_to_member_type(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_template_arg(GItaniumDContext *); +static itanium_component *itd_template_param(GItaniumDemangling *); +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_template_param(GItaniumDemangling *); +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_args(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_value_to_string(GItaniumDContext *, bool); +static itanium_component *itd_template_arg(GItaniumDemangling *); /* Extrait un composant dans un contexte Itanium. */ -static itanium_component *itd_expr_primary(GItaniumDContext *); +static itanium_component *itd_expression(GItaniumDemangling *); +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_value_to_string(GItaniumDemangling *, bool); +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_expr_primary(GItaniumDemangling *); -/* 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 *); +/* Extrait un composant dans un contexte Itanium. */ +static bool itd_seq_id(GItaniumDemangling *, char, size_t *); +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_substitution(GItaniumDemangling *); -#define itd_template_param(ctx) NULL #define itd_local_name(ctx) NULL @@ -274,8 +249,6 @@ static itanium_component *itd_substitution(GItaniumDContext *); -#define itd_expression(ctx) NULL - @@ -291,9 +264,10 @@ static itanium_component *itd_substitution(GItaniumDContext *); * * ******************************************************************************/ -itanium_component *itd_mangled_name(GItaniumDContext *context) +itanium_component *itd_mangled_name(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ /** * La règle traitée ici est la suivante : @@ -302,10 +276,12 @@ itanium_component *itd_mangled_name(GItaniumDContext *context) * */ - if (!g_itanium_dcontext_check_char(context, '_')) + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!check_input_buffer_char(ibuf, '_')) return NULL; - if (!g_itanium_dcontext_check_char(context, 'Z')) + if (!check_input_buffer_char(ibuf, 'Z')) return NULL; result = itd_encoding(context); @@ -327,11 +303,11 @@ itanium_component *itd_mangled_name(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_encoding(GItaniumDContext *context) +static itanium_component *itd_encoding(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ - itd_state saved; /* Position d'analyse courante */ - itanium_component *func; /* Composant 'function name' */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ itanium_component *types; /* Composant 'bare-function...'*/ /** @@ -343,32 +319,35 @@ static itanium_component *itd_encoding(GItaniumDContext *context) * */ - result = NULL; - g_itanium_dcontext_push_state(context, &saved); - - func = itd_name(context); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; - if (func != NULL) - { - types = itd_bare_function_type(context); + peek = peek_input_buffer_char(ibuf); - if (types != NULL) - result = itd_make_binary(context, ICT_FUNCTION_ENCODING, func, types); - else - itd_unref_comp(func); + if (peek == 'T' || peek == 'G') + result = itd_special_name(context); - } - /* - if (result == NULL) + else { - 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); + + if (result != NULL) + { + types = itd_bare_function_type(context); + + if (types != NULL) + result = itd_make_binary(ICT_FUNCTION_ENCODING, result, types); + + /** + * Si le chargement des types échoue, il peut y avoir deux explications : + * - on ne chargeait qu'un simple nom. + * - il y a eu une erreur de décodage pour les types. + * + * Le tampon aura été vidé dans le premier cas uniquement, + * donc on laisse le contexte détecter une éventuelle erreur. + */ + + } + } return result; @@ -388,7 +367,7 @@ static itanium_component *itd_encoding(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_name(GItaniumDContext *context) +static itanium_component *itd_name(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ itd_state saved; /* Position d'analyse courante */ @@ -405,13 +384,13 @@ static itanium_component *itd_name(GItaniumDContext *context) * */ - g_itanium_dcontext_push_state(context, &saved); + g_itanium_demangling_push_state(context, &saved); result = itd_nested_name(context); if (result == NULL) { - g_itanium_dcontext_pop_state(context, &saved); + g_itanium_demangling_pop_state(context, &saved); tname = itd_unscoped_template_name(context); @@ -420,10 +399,7 @@ static itanium_component *itd_name(GItaniumDContext *context) 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); - } + result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, tname, targs); else itd_unref_comp(tname); @@ -442,13 +418,13 @@ static itanium_component *itd_name(GItaniumDContext *context) if (result == NULL) { - g_itanium_dcontext_pop_state(context, &saved); + g_itanium_demangling_pop_state(context, &saved); result = itd_unscoped_name(context); } if (result == NULL) { - g_itanium_dcontext_pop_state(context, &saved); + g_itanium_demangling_pop_state(context, &saved); result = itd_local_name(context); } @@ -461,6 +437,56 @@ static itanium_component *itd_name(GItaniumDContext *context) * * * Paramètres : context = contexte de décodage à utiliser. * * * +* Description : Détermine si le composant suivant correspond à un type donné.* +* * +* Retour : true si le décodage va à priori réussir, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool is_itd_unscoped_name(GItaniumDemangling *context) +{ + bool result; /* Bilan à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ + char next_peek; /* Caractère après le prochain */ + + /** + * La règle anticipée ici est la suivante : + * + * <unscoped-name> ::= <unqualified-name> + * ::= St <unqualified-name> # ::std:: + * + */ + + result = is_itd_unqualified_name(context); + + if (!result) + { + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + peek = peek_input_buffer_char(ibuf); + + if (peek == 'S') + { + next_peek = peek_input_buffer_next_char(ibuf); + + result = (next_peek == 't'); + + } + + } + + 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. * @@ -469,9 +495,12 @@ static itanium_component *itd_name(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_unscoped_name(GItaniumDContext *context) +static itanium_component *itd_unscoped_name(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ + char next_peek; /* Caractère après le prochain */ /** * La règle traitée ici est la suivante : @@ -482,11 +511,39 @@ static itanium_component *itd_unscoped_name(GItaniumDContext *context) */ - /* TODO : 'St' */ + if (is_itd_unqualified_name(context)) + result = itd_unqualified_name(context); + + else + { + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + peek = peek_input_buffer_char(ibuf); - result = itd_unqualified_name(context); + if (peek == 'S') + { + next_peek = peek_input_buffer_next_char(ibuf); + + if (next_peek == 't') + { + advance_input_buffer(ibuf, 2); + + result = itd_unqualified_name(context); + if (result != NULL) + result = itd_make_unary(ICT_STD_UNSCOPED_NAME, result); + + } + + else + result = NULL; + + } + + else + result = NULL; + + } return result; @@ -505,10 +562,11 @@ static itanium_component *itd_unscoped_name(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_unscoped_template_name(GItaniumDContext *context) +static itanium_component *itd_unscoped_template_name(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ - itd_state saved; /* Position d'analyse courante */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ /** * La règle traitée ici est la suivante : @@ -518,14 +576,27 @@ static itanium_component *itd_unscoped_template_name(GItaniumDContext *context) * */ - g_itanium_dcontext_push_state(context, &saved); + if (is_itd_unscoped_name(context)) + { + result = itd_unscoped_name(context); - result = itd_unscoped_name(context); + if (result != NULL) + g_itanium_demangling_add_substitution(context, result); - if (result == NULL) + } + + else { - g_itanium_dcontext_pop_state(context, &saved); - result = itd_substitution(context); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + peek = peek_input_buffer_char(ibuf); + + if (peek == 'S') + result = itd_substitution(context); + + else + result = NULL; + } return result; @@ -545,21 +616,15 @@ static itanium_component *itd_unscoped_template_name(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_nested_name(GItaniumDContext *context) +static itanium_component *itd_nested_name(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ 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 : * @@ -568,96 +633,88 @@ static itanium_component *itd_nested_name(GItaniumDContext *context) * */ - if (!g_itanium_dcontext_check_char(context, 'N')) + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!check_input_buffer_char(ibuf, '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 })); - + g_itanium_demangling_push_state(context, &saved); + /** + * Comme <prefix> <unqualified-name> peut aussi être <template-prefix>, + * on commence par traiter la seconde règle. + */ - left = itd_prefix(context); + left = itd_template_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); + 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); + if (check_input_buffer_char(ibuf, 'E')) + result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, left, right); - //result = itd_make_binary(context, ICT_NESTED_NAME, left, right); + else + { + if (left != NULL) + itd_unref_comp(left); + itd_unref_comp(right); + } } - else - itd_unref_comp(left); - printf(" ---- (%d) nested prefix --> %p\n\n", val, result); + else if (left != NULL) + itd_unref_comp(left); } - if (result == NULL) { - printf("\n ----- (%d) nested template_arg '%s'\n", val, g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + g_itanium_demangling_pop_state(context, &saved); + + left = itd_prefix(context); - g_itanium_dcontext_pop_state(context, &saved); + /** + * Quand son traitement est un succès, <prefix> doit toujours + * se terminer par <unqualified-name>. + */ - left = itd_template_prefix(context); + assert(left == NULL || (left != NULL && is_itd_unqualified_name(context))); - if (left != NULL) - { - g_itanium_dcontext_add_substitution(context, left); + /** + * La règle <prefix> peut être vide, donc on se doit de tenter un + * <unqualified-name> dans tous les cas. + */ + + right = itd_unqualified_name(context); - right = itd_template_args(context); + if (right != NULL) + { + if (check_input_buffer_char(ibuf, 'E')) + result = itd_make_binary(ICT_NESTED_NAME, left, right); - if (right != NULL) + else { - 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); + if (left != NULL) + itd_unref_comp(left); + itd_unref_comp(right); } - 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); + else if (left != NULL) + itd_unref_comp(left); - if (result != NULL) - itd_unref_comp(result); - return NULL; } - */ if (result != NULL) - printf("=== (%d) NESTED OK (%p)\n\n", val, result); - - inner--; + itd_make_qualified_type(result, qualifier); return result; @@ -676,28 +733,17 @@ static itanium_component *itd_nested_name(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_prefix(GItaniumDContext *context) +static itanium_component *itd_prefix(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ - itanium_component *looping_rule; /* Extraction d'une boucle */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ + itanium_component *targs; /* Composant 'template-args' */ 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 */ - - + itanium_component *further; /* Tentative de progression */ /** - * Les deux règles traitées ici sont les suivantes : + * La règle traitée ici est la suivante : * * <prefix> ::= <prefix> <unqualified-name> * ::= <template-prefix> <template-args> @@ -705,6 +751,10 @@ static itanium_component *itd_prefix(GItaniumDContext *context) * ::= # empty * ::= <substitution> * + * On note déjà la jolie petite boucle interne. + * + * Or on a également la règle voisine suivante : + * * <template-prefix> ::= <prefix> <template unqualified-name> * ::= <template-param> * ::= <substitution> @@ -714,202 +764,237 @@ static itanium_component *itd_prefix(GItaniumDContext *context) * * <prefix> ::= <prefix> <unqualified-name> * ::= <prefix> <unqualified-name> <template-args> + * ::= <template-param> * ::= <template-param> <template-args> + * ::= <substitution> * ::= <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; + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; - while (1) + if (is_itd_unqualified_name(context)) + result = itd_unqualified_name(context); + + else { - printf("loop....\n"); + peek = peek_input_buffer_char(ibuf); - looping_rule = NULL; + if (peek == 'T') + result = itd_template_param(context); - /** - * Première partie. - */ + else if (peek == 'S') + result = itd_substitution(context); - g_itanium_dcontext_push_state(context, &saved); + else + result = NULL; - /* <template-param> <template-args> */ + } - left = itd_template_param(context); + if (result == NULL) + goto prefix_exit; - if (left != NULL) - { - g_itanium_dcontext_add_substitution(context, left); + g_itanium_demangling_add_substitution(context, result); - right = itd_template_args(context); + /** + * Détection et traitement de <template-args>. + */ - if (right != NULL) - looping_rule = itd_make_binary(context, ICT_PREFIX_BINARY, left, right); - else - itd_unref_comp(left); + peek = peek_input_buffer_char(ibuf); - } + if (peek == 'I') + { + /** + * Si la détection est avérée, on vient donc de traiter un cas <template-prefix>. + * On corrige donc le type au passage. + */ + if (itd_get_component_type(result) == ICT_PREFIX_BINARY) + itd_set_type(result, ICT_TPREFIX_BINARY); - /* <substitution> <template-args> */ + targs = itd_template_args(context); - if (looping_rule != NULL) + if (targs != NULL) { - g_itanium_dcontext_pop_state(context, &saved); - - left = itd_substitution(context); - - if (left != NULL) - { - right = itd_template_args(context); + result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs); - if (right != NULL) - looping_rule = itd_make_binary(context, ICT_PREFIX_BINARY, left, right); - else - itd_unref_comp(left); - - } + g_itanium_demangling_add_substitution(context, result); } - /* <template-param> */ - - if (looping_rule == NULL) + else { - g_itanium_dcontext_pop_state(context, &saved); - looping_rule = itd_template_param(context); + itd_unref_comp(result); + result = NULL; } - /* <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 (result == NULL) + goto prefix_exit; - if (looping_rule != NULL) - { - if (result == NULL) - result = looping_rule; - else - result = itd_make_binary(context, ICT_PREFIX_BINARY, result, looping_rule); - } + /** + * Toutes les règles <prefix> sont suivie par un <[template] unqualified-name>. + * + * On vérifie donc que c'est le cas. + */ - /** - * Seconde partie (1/3) : recherche d'un éventuel complément. - */ + if (!is_itd_unqualified_name(context)) + { + itd_unref_comp(result); + result = NULL; + goto prefix_exit; - if (looping_rule == NULL) - g_itanium_dcontext_pop_state(context, &saved); + } - /* <unqualified-name> */ + /** + * Cette vérification passée, on peut se trouver dans l'un des cas suivants : + * + * <prefix> ::= <prefix> <unqualified-name> + * ::= <prefix> <template unqualified-name> <template-args> + * + * On tente donc une itération supplémentaire. + */ - g_itanium_dcontext_push_state(context, &next_name_saved); + g_itanium_demangling_push_state(context, &saved); - next_name = itd_unqualified_name(context); + further = itd_prefix_rec(context, result); - 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. - */ + if (further != NULL) + result = further; - return NULL; + else + g_itanium_demangling_pop_state(context, &saved); - break; + prefix_exit: - } + return result; - /* <template-args> */ +} - g_itanium_dcontext_push_state(context, &next_targs_saved); - next_targs = itd_template_args(context); +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* loop = consigne pour la poursuite de la boucle. [OUT] * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ - g_itanium_dcontext_pop_state(context, &next_targs_saved); +static itanium_component *itd_prefix_rec(GItaniumDemangling *context, itanium_component *leaf) +{ + itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ + itanium_component *targs; /* Composant 'template-args' */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *further; /* Tentative de progression */ - /** - * Seconde partie (2/3) : validation de la présence d'un jeton - * <unqualified-name> en réserve pour la règle <nested-name> parente. - */ + /** + * La règle locale traitée ici est la suivante : + * + * <prefix> ::= <prefix> <unqualified-name> + * ::= <prefix> <unqualified-name> <template-args> + * + * Le premier <prefix> des règles est contenu dans l'arguement leaf. + */ - g_itanium_dcontext_push_state(context, &expected_saved); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; - expected = itd_unqualified_name(context); + /** + * La présence du <unqualified-name> intial doit être assurée + * par l'appelant. + * + * Mais comme le test ne vaut pas la création, on valide quand même derrière. + */ - 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. - */ + assert(is_itd_unqualified_name(context)); - itd_unref_comp(next_name); + result = itd_unqualified_name(context); - if (next_targs != NULL) - itd_unref_comp(next_targs); + if (result == NULL) + goto prefix_rec_exit; - g_itanium_dcontext_pop_state(context, &next_name_saved); + result = itd_make_binary(ICT_PREFIX_BINARY, leaf, result); - break; + g_itanium_demangling_add_substitution(context, result); - } + /** + * Détection et traitement de <template-args>. + */ - g_itanium_dcontext_pop_state(context, &expected_saved); + peek = peek_input_buffer_char(ibuf); + if (peek == 'I') + { /** - * 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. + * Si la détection est avérée, on vient donc de traiter un cas <template-prefix>. + * On corrige donc le type au passage. */ + if (itd_get_component_type(result) == ICT_PREFIX_BINARY) + itd_set_type(result, ICT_TPREFIX_BINARY); - if (result != NULL) - g_itanium_dcontext_add_substitution(context, result); + targs = itd_template_args(context); - printf("result = %p - next_name = %p\n", result, next_name); + if (targs != NULL) + { + result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs); + g_itanium_demangling_add_substitution(context, result); + + } - if (result == NULL) - result = next_name; else - result = itd_make_binary(context, ICT_PREFIX_BINARY, result, next_name); + { + itd_ref_comp(leaf); + itd_unref_comp(result); + result = NULL; + } - if (next_targs != NULL) - result = itd_make_binary(context, ICT_PREFIX_BINARY, result, next_targs); + } + if (result == NULL) + goto prefix_rec_exit; - printf(" > result = %p\n", result); + /** + * Toutes les règles <prefix> sont suivie par un <[template] unqualified-name>. + * + * On vérifie donc que c'est le cas. + */ + if (!is_itd_unqualified_name(context)) + { + itd_ref_comp(leaf); + itd_unref_comp(result); + result = NULL; + goto prefix_rec_exit; } - 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); + /** + * Cette vérification passée, on peut se trouver dans l'un des cas suivants : + * + * <prefix> ::= <prefix> <unqualified-name> + * ::= <prefix> <template unqualified-name> <template-args> + * + * On tente donc une itération supplémentaire. + */ + + g_itanium_demangling_push_state(context, &saved); + + further = itd_prefix_rec(context, result); - printf("### FIN DE PREFIX ### '%s'\n", - g_itanium_dcontext_get_string(context, (size_t []){ 0 })); + if (further != NULL) + result = further; + + else + g_itanium_demangling_pop_state(context, &saved); + + prefix_rec_exit: return result; @@ -928,10 +1013,11 @@ static itanium_component *itd_prefix(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_template_prefix(GItaniumDContext *context) +static itanium_component *itd_template_prefix(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ - itd_state saved; /* Position d'analyse courante */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ itanium_component *prefix; /* Premier d'un couple de comp.*/ itanium_component *name; /* Second d'un couple de comp. */ @@ -944,36 +1030,98 @@ static itanium_component *itd_template_prefix(GItaniumDContext *context) * */ - result = NULL; - g_itanium_dcontext_push_state(context, &saved); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + peek = peek_input_buffer_char(ibuf); - prefix = itd_prefix(context); + if (peek == 'S') + result = itd_substitution(context); + + else if (peek == 'T') + { + result = itd_template_param(context); + + if (result != NULL) + g_itanium_demangling_add_substitution(context, result); + + } - if (prefix != NULL) + else { + prefix = itd_prefix(context); + + /** + * Quand son traitement est un succès, <prefix> doit toujours + * se terminer par <unqualified-name>. + */ + + assert(prefix == NULL || (prefix != NULL && is_itd_unqualified_name(context))); + + /** + * Par ailleurs, la règle <prefix> peut être vide, donc on se doit + * de tenter un <unqualified-name> dans tous les cas. + */ + name = itd_unqualified_name(context); if (name != NULL) - result = itd_make_binary(context, ICT_TPREFIX_BINARY, prefix, name); + { + result = itd_make_binary(ICT_TPREFIX_BINARY, prefix, name); + + g_itanium_demangling_add_substitution(context, result); + + } + else - itd_unref_comp(prefix); + { + result = NULL; - } + if (prefix != NULL) + 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 : Détermine si le composant suivant correspond à un type donné.* +* * +* Retour : true si le décodage va à priori réussir, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool is_itd_unqualified_name(GItaniumDemangling *context) +{ + bool result; /* Bilan à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ + + /** + * La règle anticipée ici est la suivante : + * + * <unqualified-name> ::= <operator-name> + * ::= <ctor-dtor-name> + * ::= <source-name> + * + */ + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + peek = peek_input_buffer_char(ibuf); + + result = islower(peek) /* <operator-name> */ + || (peek == 'C' || peek == 'D') /* <ctor-dtor-name> */ + || isdigit(peek); /* <source-name> */ return result; @@ -992,10 +1140,11 @@ static itanium_component *itd_template_prefix(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_unqualified_name(GItaniumDContext *context) +static itanium_component *itd_unqualified_name(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ - itd_state saved; /* Position d'analyse courante */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ /** * La règle traitée ici est la suivante : @@ -1006,21 +1155,21 @@ static itanium_component *itd_unqualified_name(GItaniumDContext *context) * */ - g_itanium_dcontext_push_state(context, &saved); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; - result = itd_operator_name(context); + peek = peek_input_buffer_char(ibuf); - if (result == NULL) - { - g_itanium_dcontext_pop_state(context, &saved); + if (islower(peek)) + result = itd_operator_name(context); + + else if (peek == 'C' || peek == 'D') result = itd_ctor_dtor_name(context); - } - if (result == NULL) - { - g_itanium_dcontext_pop_state(context, &saved); + else if (isdigit(peek)) result = itd_source_name(context); - } + + else + result = NULL; return result; @@ -1039,7 +1188,7 @@ static itanium_component *itd_unqualified_name(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_source_name(GItaniumDContext *context) +static itanium_component *itd_source_name(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ ssize_t number; /* Taille positive */ @@ -1077,10 +1226,11 @@ static itanium_component *itd_source_name(GItaniumDContext *context) * * ******************************************************************************/ -static bool itd_number(GItaniumDContext *context, ssize_t *size) +static bool itd_number(GItaniumDemangling *context, ssize_t *size) { bool result; /* Validité à renvoyer */ bool negative; /* Taille négative ? */ + input_buffer *ibuf; /* Tampon de texte manipulé */ char peek; /* Prochain caractère lu */ /** @@ -1094,13 +1244,15 @@ static bool itd_number(GItaniumDContext *context, ssize_t *size) negative = false; - peek = g_itanium_dcontext_peek_char(context); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + peek = peek_input_buffer_char(ibuf); if (peek == 'n') { negative = true; - g_itanium_dcontext_advance(context, 1); - peek = g_itanium_dcontext_peek_char(context); + advance_input_buffer(ibuf, 1); + peek = peek_input_buffer_char(ibuf); } *size = 0; @@ -1109,8 +1261,8 @@ static bool itd_number(GItaniumDContext *context, ssize_t *size) { result = true; *size = *size * 10 + peek - '0'; - g_itanium_dcontext_advance(context, 1); - peek = g_itanium_dcontext_peek_char(context); + advance_input_buffer(ibuf, 1); + peek = peek_input_buffer_char(ibuf); } if (negative) @@ -1134,9 +1286,10 @@ static bool itd_number(GItaniumDContext *context, ssize_t *size) * * ******************************************************************************/ -static itanium_component *itd_identifier(GItaniumDContext *context, size_t length) +static itanium_component *itd_identifier(GItaniumDemangling *context, size_t length) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ const char *data; /* Données restantes */ size_t remaining; /* Quantité d'octets */ @@ -1147,15 +1300,17 @@ static itanium_component *itd_identifier(GItaniumDContext *context, size_t lengt * */ - data = g_itanium_dcontext_get_string(context, &remaining); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + data = get_input_buffer_string(ibuf, &remaining); if (length > remaining) return NULL; - result = itd_make_name(context, data, length); + result = itd_make_name(data, length); if (result != NULL) - g_itanium_dcontext_advance(context, length); + advance_input_buffer(ibuf, length); return result; @@ -1174,94 +1329,99 @@ static itanium_component *itd_identifier(GItaniumDContext *context, size_t lengt * * ******************************************************************************/ -static itanium_component *itd_operator_name(GItaniumDContext *context) +static itanium_component *itd_operator_name(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ char code[2]; /* Code à venir lire */ + itanium_component *type; /* Type transtypé */ 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 + * <operator-name> ::= nw # new * ::= na # new[] - * ::= dl # delete - * ::= da # delete[] + * ::= 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 # ? + * ::= 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) + * ::= cv <type> # (cast) * ::= v <digit> <source-name> # vendor extended operator * */ result = NULL; - code[0] = g_itanium_dcontext_next_char(context); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!get_input_buffer_next_char_carefully(ibuf, &code[0])) + goto itd_operator_name_exit; if (code[0] == 'v') { + type = itd_type(context); - result = NULL; /* TODO */ + if (type != NULL) + result = itd_make_cast_operator(type); + else + result = NULL; goto itd_operator_name_exit; - } - code[1] = g_itanium_dcontext_next_char(context); + if (!get_input_buffer_next_char_carefully(ibuf, &code[1])) + goto itd_operator_name_exit; if (code[0] == 'c' && code[1] == 'v') { - - result = NULL; /* TODO */ - + result = NULL; goto itd_operator_name_exit; - - } /* Recherche dans la liste des opérateurs reconnus */ @@ -1295,7 +1455,7 @@ static itanium_component *itd_operator_name(GItaniumDContext *context) sizeof(itanium_operator_info), (__compar_fn_t)comp_itanium_operators); if (found != NULL) - result = itd_make_operator(context, found); + result = itd_make_operator(found); itd_operator_name_exit: @@ -1316,54 +1476,116 @@ static itanium_component *itd_operator_name(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_special_name(GItaniumDContext *context) +static itanium_component *itd_special_name(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ char next; /* Caractère suivant */ char peek; /* Prochain caractère lu */ itanium_component *offset1; /* Décalage extrait #1 */ + itanium_component *offset2; /* Décalage extrait #2 */ 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 + * <special-name> ::= TV <type> # virtual table + * ::= TT <type> # VTT structure (construction vtable index) + * ::= TI <type> # typeinfo structure + * ::= TS <type> # typeinfo name (null-terminated byte string) + * ::= Tc <call-offset> <call-offset> <base encoding> + * # base is the nominal target function of thunk + * # first call-offset is 'this' adjustment + * # second call-offset is result adjustment + * ::= T <call-offset> <base encoding> + * # base is the nominal target function of thunk */ result = NULL; - next = g_itanium_dcontext_next_char(context); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!get_input_buffer_next_char_carefully(ibuf, &next)) + goto exit_eof; if (next == 'T') { - peek = g_itanium_dcontext_peek_char(context); + peek = peek_input_buffer_char(ibuf); switch (peek) { case 'V': - result = NULL; /* TODO */ + + advance_input_buffer(ibuf, 1); + + result = itd_type(context); + + if (result != NULL) + result = itd_make_unary(ICT_SPECIAL_NAME_VTABLE, result); + break; case 'T': - result = NULL; /* TODO */ + + advance_input_buffer(ibuf, 1); + + result = itd_type(context); + + if (result != NULL) + result = itd_make_unary(ICT_SPECIAL_NAME_VSTRUCT, result); + break; case 'I': - result = NULL; /* TODO */ + advance_input_buffer(ibuf, 1); + result = itd_type(context); break; case 'S': - result = NULL; /* TODO */ + advance_input_buffer(ibuf, 1); + result = itd_type(context); break; case 'c': - result = NULL; /* TODO */ + + advance_input_buffer(ibuf, 1); + + offset1 = itd_call_offset(context); + if (offset1 == NULL) break; + + offset2 = itd_call_offset(context); + if (offset2 == NULL) + { + itd_unref_comp(offset1); + break; + } + + encoding = itd_encoding(context); + + if (encoding == NULL) + { + itd_unref_comp(offset1); + itd_unref_comp(offset2); + } + + else + result = itd_make_ternary(ICT_FUNCTION_COVARIANT_THUNK, encoding, offset1, offset2); + break; + case '\0': + + /** + * Si on se trouve à la fin du tampon, on n'avance pas aveuglément ! + */ + + result = NULL; + break; default: + advance_input_buffer(ibuf, 1); + offset1 = itd_call_offset(context); if (offset1 == NULL) break; @@ -1372,7 +1594,7 @@ static itanium_component *itd_special_name(GItaniumDContext *context) if (encoding == NULL) itd_unref_comp(offset1); else - result = itd_make_binary(context, ICT_FUNCTION_THUNK, offset1, encoding); + result = itd_make_binary(ICT_FUNCTION_THUNK, encoding, offset1); break; @@ -1380,6 +1602,8 @@ static itanium_component *itd_special_name(GItaniumDContext *context) } + exit_eof: + return result; } @@ -1397,9 +1621,10 @@ static itanium_component *itd_special_name(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_call_offset(GItaniumDContext *context) +static itanium_component *itd_call_offset(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ char next; /* Caractère suivant */ /** @@ -1409,7 +1634,12 @@ static itanium_component *itd_call_offset(GItaniumDContext *context) * ::= v <v-offset> _ */ - next = g_itanium_dcontext_next_char(context); + result = NULL; + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (get_input_buffer_next_char_carefully(ibuf, &next)) + goto exit_eof; switch (next) { @@ -1421,18 +1651,16 @@ static itanium_component *itd_call_offset(GItaniumDContext *context) result = itd_v_offset(context); break; - default: - result = NULL; - break; - } - if (result != NULL && !g_itanium_dcontext_check_char(context, '_')) + if (result != NULL && !check_input_buffer_char(ibuf, '_')) { itd_unref_comp(result); result = NULL; } + exit_eof: + return result; } @@ -1450,7 +1678,7 @@ static itanium_component *itd_call_offset(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_nv_offset(GItaniumDContext *context) +static itanium_component *itd_nv_offset(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ ssize_t offset; /* Décalage obtenu */ @@ -1465,7 +1693,7 @@ static itanium_component *itd_nv_offset(GItaniumDContext *context) if (!itd_number(context, &offset)) return NULL; - result = itd_make_offset(context, ICT_NON_VIRTUAL_OFFSET, offset); + result = itd_make_offset(ICT_NON_VIRTUAL_OFFSET, offset); return result; @@ -1484,10 +1712,11 @@ static itanium_component *itd_nv_offset(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_v_offset(GItaniumDContext *context) +static itanium_component *itd_v_offset(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ ssize_t offset; /* Décalage obtenu #1 */ + input_buffer *ibuf; /* Tampon de texte manipulé */ ssize_t voffset; /* Décalage obtenu #2 */ /** @@ -1500,15 +1729,17 @@ static itanium_component *itd_v_offset(GItaniumDContext *context) if (!itd_number(context, &offset)) return NULL; - if (!g_itanium_dcontext_check_char(context, '_')) + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!check_input_buffer_char(ibuf, '_')) 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)); + result = itd_make_binary(ICT_DOUBLE_OFFSET, + itd_make_offset(ICT_NON_VIRTUAL_OFFSET, offset), + itd_make_offset(ICT_VIRTUAL_OFFSET, voffset)); return result; @@ -1527,9 +1758,10 @@ static itanium_component *itd_v_offset(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_ctor_dtor_name(GItaniumDContext *context) +static itanium_component *itd_ctor_dtor_name(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ char next; /* Caractère suivant */ ItaniumComponentType type; /* Type de composant */ @@ -1544,7 +1776,9 @@ static itanium_component *itd_ctor_dtor_name(GItaniumDContext *context) * ::= D2 # base object destructor */ - next = g_itanium_dcontext_peek_char(context); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + next = peek_input_buffer_char(ibuf); if (next == 'C') type = ICT_CONSTRUCTOR; @@ -1553,17 +1787,16 @@ static itanium_component *itd_ctor_dtor_name(GItaniumDContext *context) else return NULL; - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); - next = g_itanium_dcontext_peek_char(context); + next = peek_input_buffer_char(ibuf); if (next != '0' && next != '1' && next != '2') return NULL; - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); - result = itd_make_empty(context); - itd_set_type(result, type); + result = itd_make_with_type(type); return result; @@ -1582,12 +1815,17 @@ static itanium_component *itd_ctor_dtor_name(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_type(GItaniumDContext *context) +static itanium_component *itd_type(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ TypeQualifier qualifier; /* Propriétés supplémentaires */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + bool handled; /* Prise en compte effectuée ? */ itanium_component *sub; /* Sous-type lié à associer */ + itanium_component *vendor; /* Extension propriétaire */ + GDataType *builtin; /* Type construit */ itd_state saved; /* Position d'analyse courante */ + itanium_component *targs; /* Composant 'template-args' */ /** * La règle traitée ici est la suivante : @@ -1614,90 +1852,262 @@ static itanium_component *itd_type(GItaniumDContext *context) qualifier = itd_cv_qualifiers(context); - switch (g_itanium_dcontext_peek_char(context)) + if (qualifier != TQF_NONE) { + result = itd_type(context); + + if (result != NULL) + result = itd_make_qualified_type(result, qualifier); + + goto itd_type_end; + + } + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + handled = false; + + switch (peek_input_buffer_char(ibuf)) + { + case 'F': + result = itd_function_type(context); + handled = true; + break; + + case 'A': + result = itd_array_type(context); + handled = true; + break; + + case 'M': + result = itd_pointer_to_member_type(context); + handled = true; + break; + case 'P': - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); sub = itd_type(context); if (sub == NULL) return NULL; - result = itd_make_unary(context, ICT_POINTER_TO, sub); + result = itd_make_unary(ICT_POINTER_TO, sub); + handled = true; break; case 'R': - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); sub = itd_type(context); if (sub == NULL) return NULL; - result = itd_make_unary(context, ICT_REFERENCE_TO, sub); + result = itd_make_unary(ICT_REFERENCE_TO, sub); + handled = true; break; case 'O': - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); sub = itd_type(context); if (sub == NULL) return NULL; - result = itd_make_unary(context, ICT_RVALUE_REFERENCE_TO, sub); + result = itd_make_unary(ICT_RVALUE_REFERENCE_TO, sub); + handled = true; break; case 'C': - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); sub = itd_type(context); if (sub == NULL) return NULL; - result = itd_make_unary(context, ICT_COMPLEX_PAIR, sub); + result = itd_make_unary(ICT_COMPLEX_PAIR, sub); + handled = true; break; case 'G': - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); sub = itd_type(context); if (sub == NULL) return NULL; - result = itd_make_unary(context, ICT_IMAGINARY, sub); + result = itd_make_unary(ICT_IMAGINARY, sub); + handled = true; break; case 'U': - g_itanium_dcontext_advance(context, 1); - /* TODO */ - return NULL; + advance_input_buffer(ibuf, 1); + + result = NULL; + + vendor = itd_source_name(context); + + if (vendor == NULL) + result = NULL; + + else + { + builtin = g_class_enum_type_new(CET_UNKNOWN, itd_translate_component(vendor, NULL)); + result = itd_make_type(builtin); + itd_unref_comp(vendor); + + sub = itd_type(context); + + if (sub != NULL) + itd_unref_comp(sub); + + else + { + itd_unref_comp(result); + result = NULL; + } + + } + + handled = true; break; - } + case 'T': - if (result != NULL) goto itd_type_end; + /** + * Comme on a la définition suivante : + * + * <template-template-param> ::= <template-param> + * ::= <substitution> + * + * On ne sait pas laquelle de ces deux directions prendre : + * + * <type> ::= <template-param> + * ::= <template-template-param> <template-args> + * + * Comme <template-args> commence toujour par un I, on teste + * le caractère courant après <template-param> et on revient + * un poil en arrière au besoin. + * + * Le cas <substitution> est traité de façon similaire après. + */ + + g_itanium_demangling_push_state(context, &saved); - g_itanium_dcontext_push_state(context, &saved); + result = itd_template_param(context); + + if (result != NULL) + { + if (peek_input_buffer_char(ibuf) == 'I') + { + itd_unref_comp(result); + + g_itanium_demangling_pop_state(context, &saved); + + result = itd_template_template_param(context); + + if (result != NULL) + { + targs = itd_template_args(context); + + if (targs != NULL) + result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs); + + else + { + itd_unref_comp(result); + result = NULL; + } + + } + + } + + } + + handled = true; + break; + + } + + if (handled) goto itd_type_end; + + g_itanium_demangling_push_state(context, &saved); result = itd_builtin_type(context); if (result != NULL) goto itd_type_end; - g_itanium_dcontext_pop_state(context, &saved); + g_itanium_demangling_pop_state(context, &saved); result = itd_class_enum_type(context); if (result != NULL) goto itd_type_end; + g_itanium_demangling_pop_state(context, &saved); + + /** + * De façon similaire au cas <template-param> traité au dessus, + * on guette un usage de <substitution> via : + * + * <template-template-param> ::= <template-param> + * ::= <substitution> + * + * La distinction se réalise via une liste d'argument, et on tranche + * cette fois entre les deux directions suivantes : + * + * <type> ::= <template-template-param> <template-args> + * ::= <substitution> # See Compression below + */ - g_itanium_dcontext_pop_state(context, &saved); + g_itanium_demangling_push_state(context, &saved); result = itd_substitution(context); - if (result != NULL) goto itd_type_end; + if (result != NULL && peek_input_buffer_char(ibuf) == 'I') + { + itd_unref_comp(result); + + g_itanium_demangling_pop_state(context, &saved); + result = itd_template_template_param(context); + + if (result != NULL) + { + targs = itd_template_args(context); + + if (targs != NULL) + result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs); + + else + { + itd_unref_comp(result); + result = NULL; + } + + } + } itd_type_end: + if (result != NULL) + { + /** + * Les spécifications (§ 5.1.9) précisent: + * + * There are two exceptions that appear to be substitution candidates + * from the grammar, but are explicitly excluded: + * + * <builtin-type> other than vendor extended types, and + * function and operator names other than extern "C" functions. + * + * On saute donc éventuelleement certains résultats. + */ + + if (itd_get_component_type(result) != ICT_TYPE) + g_itanium_demangling_add_substitution(context, result); + + } + return result; } @@ -1715,35 +2125,38 @@ static itanium_component *itd_type(GItaniumDContext *context) * * ******************************************************************************/ -static TypeQualifier itd_cv_qualifiers(GItaniumDContext *context) +static TypeQualifier itd_cv_qualifiers(GItaniumDemangling *context) { TypeQualifier result; /* Valeur à remonter */ + input_buffer *ibuf; /* Tampon de texte manipulé */ /** * La règle traitée ici est la suivante : * - * <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const + * <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const * */ result = TQF_NONE; + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + while (1) - switch (g_itanium_dcontext_peek_char(context)) + switch (peek_input_buffer_char(ibuf)) { case 'r': result = TQF_RESTRICT; - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); break; case 'V': result = TQF_VOLATILE; - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); break; case 'K': result = TQF_CONST; - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); break; default: @@ -1771,10 +2184,12 @@ static TypeQualifier itd_cv_qualifiers(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_builtin_type(GItaniumDContext *context) +static itanium_component *itd_builtin_type(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ BaseType type; /* Type reconnu ou BTP_INVALID */ + itanium_component *vendor; /* Extension propriétaire */ GDataType *builtin; /* Type construit */ /** @@ -1805,7 +2220,9 @@ static itanium_component *itd_builtin_type(GItaniumDContext *context) * */ - switch (g_itanium_dcontext_peek_char(context)) + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + switch (peek_input_buffer_char(ibuf)) { case 'v': type = BTP_VOID; @@ -1871,10 +2288,21 @@ static itanium_component *itd_builtin_type(GItaniumDContext *context) type = BTP_ELLIPSIS; break; case 'u': - type = BTP_OTHER; - /* FIXME */ - /* <source-name> # vendor extended type */ + + vendor = itd_source_name(context); + + if (vendor == NULL) + result = NULL; + else + { + builtin = g_class_enum_type_new(CET_UNKNOWN, itd_translate_component(vendor, NULL)); + result = itd_make_type(builtin); + itd_unref_comp(vendor); + } + + goto done; break; + default: type = BTP_INVALID; break; @@ -1883,12 +2311,14 @@ static itanium_component *itd_builtin_type(GItaniumDContext *context) if (type != BTP_INVALID) { builtin = g_basic_type_new(type); - result = itd_make_type(context, builtin); - g_itanium_dcontext_advance(context, 1); + result = itd_make_type(builtin); + advance_input_buffer(ibuf, 1); } else result = NULL; + done: + return result; } @@ -1906,10 +2336,69 @@ static itanium_component *itd_builtin_type(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_bare_function_type(GItaniumDContext *context) +static itanium_component *itd_function_type(GItaniumDemangling *context) +{ + itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère dispo. */ + itanium_component *args; /* Liste des arguments */ + + /** + * La règle traitée ici est la suivante : + * + * <function-type> ::= F [Y] <bare-function-type> E + * + */ + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!check_input_buffer_char(ibuf, 'F')) + return NULL; + + peek = peek_input_buffer_char(ibuf); + + if (peek == 'Y') + advance_input_buffer(ibuf, 1); + + args = itd_bare_function_type(context); + + if (args == NULL) + result = NULL; + + else + { + result = itd_make_function_type(peek == 'Y', args); + + if (!check_input_buffer_char(ibuf, 'E')) + { + 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_bare_function_type(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ itanium_component *type; /* Nouvel élément à intégrer */ + input_buffer *ibuf; /* Tampon de texte manipulé */ itd_state saved; /* Position d'analyse courante */ /** @@ -1923,20 +2412,23 @@ static itanium_component *itd_bare_function_type(GItaniumDContext *context) type = itd_type(context); if (type == NULL) return NULL; - result = itd_append_right_to_binary(context, ICT_TYPES_LIST, NULL, type); + result = itd_append_right_to_binary(ICT_TYPES_LIST, NULL, type); - while (1) + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + while (count_input_buffer_remaining(ibuf) > 0) { - g_itanium_dcontext_push_state(context, &saved); + g_itanium_demangling_push_state(context, &saved); type = itd_type(context); + if (type == NULL) { - g_itanium_dcontext_pop_state(context, &saved); + g_itanium_demangling_pop_state(context, &saved); break; } - result = itd_append_right_to_binary(context, ICT_TYPES_LIST, result, type); + result = itd_append_right_to_binary(ICT_TYPES_LIST, result, type); } @@ -1957,7 +2449,7 @@ static itanium_component *itd_bare_function_type(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_class_enum_type(GItaniumDContext *context) +static itanium_component *itd_class_enum_type(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ @@ -1975,10 +2467,98 @@ static itanium_component *itd_class_enum_type(GItaniumDContext *context) } +/****************************************************************************** +* * +* 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_array_type(GItaniumDemangling *context) +{ + itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère dispo. */ + itanium_component *dim_expr; /* Dimension via expression */ + ssize_t dim_number; /* Dimension par un nombre */ + itanium_component *type; /* Type du tableau */ + + /** + * La règle traitée ici est la suivante : + * + * <array-type> ::= A <positive dimension number> _ <element type> + * ::= A [<dimension expression>] _ <element type> + * + */ + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!check_input_buffer_char(ibuf, 'A')) + return NULL; + + peek = peek_input_buffer_char(ibuf); + + if (peek == '[') + { + advance_input_buffer(ibuf, 1); + + dim_expr = itd_expression(context); + + if (dim_expr == NULL) + return NULL; + + if (!check_input_buffer_char(ibuf, ']')) + return NULL; + + if (!check_input_buffer_char(ibuf, '_')) + return NULL; + + type = itd_type(context); + + if (type == NULL) + { + itd_unref_comp(dim_expr); + return NULL; + } + + result = itd_make_array_with_dim_expr(dim_expr, type); + + if (result == NULL) + { + itd_unref_comp(dim_expr); + itd_unref_comp(type); + } + + } + + else + { + if (!itd_number(context, &dim_number)) + return NULL; + + if (!check_input_buffer_char(ibuf, '_')) + return NULL; + + type = itd_type(context); + + if (type == NULL) + return NULL; + result = itd_make_array_with_dim_number(dim_number, type); + if (result == NULL) + itd_unref_comp(type); + } + return result; + +} /****************************************************************************** @@ -1993,14 +2573,154 @@ static itanium_component *itd_class_enum_type(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_template_args(GItaniumDContext *context) +static itanium_component *itd_pointer_to_member_type(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + itanium_component *class; /* Classe d'appatenance */ + itanium_component *member; /* Membre représenté */ + + /** + * La règle traitée ici est la suivante : + * + * <pointer-to-member-type> ::= M <class type> <member type> + * + */ + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!check_input_buffer_char(ibuf, 'M')) + return NULL; + + class = itd_type(context); + + if (class != NULL) + { + member = itd_type(context); + + if (member != NULL) + result = itd_make_pointer_to_memeber_type(class, member); + + else + { + itd_unref_comp(class); + result = NULL; + } + + } + + 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_template_param(GItaniumDemangling *context) +{ + itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char cur; /* Caractère analysé */ + size_t id; /* Identifiant de substitution */ + + /** + * La règle traitée ici est la suivante : + * + * <template-param> ::= T_ # first template parameter + * ::= T <parameter-2 non-negative number> _ + * + */ + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!check_input_buffer_char(ibuf, 'T')) + return NULL; + + result = NULL; + + if (get_input_buffer_next_char_carefully(ibuf, &cur)) + { + if (cur == '_' || isdigit(cur) || isupper(cur)) + { + if (!itd_seq_id(context, cur, &id)) + return NULL; + + result = g_itanium_demangling_get_template_arg(context, id); + + } + + } + + 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_template_param(GItaniumDemangling *context) +{ + itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère dispo. */ + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + peek = peek_input_buffer_char(ibuf); + + if (peek == 'T') + result = itd_template_param(context); + + else + 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_template_args(GItaniumDemangling *context) +{ + itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ 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 : * @@ -2008,43 +2728,38 @@ static itanium_component *itd_template_args(GItaniumDContext *context) * */ - if (!g_itanium_dcontext_check_char(context, 'I')) + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!check_input_buffer_char(ibuf, '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); + result = itd_append_right_to_binary(ICT_TYPES_LIST, NULL, arg); while (1) { - g_itanium_dcontext_push_state(context, &saved); + g_itanium_demangling_push_state(context, &saved); arg = itd_template_arg(context); if (arg == NULL) { - g_itanium_dcontext_pop_state(context, &saved); + g_itanium_demangling_pop_state(context, &saved); break; } - result = itd_append_right_to_binary(context, ICT_TYPES_LIST, result, arg); + result = itd_append_right_to_binary(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')) + if (!check_input_buffer_char(ibuf, 'E')) { - //printf("=== TA : BAD E\n\n"); - - if (result != NULL) - itd_unref_comp(result); + itd_unref_comp(result); return NULL; } - //printf("=== TA >> %p\n\n", result); - - result = itd_make_unary(context, ICT_TEMPLATE_ARGS, result); + result = itd_make_unary(ICT_TEMPLATE_ARGS, result); return result; @@ -2063,10 +2778,11 @@ static itanium_component *itd_template_args(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_template_arg(GItaniumDContext *context) +static itanium_component *itd_template_arg(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ - itd_state saved; /* Position d'analyse courante */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ /** * La règle traitée ici est la suivante : @@ -2077,51 +2793,222 @@ static itanium_component *itd_template_arg(GItaniumDContext *context) * */ - g_itanium_dcontext_push_state(context, &saved); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; - result = itd_type(context); + peek = peek_input_buffer_char(ibuf); - if (result == NULL) + if (peek == 'X') + { + advance_input_buffer(ibuf, 1); + + result = itd_expression(context); + + if (result != NULL && !check_input_buffer_char(ibuf, 'E')) + { + itd_unref_comp(result); + result = NULL; + } + + } + + else if (peek == 'L') + result = itd_expr_primary(context); + + else + result = itd_type(context); + + if (result != NULL) + g_itanium_demangling_add_template_arg(context, 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_expression(GItaniumDemangling *context) +{ + itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ + char next_peek; /* Caractère après le prochain */ + itanium_component *targs; /* Composant 'template-args' */ + ItaniumOperatorType otype; /* Type d'opérateur */ + const void *odata; /* Données associées */ + const itanium_operator_info *simple; /* Données d'opérateur simple */ + int i; /* Boucle de parcours */ + itanium_component *list; /* Liste de sous-expressions */ + itanium_component *sub; /* Sous-expression chargée */ + + /** + * La règle traitée ici est la suivante : + * + * <expression> ::= <unary operator-name> <expression> + * ::= <binary operator-name> <expression> <expression> + * ::= <trinary operator-name> <expression> <expression> <expression> + * ::= st <type> + * ::= <template-param> + * ::= sr <type> <unqualified-name> # dependent name + * ::= sr <type> <unqualified-name> <template-args> # dependent template-id + * ::= <expr-primary> + * + */ + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + peek = peek_input_buffer_char(ibuf); + + if (peek == 'T') + result = itd_template_param(context); + + else if (peek == 'L') + result = itd_expr_primary(context); + + else if (islower(peek)) { - g_itanium_dcontext_pop_state(context, &saved); + next_peek = peek_input_buffer_next_char(ibuf); + + if (peek == 's' && next_peek == 't') + { + advance_input_buffer(ibuf, 2); + + result = itd_type(context); - if (g_itanium_dcontext_check_char(context, 'X')) + } + + else if (peek == 's' && next_peek == 'r') { - result = itd_expression(context); + advance_input_buffer(ibuf, 2); - if (result != NULL && !g_itanium_dcontext_check_char(context, 'E')) + result = itd_type(context); + + if (result != NULL) { itd_unref_comp(result); - result = NULL; + + result = itd_unqualified_name(context); + + if (result) + { + peek = peek_input_buffer_char(ibuf); + + if (peek == 'I') + { + targs = itd_template_args(context); + + if (targs != NULL) + result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs); + + else + { + itd_unref_comp(result); + result = NULL; + } + + } + + } + } } - } + else + { + result = itd_operator_name(context); - if (result == NULL) - { - g_itanium_dcontext_pop_state(context, &saved); - result = itd_expr_primary(context); - } + if (result != NULL) + { + odata = itd_get_operator_info(result, &otype); - return result; + switch (otype) + { + case IOT_SIMPLE: -} + simple = (const itanium_operator_info *)odata; + + list = NULL; + + for (i = 0; i < simple->args; i++) + { + sub = itd_expression(context); + + if (sub == NULL) + { + if (list != NULL) + { + itd_unref_comp(list); + list = NULL; + } + + break; + + } + + list = itd_append_right_to_binary(ICT_EXPR_LIST, list, sub); + } + if (list == NULL) + { + itd_unref_comp(result); + result = NULL; + } + else + result = itd_make_binary(ICT_OPERATED_EXPRESSION, result, list); + break; + case IOT_CAST: + sub = itd_expression(context); + if (sub == NULL) + { + itd_unref_comp(result); + result = NULL; + } + else + { + list = itd_append_right_to_binary(ICT_EXPR_LIST, NULL, sub); + result = itd_make_binary(ICT_OPERATED_EXPRESSION, result, list); + } + break; + default: + assert(false); + itd_unref_comp(result); + result = NULL; + break; + } + } + + } + + } + + else + result = NULL; + return result; +} /****************************************************************************** @@ -2137,9 +3024,10 @@ static itanium_component *itd_template_arg(GItaniumDContext *context) * * ******************************************************************************/ -static itanium_component *itd_value_to_string(GItaniumDContext *context, bool hex) +static itanium_component *itd_value_to_string(GItaniumDemangling *context, bool hex) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ const char *data; /* Données restantes */ itd_state saved; /* Position d'analyse initiale */ itd_state cur; /* Position d'analyse courante */ @@ -2155,23 +3043,25 @@ static itanium_component *itd_value_to_string(GItaniumDContext *context, bool he result = NULL; - data = g_itanium_dcontext_get_string(context, (size_t []) { 0 }); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + data = get_input_buffer_text_access(ibuf); - g_itanium_dcontext_push_state(context, &saved); + g_itanium_demangling_push_state(context, &saved); while (1) { - peek = g_itanium_dcontext_peek_char(context); + peek = peek_input_buffer_char(ibuf); switch (peek) { case '0' ... '9': - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); break; case 'a' ... 'f': if (hex) - g_itanium_dcontext_advance(context, 1); + advance_input_buffer(ibuf, 1); else goto exit_iits; break; @@ -2189,10 +3079,10 @@ static itanium_component *itd_value_to_string(GItaniumDContext *context, bool he exit_loop: - g_itanium_dcontext_push_state(context, &cur); + g_itanium_demangling_push_state(context, &cur); if ((cur.pos - saved.pos) > 0) - result = itd_make_name(context, data, cur.pos - saved.pos); + result = itd_make_name(data, cur.pos - saved.pos); exit_iits: @@ -2213,9 +3103,10 @@ static itanium_component *itd_value_to_string(GItaniumDContext *context, bool he * * ******************************************************************************/ -static itanium_component *itd_expr_primary(GItaniumDContext *context) +static itanium_component *itd_expr_primary(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ itd_state saved; /* Position d'analyse courante */ itanium_component *type; /* Type de valeur extrait */ itd_state saved_value; /* Position d'analyse courante */ @@ -2229,24 +3120,24 @@ static itanium_component *itd_expr_primary(GItaniumDContext *context) * */ - printf("PRIMARY :: no L\n"); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; - if (!g_itanium_dcontext_check_char(context, 'L')) + if (!check_input_buffer_char(ibuf, 'L')) return NULL; - g_itanium_dcontext_push_state(context, &saved); + g_itanium_demangling_push_state(context, &saved); type = itd_type(context); if (type != NULL) { - g_itanium_dcontext_push_state(context, &saved_value); + g_itanium_demangling_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')) + if (result != NULL && !check_input_buffer_char(ibuf, 'E')) { itd_unref_comp(result); result = NULL; @@ -2256,11 +3147,11 @@ static itanium_component *itd_expr_primary(GItaniumDContext *context) if (result == NULL) { - g_itanium_dcontext_pop_state(context, &saved_value); + g_itanium_demangling_pop_state(context, &saved_value); result = itd_value_to_string(context, true); - if (result != NULL && !g_itanium_dcontext_check_char(context, 'E')) + if (result != NULL && !check_input_buffer_char(ibuf, 'E')) { itd_unref_comp(result); result = NULL; @@ -2278,10 +3169,10 @@ static itanium_component *itd_expr_primary(GItaniumDContext *context) if (result == NULL) { - g_itanium_dcontext_pop_state(context, &saved); + g_itanium_demangling_pop_state(context, &saved); result = itd_mangled_name(context); - if (result != NULL && !g_itanium_dcontext_check_char(context, 'E')) + if (result != NULL && !check_input_buffer_char(ibuf, 'E')) { itd_unref_comp(result); result = NULL; @@ -2289,8 +3180,6 @@ static itanium_component *itd_expr_primary(GItaniumDContext *context) } - printf("PRIMARY :: %p\n", result); - return result; } @@ -2316,8 +3205,10 @@ static itanium_component *itd_expr_primary(GItaniumDContext *context) * * ******************************************************************************/ -static bool itd_seq_id(GItaniumDContext *context, char cur, size_t *id) +static bool itd_seq_id(GItaniumDemangling *context, char cur, size_t *id) { + input_buffer *ibuf; /* Tampon de texte manipulé */ + /** * La règle traitée ici est la suivante : * @@ -2332,6 +3223,8 @@ static bool itd_seq_id(GItaniumDContext *context, char cur, size_t *id) * (ie, cur == '_' || isdigit(cur) || isupper(cur)). */ + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + if (cur != '_') { do @@ -2343,7 +3236,8 @@ static bool itd_seq_id(GItaniumDContext *context, char cur, size_t *id) else return false; - cur = g_itanium_dcontext_next_char(context); + if (!get_input_buffer_next_char_carefully(ibuf, &cur)) + return false; } while (cur != '_'); @@ -2369,14 +3263,16 @@ static bool itd_seq_id(GItaniumDContext *context, char cur, size_t *id) * * ******************************************************************************/ -static itanium_component *itd_substitution(GItaniumDContext *context) +static itanium_component *itd_substitution(GItaniumDemangling *context) { itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ 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 */ + const itanium_std_subst_info *stdinfo; /* Raccourci de confort */ + GDataType *std; /* Espace de noms */ + GDataType *type; /* Type complet final */ /** * La règle traitée ici est la suivante : @@ -2393,52 +3289,56 @@ static itanium_component *itd_substitution(GItaniumDContext *context) * */ - peek = g_itanium_dcontext_peek_char(context); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; - if (!g_itanium_dcontext_check_char(context, 'S')) + if (!check_input_buffer_char(ibuf, 'S')) return NULL; - cur = g_itanium_dcontext_next_char(context); + result = NULL; + + if (!get_input_buffer_next_char_carefully(ibuf, &cur)) + goto exit_eof; 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); + result = g_itanium_demangling_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) + { + stdinfo = &itanium_standard_substitutions[i]; + + if (stdinfo->code == cur) { - /* TODO : constructeur... */ + std = g_class_enum_type_new(CET_NAMESPACE, strdup("std")); + + if (stdinfo->class == NULL) + type = std; - 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); + { + type = g_class_enum_type_new(CET_CLASS, strdup(stdinfo->class)); + g_data_type_set_namespace(type, std, "::"); + } + result = itd_make_type(type); itd_set_type(result, ICT_STD_SUBST); break; } + } + } + exit_eof: + return result; } diff --git a/src/mangling/itanium/abi.h b/plugins/itanium/abi.h index 469562f..d286b2f 100644 --- a/src/mangling/itanium/abi.h +++ b/plugins/itanium/abi.h @@ -21,8 +21,8 @@ */ -#ifndef _FORMAT_MANGLING_ITANIUM_ABI_H -#define _FORMAT_MANGLING_ITANIUM_ABI_H +#ifndef _PLUGINS_ITANIUM_ABI_H +#define _PLUGINS_ITANIUM_ABI_H #include "component.h" @@ -31,8 +31,8 @@ /* Extrait un composant dans un contexte Itanium. */ -itanium_component *itd_mangled_name(GItaniumDContext *); +itanium_component *itd_mangled_name(GItaniumDemangling *); -#endif /* _FORMAT_MANGLING_ITANIUM_ABI_H */ +#endif /* _PLUGINS_ITANIUM_ABI_H */ diff --git a/plugins/itanium/component-int.h b/plugins/itanium/component-int.h new file mode 100644 index 0000000..fb8c423 --- /dev/null +++ b/plugins/itanium/component-int.h @@ -0,0 +1,137 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * component-int.h - prototypes internes pour la description des composants Itanium + * + * Copyright (C) 2013-2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ITANIUM_COMPONENT_INT_H +#define _PLUGINS_ITANIUM_COMPONENT_INT_H + + +#include "component.h" + + + +/* Composant extrait de l'encodage */ +struct _itanium_component +{ + ItaniumComponentType type; /* Type de composant */ + + 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 */ + itanium_component *trans; /* Type transtypé */ + + }; + + } operator; + + /* ICT_NON_VIRTUAL_OFFSET */ + /* ICT_VIRTUAL_OFFSET */ + ssize_t offset; /* Décalage de fonction */ + + /* ICT_STD_SUBST */ + /* ICT_TYPE */ + GDataType *dtype; /* Type instancié */ + + /* ICT_QUALIFIED_TYPE */ + struct + { + itanium_component *sub; /* Sous-élément */ + TypeQualifier qualifier; /* Propriétés supplémentaires */ + + } qualified; + + /* ICT_FUNCTION_TYPE */ + struct + { + bool extern_c; /* Nature de la fonction */ + itanium_component *args; /* Liste des arguments */ + + } function; + + /* ICT_ARRAY */ + struct + { + bool numbered_dim; /* Dimension numérique */ + union + { + ssize_t dim_number; /* Taille du tableau */ + itanium_component *dim_expr;/* La même, en expression */ + }; + + itanium_component *atype; /* Type du tableau */ + + } array; + + /* ICT_POINTER_TO_MEMBER */ + struct + { + itanium_component *class; /* Classe d'appatenance */ + itanium_component *member; /* Membre représenté */ + + } pmember; + + /* 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 /* _PLUGINS_ITANIUM_COMPONENT_INT_H */ diff --git a/plugins/itanium/component.c b/plugins/itanium/component.c new file mode 100644 index 0000000..6e580f6 --- /dev/null +++ b/plugins/itanium/component.c @@ -0,0 +1,1842 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * component.c - représentation des composants extraits de l'ABI C++ Itanium + * + * Copyright (C) 2013-2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "component.h" + + +#include <assert.h> +#include <malloc.h> +#include <string.h> + + +#include <analysis/types/array.h> +#include <analysis/types/cse.h> +#include <analysis/types/expr.h> +#include <analysis/types/override.h> +#include <analysis/types/proto.h> +#include <analysis/types/template.h> +#include <common/extstr.h> +#include <common/fnv1a.h> + + +#include "component-int.h" + + + + +/* Procédure à appliquer sur un composant visité */ +typedef void (* visit_comp_fc) (itanium_component *); + + +#define reset_comp_hash(c) c->hash = 0 + + +/* Crée un composant de contexte Itanium complètement vierge. */ +static itanium_component *itd_alloc(void); + +/* Efface de la mémoire un composant de context Itanium. */ +static void itd_free(itanium_component *); + +/* Visite les composants en présence. */ +static void visit_comp(itanium_component *, visit_comp_fc); + +/* Traduit les composants de contexte Itanium en décalage. */ +static bool itd_translate_component_to_offset(const itanium_component *, call_offset_t *); + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée un composant de contexte Itanium complètement vierge. * +* * +* Retour : Composant créé ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_alloc(void) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = calloc(1, sizeof(itanium_component)); + + result->refcount = 1; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant à supprimer. * +* * +* Description : Efface de la mémoire un composant de context Itanium. * +* * +* Retour : Composant créé ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void itd_free(itanium_component *comp) +{ + free(comp); + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant à traiter. * +* visitor = fonction à appliquer sur les composants présents. * +* * +* Description : Visite les composants en présence. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void visit_comp(itanium_component *comp, visit_comp_fc visitor) +{ + switch (comp->type) + { + case ICT_NAME: + break; + + case ICT_STD_UNSCOPED_NAME: + visit_comp(comp->unary, visitor); + break; + + case ICT_NESTED_NAME: + if (comp->binary.left != NULL) + visit_comp(comp->binary.left, visitor); + visit_comp(comp->binary.right, visitor); + break; + + case ICT_TEMPLATE_NAME_ARGS: + visit_comp(comp->binary.left, visitor); + visit_comp(comp->binary.right, visitor); + break; + + case ICT_PREFIX_BINARY: + visit_comp(comp->binary.left, visitor); + visit_comp(comp->binary.right, visitor); + break; + + case ICT_TPREFIX_BINARY: + if (comp->binary.left != NULL) + visit_comp(comp->binary.left, visitor); + visit_comp(comp->binary.right, visitor); + break; + + case ICT_OPERATOR_NAME: + if (comp->operator.otype == IOT_CAST) + visit_comp(comp->operator.trans, visitor); + break; + + case ICT_SPECIAL_NAME_VTABLE: + case ICT_SPECIAL_NAME_VSTRUCT: + visit_comp(comp->unary, visitor); + break; + + case ICT_NON_VIRTUAL_OFFSET: + case ICT_VIRTUAL_OFFSET: + break; + + case ICT_DOUBLE_OFFSET: + visit_comp(comp->binary.left, visitor); + visit_comp(comp->binary.right, visitor); + break; + + + case ICT_FUNCTION_THUNK: + visit_comp(comp->binary.left, visitor); + visit_comp(comp->binary.right, visitor); + break; + + case ICT_FUNCTION_COVARIANT_THUNK: + visit_comp(comp->ternary.first, visitor); + visit_comp(comp->ternary.second, visitor); + visit_comp(comp->ternary.third, visitor); + break; + + case ICT_CONSTRUCTOR: + case ICT_DESSTRUCTOR: + break; + + case ICT_TYPE: + break; + + case ICT_QUALIFIED_TYPE: + visit_comp(comp->qualified.sub, visitor); + break; + + case ICT_POINTER_TO: + visit_comp(comp->unary, visitor); + break; + + case ICT_REFERENCE_TO: + visit_comp(comp->unary, visitor); + break; + + case ICT_RVALUE_REFERENCE_TO: + visit_comp(comp->unary, visitor); + break; + + case ICT_COMPLEX_PAIR: + visit_comp(comp->unary, visitor); + break; + + case ICT_IMAGINARY: + visit_comp(comp->unary, visitor); + break; + + case ICT_FUNCTION_TYPE: + visit_comp(comp->function.args, visitor); + break; + + case ICT_FUNCTION_ENCODING: + visit_comp(comp->binary.left, visitor); + visit_comp(comp->binary.right, visitor); + break; + + case ICT_ARRAY: + if (!comp->array.numbered_dim) + visit_comp(comp->array.dim_expr, visitor); + visit_comp(comp->array.atype, visitor); + break; + + case ICT_POINTER_TO_MEMBER: + visit_comp(comp->pmember.class, visitor); + visit_comp(comp->pmember.member, visitor); + break; + + case ICT_TEMPLATE_ARGS: + visit_comp(comp->unary, visitor); + break; + + case ICT_TYPES_LIST: + + visit_comp(comp->binary.left, visitor); + + if (comp->binary.right != NULL) + visit_comp(comp->binary.right, visitor); + + break; + + case ICT_EXPR_LIST: + + visit_comp(comp->binary.left, visitor); + + if (comp->binary.right != NULL) + visit_comp(comp->binary.right, visitor); + + break; + + case ICT_OPERATED_EXPRESSION: + visit_comp(comp->binary.left, visitor); + visit_comp(comp->binary.right, visitor); + break; + + case ICT_STD_SUBST: + break; + + case ICT_COUNT: + break; + + } + + visitor(comp); + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant à mettre à jour. * +* * +* Description : Incrémente le nombre d'utilisation du composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void itd_ref_comp(itanium_component *comp) +{ + void visit_for_ref(itanium_component *comp) + { + comp->refcount++; + + } + + visit_comp(comp, visit_for_ref); + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant à mettre à jour. * +* * +* Description : Décrémente le nombre d'utilisation du composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void itd_unref_comp(itanium_component *comp) +{ + void visit_for_unref(itanium_component *comp) + { + if (--comp->refcount == 0) + { + if (comp->type == ICT_TYPE || comp->type == ICT_STD_SUBST) + g_object_unref(G_OBJECT(comp->dtype)); + + itd_free(comp); + + } + + } + + visit_comp(comp, visit_for_unref); + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant à manipuler. * +* * +* Description : Détermine ou fournit l'empreinte d'un composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +fnv64_t itd_hash_comp(itanium_component *comp) +{ + char *desc; /* Description du composant */ + + if (comp->hash == 0) + { + desc = itd_translate_component(comp, NULL); + comp->hash = fnv_64a_hash(desc); + free(desc); + } + + return comp->hash; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type à définir pour le composant. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_with_type(ItaniumComponentType type) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = type; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : str = chaîne de caractères à conserver. * +* len = taille de l'identifiant à retrouver. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_name(const char *str, size_t len) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = ICT_NAME; + result->s_name.str = str; + result->s_name.len = len; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = information de base sur l'opérateur manipulé. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_operator(const itanium_operator_info *info) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = ICT_OPERATOR_NAME; + result->operator.otype = IOT_SIMPLE; + result->operator.info = *info; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : info = information de base sur l'opérateur manipulé. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_cast_operator(itanium_component *type) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = ICT_OPERATOR_NAME; + result->operator.otype = IOT_CAST; + result->operator.trans = type; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant Itanium décodé à consulter. * +* type = type d'opérateur représenté. * +* * +* Description : Donne des indications quant à un opérateur Itanium. * +* * +* Retour : Informations à interpréter selon le type transmis. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const void *itd_get_operator_info(const itanium_component *comp, ItaniumOperatorType *type) +{ + const void *result; /* Données à retourner */ + + assert(comp->type == ICT_OPERATOR_NAME); + + *type = comp->operator.otype; + + switch (*type) + { + case IOT_SIMPLE: + result = &comp->operator.info; + break; + + case IOT_CAST: + result = comp->operator.trans; + break; + + default: + assert(false); + result = NULL; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type exacte de décalage. * +* offset = décalage extrait de l'encodage. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_offset(ItaniumComponentType type, ssize_t offset) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = type; + result->offset = offset; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : dtype = instance de type en place à conserver. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_type(GDataType *dtype) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = ICT_TYPE; + result->dtype = dtype; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : sub = composant de type en place à référencer. * +* qualifier = propriétés supplémentaires pour le type. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_qualified_type(itanium_component *sub, TypeQualifier qualifier) +{ + itanium_component *result; /* Composant à renvoyer */ + + if (qualifier == TQF_NONE) + result = sub; + + else + { + result = itd_alloc(); + + result->type = ICT_QUALIFIED_TYPE; + result->qualified.sub = sub; + result->qualified.qualifier = qualifier; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : sub = composant de type en place à référencer. * +* qualifier = propriétés supplémentaires pour le type. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_function_type(bool extern_c, itanium_component *args) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = ICT_FUNCTION_TYPE; + result->function.extern_c = extern_c; + result->function.args = args; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : number = dimension du tableau. * +* type = type des membres du même tableau. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_array_with_dim_number(ssize_t number, itanium_component *type) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = ICT_ARRAY; + result->array.numbered_dim = true; + result->array.dim_number = number; + result->array.atype = type; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : expr = dimension du tableau. * +* type = type des membres du même tableau. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_array_with_dim_expr(itanium_component *expr, itanium_component *type) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = ICT_ARRAY; + result->array.numbered_dim = false; + result->array.dim_expr = expr; + result->array.atype = type; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = classe d'appatenance. * +* member = membre représenté. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_pointer_to_memeber_type(itanium_component *class, itanium_component *member) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = ICT_POINTER_TO_MEMBER; + result->pmember.class = class; + result->pmember.member = member; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type du composant à mettre en place. * +* unary = sous-composant à associer. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_unary(ItaniumComponentType type, itanium_component *unary) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = type; + result->unary = unary; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type du composant à mettre en place. * +* left = premier composant à associer. * +* right = second composant à associer. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_binary(ItaniumComponentType type, itanium_component *left, itanium_component *right) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = type; + result->binary.left = left; + result->binary.right = right; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type du composant à mettre en place. * +* left = second composant à associer. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_append_right_to_binary(ItaniumComponentType type, itanium_component *parent, itanium_component *left) +{ + itanium_component *result; /* Composant à renvoyer */ + itanium_component *iter; /* Boucle de parcours */ + + result = itd_alloc(); + + result->type = type; + result->binary.left = left; + result->binary.right = NULL; + + if (parent != NULL) + { + for (iter = parent; iter->binary.right != NULL; iter = iter->binary.right) + reset_comp_hash(iter); + iter->binary.right = result; + } + + return (parent != NULL ? parent : result); + +} + + +/****************************************************************************** +* * +* Paramètres : type = type du composant à mettre en place. * +* c0 = premier composant à associer. * +* c1 = second composant à associer. * +* c2 = troisième composant à associer. * +* * +* Description : Construit un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_make_ternary(ItaniumComponentType type, itanium_component *c0, itanium_component *c1, itanium_component *c2) +{ + itanium_component *result; /* Composant à renvoyer */ + + result = itd_alloc(); + + result->type = type; + result->ternary.first = c0; + result->ternary.second = c1; + result->ternary.third = c2; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant à mettre à jour. * +* type = type à redéfinir pour le composant. * +* * +* Description : Modifie légèrement le type d'un composant donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void itd_set_type(itanium_component *comp, ItaniumComponentType type) +{ + comp->type = type; + + reset_comp_hash(comp); + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant à consulter. * +* * +* Description : Fournit le type d'un composant issu d'un contexte Itanium. * +* * +* Retour : Type enregistré. * +* * +* Remarques : - * +* * +******************************************************************************/ + +ItaniumComponentType itd_get_component_type(const itanium_component *comp) +{ + return comp->type; + +} + + +/****************************************************************************** +* * +* Paramètres : comp = second composant à associer. * +* base = éventuelle base à compléter ou NULL si aucune. * +* * +* Description : Traduit les composants de contexte Itanium. * +* * +* Retour : Traduction en format humainement lisible effectuée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *itd_translate_component(const itanium_component *comp, char *base) +{ + char *result; /* Chaîne à retourner */ + char *name; /* Désignation à copier */ + const itanium_component *sub; /* Sous-partie de composant */ + ItaniumOperatorType otype; /* Type d'opérateur */ + const void *odata; /* Données associées */ + const itanium_operator_info *simple; /* Données d'opérateur simple */ + char *tmp; /* Transcription temporaire */ + + switch (comp->type) + { + case ICT_NAME: + result = strnadd(base, comp->s_name.str, comp->s_name.len); + break; + + case ICT_STD_UNSCOPED_NAME: + result = stradd(base, "std::"); + result = itd_translate_component(comp->unary, result); + break; + + case ICT_NESTED_NAME: + + if (comp->binary.right->type == ICT_TEMPLATE_ARGS) + { + result = itd_translate_component(comp->binary.left, base); + result = itd_translate_component(comp->binary.right, result); + } + + else + { + if (comp->binary.left != NULL) + { + result = itd_translate_component(comp->binary.left, base); + result = stradd(result, "::"); + } + else + result = base; + + result = itd_translate_component(comp->binary.right, result); + + } + + break; + + case ICT_TEMPLATE_NAME_ARGS: + result = itd_translate_component(comp->binary.left, base); + result = itd_translate_component(comp->binary.right, result); + break; + + case ICT_PREFIX_BINARY: + result = itd_translate_component(comp->binary.left, base); + if (comp->binary.right->type != ICT_TEMPLATE_ARGS) + result = stradd(result, "::"); + result = itd_translate_component(comp->binary.right, result); + break; + + case ICT_TPREFIX_BINARY: + if (comp->binary.left != NULL) + { + result = itd_translate_component(comp->binary.left, base); + if (comp->binary.right->type != ICT_TEMPLATE_ARGS) + result = stradd(result, "::"); + } + else + result = base; + result = itd_translate_component(comp->binary.right, result); + break; + + case ICT_OPERATOR_NAME: + switch (comp->operator.otype) + { + case IOT_SIMPLE: + result = stradd(base, "operator"); + result = stradd(result, comp->operator.info.name); + break; + case IOT_CAST: + result = stradd(base, "("); + sub = (const itanium_component *)odata; + result = itd_translate_component(comp->operator.trans, result); + result = stradd(result, ")"); + break; + default: + result = NULL; + break; + } + break; + + case ICT_SPECIAL_NAME_VTABLE: + result = itd_translate_component(comp->unary, base); + result = stradd(result, "::vtable"); + break; + + case ICT_SPECIAL_NAME_VSTRUCT: + result = itd_translate_component(comp->unary, base); + result = stradd(result, "::vstruct"); + break; + + case ICT_NON_VIRTUAL_OFFSET: + case ICT_VIRTUAL_OFFSET: + asprintf(&tmp, "%zd", comp->offset); + result = stradd(base, tmp); + free(tmp); + break; + + case ICT_DOUBLE_OFFSET: + result = itd_translate_component(comp->binary.left, base); + result = stradd(result, "_"); + result = itd_translate_component(comp->binary.right, result); + break; + + case ICT_FUNCTION_THUNK: + result = itd_translate_component(comp->binary.left, base); + result = stradd(result, "_"); + result = itd_translate_component(comp->binary.right, result); + break; + + case ICT_FUNCTION_COVARIANT_THUNK: + result = itd_translate_component(comp->ternary.first, base); + result = stradd(result, "_"); + result = itd_translate_component(comp->ternary.second, result); + result = stradd(result, "_"); + result = itd_translate_component(comp->ternary.third, result); + break; + + case ICT_CONSTRUCTOR: + result = stradd(base, "<ctor>"); + break; + + case ICT_DESSTRUCTOR: + result = stradd(base, "<dtor>"); + break; + + case ICT_TYPE: + name = g_data_type_to_string(comp->dtype, true); + result = stradd(base, name); + free(name); + break; + + case ICT_QUALIFIED_TYPE: + + switch (comp->qualified.qualifier) + { + case TQF_RESTRICT: + result = stradd(base, "restrict "); + break; + case TQF_VOLATILE: + result = stradd(base, "volatile "); + break; + case TQF_CONST: + result = stradd(base, "const "); + break; + default: + assert(false); + break; + } + + result = itd_translate_component(comp->qualified.sub, result); + + break; + + case ICT_POINTER_TO: + result = itd_translate_component(comp->unary, base); + result = stradd(result, " *"); + break; + + case ICT_REFERENCE_TO: + result = itd_translate_component(comp->unary, base); + result = stradd(result, " &"); + break; + + case ICT_RVALUE_REFERENCE_TO: + result = itd_translate_component(comp->unary, base); + result = stradd(result, " &"); + break; + + case ICT_COMPLEX_PAIR: + result = stradd(base, "<?>"); + result = itd_translate_component(comp->unary, result); + break; + + case ICT_IMAGINARY: + result = stradd(base, "<?>"); + result = itd_translate_component(comp->unary, result); + break; + + case ICT_FUNCTION_TYPE: + result = stradd(base, "(*) ("); + result = itd_translate_component(comp->function.args, result); + result = stradd(result, ")"); + break; + + case ICT_FUNCTION_ENCODING: + + result = stradd(base, "???"); + + result = stradd(result, " "); + + result = itd_translate_component(comp->binary.left, result); + + result = stradd(result, "("); + + result = itd_translate_component(comp->binary.right, result); + + result = stradd(result, ")"); + + break; + + case ICT_ARRAY: + + result = itd_translate_component(comp->array.atype, base); + + result = stradd(result, "["); + + if (comp->array.numbered_dim) + { + asprintf(&tmp, "%zd", comp->array.dim_number); + result = stradd(result, tmp); + free(tmp); + } + + else + result = itd_translate_component(comp->array.dim_expr, result); + + result = stradd(result, "]"); + + break; + + case ICT_POINTER_TO_MEMBER: + result = itd_translate_component(comp->pmember.class, base); + result = stradd(result, "::"); + result = itd_translate_component(comp->pmember.member, result); + break; + + case ICT_TEMPLATE_ARGS: + result = stradd(base, "<"); + result = itd_translate_component(comp->unary, result); + result = stradd(result, ">"); + break; + + case ICT_TYPES_LIST: + + result = itd_translate_component(comp->binary.left, base); + + if (comp->binary.right != NULL) + { + result = stradd(result, ", "); + result = itd_translate_component(comp->binary.right, result); + } + + break; + + case ICT_EXPR_LIST: + + /** + * A priori traité en amont. + */ + + result = itd_translate_component(comp->binary.left, base); + + if (comp->binary.right != NULL) + { + result = stradd(result, ", "); + result = itd_translate_component(comp->binary.right, result); + } + + break; + + case ICT_OPERATED_EXPRESSION: + + odata = itd_get_operator_info(comp->binary.left, &otype); + + sub = comp->binary.right; + assert(sub->type == ICT_EXPR_LIST); + + switch (otype) + { + case IOT_SIMPLE: + + simple = (const itanium_operator_info *)odata; + + switch (simple->args) + { + case 1: + result = stradd(base, simple->name); + result = itd_translate_component(sub->binary.left, result); + assert(sub->binary.right == NULL); + break; + + case 2: + + result = itd_translate_component(sub->binary.left, base); + + result = stradd(result, simple->name); + + sub = sub->binary.right; + assert(sub->type == ICT_EXPR_LIST); + result = itd_translate_component(sub->binary.left, result); + assert(sub->binary.right == NULL); + break; + + case 3: + + result = itd_translate_component(sub->binary.left, base); + + result = stradd(result, simple->name); + + sub = sub->binary.right; + assert(sub->type == ICT_EXPR_LIST); + result = itd_translate_component(sub->binary.left, result); + + result = stradd(result, ":"); + + sub = sub->binary.right; + assert(sub->type == ICT_EXPR_LIST); + result = itd_translate_component(sub->binary.left, result); + assert(sub->binary.right == NULL); + + break; + + } + + break; + + case IOT_CAST: + result = stradd(base, "("); + sub = (const itanium_component *)odata; + result = itd_translate_component(sub, result); + result = stradd(result, ")"); + break; + + default: + result = NULL; + break; + + } + + break; + + case ICT_STD_SUBST: + name = g_data_type_to_string(comp->dtype, true); + result = stradd(base, name); + free(name); + break; + + case ICT_COUNT: + result = base; + break; + + } + + + + return result; + + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant Itanium à traduire en décalage. * +* off = réceptacle pour les informations traduites. * +* * +* Description : Traduit les composants de contexte Itanium en décalage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool itd_translate_component_to_offset(const itanium_component *comp, call_offset_t *off) +{ + bool result; /* Bilan à retourner */ + + if (comp->type == ICT_DOUBLE_OFFSET) + { + result = comp->binary.left->type == ICT_NON_VIRTUAL_OFFSET + && comp->binary.right->type == ICT_VIRTUAL_OFFSET; + + assert(result); + + if (result) + { + off->values[0] = comp->binary.left->offset; + off->values[1] = comp->binary.right->offset; + off->virtual = true; + } + + } + + else if (comp->type == ICT_NON_VIRTUAL_OFFSET) + { + result = true; + + off->values[0] = comp->offset; + off->virtual = false; + + } + + else + result = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant Itanium à traduire en type. * +* * +* Description : Traduit les composants de contexte Itanium en type. * +* * +* Retour : Traduction en type décodé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDataType *itd_translate_component_to_type(const itanium_component *comp) +{ + GDataType *result; /* Type à retourner */ + char *name; /* Attribution finale */ + GDataType *ns; /* Espace de noms d'un type */ + call_offset_t off0; /* Décalage #0 */ + call_offset_t off1; /* Décalage #1 */ + itanium_component *iter; /* Boucle de parcours */ + GDataType *arg; /* Argument de prototype */ + GDataType *members; /* Type de membres de tableau */ + GDataType *param; /* Paramètre de gabarit */ + + /* Pour GCC !? */ + result = NULL; + + switch (comp->type) + { + case ICT_NAME: + name = itd_translate_component(comp, NULL); + result = g_class_enum_type_new(CET_STRUCT, name); + break; + + case ICT_STD_UNSCOPED_NAME: + result = itd_translate_component_to_type(comp->unary); + if (result != NULL) + { + ns = g_class_enum_type_new(CET_NAMESPACE, strdup("std")); + g_data_type_set_namespace(result, ns, "::"); + } + break; + + case ICT_NESTED_NAME: + + if (comp->binary.right->type == ICT_TEMPLATE_ARGS) + { + name = itd_translate_component(comp->binary.left, NULL); + name = itd_translate_component(comp->binary.right, name); + + result = g_class_enum_type_new(CET_CLASS, name); + + } + + else + { + if (comp->binary.left != NULL) + { + ns = itd_translate_component_to_type(comp->binary.left); + if (ns == NULL) + { + result = NULL; + break; + } + } + else + ns = NULL; + + result = itd_translate_component_to_type(comp->binary.right); + + if (result != NULL && ns != NULL) + g_data_type_set_namespace(result, ns, "::"); + + } + + break; + + case ICT_TEMPLATE_NAME_ARGS: + + result = itd_translate_component_to_type(comp->binary.right); + + if (result != NULL) + { + name = itd_translate_component(comp->binary.left, NULL); + g_template_type_set_name(G_TEMPLATE_TYPE(result), name); + } + + break; + + case ICT_PREFIX_BINARY: + + if (comp->binary.right->type == ICT_TEMPLATE_ARGS) + { + name = itd_translate_component(comp->binary.left, NULL); + name = itd_translate_component(comp->binary.right, name); + + result = g_class_enum_type_new(CET_CLASS, name); + + } + + else + { + ns = itd_translate_component_to_type(comp->binary.left); + if (ns == NULL) + { + result = NULL; + break; + } + + result = itd_translate_component_to_type(comp->binary.right); + + if (result != NULL) + g_data_type_set_namespace(result, ns, "::"); + + } + + break; + + case ICT_TPREFIX_BINARY: + + if (comp->binary.right->type == ICT_TEMPLATE_ARGS) + { + name = itd_translate_component(comp->binary.left, NULL); + name = itd_translate_component(comp->binary.right, name); + + result = g_class_enum_type_new(CET_CLASS, name); + + } + + else + { + if (comp->binary.left != NULL) + { + ns = itd_translate_component_to_type(comp->binary.left); + if (ns == NULL) + { + result = NULL; + break; + } + + } + else + ns = NULL; + + result = itd_translate_component_to_type(comp->binary.right); + + if (result != NULL) + { + if (ns != NULL) + g_data_type_set_namespace(result, ns, "::"); + } + else + { + if (ns != NULL) + g_object_unref(G_OBJECT(ns)); + } + + } + + break; + + case ICT_OPERATOR_NAME: + result = NULL; + break; + + case ICT_SPECIAL_NAME_VTABLE: + + ns = itd_translate_component_to_type(comp->unary); + + if (ns == NULL) + result = NULL; + + else + { + result = g_class_enum_type_new(CET_VIRTUAL_TABLE, NULL); + g_data_type_set_namespace(result, ns, "::"); + } + + break; + + case ICT_SPECIAL_NAME_VSTRUCT: + + ns = itd_translate_component_to_type(comp->unary); + + if (ns == NULL) + result = NULL; + + else + { + result = g_class_enum_type_new(CET_VIRTUAL_STRUCT, NULL); + g_data_type_set_namespace(result, ns, "::"); + } + + break; + + case ICT_NON_VIRTUAL_OFFSET: + case ICT_VIRTUAL_OFFSET: + case ICT_DOUBLE_OFFSET: + result = NULL; + break; + + case ICT_FUNCTION_THUNK: + + if (!itd_translate_component_to_offset(comp->binary.right, &off0)) + { + result = NULL; + break; + } + + result = itd_translate_component_to_type(comp->binary.left); + + if (result != NULL) + result = g_override_type_new(result, &off0); + + break; + + case ICT_FUNCTION_COVARIANT_THUNK: + + if (!itd_translate_component_to_offset(comp->ternary.second, &off0)) + { + result = NULL; + break; + } + + if (!itd_translate_component_to_offset(comp->ternary.third, &off1)) + { + result = NULL; + break; + } + + result = itd_translate_component_to_type(comp->ternary.first); + + if (result != NULL) + result = g_override_type_new_with_covariant(result, &off0, &off1); + + break; + + case ICT_CONSTRUCTOR: + case ICT_DESSTRUCTOR: + result = NULL; + break; + + case ICT_TYPE: + result = g_data_type_dup(comp->dtype); + break; + + case ICT_QUALIFIED_TYPE: + result = itd_translate_component_to_type(comp->qualified.sub); + if (result != NULL) + g_data_type_add_qualifier(result, comp->qualified.qualifier); + break; + + case ICT_POINTER_TO: + result = itd_translate_component_to_type(comp->unary); + if (result != NULL && !G_IS_PROTO_TYPE(result)) + result = g_encapsulated_type_new(ECT_POINTER, result); + break; + + case ICT_REFERENCE_TO: + result = itd_translate_component_to_type(comp->unary); + if (result != NULL) + result = g_encapsulated_type_new(ECT_REFERENCE, result); + break; + + case ICT_RVALUE_REFERENCE_TO: + result = itd_translate_component_to_type(comp->unary); + if (result != NULL) + result = g_encapsulated_type_new(ECT_RVALUE_REF, result); + break; + + case ICT_COMPLEX_PAIR: + result = itd_translate_component_to_type(comp->unary); + if (result != NULL) + result = g_encapsulated_type_new(ECT_COMPLEX, result); + break; + + case ICT_IMAGINARY: + result = itd_translate_component_to_type(comp->unary); + if (result != NULL) + result = g_encapsulated_type_new(ECT_IMAGINARY, result); + break; + + case ICT_FUNCTION_TYPE: + + result = g_proto_type_new(); + + assert(comp->function.args->type == ICT_TYPES_LIST); + + for (iter = comp->function.args; iter != NULL && result != NULL; iter = iter->binary.right) + { + assert(iter->type == ICT_TYPES_LIST); + + arg = itd_translate_component_to_type(iter->binary.left); + + if (arg == NULL) + { + g_object_unref(G_OBJECT(result)); + result = NULL; + } + + else + { + if (iter == comp->function.args) + g_proto_type_set_return_type(G_PROTO_TYPE(result), arg); + + else + g_proto_type_add_arg(G_PROTO_TYPE(result), arg); + } + + } + + break; + + case ICT_FUNCTION_ENCODING: + result = NULL; + break; + + case ICT_ARRAY: + + members = itd_translate_component_to_type(comp->array.atype); + + if (members == NULL) + result = NULL; + + else + { + result = g_array_type_new(members); + + if (comp->array.numbered_dim) + g_array_type_set_dimension_number(G_ARRAY_TYPE(result), comp->array.dim_number); + + else + g_array_type_set_dimension_expression(G_ARRAY_TYPE(result), + itd_translate_component(comp, NULL)); + + } + + break; + + case ICT_POINTER_TO_MEMBER: + + ns = itd_translate_component_to_type(comp->pmember.class); + + if (ns == NULL) + result = NULL; + + else + { + result = itd_translate_component_to_type(comp->pmember.member); + + if (result == NULL) + g_object_unref(G_OBJECT(ns)); + + else + g_data_type_set_namespace(result, ns, "::"); + + } + + break; + + case ICT_TEMPLATE_ARGS: + + assert(comp->unary->type == ICT_TYPES_LIST); + + result = g_template_type_new(); + + for (iter = comp->unary; iter != NULL && result != NULL; iter = iter->binary.right) + { + assert(iter->type == ICT_TYPES_LIST); + + param = itd_translate_component_to_type(iter->binary.left); + + if (param == NULL) + { + g_object_unref(G_OBJECT(result)); + result = NULL; + } + else + g_template_type_add_param(G_TEMPLATE_TYPE(result), param); + + } + + break; + + case ICT_TYPES_LIST: + + /** + * Les listes doient être rassemblées par l'appelant ! + */ + + assert(false); + result = NULL; + break; + + case ICT_EXPR_LIST: + + /** + * Les listes doient être rassemblées par l'appelant ! + */ + + assert(false); + result = NULL; + break; + + case ICT_OPERATED_EXPRESSION: + result = g_expr_type_new(itd_translate_component(comp, NULL)); + break; + + case ICT_STD_SUBST: + result = g_data_type_dup(comp->dtype); + break; + + case ICT_COUNT: + assert(false); + result = NULL; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : comp = composant Itanium à traduire en routine. * +* * +* Description : Traduit les composants de contexte Itanium en routine. * +* * +* Retour : Traduction en routine décodée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinRoutine *itd_translate_component_to_routine(const itanium_component *comp) +{ + GBinRoutine *result; /* Routine à retourner */ + bool has_ret; /* Type de retour présent ? */ + itanium_component *name; /* Désignation de la routine */ + char *desc; /* Description humaine */ + GDataType *ns; /* Espace de noms de la routine*/ + itanium_component *args; /* Liste de ses arguments */ + itanium_component *iter; /* Boucle de parcours */ + GDataType *type; /* Type d'un argument */ + GBinVariable *arg; /* Argument à ajouter */ + + if (comp->type != ICT_FUNCTION_ENCODING) + goto bad_encoding; + + result = g_binary_routine_new(); + + /* Nom de la routine */ + + name = comp->binary.left; + + /** + * A la fin de § 5.1.3 ("Operator Encodings") est précisé : + * + * If the conversion operator is a member template, the result type will + * appear before the template parameters. + * + * On note donc cette particularité. + */ + + has_ret = (name->type == ICT_TEMPLATE_NAME_ARGS); + + switch (name->type) + { + case ICT_NAME: + g_binary_routine_set_name(result, itd_translate_component(name, NULL)); + break; + + case ICT_NESTED_NAME: + case ICT_TEMPLATE_NAME_ARGS: + + type = itd_translate_component_to_type(name); + if (type == NULL) goto unsupported_encoding; + + ns = g_data_type_get_namespace(type); + + g_data_type_set_namespace(type, NULL, NULL); + + desc = g_data_type_to_string(type, true); + + g_object_unref(G_OBJECT(type)); + + g_binary_routine_set_name(result, desc); + + g_binary_routine_set_namespace(result, ns, "::"); + + break; + + case ICT_OPERATOR_NAME: + g_binary_routine_set_name(result, itd_translate_component(name, NULL)); + break; + + default: + goto unsupported_encoding; + break; + + } + + /* Liste d'arguments */ + + args = comp->binary.right; + + if (args->type != ICT_TYPES_LIST) + goto unsupported_encoding; + + for (iter = args; iter != NULL; iter = iter->binary.right) + { + type = itd_translate_component_to_type(iter->binary.left); + + if (type == NULL) + goto unsupported_encoding; + + if (iter == args && has_ret) + g_binary_routine_set_return_type(result, type); + + else + { + arg = g_binary_variable_new(type); + g_binary_routine_add_arg(result, arg); + } + + } + + return result; + + unsupported_encoding: + + g_object_unref(G_OBJECT(result)); + + bad_encoding: + + return NULL; + +} diff --git a/src/mangling/itanium/component.h b/plugins/itanium/component.h index 4d50d1f..f921ff9 100644 --- a/src/mangling/itanium/component.h +++ b/plugins/itanium/component.h @@ -21,8 +21,8 @@ */ -#ifndef _FORMAT_MANGLING_ITANIUM_COMPONENT_H -#define _FORMAT_MANGLING_ITANIUM_COMPONENT_H +#ifndef _PLUGINS_ITANIUM_COMPONENT_H +#define _PLUGINS_ITANIUM_COMPONENT_H #include <ctype.h> @@ -32,9 +32,9 @@ #include <sys/types.h> -#include "context.h" -#include "../../analysis/type.h" -#include "../../common/fnv1a.h" +#include <analysis/routine.h> +#include <analysis/type.h> +#include <common/fnv1a.h> @@ -42,29 +42,38 @@ typedef enum _ItaniumComponentType { /** - * Représentation d'une règle vide. + * Chaîne de caractère, terminée par un octet nul. */ - ICT_EMPTY, + ICT_NAME, /** - * Chaîne de caractère, terminée par un octet nul. + * Nom avec préfixe standard. + * Le nom en question est placé dans le champ unary. */ - ICT_NAME, - ICT_STD_SUBST, + ICT_STD_UNSCOPED_NAME, /** * Noms imbriqués, en deux parties : 'binary'. + * En cas de préfixe nul, le composant gauche peut être nul. */ ICT_NESTED_NAME, + + /** + * Noms imbriqués, en deux parties : 'binary'. + * C'est normalement le seul réceptacle pour les composants issus + * de itd_template_args (sur la branche droite). + */ ICT_TEMPLATE_NAME_ARGS, /** - * Deux types de préfixes : un ou deux éléments. - * -> 'unary' ou 'binary' + * Type avec préfixes : deux éléments, dans 'binary' */ - ICT_PREFIX_UNARY, ICT_PREFIX_BINARY, - ICT_TPREFIX_UNARY, + + /** + * Préfixes à deux éléments. + * En cas de préfixe nul, le composant gauche peut être nul. + */ ICT_TPREFIX_BINARY, /** @@ -72,15 +81,23 @@ typedef enum _ItaniumComponentType */ ICT_OPERATOR_NAME, + /** + * Particularité des notions d'objets. Les informations utiles + * sont rassemblées dans le champ unary. + */ + ICT_SPECIAL_NAME_VTABLE, + ICT_SPECIAL_NAME_VSTRUCT, /** * Fonctions virtuelles. * -> décalage : 'offset'. + * -> double décalage : 'binary'. * -> fonctions simples : 'binary'. * -> fonctions complexes : 'ternary'. */ ICT_NON_VIRTUAL_OFFSET, ICT_VIRTUAL_OFFSET, + ICT_DOUBLE_OFFSET, ICT_FUNCTION_THUNK, ICT_FUNCTION_COVARIANT_THUNK, @@ -96,6 +113,12 @@ typedef enum _ItaniumComponentType ICT_TYPE, /** + * Type qualifié ; les infos utilies sont explicitement + * conservées dans le champ qualified. + */ + ICT_QUALIFIED_TYPE, + + /** * Différentes références vers un sous-type. * Le champ impacté est 'unary'. */ @@ -106,6 +129,12 @@ typedef enum _ItaniumComponentType ICT_IMAGINARY, /** + * Prototype de fonction. + * Le champ impacté est 'function'. + */ + ICT_FUNCTION_TYPE, + + /** * Fonction (nom + retour/paramètres), sous forme binaire : * -> left = function name * -> right = bare-function-type @@ -113,6 +142,18 @@ typedef enum _ItaniumComponentType ICT_FUNCTION_ENCODING, /** + * Définition d'un tableau. Les indications de dimensions peuvent + * prendre plusieurs formes, et sont rassemblées dans le champ array. + */ + ICT_ARRAY, + + /** + * Pointeur vers un membre. Comme l'espace de noms associé est encodé + * de façon spéciale, un champ est dédié à ce composant : pmember. + */ + ICT_POINTER_TO_MEMBER, + + /** * Liste d'arguments pour templates, à encadrer par des chevrons. * 'unary' pointe vers la liste des éléments. */ @@ -125,6 +166,26 @@ typedef enum _ItaniumComponentType */ ICT_TYPES_LIST, + /** + * Liste d'expressions, sous forme binaire comme pour ICT_TYPES_LIST : + * -> left = élément de la liste de types. + * -> right = reste de la liste de types. + */ + ICT_EXPR_LIST, + + /** + * Liste de types, sous forme binaire : + * -> left = composant d'opérateur. + * -> right = liste d'expressions. + */ + ICT_OPERATED_EXPRESSION, + + /** + * Substitution avec préfixe standard. Le résultat est prêt dans le champ + * dtype. + */ + ICT_STD_SUBST, + ICT_COUNT } ItaniumComponentType; @@ -165,39 +226,53 @@ void itd_unref_comp(itanium_component *); /* Détermine ou fournit l'empreinte d'un composant. */ fnv64_t itd_hash_comp(itanium_component *); +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_with_type(ItaniumComponentType); - -/* 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_name(const char *, size_t); /* Construit un composant dans un contexte Itanium. */ -itanium_component *itd_make_empty(GItaniumDContext *); +itanium_component *itd_make_operator(const itanium_operator_info *); /* Construit un composant dans un contexte Itanium. */ -itanium_component *itd_make_name(GItaniumDContext *, const char *, size_t); +itanium_component *itd_make_cast_operator(itanium_component *); + +/* Donne des indications quant à un opérateur Itanium. */ +const void *itd_get_operator_info(const itanium_component *, ItaniumOperatorType *); +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_offset(ItaniumComponentType, ssize_t); /* Construit un composant dans un contexte Itanium. */ -itanium_component *itd_make_operator(GItaniumDContext *, const itanium_operator_info *); +itanium_component *itd_make_type(GDataType *); +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_qualified_type(itanium_component *, TypeQualifier); /* Construit un composant dans un contexte Itanium. */ -itanium_component *itd_make_offset(GItaniumDContext *, ItaniumComponentType, ssize_t); +itanium_component *itd_make_function_type(bool, itanium_component *); +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_array_with_dim_number(ssize_t, itanium_component *); /* Construit un composant dans un contexte Itanium. */ -itanium_component *itd_make_type(GItaniumDContext *, GDataType *); +itanium_component *itd_make_array_with_dim_expr(itanium_component *, itanium_component *); /* Construit un composant dans un contexte Itanium. */ -itanium_component *itd_make_binary(GItaniumDContext *, ItaniumComponentType, itanium_component *, itanium_component *); +itanium_component *itd_make_pointer_to_memeber_type(itanium_component *, itanium_component *); /* Construit un composant dans un contexte Itanium. */ -itanium_component *itd_append_right_to_binary(GItaniumDContext *, ItaniumComponentType, itanium_component *, itanium_component *); +itanium_component *itd_make_unary(ItaniumComponentType, itanium_component *); /* Construit un composant dans un contexte Itanium. */ -itanium_component *itd_make_unary(GItaniumDContext *, ItaniumComponentType, itanium_component *); +itanium_component *itd_make_binary(ItaniumComponentType, itanium_component *, itanium_component *); +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_append_right_to_binary(ItaniumComponentType, itanium_component *, itanium_component *); +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_ternary(ItaniumComponentType, itanium_component *, itanium_component *, itanium_component *); /* Modifie légèrement le type d'un composant donné. */ void itd_set_type(itanium_component *, ItaniumComponentType); @@ -206,8 +281,14 @@ void itd_set_type(itanium_component *, ItaniumComponentType); ItaniumComponentType itd_get_component_type(const itanium_component *); /* Traduit les composants de contexte Itanium. */ -char *itd_translate_component(GItaniumDContext *, const itanium_component *, char *); +char *itd_translate_component(const itanium_component *, char *); + +/* Traduit les composants de contexte Itanium en type. */ +GDataType *itd_translate_component_to_type(const itanium_component *); + +/* Traduit les composants de contexte Itanium en routine. */ +GBinRoutine *itd_translate_component_to_routine(const itanium_component *); -#endif /* _FORMAT_MANGLING_ITANIUM_COMPONENT_H */ +#endif /* _PLUGINS_ITANIUM_COMPONENT_H */ diff --git a/src/mangling/itanium/context.c b/plugins/itanium/context.c index a0c3614..1d2c365 100644 --- a/src/mangling/itanium/context.c +++ b/plugins/itanium/context.c @@ -24,36 +24,26 @@ #include "context.h" +#include <assert.h> #include <malloc.h> #include <string.h> -#include "abi.h" -#include "component-int.h" -#include "../context-int.h" - +#include <mangling/context-int.h> -/* Taille des extensions d'allocation */ -#define ITCOMP_ALLOC_BULK 200 +#include "abi.h" +#include "component-int.h" -/* Marqueur de fin pour les disponibilités */ -#define ITCOMP_INVALID ((size_t)-1) /* Contexte de décodage Itanium (instance) */ -struct _GItaniumDContext +struct _GItaniumDemangling { 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 **template_args; /* Paramètres de modèle */ + size_t targs_count; /* Quantité utilisée */ itanium_component **substitutions; /* Table de substitutions */ size_t subst_count; /* Quantité utilisée */ @@ -61,16 +51,41 @@ struct _GItaniumDContext }; /* Contexte de décodage Itanium (classe) */ -struct _GItaniumDContextClass +struct _GItaniumDemanglingClass { GDemanglingContextClass parent; /* A laisser en premier */ }; +/* Initialise la classe des contextes de décodage. */ +static void g_itanium_demangling_class_init(GItaniumDemanglingClass *); + +/* Initialise une instance de contexte pour décodage. */ +static void g_itanium_demangling_init(GItaniumDemangling *); + +/* Supprime toutes les références externes. */ +static void g_itanium_demangling_dispose(GItaniumDemangling *); + +/* Procède à la libération totale de la mémoire. */ +static void g_itanium_demangling_finalize(GItaniumDemangling *); + +/* Prépare l'environnement de contexte pour un décodage Itanium. */ +static void g_itanium_demangling_prepare(GItaniumDemangling *); + +/* Valide un composant final issu d'un décodage Itanium. */ +static void g_itanium_demangling_check(GItaniumDemangling *, itanium_component **); + +/* Décode une définition de type pour Itanium. */ +static GDataType *g_itanium_demangling_decode_type(GItaniumDemangling *); + +/* Décode une définition de routine pour Itanium. */ +static GBinRoutine *g_itanium_demangling_decode_routine(GItaniumDemangling *); + + /* Indique le type défini pour un contexte de décodage. */ -G_DEFINE_TYPE(GItaniumDContext, g_itanium_dcontext, G_TYPE_DEMANGLING_CONTEXT); +G_DEFINE_TYPE(GItaniumDemangling, g_itanium_demangling, G_TYPE_DEMANGLING_CONTEXT); /****************************************************************************** @@ -85,8 +100,20 @@ G_DEFINE_TYPE(GItaniumDContext, g_itanium_dcontext, G_TYPE_DEMANGLING_CONTEXT); * * ******************************************************************************/ -static void g_itanium_dcontext_class_init(GItaniumDContextClass *klass) +static void g_itanium_demangling_class_init(GItaniumDemanglingClass *klass) { + GObjectClass *object; /* Autre version de la classe */ + GDemanglingContextClass *context; /* Version de base du contexte */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_itanium_demangling_dispose; + object->finalize = (GObjectFinalizeFunc)g_itanium_demangling_finalize; + + context = G_DEMANGLING_CONTEXT_CLASS(klass); + + context->decode_type = (decode_type_fc)g_itanium_demangling_decode_type; + context->decode_routine = (decode_routine_fc)g_itanium_demangling_decode_routine; } @@ -103,216 +130,170 @@ static void g_itanium_dcontext_class_init(GItaniumDContextClass *klass) * * ******************************************************************************/ -static void g_itanium_dcontext_init(GItaniumDContext *context) +static void g_itanium_demangling_init(GItaniumDemangling *context) { - context->last_used = ITCOMP_INVALID; } /****************************************************************************** * * -* Paramètres : - * +* Paramètres : context = instance d'objet GLib à traiter. * * * -* Description : Prépare de quoi effectuer un décodage Itanium. * +* Description : Supprime toutes les références externes. * * * -* Retour : Instance du contexte mis en place. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GDemanglingContext *g_itanium_dcontext_new(void) +static void g_itanium_demangling_dispose(GItaniumDemangling *context) { - GDemanglingContext *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_ITANIUM_DCONTEXT, NULL); - - return result; + G_OBJECT_CLASS(g_itanium_demangling_parent_class)->dispose(G_OBJECT(context)); } /****************************************************************************** * * -* Paramètres : context = contexte de décodage sur lequel s'appuyer. * -* desc = chaîne de caractères à décoder. * +* Paramètres : context = instance d'objet GLib à traiter. * * * -* Description : Tente de décoder une chaîne de caractères donnée. * +* Description : Procède à la libération totale de la mémoire. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -void /*GBinRoutine **/g_itanium_dcontext_demangle_routine(GItaniumDContext *context, const char *desc) +static void g_itanium_demangling_finalize(GItaniumDemangling *context) { - 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 *)); - + size_t i; /* Boucle de parcours */ - comp = itd_mangled_name(context); + for (i = 0; i < context->targs_count; i++) + itd_unref_comp(context->template_args[i]); + if (context->template_args != NULL) + free(context->template_args); - printf("Got :: %p\n", comp); + for (i = 0; i < context->subst_count; i++) + itd_unref_comp(context->substitutions[i]); - str = itd_translate_component(context, comp, NULL); + if (context->substitutions != NULL) + free(context->substitutions); - printf("==>> %s\n", str); + G_OBJECT_CLASS(g_itanium_demangling_parent_class)->finalize(G_OBJECT(context)); } /****************************************************************************** * * -* Paramètres : context = contexte de décodage à manipuler. * -* state = état courant à sauvegarder. [OUT] * +* Paramètres : context = environnement de décodage à manipuler. * * * -* Description : Fournit l'état courant à une fin de retour en arrière. * +* Description : Prépare l'environnement de contexte pour un décodage Itanium.* * * -* Retour : - * +* Retour : - . * * * * Remarques : - * * * ******************************************************************************/ -void g_itanium_dcontext_push_state(const GItaniumDContext *context, itd_state *state) +static void g_itanium_demangling_prepare(GItaniumDemangling *context) { - state->pos = context->pos; - state->subst_count = context->subst_count; + input_buffer *ibuf; /* Tampon de texte manipulé */ + size_t len; /* Taille de chaîne à traiter */ -} + /** + * On part du principe qu'il n'y aura jamais plus de paramètres de modèle + * ou de substitutions à enregistrer que de caractères dans la chaîne à traiter. + * Du coup, on peut tout allouer d'un coup ! + */ + assert(context->template_args == NULL); -/****************************************************************************** -* * -* 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 : - * -* * -******************************************************************************/ + assert(context->substitutions == NULL); -void g_itanium_dcontext_pop_state(GItaniumDContext *context, const itd_state *state) -{ - size_t i; /* Boucle de parcours */ + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; - /* - printf("--deleting subst-- from %zu to %zu\n", - state->subst_count, context->subst_count); - */ + len = get_input_buffer_size(ibuf); - for (i = state->subst_count; i < context->subst_count; i++) - itd_unref_comp(context->substitutions[i]); + context->template_args = (itanium_component **)malloc(len * sizeof(itanium_component *)); - context->pos = state->pos; - context->subst_count = state->subst_count; + context->substitutions = (itanium_component **)malloc(len * sizeof(itanium_component *)); } /****************************************************************************** * * -* Paramètres : context = contexte de décodage à utiliser. * +* Paramètres : context = environnement de décodage à manipuler. * +* comp = composant final à valider. [OUT] * * * -* Description : Fournit la valeur du caractère courant. * +* Description : Valide un composant final issu d'un décodage Itanium. * * * -* Retour : Caractère courant. * +* Retour : - . * * * * Remarques : - * * * ******************************************************************************/ -char g_itanium_dcontext_peek_char(const GItaniumDContext *context) +static void g_itanium_demangling_check(GItaniumDemangling *context, itanium_component **comp) { - return *(context->mangled + context->pos); + input_buffer *ibuf; /* Tampon de texte manipulé */ + size_t remaining; /* Données restant à consommer */ -} + if (*comp != NULL) + { + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + remaining = count_input_buffer_remaining(ibuf); -/****************************************************************************** -* * -* 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 : - * -* * -******************************************************************************/ + if (remaining > 0) + { + itd_unref_comp(*comp); + *comp = NULL; + } -void g_itanium_dcontext_advance(GItaniumDContext *context, size_t quantity) -{ - context->pos += quantity; + } } /****************************************************************************** * * -* Paramètres : context = contexte de décodage à utiliser. * +* Paramètres : context = environnement de décodage à manipuler. * * * -* Description : Fournit et avance la tête de lecture courante. * +* Description : Décode une définition de type pour Itanium. * * * -* Retour : Caractère courant. * +* Retour : Nouvelle instance créée ou NULL en cas d'erreur fatale. * * * * Remarques : - * * * ******************************************************************************/ -char g_itanium_dcontext_next_char(GItaniumDContext *context) +static GDataType *g_itanium_demangling_decode_type(GItaniumDemangling *context) { - return *(context->mangled + context->pos++); + GDataType *result; /* Type construit à retourner */ + itanium_component *comp; /* Composants décodés */ -} + g_itanium_demangling_prepare(context); + comp = itd_mangled_name(context); -/****************************************************************************** -* * -* 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 : - * -* * -******************************************************************************/ + g_itanium_demangling_check(context, &comp); -bool g_itanium_dcontext_check_char(GItaniumDContext *context, char c) -{ - bool result; /* Validation à retourner */ + if (comp == NULL) + result = NULL; - if (g_itanium_dcontext_peek_char(context) == c) + else { - result = true; - g_itanium_dcontext_advance(context, 1); + result = itd_translate_component_to_type(comp); + + itd_unref_comp(comp); + } - else - result = false; return result; @@ -321,111 +302,121 @@ bool g_itanium_dcontext_check_char(GItaniumDContext *context, char c) /****************************************************************************** * * -* Paramètres : context = contexte de décodage à utiliser. * -* remaining = taille de la chaîne retournée. [OUT] * +* Paramètres : context = environnement de décodage à manipuler. * * * -* Description : Fournit la chaîne de caractère restant à traiter. * +* Description : Décode une définition de routine pour Itanium. * * * -* Retour : Pointeur vers les données courantes. * +* Retour : Nouvelle instance créée ou NULL en cas d'erreur fatale. * * * * Remarques : - * * * ******************************************************************************/ -const char *g_itanium_dcontext_get_string(const GItaniumDContext *context, size_t *remaining) +static GBinRoutine *g_itanium_demangling_decode_routine(GItaniumDemangling *context) { - const char *result; /* Données à renvoyer */ - - *remaining = context->len - context->pos; - - result = &context->mangled[context->pos]; - - return result; - -} - + GBinRoutine *result; /* Routine en place à retourner*/ + itanium_component *comp; /* Composants décodés */ + g_itanium_demangling_prepare(context); + comp = itd_mangled_name(context); + g_itanium_demangling_check(context, &comp); -/* + if (comp == NULL) + result = NULL; -################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) + else + { + result = itd_translate_component_to_routine(comp); + itd_unref_comp(comp); -*/ + } + return result; +} /****************************************************************************** * * * Paramètres : context = contexte de décodage à manipuler. * +* state = état courant à sauvegarder. [OUT] * * * -* Description : Fournit un nouveau composant vierge. * +* Description : Fournit l'état courant à une fin de retour en arrière. * * * -* Retour : Composant prêt à être défini. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -itanium_component *g_itanium_dcontext_get_empty_component(GItaniumDContext *context) +void g_itanium_demangling_push_state(const GItaniumDemangling *context, itd_state *state) { - itanium_component *result; /* Disponibilité à retourner */ - size_t i; /* Boucle de parcours */ - size_t next; /* Indice de disponibilité */ + input_buffer *ibuf; /* Tampon de texte manipulé */ - 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)); + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; - context->next_links = (size_t *) - realloc(context->next_links, (context->length + ITCOMP_ALLOC_BULK) * sizeof(size_t)); + save_input_buffer_pos(ibuf, &state->pos); + state->targs_count = context->targs_count; + state->subst_count = context->subst_count; - /* 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; +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ - if (context->last_used != ITCOMP_INVALID) - context->next_links[context->last_used] = context->length; +void g_itanium_demangling_pop_state(GItaniumDemangling *context, const itd_state *state) +{ + size_t i; /* Boucle de parcours */ + input_buffer *ibuf; /* Tampon de texte manipulé */ - /* Mise à jour globale */ + for (i = state->targs_count; i < context->targs_count; i++) + itd_unref_comp(context->template_args[i]); - context->length += ITCOMP_ALLOC_BULK; + for (i = state->subst_count; i < context->subst_count; i++) + itd_unref_comp(context->substitutions[i]); - } + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; - /* Extraction d'un composant disponible */ + restore_input_buffer_pos(ibuf, state->pos); + context->targs_count = state->targs_count; + context->subst_count = state->subst_count; - 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)); +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à manipuler. * +* comp = composant à conserver en mémoire. * +* * +* Description : Indexe un composant représentant un argument de modèle. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - result->context = context; - g_object_ref(G_OBJECT(result->context)); - result->refcount = 1; +void g_itanium_demangling_add_template_arg(GItaniumDemangling *context, itanium_component *comp) +{ + assert(comp != NULL); - return result; + context->template_args[context->targs_count++] = comp; + itd_ref_comp(comp); } @@ -433,28 +424,29 @@ itanium_component *g_itanium_dcontext_get_empty_component(GItaniumDContext *cont /****************************************************************************** * * * Paramètres : context = contexte de décodage à manipuler. * -* comp = composant à libérer. * +* index = indice de l'argument visé. * * * -* Description : Marque un composant comme étant disponible pour un usage. * +* Description : Fournit un composant représentant un argument de modèle. * * * -* Retour : - * +* Retour : Composant déjà extrait et conservé. * * * * Remarques : - * * * ******************************************************************************/ -void g_itanium_dcontext_mark_component_as_free(GItaniumDContext *context, itanium_component *comp) +itanium_component *g_itanium_demangling_get_template_arg(GItaniumDemangling *context, size_t index) { - size_t index; /* Indice du composant concerné*/ - - /*BUG_ON(comp->refcount != 0);*/ - - g_object_unref(G_OBJECT(comp->context)); + itanium_component *result; /* Composant à retourner */ - index = comp - context->components; + if (index < context->targs_count) + { + result = context->template_args[index]; + itd_ref_comp(result); + } + else + result = NULL; - context->next_links[index] = context->next_links[context->last_used]; - context->next_links[context->last_used] = index; + return result; } @@ -472,11 +464,13 @@ void g_itanium_dcontext_mark_component_as_free(GItaniumDContext *context, itaniu * * ******************************************************************************/ -void g_itanium_dcontext_add_substitution(GItaniumDContext *context, itanium_component *comp) +void g_itanium_demangling_add_substitution(GItaniumDemangling *context, itanium_component *comp) { fnv64_t hash; /* Empreinte du candidat */ size_t i; /* Boucle de parcours */ + assert(comp != NULL); + hash = itd_hash_comp(comp); for (i = 0; i < context->subst_count; i++) @@ -485,15 +479,8 @@ void g_itanium_dcontext_add_substitution(GItaniumDContext *context, itanium_comp 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); - } } @@ -512,7 +499,7 @@ void g_itanium_dcontext_add_substitution(GItaniumDContext *context, itanium_comp * * ******************************************************************************/ -itanium_component *g_itanium_dcontext_get_substitution(GItaniumDContext *context, size_t index) +itanium_component *g_itanium_demangling_get_substitution(GItaniumDemangling *context, size_t index) { itanium_component *result; /* Composant à retourner */ @@ -527,45 +514,3 @@ itanium_component *g_itanium_dcontext_get_substitution(GItaniumDContext *context 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/plugins/itanium/context.h b/plugins/itanium/context.h new file mode 100644 index 0000000..6ec65ae --- /dev/null +++ b/plugins/itanium/context.h @@ -0,0 +1,83 @@ + +/* 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ITANIUM_CONTEXT_H +#define _PLUGINS_ITANIUM_CONTEXT_H + + +#include <glib-object.h> +#include <stdbool.h> + + +#include "component.h" + + + +#define G_TYPE_ITANIUM_DEMANGLING g_itanium_demangling_get_type() +#define G_ITANIUM_DEMANGLING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ITANIUM_DEMANGLING, GItaniumDemangling)) +#define G_IS_ITANIUM_DEMANGLING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ITANIUM_DEMANGLING)) +#define G_ITANIUM_DEMANGLING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ITANIUM_DEMANGLING, GItaniumDemanglingClass)) +#define G_IS_ITANIUM_DEMANGLING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ITANIUM_DEMANGLING)) +#define G_ITANIUM_DEMANGLING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ITANIUM_DEMANGLING, GItaniumDemanglingClass)) + + +/* Contexte de décodage Itanium (instance) */ +typedef struct _GItaniumDemangling GItaniumDemangling; + +/* Contexte de décodage Itanium (classe) */ +typedef struct _GItaniumDemanglingClass GItaniumDemanglingClass; + + +/* Indique le type défini pour un contexte de décodage. */ +GType g_itanium_demangling_get_type(void); + +/* Sauvegarde d'un état courant */ +typedef struct _itd_state +{ + size_t pos; /* Position courante */ + size_t targs_count; /* Quantité utilisée */ + size_t subst_count; /* Nombre de substitutions */ + +} itd_state; + +/* Fournit l'état courant à une fin de retour en arrière. */ +void g_itanium_demangling_push_state(const GItaniumDemangling *, itd_state *); + +/* Définit l'état courant suite à un retour en arrière. */ +void g_itanium_demangling_pop_state(GItaniumDemangling *, const itd_state *); + +/* Indexe un composant représentant un argument de modèle. */ +void g_itanium_demangling_add_template_arg(GItaniumDemangling *, itanium_component *); + +/* Fournit un composant représentant un argument de modèle. */ +itanium_component *g_itanium_demangling_get_template_arg(GItaniumDemangling *, size_t); + +/* Indexe un composant comme future substitution potentielle. */ +void g_itanium_demangling_add_substitution(GItaniumDemangling *, itanium_component *); + +/* Fournit un composant en place pour une substitution. */ +itanium_component *g_itanium_demangling_get_substitution(GItaniumDemangling *, size_t); + + + +#endif /* _PLUGINS_ITANIUM_CONTEXT_H */ diff --git a/plugins/itanium/core.c b/plugins/itanium/core.c new file mode 100644 index 0000000..ecfd7f0 --- /dev/null +++ b/plugins/itanium/core.c @@ -0,0 +1,64 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.c - intégration du décodage pour symboles Itanium + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "core.h" + + +#include <core/demanglers.h> +#include <plugins/plugin-def.h> + + +#include "demangler.h" +#include "python/module.h" + + + +DEFINE_CHRYSALIDE_PLUGIN("itanium", "Symbol demangler for Itanium", "0.1.0", + RL("PyChrysalide"), AL(PGA_PLUGIN_INIT)); + + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * +* * +* Description : Prend acte du chargement du greffon. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) +{ + bool result; /* Bilan à retourner */ + + result = register_demangler_type("itanium", G_TYPE_ITANIUM_DEMANGLER); + + if (result) + result = add_mangling_itanium_module_to_python_module(); + + return result; + +} diff --git a/plugins/itanium/core.h b/plugins/itanium/core.h new file mode 100644 index 0000000..f59f4e9 --- /dev/null +++ b/plugins/itanium/core.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.h - prototypes pour l'intégration du décodage pour symboles Itanium + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ITANIUM_CORE_H +#define _PLUGINS_ITANIUM_CORE_H + + +#include <plugins/plugin.h> +#include <plugins/plugin-int.h> + + + +/* Prend acte du chargement du greffon. */ +G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *); + + + +#endif /* _PLUGINS_ITANIUM_CORE_H */ diff --git a/plugins/itanium/demangler.c b/plugins/itanium/demangler.c new file mode 100644 index 0000000..690f7c8 --- /dev/null +++ b/plugins/itanium/demangler.c @@ -0,0 +1,174 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * demangler.c - décodage des noms d'éléments Itanium + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "demangler.h" + + +#include <mangling/demangler-int.h> + + +#include "context.h" + + + +/* Décodeur de désignations Itanium (instance) */ +struct _GItaniumDemangler +{ + GCompDemangler parent; /* A laisser en premier */ + +}; + +/* Décodeur de désignations Itanium (classe) */ +struct _GItaniumDemanglerClass +{ + GCompDemanglerClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des décodeurs de désignations. */ +static void g_itanium_demangler_class_init(GItaniumDemanglerClass *); + +/* Initialise une instance de décodeur de désignations. */ +static void g_itanium_demangler_init(GItaniumDemangler *); + +/* Supprime toutes les références externes. */ +static void g_itanium_demangler_dispose(GItaniumDemangler *); + +/* Procède à la libération totale de la mémoire. */ +static void g_itanium_demangler_finalize(GItaniumDemangler *); + + + +/* Indique le type défini pour un décodeur de désignations. */ +G_DEFINE_TYPE(GItaniumDemangler, g_itanium_demangler, G_TYPE_COMP_DEMANGLER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des décodeurs de désignations Itanium. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_itanium_demangler_class_init(GItaniumDemanglerClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GCompDemanglerClass *demangler; /* Version parente basique */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_itanium_demangler_dispose; + object->finalize = (GObjectFinalizeFunc)g_itanium_demangler_finalize; + + demangler = G_COMP_DEMANGLER_CLASS(klass); + + demangler->can_demangle = (can_be_demangled_fc)NULL; + + demangler->context_type = G_TYPE_ITANIUM_DEMANGLING; + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = instance à initialiser. * +* * +* Description : Initialise une instance de décodeur de désignations Itanium. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_itanium_demangler_init(GItaniumDemangler *demangler) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_itanium_demangler_dispose(GItaniumDemangler *demangler) +{ + G_OBJECT_CLASS(g_itanium_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_itanium_demangler_finalize(GItaniumDemangler *demangler) +{ + G_OBJECT_CLASS(g_itanium_demangler_parent_class)->finalize(G_OBJECT(demangler)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Met en place un nouveau décodeur de symboles pour Itanium. * +* * +* Retour : Instance obtenue ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GCompDemangler *g_itanium_demangler_new(void) +{ + GItaniumDemangler *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_ITANIUM_DEMANGLER, NULL); + + return G_COMP_DEMANGLER(result); + +} diff --git a/plugins/itanium/demangler.h b/plugins/itanium/demangler.h new file mode 100644 index 0000000..8b901cc --- /dev/null +++ b/plugins/itanium/demangler.h @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * demangler.h - prototypes pour le décodage des noms d'éléments Itanium + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ITANIUM_DEMANGLER_H +#define _PLUGINS_ITANIUM_DEMANGLER_H + + +#include <glib-object.h> + + +#include <mangling/demangler.h> + + + +#define G_TYPE_ITANIUM_DEMANGLER g_itanium_demangler_get_type() +#define G_ITANIUM_DEMANGLER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ITANIUM_DEMANGLER, GItaniumDemangler)) +#define G_IS_ITANIUM_DEMANGLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ITANIUM_DEMANGLER)) +#define G_ITANIUM_DEMANGLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ITANIUM_DEMANGLER, GItaniumDemanglerClass)) +#define G_IS_ITANIUM_DEMANGLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ITANIUM_DEMANGLER)) +#define G_ITANIUM_DEMANGLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ITANIUM_DEMANGLER, GItaniumDemanglerClass)) + + +/* Décodeur de désignations Itanium (instance) */ +typedef struct _GItaniumDemangler GItaniumDemangler; + +/* Décodeur de désignations Itanium (classe) */ +typedef struct _GItaniumDemanglerClass GItaniumDemanglerClass; + + +/* Indique le type défini pour un décodeur de désignations Itanium. */ +GType g_itanium_demangler_get_type(void); + +/* Met en place un nouveau décodeur de symboles pour Itanium. */ +GCompDemangler *g_itanium_demangler_new(void); + + + +#endif /* _PLUGINS_ITANIUM_DEMANGLER_H */ diff --git a/plugins/itanium/python/Makefile.am b/plugins/itanium/python/Makefile.am new file mode 100644 index 0000000..97abc50 --- /dev/null +++ b/plugins/itanium/python/Makefile.am @@ -0,0 +1,19 @@ + +noinst_LTLIBRARIES = libitaniumpython.la + +libitaniumpython_la_SOURCES = \ + demangler.h demangler.c \ + module.h module.c + +libitaniumpython_la_LDFLAGS = + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libitaniumpython_la_SOURCES:%c=) + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/plugins/itanium/python/demangler.c b/plugins/itanium/python/demangler.c new file mode 100644 index 0000000..dfade68 --- /dev/null +++ b/plugins/itanium/python/demangler.c @@ -0,0 +1,145 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * demangler.c - équivalent Python du fichier "plugins/itanium/demangler.c" + * + * Copyright (C) 2018 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "demangler.h" + + +#include <pygobject.h> + + +#include <plugins/pychrysalide/helpers.h> +#include <plugins/pychrysalide/mangling/demangler.h> + + +#include "../demangler.h" + + + +/* Crée un nouvel objet Python de type 'ItaniumDemangler'. */ +static PyObject *py_itanium_demangler_new(PyTypeObject *, PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : type = type de l'objet à instancier. * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Crée un nouvel objet Python de type 'ItaniumDemangler'. * +* * +* Retour : Instance Python mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_itanium_demangler_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Instance à retourner */ + GCompDemangler *demangler; /* Instance à transposer */ + + demangler = g_itanium_demangler_new(); + + result = pygobject_new(G_OBJECT(demangler)); + + g_object_unref(G_OBJECT(demangler)); + + return (PyObject *)result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_itanium_demangler_type(void) +{ + static PyMethodDef py_itanium_demangler_methods[] = { + { NULL } + }; + + static PyGetSetDef py_itanium_demangler_getseters[] = { + { NULL } + }; + + static PyTypeObject py_itanium_demangler_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.mangling.ItaniumDemangler", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = "PyChrysalide Itanium demangler", + + .tp_methods = py_itanium_demangler_methods, + .tp_getset = py_itanium_demangler_getseters, + .tp_new = (newfunc)py_itanium_demangler_new + + }; + + return &py_itanium_demangler_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.....ItaniumDemangler'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool register_python_itanium_demangler(PyObject *module) +{ + PyTypeObject *py_itanium_demangler_type;/* Type 'ItaniumDemangler' */ + PyObject *dict; /* Dictionnaire du module */ + + py_itanium_demangler_type = get_python_itanium_demangler_type(); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_ITANIUM_DEMANGLER, + py_itanium_demangler_type, get_python_compiler_demangler_type())) + return false; + + return true; + +} diff --git a/plugins/itanium/python/demangler.h b/plugins/itanium/python/demangler.h new file mode 100644 index 0000000..e84313a --- /dev/null +++ b/plugins/itanium/python/demangler.h @@ -0,0 +1,42 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * demangler.h - prototypes pour l'équivalent Python du fichier "plugins/itanium/demangler.h" + * + * Copyright (C) 2018 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_ITANIUM_PYTHON_DEMANGLER_H +#define _PLUGINS_ITANIUM_PYTHON_DEMANGLER_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_itanium_demangler_type(void); + +/* Prend en charge l'objet 'pychrysalide.format.mangling.ItaniumDemangler'. */ +bool register_python_itanium_demangler(PyObject *); + + + +#endif /* _PLUGINS_ITANIUM_PYTHON_DEMANGLER_H */ diff --git a/plugins/itanium/python/module.c b/plugins/itanium/python/module.c new file mode 100644 index 0000000..d42d783 --- /dev/null +++ b/plugins/itanium/python/module.c @@ -0,0 +1,61 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire itanium en tant que module + * + * Copyright (C) 2018 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "module.h" + + +#include <Python.h> + + +#include <plugins/pychrysalide/access.h> + + +#include "demangler.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Etend le module 'mangling' avec des compléments pour Itanium.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_mangling_itanium_module_to_python_module(void) +{ + bool result; /* Bilan à retourner */ + PyObject *super; /* Module à compléter */ + + super = get_access_to_python_module("pychrysalide.mangling"); + + result = register_python_itanium_demangler(super); + + return result; + +} diff --git a/plugins/itanium/python/module.h b/plugins/itanium/python/module.h new file mode 100644 index 0000000..7e35a81 --- /dev/null +++ b/plugins/itanium/python/module.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire itanium en tant que module + * + * Copyright (C) 2018 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_ITANIUM_PYTHON_MODULE_H +#define _PLUGINS_ITANIUM_PYTHON_MODULE_H + + +#include <stdbool.h> + + + +/* Etend le module 'mangling' avec des compléments pour Itanium. */ +bool add_mangling_itanium_module_to_python_module(void); + + + +#endif /* _PLUGINS_ITANIUM_PYTHON_MODULE_H */ diff --git a/src/common/ibuf.c b/src/common/ibuf.c index f0ea0ac..5d90eb4 100644 --- a/src/common/ibuf.c +++ b/src/common/ibuf.c @@ -50,6 +50,28 @@ void init_text_input_buffer(input_buffer *ibuf, const char *text) } +/****************************************************************************** +* * +* Paramètres : ibuf = tampon de données à consulter. * +* * +* Description : Fournit la taille totale du tampon constitué. * +* * +* Retour : Valeur positive (ou nulle !). * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t get_input_buffer_size(const input_buffer *ibuf) +{ + size_t result; /* Quantité à retourner */ + + result = ibuf->len; + + return result; + +} + /****************************************************************************** * * @@ -65,10 +87,47 @@ void init_text_input_buffer(input_buffer *ibuf, const char *text) size_t count_input_buffer_remaining(const input_buffer *ibuf) { - return ibuf->len - ibuf->pos; + size_t result; /* Quantité à renvoyer */ + + assert(ibuf->pos <= (ibuf->len + 1)); + + if (ibuf->pos > ibuf->len) + result = 0; + + else + result = ibuf->len - ibuf->pos; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : ibuf = tampon de données à consulter. * +* * +* Description : Détermine s'il reste encore des données disponibles. * +* * +* Retour : true si des données sont encore présentes, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool input_buffer_contain_data(const input_buffer *ibuf) +{ + bool result; /* Bilan à retourner */ + size_t remaining; /* Quantité restante */ + + remaining = count_input_buffer_remaining(ibuf); + + result = (remaining > 0); + + return result; } + /****************************************************************************** * * * Paramètres : ibuf = tampon de données à modifier. * @@ -84,7 +143,7 @@ size_t count_input_buffer_remaining(const input_buffer *ibuf) void advance_input_buffer(input_buffer *ibuf, size_t count) { - assert((ibuf->pos + count) <= ibuf->len); + assert((ibuf->pos + count) <= (ibuf->len + 1)); ibuf->pos += count; @@ -112,6 +171,84 @@ const char *get_input_buffer_text_access(const input_buffer *ibuf) /****************************************************************************** * * +* Paramètres : ibuf = tampon de données à consulter. * +* 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 *get_input_buffer_string(const input_buffer *ibuf, size_t *remaining) +{ + const char *result; /* Pointeur à retourner */ + + assert(ibuf->pos <= ibuf->len); + + result = ibuf->text + ibuf->pos; + + *remaining = ibuf->len - ibuf->pos; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : ibuf = tampon de données à parcourir. * +* * +* Description : Fournit le caractère courant à la tête de lecture courante. * +* * +* Retour : Caractère courant. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char peek_input_buffer_char(const input_buffer *ibuf) +{ + assert(ibuf->pos <= ibuf->len); + + return *(ibuf->text + ibuf->pos); + +} + + +/****************************************************************************** +* * +* Paramètres : ibuf = tampon de données à parcourir. * +* * +* Description : Fournit le caractère suivant la tête de lecture courante. * +* * +* Retour : Caractère courant. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char peek_input_buffer_next_char(const input_buffer *ibuf) +{ + char result; /* Valeur à retourner */ + + assert(ibuf->pos <= ibuf->len); + + if (ibuf->pos == ibuf->len) + result = '\0'; + + else + result = *(ibuf->text + ibuf->pos + 1); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : ibuf = tampon de données à parcourir. * * * * Description : Fournit et avance la tête de lecture courante. * @@ -124,9 +261,79 @@ const char *get_input_buffer_text_access(const input_buffer *ibuf) char text_input_buffer_next_char(input_buffer *ibuf) { + char result; /* Valeur à retourner */ + + assert(ibuf->pos <= ibuf->len); + + result = *(ibuf->text + ibuf->pos); + + advance_input_buffer(ibuf, 1); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : ibuf = tampon de données à parcourir. * +* out = caractère courant, s'il existe. * +* * +* Description : Fournit et avance la tête de lecture courante, si possible. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_input_buffer_next_char_carefully(input_buffer *ibuf, char *out) +{ + char result; /* Valeur à retourner */ + assert(ibuf->pos <= ibuf->len); - return *(ibuf->text + ibuf->pos++); + result = input_buffer_contain_data(ibuf); + + if (result) + { + *out = *(ibuf->text + ibuf->pos); + + advance_input_buffer(ibuf, 1); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : ibuf = tampon de données à parcourir. * +* c = caractère à retrouver. * +* * +* Description : Vérifie la nature du caractère courant. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool check_input_buffer_char(input_buffer *ibuf, char c) +{ + bool result; /* Validation à retourner */ + + if (peek_input_buffer_char(ibuf) == c) + { + result = true; + advance_input_buffer(ibuf, 1); + } + else + result = false; + + return result; } diff --git a/src/common/ibuf.h b/src/common/ibuf.h index 3d0d5d1..ecd8814 100644 --- a/src/common/ibuf.h +++ b/src/common/ibuf.h @@ -25,6 +25,7 @@ #define _COMMON_IBUF_H +#include <stdbool.h> #include <stdint.h> #include <sys/types.h> @@ -48,18 +49,39 @@ typedef struct _input_buffer /* Initialise un contenu textuel pour une lecture ultérieure. */ void init_text_input_buffer(input_buffer *, const char *); +/* Fournit la taille totale du tampon constitué. */ +size_t get_input_buffer_size(const input_buffer *); + /* Compte le nombre d'octets encore non lus. */ size_t count_input_buffer_remaining(const input_buffer *); +/* Détermine s'il reste encore des données disponibles. */ +bool input_buffer_contain_data(const input_buffer *); + /* Avance la tête de lecture dans le tampon de données. */ void advance_input_buffer(input_buffer *, size_t); /* Fournit un accès brut au niveau de la tête de lecture. */ const char *get_input_buffer_text_access(const input_buffer *); +/* Fournit la chaîne de caractère restant à traiter. */ +const char *get_input_buffer_string(const input_buffer *, size_t *); + +/* Fournit le caractère courant à la tête de lecture courante. */ +char peek_input_buffer_char(const input_buffer *); + +/* Fournit le caractère suivant la tête de lecture courante. */ +char peek_input_buffer_next_char(const input_buffer *); + /* Fournit et avance la tête de lecture courante. */ char text_input_buffer_next_char(input_buffer *); +/* Fournit et avance la tête de lecture courante, si possible. */ +bool get_input_buffer_next_char_carefully(input_buffer *, char *); + +/* Vérifie la nature du caractère courant. */ +bool check_input_buffer_char(input_buffer *, char); + /* Note la position courante de la tête de lecture. */ void save_input_buffer_pos(const input_buffer *, size_t *); diff --git a/src/mangling/Makefile.am b/src/mangling/Makefile.am index b78c439..3ed04ef 100644 --- a/src/mangling/Makefile.am +++ b/src/mangling/Makefile.am @@ -14,8 +14,7 @@ libmangling_la_SOURCES = \ libmangling_la_LDFLAGS = libmangling_la_LIBADD = \ - libjavamangling.la \ - itanium/libmanglingitanium.la + libjavamangling.la devdir = $(includedir)/chrysalide/$(subdir:src/%=%) @@ -45,4 +44,4 @@ 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 = itanium +SUBDIRS = diff --git a/src/mangling/itanium/Makefile.am b/src/mangling/itanium/Makefile.am deleted file mode 100644 index d393a95..0000000 --- a/src/mangling/itanium/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ - -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 = - - -devdir = $(includedir)/chrysalide/$(subdir:src/%=%) - -dev_HEADERS = $(libmanglingitanium_la_SOURCES:%c=) - - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) - -SUBDIRS = diff --git a/src/mangling/itanium/component-int.h b/src/mangling/itanium/component-int.h deleted file mode 100644 index 3d4c1d0..0000000 --- a/src/mangling/itanium/component-int.h +++ /dev/null @@ -1,79 +0,0 @@ - - -#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 deleted file mode 100644 index 65c2d7e..0000000 --- a/src/mangling/itanium/component.c +++ /dev/null @@ -1,717 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * component.c - représentation des composants extraits de l'ABI C++ Itanium - * - * Copyright (C) 2013-2017 Cyrille Bagard - * - * This file is part of Chrysalide. - * - * Chrysalide is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Chrysalide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "component.h" - - -#include <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/context.h b/src/mangling/itanium/context.h deleted file mode 100644 index 0ac5a6c..0000000 --- a/src/mangling/itanium/context.h +++ /dev/null @@ -1,118 +0,0 @@ - -/* 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 Chrysalide. 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_TYPE_ITANIUM_DCONTEXT, GItaniumDContext)) -#define G_IS_ITANIUM_DCONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ITANIUM_DCONTEXT)) -#define G_ITANIUM_DCONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ITANIUM_DCONTEXT, GItaniumDContextClass)) -#define G_IS_ITANIUM_DCONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ITANIUM_DCONTEXT)) -#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/tests/mangling/itanium.py b/tests/mangling/itanium.py new file mode 100644 index 0000000..6bb49d3 --- /dev/null +++ b/tests/mangling/itanium.py @@ -0,0 +1,111 @@ +#!/usr/bin/python3-dbg +# -*- coding: utf-8 -*- + + +# Tests validant le décodage des types et des routines pour le format Itanium + + +from chrysacase import ChrysalideTestCase +from pychrysalide.mangling import ItaniumDemangler + + +class TestItaniumMangling(ChrysalideTestCase): + """TestCase for pychrysalide.mangling.ItaniumDemangler.""" + + def check_demangling(self, got, expected): + """Check a given demangling result.""" + + self.assertEqual(str(got), expected) + + + def testItaniumTypeMangling(self): + """Check Itanium type demangling with specifications samples.""" + + # https://itanium-cxx-abi.github.io/cxx-abi/abi-examples.html#mangling + + demangler = ItaniumDemangler() + + demangled = demangler.decode_type('_ZN3FooIA4_iE3barE') + self.check_demangling(demangled, 'Foo<int[4]>::bar') + + demangled = demangler.decode_type('_ZN1N1fE') + self.check_demangling(demangled, 'N::f') + + demangled = demangler.decode_type('_ZN5Arena5levelE') + self.check_demangling(demangled, 'Arena::level') + + demangled = demangler.decode_type('_ZN5StackIiiE5levelE') + self.check_demangling(demangled, 'Stack<int, int>::level') + + + def testItaniumRoutineMangling(self): + """Check Itanium routine demangling with specifications samples.""" + + # https://itanium-cxx-abi.github.io/cxx-abi/abi-examples.html#mangling + + demangler = ItaniumDemangler() + + demangled = demangler.decode_routine('_Z1fv') + self.check_demangling(demangled, '??? f(void)') + + demangled = demangler.decode_routine('_Z1fi') + self.check_demangling(demangled, '??? f(int)') + + demangled = demangler.decode_routine('_Z3foo3bar') + self.check_demangling(demangled, '??? foo(bar)') + + demangled = demangler.decode_routine('_Zrm1XS_') + self.check_demangling(demangled, '??? operator%(X, X)') + + demangled = demangler.decode_routine('_ZplR1XS0_') + self.check_demangling(demangled, '??? operator+(X &, X &)') + + demangled = demangler.decode_routine('_ZlsRK1XS1_') + self.check_demangling(demangled, '??? operator<<(const X &, const X &)') + + demangled = demangler.decode_routine('_Z1fIiEvi') + self.check_demangling(demangled, 'void f<int>(int)') + + demangled = demangler.decode_routine('_Z5firstI3DuoEvS0_') + self.check_demangling(demangled, 'void first<Duo>(Duo)') + + demangled = demangler.decode_routine('_Z5firstI3DuoEvT_') + self.check_demangling(demangled, 'void first<Duo>(Duo)') + + demangled = demangler.decode_routine('_Z3fooIiPFidEiEvv') + self.check_demangling(demangled, 'void foo<int, int (*) (double), int>(void)') + + demangled = demangler.decode_routine('_ZN6System5Sound4beepEv') + self.check_demangling(demangled, '??? System::Sound::beep(void)') + + demangled = demangler.decode_routine('_Z1fI1XEvPVN1AIT_E1TE') + self.check_demangling(demangled, 'void f<X>(volatile A<X>::T *)') + + demangled = demangler.decode_routine('_ZngILi42EEvN1AIXplT_Li2EEE1TE') + self.check_demangling(demangled, 'void operator-<42>(A<42+2>::T)') + + demangled = demangler.decode_routine('_Z4makeI7FactoryiET_IT0_Ev') + self.check_demangling(demangled, 'Factory<int> make<Factory, int>(void)') + + demangled = demangler.decode_routine('_Z3foo5Hello5WorldS0_S_') + self.check_demangling(demangled, '??? foo(Hello, World, World, Hello)') + + demangled = demangler.decode_routine('_ZlsRSoRKSs') + self.check_demangling(demangled, '??? operator<<(std::ostream &, const std::string &)') + + + def testItaniumRoutineManglingInside(self): + """Check Itanium routine demangling examples within the specifications.""" + + # http://refspecs.linuxbase.org/cxxabi-1.83.html#linkage + + demangler = ItaniumDemangler() + + demangled = demangler.decode_routine('_Z1fM1AKFvvE') + self.check_demangling(demangled, '??? f(const void (A::*) (void))') + + demangled = demangler.decode_routine('_Z1fPFvvEM1SFvvE') + self.check_demangling(demangled, '??? f(void (*) (void), void (S::*) (void))') + + demangled = demangler.decode_routine('_ZN1N1TIiiE2mfES0_IddE') + self.check_demangling(demangled, '??? N::T<int, int>::mf(N::T<double, double>)') diff --git a/tools/afl/Makefile b/tools/afl/Makefile new file mode 100644 index 0000000..4f684aa --- /dev/null +++ b/tools/afl/Makefile @@ -0,0 +1,13 @@ + +all: itanium + +itanium: itanium.c + afl-gcc -o $@ \ + `pkg-config --libs --cflags gtk+-3.0 glib-2.0 libxml-2.0` \ + -I../.. -I../../src \ + -Wl,-rpath,$(PWD)/../../src/.libs -L../../src/.libs -lchrysacore \ + -Wl,-rpath,$(PWD)/../../plugins/itanium/.libs -L../../plugins/itanium/.libs -litanium \ + $^ + +clean: + rm -f itanium *~ diff --git a/tools/afl/demangler.sh b/tools/afl/demangler.sh new file mode 100755 index 0000000..e82ccbf --- /dev/null +++ b/tools/afl/demangler.sh @@ -0,0 +1,27 @@ +#§/bin/sh + + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 <type>" + exit +fi + +rm -rf testcase_dir findings_dir + +mkdir testcase_dir findings_dir + +n=0 + +for enc in $( cat ../../tests/mangling/$1.py | grep decode_routine | cut -d\' -f 2 ); +do + + echo -n $enc > testcase_dir/$( printf "%03d" $n ) + + n=$(( n + 1 )) + +done + + +#echo -n '_Z4makeI7FactoryiET_IT0_Ev' > testcase_dir/00 + +afl-fuzz -t 100 -m 4096 -i testcase_dir -o findings_dir -- ./$1 diff --git a/tools/afl/itanium.c b/tools/afl/itanium.c new file mode 100644 index 0000000..9e68078 --- /dev/null +++ b/tools/afl/itanium.c @@ -0,0 +1,69 @@ + +#include <malloc.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +#include <common/io.h> +#include <plugins/itanium/demangler.h> + + + +/* Tampon d'entrée */ +static char _input_buffer[4096]; + + + +/****************************************************************************** +* * +* Paramètres : argc = nombre d'arguments dans la ligne de commande. * +* argv = arguments de la ligne de commande. * +* * +* Description : Point d'entrée du programme. * +* * +* Retour : EXIT_SUCCESS si le prgm s'est déroulé sans encombres. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int main(int argc, char **argv) +{ + int result; /* Bilan de l'exécution */ + ssize_t got; /* Quantité de données lues */ + GCompDemangler *demangler; /* Décodeur à solliciter */ + GBinRoutine *routine; /* Routine obtenue par décodage*/ + char *desc; /* Description finale obtenue */ + + result = EXIT_FAILURE; + + got = safe_read_partial(STDIN_FILENO, _input_buffer, sizeof(_input_buffer)); + if (got <= 0) goto exit; + + printf("input: %zd bytes ('%s')\n", got, _input_buffer); + + demangler = g_itanium_demangler_new(); + + routine = g_compiler_demangler_decode_routine(demangler, _input_buffer); + if (routine == NULL) goto demangling_exit; + + desc = g_binary_routine_to_string(routine, true); + + g_object_unref(G_OBJECT(routine)); + + printf("routine: %s\n", desc); + + free(desc); + + result = EXIT_SUCCESS; + + demangling_exit: + + g_object_unref(G_OBJECT(demangler)); + + exit: + + return result; + +} |