From 8dc83465a6ca2d5b94b983b39f6c06d37e4126a0 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 3 Jul 2018 00:46:14 +0200 Subject: Improved the Itanium C++ demangling. --- configure.ac | 3 +- plugins/Makefile.am | 2 +- plugins/dexbnf/context.c | 6 +- plugins/dexbnf/demangler.c | 2 +- plugins/dexbnf/python/demangler.c | 2 +- plugins/dexbnf/python/demangler.h | 2 +- plugins/itanium/Makefile.am | 32 + plugins/itanium/abi.c | 3344 ++++++++++++++++++++++++++++++++++ plugins/itanium/abi.h | 38 + plugins/itanium/component-int.h | 137 ++ plugins/itanium/component.c | 1842 +++++++++++++++++++ plugins/itanium/component.h | 294 +++ plugins/itanium/context.c | 516 ++++++ plugins/itanium/context.h | 83 + plugins/itanium/core.c | 64 + plugins/itanium/core.h | 38 + plugins/itanium/demangler.c | 174 ++ plugins/itanium/demangler.h | 58 + plugins/itanium/python/Makefile.am | 19 + plugins/itanium/python/demangler.c | 145 ++ plugins/itanium/python/demangler.h | 42 + plugins/itanium/python/module.c | 61 + plugins/itanium/python/module.h | 38 + src/common/ibuf.c | 213 ++- src/common/ibuf.h | 22 + src/mangling/Makefile.am | 5 +- src/mangling/itanium/Makefile.am | 24 - src/mangling/itanium/abi.c | 2444 ------------------------- src/mangling/itanium/abi.h | 38 - src/mangling/itanium/component-int.h | 79 - src/mangling/itanium/component.c | 717 -------- src/mangling/itanium/component.h | 213 --- src/mangling/itanium/context.c | 571 ------ src/mangling/itanium/context.h | 118 -- tests/mangling/itanium.py | 111 ++ tools/afl/Makefile | 13 + tools/afl/demangler.sh | 27 + tools/afl/itanium.c | 69 + 38 files changed, 7388 insertions(+), 4218 deletions(-) create mode 100644 plugins/itanium/Makefile.am create mode 100644 plugins/itanium/abi.c create mode 100644 plugins/itanium/abi.h create mode 100644 plugins/itanium/component-int.h create mode 100644 plugins/itanium/component.c create mode 100644 plugins/itanium/component.h create mode 100644 plugins/itanium/context.c create mode 100644 plugins/itanium/context.h create mode 100644 plugins/itanium/core.c create mode 100644 plugins/itanium/core.h create mode 100644 plugins/itanium/demangler.c create mode 100644 plugins/itanium/demangler.h create mode 100644 plugins/itanium/python/Makefile.am create mode 100644 plugins/itanium/python/demangler.c create mode 100644 plugins/itanium/python/demangler.h create mode 100644 plugins/itanium/python/module.c create mode 100644 plugins/itanium/python/module.h delete mode 100644 src/mangling/itanium/Makefile.am delete mode 100644 src/mangling/itanium/abi.c delete mode 100644 src/mangling/itanium/abi.h delete mode 100644 src/mangling/itanium/component-int.h delete mode 100644 src/mangling/itanium/component.c delete mode 100644 src/mangling/itanium/component.h delete mode 100644 src/mangling/itanium/context.c delete mode 100644 src/mangling/itanium/context.h create mode 100644 tests/mangling/itanium.py create mode 100644 tools/afl/Makefile create mode 100755 tools/afl/demangler.sh create mode 100644 tools/afl/itanium.c 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/plugins/itanium/abi.c b/plugins/itanium/abi.c new file mode 100644 index 0000000..5f76342 --- /dev/null +++ b/plugins/itanium/abi.c @@ -0,0 +1,3344 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * abi.c - décodage des noms d'éléments selon l'ABI C++ Itanium + * + * Copyright (C) 2013-2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see . + */ + + +#include "abi.h" + + +#include +#include +#include + + +#include +#include +#include +#include + + + +/* Liste des opérateurs reconnus */ + +#define IDT_NL(s) s, sizeof(s) - 1 + +const itanium_operator_info itanium_demangle_operators[] = { + + { "aN", IDT_NL("&="), 2 }, + { "aS", IDT_NL("="), 2 }, + { "aa", IDT_NL("&&"), 2 }, + { "ad", IDT_NL("&"), 1 }, + { "an", IDT_NL("&"), 2 }, + { "at", IDT_NL("alignof "), 1 }, + { "az", IDT_NL("alignof "), 1 }, + { "cc", IDT_NL("const_cast"), 2 }, + { "cl", IDT_NL("()"), 2 }, + { "cm", IDT_NL(","), 2 }, + { "co", IDT_NL("~"), 1 }, + { "dV", IDT_NL("/="), 2 }, + { "da", IDT_NL("delete[] "), 1 }, + { "dc", IDT_NL("dynamic_cast"), 2 }, + { "de", IDT_NL("*"), 1 }, + { "dl", IDT_NL("delete "), 1 }, + { "ds", IDT_NL(".*"), 2 }, + { "dt", IDT_NL("."), 2 }, + { "dv", IDT_NL("/"), 2 }, + { "eO", IDT_NL("^="), 2 }, + { "eo", IDT_NL("^"), 2 }, + { "eq", IDT_NL("=="), 2 }, + { "ge", IDT_NL(">="), 2 }, + { "gs", IDT_NL("::"), 1 }, + { "gt", IDT_NL(">"), 2 }, + { "ix", IDT_NL("[]"), 2 }, + { "lS", IDT_NL("<<="), 2 }, + { "le", IDT_NL("<="), 2 }, + { "li", IDT_NL("operator\"\" "), 1 }, + { "ls", IDT_NL("<<"), 2 }, + { "lt", IDT_NL("<"), 2 }, + { "mI", IDT_NL("-="), 2 }, + { "mL", IDT_NL("*="), 2 }, + { "mi", IDT_NL("-"), 2 }, + { "ml", IDT_NL("*"), 2 }, + { "mm", IDT_NL("--"), 1 }, + { "na", IDT_NL("new[]"), 3 }, + { "ne", IDT_NL("!="), 2 }, + { "ng", IDT_NL("-"), 1 }, + { "nt", IDT_NL("!"), 1 }, + { "nw", IDT_NL("new"), 3 }, + { "oR", IDT_NL("|="), 2 }, + { "oo", IDT_NL("||"), 2 }, + { "or", IDT_NL("|"), 2 }, + { "pL", IDT_NL("+="), 2 }, + { "pl", IDT_NL("+"), 2 }, + { "pm", IDT_NL("->*"), 2 }, + { "pp", IDT_NL("++"), 1 }, + { "ps", IDT_NL("+"), 1 }, + { "pt", IDT_NL("->"), 2 }, + { "qu", IDT_NL("?"), 3 }, + { "rM", IDT_NL("%="), 2 }, + { "rS", IDT_NL(">>="), 2 }, + { "rc", IDT_NL("reinterpret_cast"), 2 }, + { "rm", IDT_NL("%"), 2 }, + { "rs", IDT_NL(">>"), 2 }, + { "sc", IDT_NL("static_cast"), 2 }, + { "st", IDT_NL("sizeof "), 1 }, + { "sz", IDT_NL("sizeof "), 1 } +}; + +/* Substitutions standards */ + +typedef struct _itanium_std_subst_info +{ + char code; /* Identifiant associé */ + const char *class; /* Classe visée dans l'espace */ + +} itanium_std_subst_info; + +const itanium_std_subst_info itanium_standard_substitutions[] = { + + { '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_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_unscoped_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_unscoped_template_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_nested_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_prefix(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_prefix_rec(GItaniumDemangling *, itanium_component *); + +/* Extrait un composant dans un contexte Itanium. */ +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(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_source_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static bool itd_number(GItaniumDemangling *, ssize_t *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_identifier(GItaniumDemangling *, size_t); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_operator_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_special_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_call_offset(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_nv_offset(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_v_offset(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_ctor_dtor_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_type(GItaniumDemangling *); + +/* Extrait une propriété de composant pour un contexte Itanium. */ +static TypeQualifier itd_cv_qualifiers(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_builtin_type(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_function_type(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +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_pointer_to_member_type(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +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_template_arg(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +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(GItaniumDemangling *, char, size_t *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_substitution(GItaniumDemangling *); + + + + + + +#define itd_local_name(ctx) NULL + + + + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +itanium_component *itd_mangled_name(GItaniumDemangling *context) +{ + itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + + /** + * La règle traitée ici est la suivante : + * + * ::= _Z + * + */ + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!check_input_buffer_char(ibuf, '_')) + return NULL; + + if (!check_input_buffer_char(ibuf, 'Z')) + return NULL; + + result = itd_encoding(context); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_encoding(GItaniumDemangling *context) +{ + itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ + itanium_component *types; /* Composant 'bare-function...'*/ + + /** + * La règle traitée ici est la suivante : + * + * ::= + * ::= + * ::= + * + */ + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + peek = peek_input_buffer_char(ibuf); + + if (peek == 'T' || peek == 'G') + result = itd_special_name(context); + + else + { + result = itd_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; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_name(GItaniumDemangling *context) +{ + itanium_component *result; /* Construction à retourner */ + itd_state saved; /* Position d'analyse courante */ + itanium_component *tname; /* Composant '...template-name'*/ + itanium_component *targs; /* Composant 'template-args' */ + + /** + * La règle traitée ici est la suivante : + * + * ::= + * ::= + * ::= + * ::= + * + */ + + g_itanium_demangling_push_state(context, &saved); + + result = itd_nested_name(context); + + if (result == NULL) + { + g_itanium_demangling_pop_state(context, &saved); + + tname = itd_unscoped_template_name(context); + + if (tname != NULL) + { + targs = itd_template_args(context); + + if (targs != NULL) + result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, tname, targs); + + else + itd_unref_comp(tname); + + } + + } + + /** + * La règle doit être traitée après , + * car ces deux dernières ont une base commune et la seconde peut avoir besoin + * d'aller plus loin avec la règle . + * + * On termine donc par moins gourmand si la règle la plus complexe n'a pas abouti. + */ + + if (result == NULL) + { + g_itanium_demangling_pop_state(context, &saved); + result = itd_unscoped_name(context); + } + + if (result == NULL) + { + g_itanium_demangling_pop_state(context, &saved); + result = itd_local_name(context); + } + + 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_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 : + * + * ::= + * ::= St # ::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. * +* * +* Remarques : - * +* * +******************************************************************************/ + +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 : + * + * ::= + * ::= St # ::std:: + * + */ + + + if (is_itd_unqualified_name(context)) + result = itd_unqualified_name(context); + + else + { + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + peek = peek_input_buffer_char(ibuf); + + 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; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_unscoped_template_name(GItaniumDemangling *context) +{ + itanium_component *result; /* Construction à retourner */ + input_buffer *ibuf; /* Tampon de texte manipulé */ + char peek; /* Prochain caractère lu */ + + /** + * La règle traitée ici est la suivante : + * + * ::= + * ::= + * + */ + + if (is_itd_unscoped_name(context)) + { + result = itd_unscoped_name(context); + + if (result != NULL) + g_itanium_demangling_add_substitution(context, result); + + } + + else + { + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + peek = peek_input_buffer_char(ibuf); + + if (peek == 'S') + result = itd_substitution(context); + + 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_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 */ + + /** + * La règle traitée ici est la suivante : + * + * ::= N [] E + * ::= N [] E + * + */ + + ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + + if (!check_input_buffer_char(ibuf, 'N')) + return NULL; + + qualifier = itd_cv_qualifiers(context); + + result = NULL; + + g_itanium_demangling_push_state(context, &saved); + + /** + * Comme peut aussi être , + * on commence par traiter la seconde règle. + */ + + left = itd_template_prefix(context); + + if (left != NULL) + { + right = itd_template_args(context); + + if (right != NULL) + { + if (check_input_buffer_char(ibuf, 'E')) + result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, left, right); + + else + { + if (left != NULL) + itd_unref_comp(left); + itd_unref_comp(right); + } + + } + + else if (left != NULL) + itd_unref_comp(left); + + } + + if (result == NULL) + { + g_itanium_demangling_pop_state(context, &saved); + + left = itd_prefix(context); + + /** + * Quand son traitement est un succès, doit toujours + * se terminer par . + */ + + assert(left == NULL || (left != NULL && is_itd_unqualified_name(context))); + + /** + * La règle peut être vide, donc on se doit de tenter un + * dans tous les cas. + */ + + right = itd_unqualified_name(context); + + if (right != NULL) + { + if (check_input_buffer_char(ibuf, 'E')) + result = itd_make_binary(ICT_NESTED_NAME, left, right); + + else + { + if (left != NULL) + itd_unref_comp(left); + itd_unref_comp(right); + } + + } + + else if (left != NULL) + itd_unref_comp(left); + + } + + if (result != NULL) + itd_make_qualified_type(result, qualifier); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : context = contexte de décodage à utiliser. * +* * +* Description : Extrait un composant dans un contexte Itanium. * +* * +* Retour : Composant extrait ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static itanium_component *itd_prefix(GItaniumDemangling *context) +{ + 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 */ + + /** + * La règle traitée ici est la suivante : + * + * ::= + * ::= + * ::= + * ::= # empty + * ::= + * + * On note déjà la jolie petite boucle interne. + * + * Or on a également la règle voisine suivante : + * + * ::=