diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2018-07-02 22:46:14 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2018-07-02 22:46:14 (GMT) | 
| commit | 8dc83465a6ca2d5b94b983b39f6c06d37e4126a0 (patch) | |
| tree | b5594fe7cd0d9e9a9269eaa3454412da2bd9dd5a | |
| parent | de2cb8e2fad4a3031d7b7c2cb189a6dbdaf8d5a9 (diff) | |
Improved the Itanium C++ demangling.
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; + +} | 
