diff options
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/Makefile.am | 2 | ||||
| -rw-r--r-- | plugins/dexbnf/context.c | 6 | ||||
| -rw-r--r-- | plugins/dexbnf/demangler.c | 2 | ||||
| -rw-r--r-- | plugins/dexbnf/python/demangler.c | 2 | ||||
| -rw-r--r-- | plugins/dexbnf/python/demangler.h | 2 | ||||
| -rw-r--r-- | plugins/itanium/Makefile.am | 32 | ||||
| -rw-r--r-- | plugins/itanium/abi.c | 3344 | ||||
| -rw-r--r-- | plugins/itanium/abi.h | 38 | ||||
| -rw-r--r-- | plugins/itanium/component-int.h | 137 | ||||
| -rw-r--r-- | plugins/itanium/component.c | 1842 | ||||
| -rw-r--r-- | plugins/itanium/component.h | 294 | ||||
| -rw-r--r-- | plugins/itanium/context.c | 516 | ||||
| -rw-r--r-- | plugins/itanium/context.h | 83 | ||||
| -rw-r--r-- | plugins/itanium/core.c | 64 | ||||
| -rw-r--r-- | plugins/itanium/core.h | 38 | ||||
| -rw-r--r-- | plugins/itanium/demangler.c | 174 | ||||
| -rw-r--r-- | plugins/itanium/demangler.h | 58 | ||||
| -rw-r--r-- | plugins/itanium/python/Makefile.am | 19 | ||||
| -rw-r--r-- | plugins/itanium/python/demangler.c | 145 | ||||
| -rw-r--r-- | plugins/itanium/python/demangler.h | 42 | ||||
| -rw-r--r-- | plugins/itanium/python/module.c | 61 | ||||
| -rw-r--r-- | plugins/itanium/python/module.h | 38 | 
22 files changed, 6932 insertions, 7 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 257e0d5..6b0c295 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -4,4 +4,4 @@ if HAVE_PYTHON3_CONFIG  endif  # androhelpers -SUBDIRS = $(PYTHON3_SUBDIRS) arm dex dalvik devdbg dexbnf elf fmtp libcsem lnxsyscalls mobicore readdex readelf readmc ropgadgets +SUBDIRS = $(PYTHON3_SUBDIRS) arm dex dalvik devdbg dexbnf elf fmtp itanium libcsem lnxsyscalls mobicore readdex readelf readmc ropgadgets diff --git a/plugins/dexbnf/context.c b/plugins/dexbnf/context.c index ebf7c0d..2daeb52 100644 --- a/plugins/dexbnf/context.c +++ b/plugins/dexbnf/context.c @@ -121,7 +121,7 @@ static void g_dex_demangling_init(GDexDemangling *context)  /******************************************************************************  *                                                                             * -*  Paramètres  : demangler = instance d'objet GLib à traiter.                 * +*  Paramètres  : context = instance d'objet GLib à traiter.                   *  *                                                                             *  *  Description : Supprime toutes les références externes.                     *  *                                                                             * @@ -140,7 +140,7 @@ static void g_dex_demangling_dispose(GDexDemangling *context)  /******************************************************************************  *                                                                             * -*  Paramètres  : demangler = instance d'objet GLib à traiter.                 * +*  Paramètres  : context = instance d'objet GLib à traiter.                   *  *                                                                             *  *  Description : Procède à la libération totale de la mémoire.                *  *                                                                             * @@ -197,7 +197,7 @@ static GDataType *g_dex_demangling_decode_type(GDexDemangling *context)  static GBinRoutine *g_dex_demangling_decode_routine(GDexDemangling *context)  { -    GBinRoutine *result;                    /* Routine en place à retourner */ +    GBinRoutine *result;                    /* Routine en place à retourner*/      GDemanglingContext *base;               /* Autre version du contexte   */      base = G_DEMANGLING_CONTEXT(context); diff --git a/plugins/dexbnf/demangler.c b/plugins/dexbnf/demangler.c index 32aa36f..3489f15 100644 --- a/plugins/dexbnf/demangler.c +++ b/plugins/dexbnf/demangler.c @@ -1,6 +1,6 @@  /* Chrysalide - Outil d'analyse de fichiers binaires - * demangler.c - décodage des noms d'éléments + * demangler.c - décodage des noms d'éléments Dex   *   * Copyright (C) 2018 Cyrille Bagard   * diff --git a/plugins/dexbnf/python/demangler.c b/plugins/dexbnf/python/demangler.c index f47eefe..e9dba41 100644 --- a/plugins/dexbnf/python/demangler.c +++ b/plugins/dexbnf/python/demangler.c @@ -129,7 +129,7 @@ PyTypeObject *get_python_dex_demangler_type(void)  bool register_python_dex_demangler(PyObject *module)  { -    PyTypeObject *py_dex_demangler_type;    /* Type Python 'ElfFormat'     */ +    PyTypeObject *py_dex_demangler_type;    /* Type Python 'DexDemangler'  */      PyObject *dict;                         /* Dictionnaire du module      */      py_dex_demangler_type = get_python_dex_demangler_type(); diff --git a/plugins/dexbnf/python/demangler.h b/plugins/dexbnf/python/demangler.h index af56289..f2cd964 100644 --- a/plugins/dexbnf/python/demangler.h +++ b/plugins/dexbnf/python/demangler.h @@ -34,7 +34,7 @@  /* Fournit un accès à une définition de type à diffuser. */  PyTypeObject *get_python_dex_demangler_type(void); -/* Prend en charge l'objet 'pychrysalide.format.elf.ElfFormat'. */ +/* Prend en charge l'objet 'pychrysalide.format.mangling.DexDemangler'. */  bool register_python_dex_demangler(PyObject *); diff --git a/plugins/itanium/Makefile.am b/plugins/itanium/Makefile.am new file mode 100644 index 0000000..b4a9cb7 --- /dev/null +++ b/plugins/itanium/Makefile.am @@ -0,0 +1,32 @@ + +lib_LTLIBRARIES  = libitanium.la + +libdir = $(pluginsdir) + +libitanium_la_SOURCES =					\ +	abi.h abi.c							\ +	component-int.h						\ +	component.h component.c				\ +	context.h context.c					\ +	core.h core.c						\ +	demangler.h demangler.c + +libitanium_la_LIBADD =					\ +	python/libitaniumpython.la + +libitanium_la_LDFLAGS =												\ +	-L$(top_srcdir)/src/.libs -lchrysacore							\ +	-Wl,-rpath,$(abs_top_srcdir)/plugins/pychrysalide/.libs			\ +	-L$(top_srcdir)/plugins/pychrysalide/.libs -l:pychrysalide.so + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libitanium_la_SOURCES:%c=) + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + +SUBDIRS = python diff --git a/plugins/itanium/abi.c b/plugins/itanium/abi.c new file mode 100644 index 0000000..5f76342 --- /dev/null +++ b/plugins/itanium/abi.c @@ -0,0 +1,3344 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * abi.c - décodage des noms d'éléments selon l'ABI C++ Itanium + * + * Copyright (C) 2013-2017 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "abi.h" + + +#include <assert.h> +#include <ctype.h> +#include <stdlib.h> + + +#include <analysis/types/basic.h> +#include <analysis/types/cse.h> +#include <common/cpp.h> +#include <mangling/context-int.h> + + + +/* Liste des opérateurs reconnus */ + +#define IDT_NL(s) s, sizeof(s) - 1 + +const itanium_operator_info itanium_demangle_operators[] = { + +    { "aN", IDT_NL("&="),               2 }, +    { "aS", IDT_NL("="),                2 }, +    { "aa", IDT_NL("&&"),               2 }, +    { "ad", IDT_NL("&"),                1 }, +    { "an", IDT_NL("&"),                2 }, +    { "at", IDT_NL("alignof "),         1 }, +    { "az", IDT_NL("alignof "),         1 }, +    { "cc", IDT_NL("const_cast"),       2 }, +    { "cl", IDT_NL("()"),               2 }, +    { "cm", IDT_NL(","),                2 }, +    { "co", IDT_NL("~"),                1 }, +    { "dV", IDT_NL("/="),               2 }, +    { "da", IDT_NL("delete[] "),        1 }, +    { "dc", IDT_NL("dynamic_cast"),     2 }, +    { "de", IDT_NL("*"),                1 }, +    { "dl", IDT_NL("delete "),          1 }, +    { "ds", IDT_NL(".*"),               2 }, +    { "dt", IDT_NL("."),                2 }, +    { "dv", IDT_NL("/"),                2 }, +    { "eO", IDT_NL("^="),               2 }, +    { "eo", IDT_NL("^"),                2 }, +    { "eq", IDT_NL("=="),               2 }, +    { "ge", IDT_NL(">="),               2 }, +    { "gs", IDT_NL("::"),               1 }, +    { "gt", IDT_NL(">"),                2 }, +    { "ix", IDT_NL("[]"),               2 }, +    { "lS", IDT_NL("<<="),              2 }, +    { "le", IDT_NL("<="),               2 }, +    { "li", IDT_NL("operator\"\" "),    1 }, +    { "ls", IDT_NL("<<"),               2 }, +    { "lt", IDT_NL("<"),                2 }, +    { "mI", IDT_NL("-="),               2 }, +    { "mL", IDT_NL("*="),               2 }, +    { "mi", IDT_NL("-"),                2 }, +    { "ml", IDT_NL("*"),                2 }, +    { "mm", IDT_NL("--"),               1 }, +    { "na", IDT_NL("new[]"),            3 }, +    { "ne", IDT_NL("!="),               2 }, +    { "ng", IDT_NL("-"),                1 }, +    { "nt", IDT_NL("!"),                1 }, +    { "nw", IDT_NL("new"),              3 }, +    { "oR", IDT_NL("|="),               2 }, +    { "oo", IDT_NL("||"),               2 }, +    { "or", IDT_NL("|"),                2 }, +    { "pL", IDT_NL("+="),               2 }, +    { "pl", IDT_NL("+"),                2 }, +    { "pm", IDT_NL("->*"),              2 }, +    { "pp", IDT_NL("++"),               1 }, +    { "ps", IDT_NL("+"),                1 }, +    { "pt", IDT_NL("->"),               2 }, +    { "qu", IDT_NL("?"),                3 }, +    { "rM", IDT_NL("%="),               2 }, +    { "rS", IDT_NL(">>="),              2 }, +    { "rc", IDT_NL("reinterpret_cast"), 2 }, +    { "rm", IDT_NL("%"),                2 }, +    { "rs", IDT_NL(">>"),               2 }, +    { "sc", IDT_NL("static_cast"),      2 }, +    { "st", IDT_NL("sizeof "),          1 }, +    { "sz", IDT_NL("sizeof "),          1 } +}; + +/* Substitutions standards */ + +typedef struct _itanium_std_subst_info +{ +    char code;                              /* Identifiant associé         */ +    const char *class;                      /* Classe visée dans l'espace  */ + +} itanium_std_subst_info; + +const itanium_std_subst_info itanium_standard_substitutions[] = { + +    { 't', NULL }, +    { 'a', "allocator" }, +    { 'b', "basic_string" }, +    { 's', "string" }, +    { 'i', "istream" }, +    { 'o', "ostream" }, +    { 'd', "iostream" } + +}; + + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_encoding(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_name(GItaniumDemangling *); + +/* Détermine si le composant suivant correspond à un type donné. */ +static bool is_itd_unscoped_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_unscoped_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_unscoped_template_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_nested_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_prefix(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_prefix_rec(GItaniumDemangling *, itanium_component *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_prefix(GItaniumDemangling *); + +/* Détermine si le composant suivant correspond à un type donné. */ +static bool is_itd_unqualified_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_unqualified_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_source_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static bool itd_number(GItaniumDemangling *, ssize_t *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_identifier(GItaniumDemangling *, size_t); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_operator_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_special_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_call_offset(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_nv_offset(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_v_offset(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_ctor_dtor_name(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_type(GItaniumDemangling *); + +/* Extrait une propriété de composant pour un contexte Itanium. */ +static TypeQualifier itd_cv_qualifiers(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_builtin_type(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_function_type(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_bare_function_type(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_class_enum_type(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_array_type(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_pointer_to_member_type(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_param(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_template_param(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_args(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_template_arg(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_expression(GItaniumDemangling *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_value_to_string(GItaniumDemangling *, bool); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_expr_primary(GItaniumDemangling *); + + + + +/* Extrait un composant dans un contexte Itanium. */ +static bool itd_seq_id(GItaniumDemangling *, char, size_t *); + +/* Extrait un composant dans un contexte Itanium. */ +static itanium_component *itd_substitution(GItaniumDemangling *); + + + + + + +#define itd_local_name(ctx) NULL + + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +itanium_component *itd_mangled_name(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <mangled-name> ::= _Z <encoding> +     * +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    if (!check_input_buffer_char(ibuf, '_')) +        return NULL; + +    if (!check_input_buffer_char(ibuf, 'Z')) +        return NULL; + +    result = itd_encoding(context); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_encoding(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ +    char peek;                              /* Prochain caractère lu       */ +    itanium_component *types;               /* Composant 'bare-function...'*/ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <encoding> ::= <function name> <bare-function-type> +     *            ::= <data name> +     *            ::= <special-name> +     * +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    peek = peek_input_buffer_char(ibuf); + +    if (peek == 'T' || peek == 'G') +        result = itd_special_name(context); + +    else +    { +        result = itd_name(context); + +        if (result != NULL) +        { +            types = itd_bare_function_type(context); + +            if (types != NULL) +                result = itd_make_binary(ICT_FUNCTION_ENCODING, result, types); + +            /** +             * Si le chargement des types échoue, il peut y avoir deux explications : +             *    - on ne chargeait qu'un simple nom. +             *    - il y a eu une erreur de décodage pour les types. +             * +             * Le tampon aura été vidé dans le premier cas uniquement, +             * donc on laisse le contexte détecter une éventuelle erreur. +             */ + +        } + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_name(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    itd_state saved;                        /* Position d'analyse courante */ +    itanium_component *tname;               /* Composant '...template-name'*/ +    itanium_component *targs;               /* Composant 'template-args'   */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <name> ::= <nested-name> +     *        ::= <unscoped-name> +     *        ::= <unscoped-template-name> <template-args> +     *        ::= <local-name> +     * +     */ + +    g_itanium_demangling_push_state(context, &saved); + +    result = itd_nested_name(context); + +    if (result == NULL) +    { +        g_itanium_demangling_pop_state(context, &saved); + +        tname = itd_unscoped_template_name(context); + +        if (tname != NULL) +        { +            targs = itd_template_args(context); + +            if (targs != NULL) +                result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, tname, targs); + +            else +                itd_unref_comp(tname); + +        } + +    } + +    /** +     * La règle <unscoped-name> doit être traitée après <unscoped-template-name>, +     * car ces deux dernières ont une base commune et la seconde peut avoir besoin +     * d'aller plus loin avec la règle <template-args>. +     * +     * On termine donc par moins gourmand si la règle la plus complexe n'a pas abouti. +     */ + +    if (result == NULL) +    { +        g_itanium_demangling_pop_state(context, &saved); +        result = itd_unscoped_name(context); +    } + +    if (result == NULL) +    { +        g_itanium_demangling_pop_state(context, &saved); +        result = itd_local_name(context); +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Détermine si le composant suivant correspond à un type donné.* +*                                                                             * +*  Retour      : true si le décodage va à priori réussir, false sinon.        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool is_itd_unscoped_name(GItaniumDemangling *context) +{ +    bool result;                            /* Bilan à retourner           */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ +    char peek;                              /* Prochain caractère lu       */ +    char next_peek;                         /* Caractère après le prochain */ + +    /** +     * La règle anticipée ici est la suivante : +     * +     * <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.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_unscoped_name(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ +    char peek;                              /* Prochain caractère lu       */ +    char next_peek;                         /* Caractère après le prochain */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <unscoped-name> ::= <unqualified-name> +     *                 ::= St <unqualified-name>   # ::std:: +     * +     */ + + +    if (is_itd_unqualified_name(context)) +        result = itd_unqualified_name(context); + +    else +    { +        ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +        peek = peek_input_buffer_char(ibuf); + +        if (peek == 'S') +        { +            next_peek = peek_input_buffer_next_char(ibuf); + +            if (next_peek == 't') +            { +                advance_input_buffer(ibuf, 2); + +                result = itd_unqualified_name(context); + +                if (result != NULL) +                    result = itd_make_unary(ICT_STD_UNSCOPED_NAME, result); + +            } + +            else +                result = NULL; + +        } + +        else +            result = NULL; + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_unscoped_template_name(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ +    char peek;                              /* Prochain caractère lu       */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <unscoped-template-name> ::= <unscoped-name> +     *                          ::= <substitution> +     * +     */ + +    if (is_itd_unscoped_name(context)) +    { +        result = itd_unscoped_name(context); + +        if (result != NULL) +            g_itanium_demangling_add_substitution(context, result); + +    } + +    else +    { +        ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +        peek = peek_input_buffer_char(ibuf); + +        if (peek == 'S') +            result = itd_substitution(context); + +        else +            result = NULL; + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_nested_name(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ +    TypeQualifier qualifier;                /* Propriétés supplémentaires  */ +    itd_state saved;                        /* Position d'analyse courante */ +    itanium_component *left;                /* Première partie             */ +    itanium_component *right;               /* Seconde partie              */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E +     *               ::= N [<CV-qualifiers>] <template-prefix> <template-args> E +     * +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    if (!check_input_buffer_char(ibuf, 'N')) +        return NULL; + +    qualifier = itd_cv_qualifiers(context); + +    result = NULL; + +    g_itanium_demangling_push_state(context, &saved); + +    /** +     * Comme <prefix> <unqualified-name> peut aussi être <template-prefix>, +     * on commence par traiter la seconde règle. +     */ + +    left = itd_template_prefix(context); + +    if (left != NULL) +    { +        right = itd_template_args(context); + +        if (right != NULL) +        { +            if (check_input_buffer_char(ibuf, 'E')) +                result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, left, right); + +            else +            { +                if (left != NULL) +                    itd_unref_comp(left); +                itd_unref_comp(right); +            } + +        } + +        else if (left != NULL) +            itd_unref_comp(left); + +    } + +    if (result == NULL) +    { +        g_itanium_demangling_pop_state(context, &saved); + +        left = itd_prefix(context); + +        /** +         * Quand son traitement est un succès, <prefix> doit toujours +         * se terminer par <unqualified-name>. +         */ + +        assert(left == NULL || (left != NULL && is_itd_unqualified_name(context))); + +        /** +         * 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); + +        if (right != NULL) +        { +            if (check_input_buffer_char(ibuf, 'E')) +                result = itd_make_binary(ICT_NESTED_NAME, left, right); + +            else +            { +                if (left != NULL) +                    itd_unref_comp(left); +                itd_unref_comp(right); +            } + +        } + +        else if (left != NULL) +            itd_unref_comp(left); + +    } + +    if (result != NULL) +        itd_make_qualified_type(result, qualifier); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_prefix(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ +    char peek;                              /* Prochain caractère lu       */ +    itanium_component *targs;               /* Composant 'template-args'   */ +    itd_state saved;                        /* Position d'analyse courante */ +    itanium_component *further;             /* Tentative de progression    */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <prefix> ::= <prefix> <unqualified-name> +     *          ::= <template-prefix> <template-args> +     *          ::= <template-param> +     *          ::= # 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> +     * +     * Pour éviter une récursivité qui ferait exploser la pile, on les fusionne +     * en une nouvelle règle <prefix> étendue : +     * +     * <prefix> ::= <prefix> <unqualified-name> +     *          ::= <prefix> <unqualified-name> <template-args> +     *          ::= <template-param> +     *          ::= <template-param> <template-args> +     *          ::= <substitution> +     *          ::= <substitution> <template-args> +     *          ::= # empty +     * +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    if (is_itd_unqualified_name(context)) +        result = itd_unqualified_name(context); + +    else +    { +        peek = peek_input_buffer_char(ibuf); + +        if (peek == 'T') +            result = itd_template_param(context); + +        else if (peek == 'S') +            result = itd_substitution(context); + +        else +            result = NULL; + +    } + +    if (result == NULL) +        goto prefix_exit; + +    g_itanium_demangling_add_substitution(context, result); + +    /** +     * Détection et traitement de <template-args>. +     */ + +    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); + +        targs = itd_template_args(context); + +        if (targs != NULL) +        { +            result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs); + +            g_itanium_demangling_add_substitution(context, result); + +        } + +        else +        { +            itd_unref_comp(result); +            result = NULL; +        } + +    } + +    if (result == NULL) +        goto prefix_exit; + +    /** +     * 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_unref_comp(result); +        result = NULL; +        goto prefix_exit; + +    } + +    /** +     * 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); + +    if (further != NULL) +        result = further; + +    else +        g_itanium_demangling_pop_state(context, &saved); + + prefix_exit: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  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   : -                                                            * +*                                                                             * +******************************************************************************/ + +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    */ + +    /** +     * 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. +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    /** +     * 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. +     */ + +    assert(is_itd_unqualified_name(context)); + +    result = itd_unqualified_name(context); + +    if (result == NULL) +        goto prefix_rec_exit; + +    result = itd_make_binary(ICT_PREFIX_BINARY, leaf, result); + +    g_itanium_demangling_add_substitution(context, result); + +    /** +     * Détection et traitement de <template-args>. +     */ + +    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); + +        targs = itd_template_args(context); + +        if (targs != NULL) +        { +            result = itd_make_binary(ICT_TEMPLATE_NAME_ARGS, result, targs); + +            g_itanium_demangling_add_substitution(context, result); + +        } + +        else +        { +            itd_ref_comp(leaf); +            itd_unref_comp(result); +            result = NULL; +        } + +    } + +    if (result == NULL) +        goto prefix_rec_exit; + +    /** +     * 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; +    } + +    /** +     * 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); + +    if (further != NULL) +        result = further; + +    else +        g_itanium_demangling_pop_state(context, &saved); + + prefix_rec_exit: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_template_prefix(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    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. */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <template-prefix> ::= <prefix> <template unqualified-name> +     *                   ::= <template-param> +     *                   ::= <substitution> +     * +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    peek = peek_input_buffer_char(ibuf); + +    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); + +    } + +    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(ICT_TPREFIX_BINARY, prefix, name); + +            g_itanium_demangling_add_substitution(context, result); + +        } + +        else +        { +            result = NULL; + +            if (prefix != NULL) +                itd_unref_comp(prefix); + +        } + +    } + +    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; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_unqualified_name(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ +    char peek;                              /* Prochain caractère lu       */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <unqualified-name> ::= <operator-name> +     *                    ::= <ctor-dtor-name> +     *                    ::= <source-name> +     * +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    peek = peek_input_buffer_char(ibuf); + +    if (islower(peek)) +        result = itd_operator_name(context); + +    else if (peek == 'C' || peek == 'D') +        result = itd_ctor_dtor_name(context); + +    else if (isdigit(peek)) +        result = itd_source_name(context); + +    else +        result = NULL; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_source_name(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    ssize_t number;                         /* Taille positive             */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <source-name> ::= <positive length number> <identifier> +     * +     */ + +    if (!itd_number(context, &number)) +        return NULL; + +    if (number <= 0) +        return NULL; + +    result = itd_identifier(context, number); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                size    = taille positive ou non lue. [OUT]                  * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Bilan de l'opération (un chifre lu au moins).                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool itd_number(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       */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <number> ::= [n] <non-negative decimal integer> +     * +     */ + +    result = false; + +    negative = false; + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    peek = peek_input_buffer_char(ibuf); + +    if (peek == 'n') +    { +        negative = true; +        advance_input_buffer(ibuf, 1); +        peek = peek_input_buffer_char(ibuf); +    } + +    *size = 0; + +    while (isdigit(peek)) +    { +        result = true; +        *size = *size * 10 + peek - '0'; +        advance_input_buffer(ibuf, 1); +        peek = peek_input_buffer_char(ibuf); +    } + +    if (negative) +        *size *= -1; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                length  = taille de l'identifiant à retrouver.               * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_identifier(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           */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <identifier> ::= <unqualified source code identifier> +     * +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    data = get_input_buffer_string(ibuf, &remaining); + +    if (length > remaining) +        return NULL; + +    result = itd_make_name(data, length); + +    if (result != NULL) +        advance_input_buffer(ibuf, length); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_operator_name(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 +     *                 ::= na    # new[] +     *                 ::= dl    # delete +     *                 ::= da    # delete[] +     *                 ::= ps    # + (unary) +     *                 ::= ng    # - (unary) +     *                 ::= ad    # & (unary) +     *                 ::= de    # * (unary) +     *                 ::= co    # ~ +     *                 ::= pl    # + +     *                 ::= mi    # - +     *                 ::= ml    # * +     *                 ::= dv    # / +     *                 ::= rm    # % +     *                 ::= an    # & +     *                 ::= or    # | +     *                 ::= eo    # ^ +     *                 ::= aS    # = +     *                 ::= pL    # += +     *                 ::= mI    # -= +     *                 ::= mL    # *= +     *                 ::= dV    # /= +     *                 ::= rM    # %= +     *                 ::= aN    # &= +     *                 ::= oR    # |= +     *                 ::= eO    # ^= +     *                 ::= ls    # << +     *                 ::= rs    # >> +     *                 ::= lS    # <<= +     *                 ::= rS    # >>= +     *                 ::= eq    # == +     *                 ::= ne    # != +     *                 ::= lt    # < +     *                 ::= gt    # > +     *                 ::= le    # <= +     *                 ::= ge    # >= +     *                 ::= nt    # ! +     *                 ::= aa    # && +     *                 ::= oo    # || +     *                 ::= pp    # ++ +     *                 ::= mm    # -- +     *                 ::= cm    # , +     *                 ::= pm    # ->* +     *                 ::= pt    # -> +     *                 ::= cl    # () +     *                 ::= ix    # [] +     *                 ::= qu    # ? +     *                 ::= st    # sizeof (a type) +     *                 ::= sz    # sizeof (an expression) +     *                 ::= cv <type> # (cast) +     *                 ::= v <digit> <source-name>   # vendor extended operator +     * +     */ + +    result = NULL; + +    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); + +        if (type != NULL) +            result = itd_make_cast_operator(type); +        else +            result = NULL; + +        goto itd_operator_name_exit; + +    } + +    if (!get_input_buffer_next_char_carefully(ibuf, &code[1])) +        goto itd_operator_name_exit; + +    if (code[0] == 'c' && code[1] == 'v') +    { +        result = NULL; +        goto itd_operator_name_exit; +    } + +    /* Recherche dans la liste des opérateurs reconnus */ + +    info.code = code; + +    int comp_itanium_operators(const itanium_operator_info *a, const itanium_operator_info *b) +    { +        int result;                         /* Bilan à renvoyer            */ + +        if (a->code[0] < b->code[0]) +            result = -1; +        else if (a->code[0] > b->code[0]) +            result = 1; +        else +        { +            if (a->code[1] < b->code[1]) +                result = -1; +            else if (a->code[1] > b->code[1]) +                result = 1; +            else +                result = 0; +        } + +        return result; + +    } + +    found = bsearch(&info, itanium_demangle_operators, +                    ARRAY_SIZE(itanium_demangle_operators), +                    sizeof(itanium_operator_info), (__compar_fn_t)comp_itanium_operators); + +    if (found != NULL) +        result = itd_make_operator(found); + + itd_operator_name_exit: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_special_name(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> ::= 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; + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    if (!get_input_buffer_next_char_carefully(ibuf, &next)) +        goto exit_eof; + +    if (next == 'T') +    { +        peek = peek_input_buffer_char(ibuf); + +        switch (peek) +        { +            case 'V': + +                advance_input_buffer(ibuf, 1); + +                result = itd_type(context); + +                if (result != NULL) +                    result = itd_make_unary(ICT_SPECIAL_NAME_VTABLE, result); + +                break; + +            case 'T': + +                advance_input_buffer(ibuf, 1); + +                result = itd_type(context); + +                if (result != NULL) +                    result = itd_make_unary(ICT_SPECIAL_NAME_VSTRUCT, result); + +                break; + +            case 'I': +                advance_input_buffer(ibuf, 1); +                result = itd_type(context); +                break; + +            case 'S': +                advance_input_buffer(ibuf, 1); +                result = itd_type(context); +                break; + +            case 'c': + +                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; + +                encoding = itd_encoding(context); + +                if (encoding == NULL) +                    itd_unref_comp(offset1); +                else +                    result = itd_make_binary(ICT_FUNCTION_THUNK, encoding, offset1); + +                break; + +        } + +    } + + exit_eof: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_call_offset(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ +    char next;                              /* Caractère suivant           */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <call-offset> ::= h <nv-offset> _ +     *               ::= v <v-offset> _ +     */ + +    result = NULL; + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    if (get_input_buffer_next_char_carefully(ibuf, &next)) +        goto exit_eof; + +    switch (next) +    { +        case 'h': +            result = itd_nv_offset(context); +            break; + +        case 'v': +            result = itd_v_offset(context); +            break; + +    } + +    if (result != NULL && !check_input_buffer_char(ibuf, '_')) +    { +        itd_unref_comp(result); +        result = NULL; +    } + + exit_eof: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_nv_offset(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    ssize_t offset;                         /* Décalage obtenu             */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <nv-offset> ::= <offset number> +     *                     # non-virtual base override +     */ + +    if (!itd_number(context, &offset)) +        return NULL; + +    result = itd_make_offset(ICT_NON_VIRTUAL_OFFSET, offset); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_v_offset(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          */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <v-offset>  ::= <offset number> _ <virtual offset number> +     *                     # virtual base override, with vcall offset +     */ + +    if (!itd_number(context, &offset)) +        return NULL; + +    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(ICT_DOUBLE_OFFSET, +                             itd_make_offset(ICT_NON_VIRTUAL_OFFSET, offset), +                             itd_make_offset(ICT_VIRTUAL_OFFSET, voffset)); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_ctor_dtor_name(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ +    char next;                              /* Caractère suivant           */ +    ItaniumComponentType type;              /* Type de composant           */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <ctor-dtor-name> ::= C1   # complete object constructor +     *                  ::= C2   # base object constructor +     *                  ::= C3   # complete object allocating constructor +     *                  ::= D0   # deleting destructor +     *                  ::= D1   # complete object destructor +     *                  ::= D2   # base object destructor +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    next = peek_input_buffer_char(ibuf); + +    if (next == 'C') +        type = ICT_CONSTRUCTOR; +    else if (next == 'D') +        type = ICT_DESSTRUCTOR; +    else +        return NULL; + +    advance_input_buffer(ibuf, 1); + +    next = peek_input_buffer_char(ibuf); + +    if (next != '0' && next != '1' && next != '2') +        return NULL; + +    advance_input_buffer(ibuf, 1); + +    result = itd_make_with_type(type); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_type(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 : +     * +     * <type> ::= <builtin-type> +     *        ::= <function-type> +     *        ::= <class-enum-type> +     *        ::= <array-type> +     *        ::= <pointer-to-member-type> +     *        ::= <template-param> +     *        ::= <template-template-param> <template-args> +     *        ::= <substitution> # See Compression below +     *        ::= <CV-qualifiers> <type> +     *        ::= P <type>   # pointer-to +     *        ::= R <type>   # reference-to +     *        ::= O <type>   # rvalue reference-to (C++0x) +     *        ::= C <type>   # complex pair (C 2000) +     *        ::= G <type>   # imaginary (C 2000) +     *        ::= U <source-name> <type> # vendor extended type qualifier +     * +     */ + +    result = NULL; + +    qualifier = itd_cv_qualifiers(context); + +    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': + +            advance_input_buffer(ibuf, 1); + +            sub = itd_type(context); +            if (sub == NULL) return NULL; + +            result = itd_make_unary(ICT_POINTER_TO, sub); +            handled = true; +            break; + +        case 'R': + +            advance_input_buffer(ibuf, 1); + +            sub = itd_type(context); +            if (sub == NULL) return NULL; + +            result = itd_make_unary(ICT_REFERENCE_TO, sub); +            handled = true; +            break; + +        case 'O': + +            advance_input_buffer(ibuf, 1); + +            sub = itd_type(context); +            if (sub == NULL) return NULL; + +            result = itd_make_unary(ICT_RVALUE_REFERENCE_TO, sub); +            handled = true; +            break; + +        case 'C': + +            advance_input_buffer(ibuf, 1); + +            sub = itd_type(context); +            if (sub == NULL) return NULL; + +            result = itd_make_unary(ICT_COMPLEX_PAIR, sub); +            handled = true; +            break; + +        case 'G': + +            advance_input_buffer(ibuf, 1); + +            sub = itd_type(context); +            if (sub == NULL) return NULL; + +            result = itd_make_unary(ICT_IMAGINARY, sub); +            handled = true; +            break; + +        case 'U': + +            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': + +            /** +             * 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); + +            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_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_demangling_push_state(context, &saved); + +    result = itd_substitution(context); + +    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; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait une propriété de composant pour un contexte Itanium. * +*                                                                             * +*  Retour      : Indication extraite.                                         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static TypeQualifier itd_cv_qualifiers(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 +     * +     */ + +    result = TQF_NONE; + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    while (1) +        switch (peek_input_buffer_char(ibuf)) +        { +            case 'r': +                result = TQF_RESTRICT; +                advance_input_buffer(ibuf, 1); +                break; + +            case 'V': +                result = TQF_VOLATILE; +                advance_input_buffer(ibuf, 1); +                break; + +            case 'K': +                result = TQF_CONST; +                advance_input_buffer(ibuf, 1); +                break; + +            default: +                goto itd_cv_qualifiers_exit; +                break; + +        } + + itd_cv_qualifiers_exit: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_builtin_type(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              */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <builtin-type> ::= v  # void +     *                ::= w  # wchar_t +     *                ::= b  # bool +     *                ::= c  # char +     *                ::= a  # signed char +     *                ::= h  # unsigned char +     *                ::= s  # short +     *                ::= t  # unsigned short +     *                ::= i  # int +     *                ::= j  # unsigned int +     *                ::= l  # long +     *                ::= m  # unsigned long +     *                ::= x  # long long, __int64 +     *                ::= y  # unsigned long long, __int64 +     *                ::= n  # __int128 +     *                ::= o  # unsigned __int128 +     *                ::= f  # float +     *                ::= d  # double +     *                ::= e  # long double, __float80 +     *                ::= g  # __float128 +     *                ::= z  # ellipsis +     *                ::= u <source-name>    # vendor extended type +     * +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    switch (peek_input_buffer_char(ibuf)) +    { +        case 'v': +            type = BTP_VOID; +            break; +        case 'w': +            type = BTP_WCHAR_T; +            break; +        case 'b': +            type = BTP_BOOL; +            break; +        case 'c': +            type = BTP_CHAR; +            break; +        case 'a': +            type = BTP_SCHAR; +            break; +        case 'h': +            type = BTP_UCHAR; +            break; +        case 's': +            type = BTP_SHORT; +            break; +        case 't': +            type = BTP_USHORT; +            break; +        case 'i': +            type = BTP_INT; +            break; +        case 'j': +            type = BTP_UINT; +            break; +        case 'l': +            type = BTP_LONG; +            break; +        case 'm': +            type = BTP_ULONG; +            break; +        case 'x': +            type = BTP_LONG_LONG; +            break; +        case 'y': +            type = BTP_ULONG_LONG; +            break; +        case 'n': +            type = BTP_INT128; +            break; +        case 'o': +            type = BTP_UINT128; +            break; +        case 'f': +            type = BTP_FLOAT; +            break; +        case 'd': +            type = BTP_DOUBLE; +            break; +        case 'e': +            type = BTP_LONG_DOUBLE; +            break; +        case 'g': +            type = BTP_FLOAT128; +            break; +        case 'z': +            type = BTP_ELLIPSIS; +            break; +        case 'u': + +            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; +    } + +    if (type != BTP_INVALID) +    { +        builtin = g_basic_type_new(type); +        result = itd_make_type(builtin); +        advance_input_buffer(ibuf, 1); +    } +    else +        result = NULL; + + done: + +    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_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 */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <bare-function-type> ::= <signature type>+ +     *       # types are possible return type, then parameter types +     * +     */ + +    type = itd_type(context); +    if (type == NULL) return NULL; + +    result = itd_append_right_to_binary(ICT_TYPES_LIST, NULL, type); + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    while (count_input_buffer_remaining(ibuf) > 0) +    { +        g_itanium_demangling_push_state(context, &saved); + +        type = itd_type(context); + +        if (type == NULL) +        { +            g_itanium_demangling_pop_state(context, &saved); +            break; +        } + +        result = itd_append_right_to_binary(ICT_TYPES_LIST, result, type); + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_class_enum_type(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <class-enum-type> ::= <name> +     * +     */ + +    result = itd_name(context); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_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; + +} + + +/****************************************************************************** +*                                                                             * +*  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_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 */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <template-args> ::= I <template-arg>+ E +     * +     */ + +    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(ICT_TYPES_LIST, NULL, arg); + +    while (1) +    { +        g_itanium_demangling_push_state(context, &saved); + +        arg = itd_template_arg(context); +        if (arg == NULL) +        { +            g_itanium_demangling_pop_state(context, &saved); +            break; +        } + +        result = itd_append_right_to_binary(ICT_TYPES_LIST, result, arg); + +    } + +    if (!check_input_buffer_char(ibuf, 'E')) +    { +        itd_unref_comp(result); +        return NULL; +    } + +    result = itd_make_unary(ICT_TEMPLATE_ARGS, result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_template_arg(GItaniumDemangling *context) +{ +    itanium_component *result;              /* Construction à retourner    */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ +    char peek;                              /* Prochain caractère lu       */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <template-arg> ::= <type>                     # type or template +     *                ::= X <expression> E           # expression +     *                ::= <expr-primary>             # simple expressions +     * +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    peek = peek_input_buffer_char(ibuf); + +    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)) +    { +        next_peek = peek_input_buffer_next_char(ibuf); + +        if (peek == 's' && next_peek == 't') +        { +            advance_input_buffer(ibuf, 2); + +            result = itd_type(context); + +        } + +        else if (peek == 's' && next_peek == 'r') +        { +            advance_input_buffer(ibuf, 2); + +            result = itd_type(context); + +            if (result != NULL) +            { +                itd_unref_comp(result); + +                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) +            { +                odata = itd_get_operator_info(result, &otype); + +                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; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                hex     = prise en compte des caractères hexadécimaux ?      * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_value_to_string(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 */ +    char peek;                              /* Prochain caractère lu       */ + +    /** +     * Les règles traitées ici sont les suivantes : +     * +     * <value number>  # integer literal +     * <value float>   # floating literal +     * +     */ + +    result = NULL; + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    data = get_input_buffer_text_access(ibuf); + +    g_itanium_demangling_push_state(context, &saved); + +    while (1) +    { +        peek = peek_input_buffer_char(ibuf); + +        switch (peek) +        { +            case '0' ... '9': +                advance_input_buffer(ibuf, 1); +                break; + +            case 'a' ... 'f': +                if (hex) +                    advance_input_buffer(ibuf, 1); +                else +                    goto exit_iits; +                break; + +            case 'E': +                goto exit_loop; +                break; + +            default: +                goto exit_iits; + +        } + +    } + + exit_loop: + +    g_itanium_demangling_push_state(context, &cur); + +    if ((cur.pos - saved.pos) > 0) +        result = itd_make_name(data, cur.pos - saved.pos); + + exit_iits: + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_expr_primary(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 */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <expr-primary> ::= L <type> <value number> E  # integer literal +     *                ::= L <type> <value float> E   # floating literal +     *                ::= L <mangled-name> E         # external name +     * +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    if (!check_input_buffer_char(ibuf, 'L')) +        return NULL; + +    g_itanium_demangling_push_state(context, &saved); + +    type = itd_type(context); + +    if (type != NULL) +    { +        g_itanium_demangling_push_state(context, &saved_value); + +        /* Règle <type> <value number> */ + +        result = itd_value_to_string(context, false); + +        if (result != NULL && !check_input_buffer_char(ibuf, 'E')) +        { +            itd_unref_comp(result); +            result = NULL; +        } + +        /* Règle <type> <value float> */ + +        if (result == NULL) +        { +            g_itanium_demangling_pop_state(context, &saved_value); + +            result = itd_value_to_string(context, true); + +            if (result != NULL && !check_input_buffer_char(ibuf, 'E')) +            { +                itd_unref_comp(result); +                result = NULL; +            } + +        } + +        itd_unref_comp(type); + +    } +    else +        result = NULL; + +    /* Règle <mangled-name> */ + +    if (result == NULL) +    { +        g_itanium_demangling_pop_state(context, &saved); +        result = itd_mangled_name(context); + +        if (result != NULL && !check_input_buffer_char(ibuf, 'E')) +        { +            itd_unref_comp(result); +            result = NULL; +        } + +    } + +    return result; + +} + + + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                cur     = caractère courant.                                 * +*                id      = identifiant lu en cas de succès. [OUT]             * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool itd_seq_id(GItaniumDemangling *context, char cur, size_t *id) +{ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ + +    /** +     * La règle traitée ici est la suivante : +     * +     * <seq-id> +     * +     */ + +    *id = 0; + +    /** +     * La fonction n'est appelée que si un début de séquence est détecté. +     * (ie, cur == '_' || isdigit(cur) || isupper(cur)). +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    if (cur != '_') +    { +        do +        { +            if (isdigit(cur)) +                *id = *id * 36 + cur - '0'; +            else if (isupper(cur)) +                *id = *id * 36 + cur - 'A' + 10; +            else +                return false; + +            if (!get_input_buffer_next_char_carefully(ibuf, &cur)) +                return false; + +        } +        while (cur != '_'); + +        (*id)++; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à utiliser.                   * +*                                                                             * +*  Description : Extrait un composant dans un contexte Itanium.               * +*                                                                             * +*  Retour      : Composant extrait ou NULL en cas d'échec.                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static itanium_component *itd_substitution(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 */ +    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 : +     * +     * <substitution> ::= S <seq-id> _ +     *                ::= S_ +     *                ::= St # ::std:: +     *                ::= Sa # ::std::allocator +     *                ::= Sb # ::std::basic_string +     *                ::= Ss # ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>> +     *                ::= Si # ::std::basic_istream<char, std::char_traits<char>> +     *                ::= So # ::std::basic_ostream<char, std::char_traits<char>> +     *                ::= Sd # ::std::basic_iostream<char, std::char_traits<char>> +     * +     */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    if (!check_input_buffer_char(ibuf, 'S')) +        return NULL; + +    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; + +        result = g_itanium_demangling_get_substitution(context, id); + +    } +    else +    { +        for (i = 0; i < ARRAY_SIZE(itanium_standard_substitutions); i++) +        { +            stdinfo = &itanium_standard_substitutions[i]; + +            if (stdinfo->code == cur) +            { +                std = g_class_enum_type_new(CET_NAMESPACE, strdup("std")); + +                if (stdinfo->class == NULL) +                    type = std; + +                else +                { +                    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/plugins/itanium/abi.h b/plugins/itanium/abi.h new file mode 100644 index 0000000..d286b2f --- /dev/null +++ b/plugins/itanium/abi.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * abi.h - prototypes pour le décodage des noms d'éléments selon l'ABI C++ Itanium + * + * Copyright (C) 2013-2017 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ITANIUM_ABI_H +#define _PLUGINS_ITANIUM_ABI_H + + +#include "component.h" +#include "context.h" + + + +/* Extrait un composant dans un contexte Itanium. */ +itanium_component *itd_mangled_name(GItaniumDemangling *); + + + +#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/plugins/itanium/component.h b/plugins/itanium/component.h new file mode 100644 index 0000000..f921ff9 --- /dev/null +++ b/plugins/itanium/component.h @@ -0,0 +1,294 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * component.h - prototypes pour la représentation des composants extraits de l'ABI C++ Itanium + * + * Copyright (C) 2013-2017 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ITANIUM_COMPONENT_H +#define _PLUGINS_ITANIUM_COMPONENT_H + + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <malloc.h> +#include <sys/types.h> + + +#include <analysis/routine.h> +#include <analysis/type.h> +#include <common/fnv1a.h> + + + +/* Type de composants */ +typedef enum _ItaniumComponentType +{ +    /** +     * Chaîne de caractère, terminée par un octet nul. +     */ +    ICT_NAME, + +    /** +     * Nom avec préfixe standard. +     * Le nom en question est placé dans le champ unary. +     */ +    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, + +    /** +     * Type avec préfixes : deux éléments, dans 'binary' +     */ +    ICT_PREFIX_BINARY, + +    /** +     * Préfixes à deux éléments. +     * En cas de préfixe nul, le composant gauche peut être nul. +     */ +    ICT_TPREFIX_BINARY, + +    /** +     * Encodage d'un nom d'opérateur, consigné dans 'operator'. +     */ +    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, + +    /** +     * Constructeur ou destructeur, sans plus de détail. +     */ +    ICT_CONSTRUCTOR, +    ICT_DESSTRUCTOR, + +    /** +     * Type instanciable dans le programme. +     */ +    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'. +     */ +    ICT_POINTER_TO, +    ICT_REFERENCE_TO, +    ICT_RVALUE_REFERENCE_TO, +    ICT_COMPLEX_PAIR, +    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 +     */ +    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. +     */ +    ICT_TEMPLATE_ARGS, + +    /** +     * Liste de types, sous forme binaire : +     *  -> left = élément de la liste de types. +     *  -> right = reste de la liste de types. +     */ +    ICT_TYPES_LIST, + +    /** +     * 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; + + +/* Catégories d'opérateurs */ +typedef enum _ItaniumOperatorType +{ +    IOT_SIMPLE,                             /* Présent dans la liste       */ +    IOT_CAST,                               /* Conversion forcée           */ +    IOT_VENDOR                              /* Défini par un vendeur       */ + +} ItaniumOperatorType; + + +/* Enregistrement des opérateurs */ +typedef struct _itanium_operator_info +{ +    const char *code;                       /* Nom encodé                  */ +    const char *name;                       /* Désignation humaine         */ +    size_t name_len;                        /* Taille du nom humain        */ +    int args;                               /* Nombre d'arguments          */ + +} itanium_operator_info; + + +/* Composant extrait de l'encodage */ +typedef struct _itanium_component itanium_component; + + + +/* Incrémente le nombre d'utilisation du composant. */ +void itd_ref_comp(itanium_component *); + +/* Décrémente le nombre d'utilisation du composant. */ +void itd_unref_comp(itanium_component *); + +/* Détermine ou fournit l'empreinte d'un composant. */ +fnv64_t itd_hash_comp(itanium_component *); + +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_with_type(ItaniumComponentType); + +/* 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_operator(const itanium_operator_info *); + +/* Construit un composant dans un contexte Itanium. */ +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_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_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_array_with_dim_expr(itanium_component *, itanium_component *); + +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_pointer_to_memeber_type(itanium_component *, itanium_component *); + +/* Construit un composant dans un contexte Itanium. */ +itanium_component *itd_make_unary(ItaniumComponentType, itanium_component *); + +/* Construit un composant dans un contexte Itanium. */ +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); + +/* Fournit le type d'un composant issu d'un contexte Itanium. */ +ItaniumComponentType itd_get_component_type(const itanium_component *); + +/* Traduit les composants de contexte Itanium. */ +char *itd_translate_component(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  /* _PLUGINS_ITANIUM_COMPONENT_H */ diff --git a/plugins/itanium/context.c b/plugins/itanium/context.c new file mode 100644 index 0000000..1d2c365 --- /dev/null +++ b/plugins/itanium/context.c @@ -0,0 +1,516 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * context.c - contexte de décodage à la sauce ABI C++ Itanium + * + * Copyright (C) 2013-2017 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  Chrysalide is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  Chrysalide is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "context.h" + + +#include <assert.h> +#include <malloc.h> +#include <string.h> + + +#include <mangling/context-int.h> + + +#include "abi.h" +#include "component-int.h" + + + +/* Contexte de décodage Itanium (instance) */ +struct _GItaniumDemangling +{ +    GDemanglingContext parent;              /* A laisser en premier        */ + +    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           */ + +}; + +/* Contexte de décodage Itanium (classe) */ +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(GItaniumDemangling, g_itanium_demangling, G_TYPE_DEMANGLING_CONTEXT); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des contextes de décodage.              * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +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; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = instance à initialiser.                            * +*                                                                             * +*  Description : Initialise une instance de contexte pour décodage.           * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_itanium_demangling_init(GItaniumDemangling *context) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = instance d'objet GLib à traiter.                   * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_itanium_demangling_dispose(GItaniumDemangling *context) +{ +    G_OBJECT_CLASS(g_itanium_demangling_parent_class)->dispose(G_OBJECT(context)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = instance d'objet GLib à traiter.                   * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_itanium_demangling_finalize(GItaniumDemangling *context) +{ +    size_t i;                               /* Boucle de parcours          */ + +    for (i = 0; i < context->targs_count; i++) +        itd_unref_comp(context->template_args[i]); + +    if (context->template_args != NULL) +        free(context->template_args); + +    for (i = 0; i < context->subst_count; i++) +        itd_unref_comp(context->substitutions[i]); + +    if (context->substitutions != NULL) +        free(context->substitutions); + +    G_OBJECT_CLASS(g_itanium_demangling_parent_class)->finalize(G_OBJECT(context)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = environnement de décodage à manipuler.             * +*                                                                             * +*  Description : Prépare l'environnement de contexte pour un décodage Itanium.* +*                                                                             * +*  Retour      : -                                                     .      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_itanium_demangling_prepare(GItaniumDemangling *context) +{ +    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); + +    assert(context->substitutions == NULL); + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    len = get_input_buffer_size(ibuf); + +    context->template_args = (itanium_component **)malloc(len * sizeof(itanium_component *)); + +    context->substitutions = (itanium_component **)malloc(len * sizeof(itanium_component *)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = environnement de décodage à manipuler.             * +*                comp    = composant final à valider. [OUT]                   * +*                                                                             * +*  Description : Valide un composant final issu d'un décodage Itanium.        * +*                                                                             * +*  Retour      : -                                                     .      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_itanium_demangling_check(GItaniumDemangling *context, itanium_component **comp) +{ +    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); + +        if (remaining > 0) +        { +            itd_unref_comp(*comp); +            *comp = NULL; +        } + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = environnement de décodage à manipuler.             * +*                                                                             * +*  Description : Décode une définition de type pour Itanium.                  * +*                                                                             * +*  Retour      : Nouvelle instance créée ou NULL en cas d'erreur fatale.      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static GDataType *g_itanium_demangling_decode_type(GItaniumDemangling *context) +{ +    GDataType *result;                      /* Type construit à 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; + +    else +    { +        result = itd_translate_component_to_type(comp); + +        itd_unref_comp(comp); + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = environnement de décodage à manipuler.             * +*                                                                             * +*  Description : Décode une définition de routine pour Itanium.               * +*                                                                             * +*  Retour      : Nouvelle instance créée ou NULL en cas d'erreur fatale.      * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static GBinRoutine *g_itanium_demangling_decode_routine(GItaniumDemangling *context) +{ +    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; + +    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 l'état courant à une fin de retour en arrière.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_itanium_demangling_push_state(const GItaniumDemangling *context, itd_state *state) +{ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    save_input_buffer_pos(ibuf, &state->pos); +    state->targs_count = context->targs_count; +    state->subst_count = context->subst_count; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à manipuler.                  * +*                state   = état courant à restaurer.                          * +*                                                                             * +*  Description : Définit l'état courant suite à un retour en arrière.         * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_itanium_demangling_pop_state(GItaniumDemangling *context, const itd_state *state) +{ +    size_t i;                               /* Boucle de parcours          */ +    input_buffer *ibuf;                     /* Tampon de texte manipulé    */ + +    for (i = state->targs_count; i < context->targs_count; i++) +        itd_unref_comp(context->template_args[i]); + +    for (i = state->subst_count; i < context->subst_count; i++) +        itd_unref_comp(context->substitutions[i]); + +    ibuf = &G_DEMANGLING_CONTEXT(context)->buffer; + +    restore_input_buffer_pos(ibuf, state->pos); +    context->targs_count = state->targs_count; +    context->subst_count = state->subst_count; + +} + + +/****************************************************************************** +*                                                                             * +*  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   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_itanium_demangling_add_template_arg(GItaniumDemangling *context, itanium_component *comp) +{ +    assert(comp != NULL); + +    context->template_args[context->targs_count++] = comp; +    itd_ref_comp(comp); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à manipuler.                  * +*                index   = indice de l'argument visé.                         * +*                                                                             * +*  Description : Fournit un composant représentant un argument de modèle.     * +*                                                                             * +*  Retour      : Composant déjà extrait et conservé.                          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +itanium_component *g_itanium_demangling_get_template_arg(GItaniumDemangling *context, size_t index) +{ +    itanium_component *result;              /* Composant à retourner       */ + +    if (index < context->targs_count) +    { +        result = context->template_args[index]; +        itd_ref_comp(result); +    } +    else +        result = NULL; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à manipuler.                  * +*                comp    = composant à conserver en mémoire.                  * +*                                                                             * +*  Description : Indexe un composant comme future substitution potentielle.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_itanium_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++) +        if (cmp_fnv_64a(itd_hash_comp(context->substitutions[i]), hash) == 0) +            break; + +    if (i == context->subst_count) +    { +        context->substitutions[context->subst_count++] = comp; +        itd_ref_comp(comp); +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : context = contexte de décodage à manipuler.                  * +*                index   = indice de la substitution visée.                   * +*                                                                             * +*  Description : Fournit un composant en place pour une substitution.         * +*                                                                             * +*  Retour      : Composant déjà extrait et conservé.                          * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +itanium_component *g_itanium_demangling_get_substitution(GItaniumDemangling *context, size_t index) +{ +    itanium_component *result;              /* Composant à retourner       */ + +    if (index < context->subst_count) +    { +        result = context->substitutions[index]; +        itd_ref_comp(result); +    } +    else +        result = NULL; + +    return result; + +} 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 */  | 
