From 29a22c425f492427f45b71de937f2d99587c8d34 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 8 Mar 2009 22:05:09 +0000 Subject: Added a partial support of the Itanium C++ ABI mangling. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@52 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 44 +++ configure.ac | 3 + src/Makefile.am | 3 +- src/analysis/Makefile.am | 4 +- src/analysis/prototype.c | 260 +++++++++++++ src/analysis/prototype.h | 69 ++++ src/analysis/variable.c | 728 ++++++++++++++++++++++++++++++++++++ src/analysis/variable.h | 176 +++++++++ src/binary.c | 2 + src/common/Makefile.am | 3 +- src/common/extstr.c | 85 +++++ src/common/extstr.h | 37 ++ src/editor.c | 4 + src/format/Makefile.am | 2 +- src/format/mangling/Makefile.am | 25 ++ src/format/mangling/demangler-int.h | 53 +++ src/format/mangling/demangler.c | 134 +++++++ src/format/mangling/demangler.h | 59 +++ src/format/mangling/itanium.h | 37 ++ src/format/mangling/itanium_gram.y | 518 +++++++++++++++++++++++++ src/format/mangling/itanium_tok.l | 116 ++++++ 21 files changed, 2358 insertions(+), 4 deletions(-) create mode 100644 src/analysis/prototype.c create mode 100644 src/analysis/prototype.h create mode 100644 src/analysis/variable.c create mode 100644 src/analysis/variable.h create mode 100644 src/common/extstr.c create mode 100644 src/common/extstr.h create mode 100644 src/format/mangling/Makefile.am create mode 100644 src/format/mangling/demangler-int.h create mode 100644 src/format/mangling/demangler.c create mode 100644 src/format/mangling/demangler.h create mode 100644 src/format/mangling/itanium.h create mode 100644 src/format/mangling/itanium_gram.y create mode 100644 src/format/mangling/itanium_tok.l diff --git a/ChangeLog b/ChangeLog index c189e02..3603eed 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,49 @@ 2009-03-04 Cyrille Bagard + * configure.ac: + Look for the lex and yacc programs. Add the new Makefile from + 'src/format/mangling' directory to AC_CONFIG_FILES. + + * src/analysis/Makefile.am: + Add prototype.h.[ch] and variable.h.[ch] to libanalysis_a_SOURCES. + + * src/analysis/prototype.c: + * src/analysis/prototype.h: + * src/analysis/variable.c: + * src/analysis/variable.h: + New entries: create an abstract representation of prototypes, types + and variables. + + * src/binary.c: + Load strings and symbols again. + + * src/common/extstr.c: + * src/common/extstr.h: + New entries: provide an extension to usual string functions. + + * src/common/Makefile.am: + Add extstr.[ch] to libcommon_a_SOURCES. + + * src/editor.c: + Load all demanglers. + + * src/format/Makefile.am: + Add mangling to SUBDIRS. + + * src/format/mangling/demangler.c: + * src/format/mangling/demangler.h: + * src/format/mangling/demangler-int.h: + * src/format/mangling/itanium_gram.y: + * src/format/mangling/itanium.h: + * src/format/mangling/itanium_tok.l: + * src/format/mangling/Makefile.am: + New entries: support (partially) Itanium C++ ABI mangling. + + * src/Makefile.am: + Add format/mangling/libformatmangling.a to openida_LDADD and reorder it. + +2009-03-04 Cyrille Bagard + * src/analysis/line.c: * src/analysis/line.h: Add a line type for binary code display and some generic diff --git a/configure.ac b/configure.ac index 86334a5..7a95ffd 100644 --- a/configure.ac +++ b/configure.ac @@ -24,6 +24,8 @@ AC_CONFIG_SRCDIR([src/editor.c]) AC_PROG_CC AM_PROG_CC_C_O +AC_PROG_LEX +AC_PROG_YACC AC_PROG_INSTALL AC_PROG_MAKE_SET AC_PROG_LIBTOOL @@ -190,6 +192,7 @@ AC_CONFIG_FILES([Makefile src/format/dwarf/Makefile src/format/elf/Makefile src/format/java/Makefile + src/format/mangling/Makefile src/format/pe/Makefile src/gtkext/Makefile src/panel/Makefile]) diff --git a/src/Makefile.am b/src/Makefile.am index 948cc32..30dc2d2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,16 +27,17 @@ openida_LDFLAGS = $(LIBGTK_LIBS) -L/usr/X11R6/lib -ldl -lm $(LIBXML_LIBS) `pkg-c openida_LDADD = $(LIBINTL) \ - analysis/libanalysis.a \ arch/libarch.a \ arch/x86/libarchx86.a \ format/libformat.a \ format/dwarf/libformatdwarf.a \ format/elf/libformatelf.a \ format/java/libformatjava.a \ + format/mangling/libformatmangling.a \ format/pe/libformatpe.a \ gtkext/libgtkext.a \ panel/libpanel.a \ + analysis/libanalysis.a \ common/libcommon.a diff --git a/src/analysis/Makefile.am b/src/analysis/Makefile.am index c3b2e64..e652f5d 100755 --- a/src/analysis/Makefile.am +++ b/src/analysis/Makefile.am @@ -2,7 +2,9 @@ lib_LIBRARIES = libanalysis.a libanalysis_a_SOURCES = \ - line.h line.c + line.h line.c \ + prototype.h prototype.c \ + variable.h variable.c libanalysis_a_CFLAGS = $(AM_CFLAGS) diff --git a/src/analysis/prototype.c b/src/analysis/prototype.c new file mode 100644 index 0000000..aa3ca2f --- /dev/null +++ b/src/analysis/prototype.c @@ -0,0 +1,260 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * prototype.c - manipulation des prototypes de fonctions et de variables + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include "prototype.h" + + +#include + + +#include "../common/extstr.h" + + + +/* Variable représentant un prototype de routine */ +struct _bin_routine +{ + RoutineType type; /* Type de routine */ + + variable *ret_type; /* Type retourné */ + + char *name; /* Désignation humaine */ + + variable **args_types; /* Types d'arguments */ + size_t args_count; /* Nombre d'arguments */ + +}; + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une représentation de routine. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bin_routine *create_binary_routine(void) +{ + bin_routine *result; /* Structure à retourner */ + + result = (bin_routine *)calloc(1, sizeof(bin_routine)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : routine = routine à effacer. * +* * +* Description : Supprime une représentation de routine de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_binary_routine(bin_routine *routine) +{ + size_t i; /* Boucle de parcours */ + + if (routine->ret_type) + delete_var(routine->ret_type); + + if (routine->name != NULL) + free(routine->name); + + for (i = 0; i < routine->args_count; i++) + delete_var(routine->args_types[i]); + + free(routine); + +} + + +/****************************************************************************** +* * +* Paramètres : routine = routine à mettre à jour. * +* type = type de routine spécifié. * +* * +* Description : Définit le type d'une routine. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void set_binary_routine_type(bin_routine *routine, RoutineType type) +{ + routine->type = type; + +} + + +/****************************************************************************** +* * +* Paramètres : routine = routine à mettre à jour. * +* name = désignation humainement lisible. * +* * +* Description : Définit le nom humain d'une routine. * +* * +* Retour : - * +* * +* Remarques : Le nom ne doit pas ensuite être libéré par l'appelant ! * +* * +******************************************************************************/ + +void set_binary_routine_name(bin_routine *routine, char *name) +{ + if (routine->name != NULL) + free(routine->name); + + routine->name = name; + +} + + +/****************************************************************************** +* * +* Paramètres : routine = routine à mettre à jour. * +* var = variable représentant un type de retour. * +* * +* Description : Définit le type de retour d'une routine. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void set_binary_routine_return_type(bin_routine *routine, variable *var) +{ + if (routine->ret_type != NULL) + delete_var(routine->ret_type); + + routine->ret_type = var; + +} + + +/****************************************************************************** +* * +* Paramètres : routine = routine à mettre à jour. * +* var = variable représentant un argument supplémentaire. * +* * +* Description : Ajoute un argument à une routine. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void add_arg_to_binary_routine(bin_routine *routine, variable *var) +{ + routine->args_count++; + + routine->args_types = (variable **)realloc(routine->args_types, + routine->args_count * sizeof(variable *)); + + routine->args_types[routine->args_count - 1] = var; + +} + + +/****************************************************************************** +* * +* Paramètres : routine = routine à consulter. * +* * +* Description : Décrit le prototype de la routine sous forme de caractères. * +* * +* Retour : Chaîne de caractères à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *routine_to_string(const bin_routine *routine) +{ + char *result; /* Chaîne à renvoyer */ + size_t i; /* Boucle de parcours */ + char *typestr; /* Stockage de nom temporaire */ + + /* Retour de la fonction */ + + switch (routine->type) + { + case RTT_CONSTRUCTOR: + result = strdup(routine->name); + result = stradd(result, "::"); + break; + + case RTT_DESTRUCTOR: + result = strdup(routine->name); + result = stradd(result, "::~"); + break; + + default: /* Pour gcc */ + case RTT_CLASSIC: + if (routine->ret_type == NULL) result = strdup("??? "); + else + { + result = var_to_string(routine->ret_type); + result = stradd(result, " "); + } + break; + + } + + /* Nom de la routine */ + + result = stradd(result, routine->name); + + /* Liste des arguments */ + + result = stradd(result, "("); + + for (i = 0; i < routine->args_count; i++) + { + if (i > 0) result = stradd(result, ", "); + + typestr = var_to_string(routine->args_types[i]); + result = stradd(result, typestr); + free(typestr); + + } + + result = stradd(result, ")"); + + return result; + +} diff --git a/src/analysis/prototype.h b/src/analysis/prototype.h new file mode 100644 index 0000000..f86d541 --- /dev/null +++ b/src/analysis/prototype.h @@ -0,0 +1,69 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * prototype.h - prototypes pour la manipulation des prototypes de fonctions et de variables + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#ifndef _ANALYSIS_PROTOTYPE_H +#define _ANALYSIS_PROTOTYPE_H + + +#include "variable.h" + + + +/* Type de routine traitée */ +typedef enum _RoutineType +{ + RTT_CLASSIC, /* Fonction ou méthode */ + RTT_CONSTRUCTOR, /* Constructeur */ + RTT_DESTRUCTOR /* Destructeur */ + +} RoutineType; + + +/* Variable représentant un prototype de routine */ +typedef struct _bin_routine bin_routine; + + +/* Crée une représentation de routine. */ +bin_routine *create_binary_routine(void); + +/* Supprime une représentation de routine de la mémoire. */ +void delete_binary_routine(bin_routine *); + +/* Définit le type d'une routine. */ +void set_binary_routine_type(bin_routine *, RoutineType); + +/* Définit le nom humain d'une routine. */ +void set_binary_routine_name(bin_routine *, char *); + +/* Définit le type de retour d'une routine. */ +void set_binary_routine_return_type(bin_routine *, variable *); + +/* Ajoute un argument à une routine. */ +void add_arg_to_binary_routine(bin_routine *, variable *); + +/* Décrit le prototype de la routine sous forme de caractères. */ +char *routine_to_string(const bin_routine *); + + + +#endif /* _ANALYSIS_PROTOTYPE_H */ diff --git a/src/analysis/variable.c b/src/analysis/variable.c new file mode 100644 index 0000000..058c152 --- /dev/null +++ b/src/analysis/variable.c @@ -0,0 +1,728 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * variable.c - manipulation des variables en tout genre + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include "variable.h" + + +#include +#include +#include + + +#include "../common/extstr.h" + + + +/* ---------------------------- TYPES DE DONNEES SIMPLES ---------------------------- */ + + +/* Variable représentant un argument ou un type de retour */ +struct _simple_variable +{ + BaseType type; /* Type représenté */ + +}; + + +/* Décrit la variable simple sous forme de caractères. */ +char *simple_var_to_string(const simple_variable *); + +/* Supprime de la mémoire une variable de type simple. */ +void delete_simple_var(simple_variable *); + + + +/* --------------------- ENCAPSULATIONS DES VARIABLES COMPLEXES --------------------- */ + + +/* Supprime de la mémoire une variable de type complexe. */ +typedef void (* delete_complex_fc) (complex_variable *); + +/* Décrit la variable complexe sous forme de caractères. */ +typedef char * (* complex_to_string_fc) (const complex_variable *); + + +/* Représentation d'une variable complexe */ +struct _complex_variable +{ + delete_complex_fc delete; /* Procédure de suppression */ + complex_to_string_fc to_string; /* Conversion en chaîne */ + +}; + + +/* Initialise une représentation de variable complexe. */ +void init_complex_var(complex_variable *); + +/* Supprime de la mémoire une variable de type complexe. */ +void delete_complex_var(complex_variable *); + +/* Décrit la variable simple sous forme de caractères. */ +char *complex_var_to_string(const complex_variable *); + + + +/* ---------------------- VARIABLES DE CLASSES ET ENUMERATIONS ---------------------- */ + + +/* Représentation des classes et des énumérations */ +struct _class_enum_variable +{ + complex_variable complex; /* A laisser en premier */ + + ClassEnumType type; /* Type représenté si connu */ + + char *desc; /* Description humaine */ + +}; + + +/* Supprime de la mémoire une variable de classe/enumération. */ +void delete_class_enum_var(class_enum_variable *); + +/* Décrit la variable complexe sous forme de caractères. */ +char *class_enum_var_to_string(const class_enum_variable *); + + + +/* -------------------------- VARIABLES DEPENDANT D'AUTRES -------------------------- */ + + +/* Représentation des variables dérivées */ +struct _encapsulated_variable +{ + complex_variable complex; /* A laisser en premier */ + + EncapsulationType type; /* Encapsulation utilisée */ + variable *child; /* Sous-type encadré */ + +}; + + +/* Supprime de la mémoire une variable dérivée. */ +void delete_encapsulated_var(encapsulated_variable *); + +/* Décrit la variable dérivée sous forme de caractères. */ +char *encapsulated_var_to_string(const encapsulated_variable *); + + + +/* ---------------------- MANIPULATION GENERIQUE DES VARIABLES ---------------------- */ + + +/* Variable représentant un argument ou un type de retour */ +struct _variable +{ + union + { + simple_variable *simple; /* Variable simple */ + complex_variable *complex; /* Variable plus compliquée */ + + } value; + + bool is_simple; /* Choix du champ valide */ + + VariableQualifier qualifiers; /* Eventuels qualificatifs */ + +}; + + + +/* ---------------------------------------------------------------------------------- */ +/* TYPES DE DONNEES SIMPLES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une représentation de variable. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +simple_variable *create_simple_var(void) +{ + simple_variable *result; /* Structure à retourner */ + + result = (simple_variable *)calloc(1, sizeof(simple_variable)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type de base à représenter. * +* * +* Description : Crée une représentation de variable à type connu. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +simple_variable *create_typed_simple_var(BaseType type) +{ + simple_variable *result; /* Structure à retourner */ + + result = create_simple_var(); + + set_simple_var_type(result, type); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à effacer. * +* * +* Description : Supprime de la mémoire une variable de type simple. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_simple_var(simple_variable *var) +{ + free(var); + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à mettre à jour. * +* type = type de base à représenter. * +* * +* Description : Définit le type d'une variable simple. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void set_simple_var_type(simple_variable *var, BaseType type) +{ + var->type = type; + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à consulter. * +* * +* Description : Décrit la variable simple sous forme de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *simple_var_to_string(const simple_variable *var) +{ + char *result; /* Chaîne à renvoyer */ + + switch (var->type) + { + case BTP_VOID: + result = "void"; + break; + case BTP_WCHAR_T: + result = "wchar_t"; + break; + case BTP_BOOL: + result = "bool"; + break; + case BTP_CHAR: + result = "char"; + break; + case BTP_SCHAR: + result = "signed char"; + break; + case BTP_UCHAR: + result = "unsigned char"; + break; + case BTP_SHORT: + result = "short"; + break; + case BTP_USHORT: + result = "unsigned short"; + break; + case BTP_INT: + result = "int"; + break; + case BTP_UINT: + result = "unsigned int"; + break; + case BTP_LONG: + result = "long"; + break; + case BTP_ULONG: + result = "unsigned long"; + break; + case BTP_LONG_LONG: + result = "long long"; + break; + case BTP_ULONG_LONG: + result = "unsigned long long"; + break; + case BTP_INT128: + result = "__int128"; + break; + case BTP_UINT128: + result = "__uint128"; + break; + case BTP_FLOAT: + result = "float"; + break; + case BTP_DOUBLE: + result = "double"; + break; + case BTP_LONG_DOUBLE: + result = "__float80"; + break; + case BTP_FLOAT128: + result = "__float128"; + break; + case BTP_ELLIPSIS: + result = "..."; + break; + case BTP_754R_64: + result = "754r_float64"; + break; + case BTP_754R_128: + result = "754r_float128"; + break; + case BTP_754R_32: + result = "754r_float32"; + break; + case BTP_754R_16: + result = "754r_float16"; + break; + case BTP_CHAR32_T: + result = "char32_t"; + break; + case BTP_CHAR16_T: + result = "char16_t"; + break; + case BTP_OTHER: + result = "[toto]"; /* FIXME */ + break; + default: + result = "/* pour gcc */"; + break; + } + + result = strdup(result); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* ENCAPSULATIONS DES VARIABLES COMPLEXES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : var = structure vierge à préparer. * +* * +* Description : Initialise une représentation de variable complexe. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +void init_complex_var(complex_variable *var) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à effacer. * +* * +* Description : Supprime de la mémoire une variable de type complexe. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_complex_var(complex_variable *var) +{ + var->delete(var); + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à consulter. * +* * +* Description : Décrit la variable complexe sous forme de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *complex_var_to_string(const complex_variable *var) +{ + return var->to_string(var); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* VARIABLES DE CLASSES ET ENUMERATIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : type = type de base à représenter. * +* desc = description humaine de la variable. * +* * +* Description : Crée une représentation de variable de classe/enumération. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : La description ne doit pas être libérée par l'appelant ! * +* * +******************************************************************************/ + +complex_variable *create_class_enum_var(char *desc) +{ + class_enum_variable *result; /* Structure à retourner */ + + result = (class_enum_variable *)calloc(1, sizeof(class_enum_variable)); + + init_complex_var(COMPLEX_VAR(result)); + + COMPLEX_VAR(result)->delete = (delete_complex_fc)delete_class_enum_var; + COMPLEX_VAR(result)->to_string = (complex_to_string_fc)class_enum_var_to_string; + + result->desc = desc; + + return COMPLEX_VAR(result); + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à effacer. * +* * +* Description : Supprime de la mémoire une variable de classe/enumération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_class_enum_var(class_enum_variable *var) +{ + free(var->desc); + + free(var); + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à consulter. * +* * +* Description : Décrit la variable complexe sous forme de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *class_enum_var_to_string(const class_enum_variable *var) +{ + return strdup(var->desc); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* VARIABLES DEPENDANT D'AUTRES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : type = type d'extension à représenter. * +* child = variable dont on doit dériver. * +* * +* Description : Crée une représentation de variable dérivée. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +complex_variable *create_encapsulated_var(EncapsulationType type, variable *child) +{ + encapsulated_variable *result; /* Structure à retourner */ + + result = (encapsulated_variable *)calloc(1, sizeof(encapsulated_variable)); + + init_complex_var(COMPLEX_VAR(result)); + + COMPLEX_VAR(result)->delete = (delete_complex_fc)delete_encapsulated_var; + COMPLEX_VAR(result)->to_string = (complex_to_string_fc)encapsulated_var_to_string; + + result->type = type; + result->child = child; + + return COMPLEX_VAR(result); + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à effacer. * +* * +* Description : Supprime de la mémoire une variable dérivée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_encapsulated_var(encapsulated_variable *var) +{ + delete_var(var->child); + + free(var); + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à consulter. * +* * +* Description : Décrit la variable dérivée sous forme de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *encapsulated_var_to_string(const encapsulated_variable *var) +{ + char *result; /* Chaîne finale à renvoyer */ + + result = var_to_string(var->child); + + switch (var->type) + { + case ECT_POINTER: + if (result[strlen(result) - 1] == '*') result = stradd(result, "*"); + else result = stradd(result, " *"); + break; + case ECT_REFERENCE: + result = stradd(result, " &"); + break; + case ECT_RVALUE_REF: + result = stradd(result, " [[rval ???]]") /* FIXME */; + break; + case ECT_COMPLEX: + result = stradd(result, " complex"); + break; + case ECT_IMAGINARY: + result = stradd(result, " imaginary"); + break; + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION GENERIQUE DES VARIABLES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : var = variable à emballer. * +* * +* Description : Crée une représentation de variable (simple). * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +variable *create_var_from_simple_one(simple_variable *var) +{ + variable *result; /* Structure à retourner */ + + result = (variable *)calloc(1, sizeof(variable)); + + result->value.simple = var; + result->is_simple = true; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à emballer. * +* * +* Description : Crée une représentation de variable (complexe). * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +variable *create_var_from_complex_one(complex_variable *var) +{ + variable *result; /* Structure à retourner */ + + result = (variable *)calloc(1, sizeof(variable)); + + result->value.complex = var; + result->is_simple = false; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à effecer. * +* * +* Description : Supprime la représentation de variable de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void delete_var(variable *var) +{ + if (var->is_simple) delete_simple_var(var->value.simple); + else delete_complex_var(var->value.complex); + + free(var); + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à mettre à jour. * +* qualifier = nouveau qualificatif pour la variable. * +* * +* Description : Ajoute un qualificatif à la variable. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void add_qualifier_to_var(variable *var, VariableQualifier qualifier) +{ + var->qualifiers |= qualifier; + +} + + +/****************************************************************************** +* * +* Paramètres : var = variable à consulter. * +* * +* Description : Décrit la variable sous forme de caractères. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *var_to_string(const variable *var) +{ + char *result; /* Chaîne à renvoyer */ + + if (var->is_simple) result = simple_var_to_string(var->value.simple); + else result = complex_var_to_string(var->value.complex); + + if (var->qualifiers & VQF_RESTRICT) + strprep(result, "restrict "); + + if (var->qualifiers & VQF_VOLATILE) + strprep(result, "volatile "); + + if (var->qualifiers & VQF_CONST) + strprep(result, "const "); + + return result; + +} diff --git a/src/analysis/variable.h b/src/analysis/variable.h new file mode 100644 index 0000000..8b50cf4 --- /dev/null +++ b/src/analysis/variable.h @@ -0,0 +1,176 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * variable.h - prototypes pour la manipulation des variables en tout genre + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#ifndef _ANALYSIS_VARIABLE_H +#define _ANALYSIS_VARIABLE_H + + + +/* Variable repésentant un argument ou un type de retour */ +typedef struct _variable variable; + + + +/* ---------------------------- TYPES DE DONNEES SIMPLES ---------------------------- */ + + +/* Liste des types de base existants */ +typedef enum _BaseType +{ + BTP_VOID, /* void */ + BTP_WCHAR_T, /* wchar_t */ + BTP_BOOL, /* bool */ + BTP_CHAR, /* char */ + BTP_SCHAR, /* signed char */ + BTP_UCHAR, /* unsigned char */ + BTP_SHORT, /* short */ + BTP_USHORT, /* unsigned short */ + BTP_INT, /* int */ + BTP_UINT, /* unsigned int */ + BTP_LONG, /* long */ + BTP_ULONG, /* unsigned long */ + BTP_LONG_LONG, /* long long, __int64 */ + BTP_ULONG_LONG, /* unsigned long long, __int64 */ + BTP_INT128, /* __int128 */ + BTP_UINT128, /* unsigned __int128 */ + BTP_FLOAT, /* float */ + BTP_DOUBLE, /* double */ + BTP_LONG_DOUBLE, /* long double, __float80 */ + BTP_FLOAT128, /* __float128 */ + BTP_ELLIPSIS, /* ... */ + BTP_754R_64, /* IEEE 754r float (64 bits) */ + BTP_754R_128, /* IEEE 754r float (128 bits) */ + BTP_754R_32, /* IEEE 754r float (32 bits) */ + BTP_754R_16, /* IEEE 754r float (16 bits) */ + BTP_CHAR32_T, /* char32_t */ + BTP_CHAR16_T, /* char16_t */ + BTP_OTHER /* Extension utilisateur */ + +} BaseType; + + + +/* Variable repésentant un argument ou un type de retour */ +typedef struct _simple_variable simple_variable; + + +/* Crée une représentation de variable. */ +simple_variable *create_simple_var(void); + +/* Crée une représentation de variable à type connu. */ +simple_variable *create_typed_simple_var(BaseType); + +/* Définit le type d'une variable simple. */ +void set_simple_var_type(simple_variable *, BaseType); + + + +/* --------------------- ENCAPSULATIONS DES VARIABLES COMPLEXES --------------------- */ + + +/* Représentation d'une variable complexe */ +typedef struct _complex_variable complex_variable; + + +#define COMPLEX_VAR(v) ((complex_variable *)v) + + + +/* ---------------------- VARIABLES DE CLASSES ET ENUMERATIONS ---------------------- */ + + +/* Type de ces variables */ +typedef enum _ClassEnumType +{ + CET_UNKNOWN, /* Statut inconnu */ + CET_STRUCT, /* Structure */ + CET_ENUM, /* Enumération */ + CET_CLASS /* Classe */ + +} ClassEnumType; + + +/* Représentation des classes et des énumérations */ +typedef struct _class_enum_variable class_enum_variable; + + +/* Crée une représentation de variable de classe/enumération. */ +complex_variable *create_class_enum_var(char *); + + + +/* -------------------------- VARIABLES DEPENDANT D'AUTRES -------------------------- */ + + +/* Cas d'encapsulation possibles */ +typedef enum _EncapsulationType +{ + ECT_POINTER, /* Pointeur */ + ECT_REFERENCE, /* Référence */ + ECT_RVALUE_REF, /* Référence ?? (C++0x) */ + ECT_COMPLEX, /* Complexe (C 2000) */ + ECT_IMAGINARY /* Imaginaire (C 2000) */ + +} EncapsulationType; + + +/* Représentation des variables dérivées */ +typedef struct _encapsulated_variable encapsulated_variable; + + +/* Crée une représentation de variable dérivée. */ +complex_variable *create_encapsulated_var(EncapsulationType, variable *); + + + +/* ---------------------- MANIPULATION GENERIQUE DES VARIABLES ---------------------- */ + + +/* Qualificatifs de variables */ +typedef enum _VariableQualifier +{ + VQF_RESTRICT = (1 << 0), /* restrict (C99) */ + VQF_VOLATILE = (1 << 1), /* volatile */ + VQF_CONST = (1 << 2) /* const */ + +} VariableQualifier; + + +/* Crée une représentation de variable (simple). */ +variable *create_var_from_simple_one(simple_variable *); + +/* Crée une représentation de variable (complexe). */ +variable *create_var_from_complex_one(complex_variable *); + +/* Supprime la représentation de variable de la mémoire. */ +void delete_var(variable *); + +/* Ajoute un qualificatif à la variable. */ +void add_qualifier_to_var(variable *, VariableQualifier); + +/* Décrit la variable sous forme de caractères. */ +char *var_to_string(const variable *); + + + +#endif /* _ANALYSIS_VARIABLE_H */ diff --git a/src/binary.c b/src/binary.c index d55eb4a..427ad4e 100644 --- a/src/binary.c +++ b/src/binary.c @@ -549,6 +549,8 @@ void fill_snippet(GtkSnippet *snippet, GtkWidget *panel, GtkWidget *panel2) gtk_snippet_set_rendering_lines(snippet, lines); + handle_new_exe_on_symbols_panel(panel, format); + handle_new_exe_on_strings_panel(panel2, format); return; diff --git a/src/common/Makefile.am b/src/common/Makefile.am index a27a192..6ad3fc3 100755 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -3,7 +3,8 @@ lib_LIBRARIES = libcommon.a libcommon_a_SOURCES = \ dllist.h dllist.c \ - endianness.h endianness.c + endianness.h endianness.c \ + extstr.h extstr.c libcommon_a_CFLAGS = $(AM_CFLAGS) diff --git a/src/common/extstr.c b/src/common/extstr.c new file mode 100644 index 0000000..aba9830 --- /dev/null +++ b/src/common/extstr.c @@ -0,0 +1,85 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * extstr.c - extension des fonctions relatives aux chaînes + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include "extstr.h" + + +#include +#include + + + +/****************************************************************************** +* * +* Paramètres : str1 = chaîne de caractères à compléter. * +* str2 = chaîne de caractères à ajouter. * +* * +* Description : Complète une chaîne de caractères avec une autre. * +* * +* Retour : Chaîne de caractères complétée, à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *stradd(char *str1, const char *str2) +{ + char *result; /* Chaîne à renvoyer */ + + result = (char *)realloc(str1, (strlen(str1) + strlen(str2) + 1) * sizeof(char)); + + strcat(result, str2); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : str1 = chaîne de caractères à compléter. * +* str2 = chaîne de caractères à ajouter. * +* * +* Description : Fait précéder une chaîne de caractères par une autre. * +* * +* Retour : Chaîne de caractères complétée, à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *strprep(char *str1, const char *str2) +{ + char *result; /* Chaîne à renvoyer */ + size_t len2; /* Taille de la seconde chaîne */ + + result = (char *)realloc(str1, (strlen(str1) + strlen(str2) + 1) * sizeof(char)); + + len2 = strlen(str2); + + memmove(&result[len2], result, strlen(result) + 1); + memcpy(result, str2, len2); + + return result; + +} diff --git a/src/common/extstr.h b/src/common/extstr.h new file mode 100644 index 0000000..8975000 --- /dev/null +++ b/src/common/extstr.h @@ -0,0 +1,37 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * extstr.h - prototypes pour une extension des fonctions relatives aux chaînes + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#ifndef _COMMON_EXTSTR_H +#define _COMMON_EXTSTR_H + + + +/* Complète une chaîne de caractères avec une autre. */ +char *stradd(char *str1, const char *str2); + +/* Fait précéder une chaîne de caractères par une autre. */ +char *strprep(char *, const char *); + + + +#endif /* _COMMON_EXTSTR_H */ diff --git a/src/editor.c b/src/editor.c index e6d7516..c1041c6 100644 --- a/src/editor.c +++ b/src/editor.c @@ -57,6 +57,7 @@ #include "pan_strings.h" #include "pan_symbols.h" #include "gtkext/gtkdockpanel.h" +#include "format/mangling/demangler.h" #include "panel/panels.h" @@ -161,6 +162,9 @@ int main(int argc, char **argv) add_pixmap_directory(PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "pixmaps"); /* Initialisation du programme */ + init_all_demanglers(); + + /* Création de l'interface */ editor = create_editor(); gtk_widget_show(editor); diff --git a/src/format/Makefile.am b/src/format/Makefile.am index 7c2c524..13f80a6 100644 --- a/src/format/Makefile.am +++ b/src/format/Makefile.am @@ -16,4 +16,4 @@ AM_CPPFLAGS = AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) -SUBDIRS = dwarf elf java pe +SUBDIRS = dwarf elf java mangling pe diff --git a/src/format/mangling/Makefile.am b/src/format/mangling/Makefile.am new file mode 100644 index 0000000..71a0923 --- /dev/null +++ b/src/format/mangling/Makefile.am @@ -0,0 +1,25 @@ + +BUILT_SOURCES = itanium_gram.h + +AM_YFLAGS = -d + +lib_LIBRARIES = libformatmangling.a + +libformatmangling_a_SOURCES = \ + demangler.h demangler.c \ + itanium.h \ + itanium_gram.y \ + itanium_tok.l + +libformatmangling_a_CFLAGS = $(AM_CFLAGS) + + +INCLUDES = $(LIBGTK_CFLAGS) + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) + + +# Automake fait les choses à moitié +CLEANFILES = itanium_gram.h itanium_gram.c itanium_tok.c diff --git a/src/format/mangling/demangler-int.h b/src/format/mangling/demangler-int.h new file mode 100644 index 0000000..2189bd0 --- /dev/null +++ b/src/format/mangling/demangler-int.h @@ -0,0 +1,53 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * demangler-int.h - prototypes internes pour le décodage des noms d'éléments + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#ifndef _FORMAT_MANGLING_DEMANGLER_INT_H +#define _FORMAT_MANGLING_DEMANGLER_INT_H + + +#include "demangler.h" +#include "../../analysis/prototype.h" + + + +/* Indique si une chaîne peut être traitée par le décodeur. */ +typedef bool (* can_be_demangled_fc) (name_demangler *, const char *); + +/* Procède au décodage d'une chaîne de caractères. */ +typedef bin_routine * (* demangle_routine_fc) (name_demangler *, const char *); + + +/* Décodeur de nom d'éléments */ +struct _name_demangler +{ + can_be_demangled_fc can_be_demangled; /* Capacité de traitement */ + demangle_routine_fc demangle_routine; /* Décodage de chaînes */ + +}; + + +#define NAME_DEMANGLER(dmgl) ((name_demangler *)dmgl) + + + +#endif /* _FORMAT_MANGLING_DEMANGLER_INT_H */ diff --git a/src/format/mangling/demangler.c b/src/format/mangling/demangler.c new file mode 100644 index 0000000..5675800 --- /dev/null +++ b/src/format/mangling/demangler.c @@ -0,0 +1,134 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * demangler.c - décodage des noms d'éléments + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include "demangler.h" + + +#include + + +#include "demangler-int.h" +#include "itanium.h" + + + +static name_demangler **demanglers = NULL; +static size_t demanglers_count = 0; + + + +/* Enregistre un nouveau décodeur de noms. */ +void register_new_demangler(name_demangler *); + + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Procède au chargement des différents décodeurs de noms. * +* * +* Retour : true pour indiquer un chargement réussi, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_all_demanglers(void) +{ + register_new_demangler(create_itanium_demangler()); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = décodeur opérationnel. * +* * +* Description : Enregistre un nouveau décodeur de noms. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void register_new_demangler(name_demangler *demangler) +{ + demanglers = (name_demangler **)realloc(demanglers, ++demanglers_count * sizeof(name_demangler *)); + demanglers[demanglers_count - 1] = demangler; + +} + + +/****************************************************************************** +* * +* Paramètres : type = identifiant du décodeur visé. * +* * +* Description : Fournit la référence correspondant à un décodeur donné. * +* * +* Retour : Adresse du décodeur trouvé ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +name_demangler *get_demangler_by_type(DemanglerType type) +{ + name_demangler *result; /* Adresse à retourner */ + + result = demanglers[0]; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = décodeur à utiliser. * +* name = chaîne de caractères à décoder. * +* * +* Description : Tente de décoder une chaîne de caractères donnée. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bin_routine *try_to_demangle_routine(name_demangler *demangler, const char *name) +{ + bin_routine *result; /* Construction à remonter */ + + result = NULL; + + if (demangler->can_be_demangled(demangler, name)) + result = demangler->demangle_routine(demangler, name); + + return result; + +} diff --git a/src/format/mangling/demangler.h b/src/format/mangling/demangler.h new file mode 100644 index 0000000..259d73d --- /dev/null +++ b/src/format/mangling/demangler.h @@ -0,0 +1,59 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * demangler.h - prototypes pour le décodage des noms d'éléments + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#ifndef _FORMAT_MANGLING_DEMANGLER_H +#define _FORMAT_MANGLING_DEMANGLER_H + + +#include + + +#include "../../analysis/prototype.h" + + + +/* Identifiant des décodeurs existants */ +typedef enum _DemanglerType +{ + DGT_ITANIUM /* Gnu V3 */ + +} DemanglerType; + + +/* Décodeur de nom d'éléments */ +typedef struct _name_demangler name_demangler; + + + +/* Procède au chargement des différents décodeurs de noms. */ +bool init_all_demanglers(void); + +/* Fournit la référence correspondant à un décodeur donné. */ +name_demangler *get_demangler_by_type(DemanglerType); + +/* Tente de décoder une chaîne de caractères donnée. */ +bin_routine *try_to_demangle_routine(name_demangler *, const char *); + + + +#endif /* _FORMAT_MANGLING_DEMANGLER_H */ diff --git a/src/format/mangling/itanium.h b/src/format/mangling/itanium.h new file mode 100644 index 0000000..8482af3 --- /dev/null +++ b/src/format/mangling/itanium.h @@ -0,0 +1,37 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * itanium.h - prototypes pour le décodage des noms d'éléments selon Intel + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#ifndef _FORMAT_MANGLING_ITANIUM_H +#define _FORMAT_MANGLING_ITANIUM_H + + +#include "demangler.h" + + + +/* Définit un décodeur répondant à la norme d'Intel. */ +name_demangler *create_itanium_demangler(void); + + + +#endif /* _FORMAT_MANGLING_ITANIUM_H */ diff --git a/src/format/mangling/itanium_gram.y b/src/format/mangling/itanium_gram.y new file mode 100644 index 0000000..7c13c79 --- /dev/null +++ b/src/format/mangling/itanium_gram.y @@ -0,0 +1,518 @@ + +%{ + + +#include +#include +#include + + +#include "demangler-int.h" +#include "itanium.h" +#include "../../common/extstr.h" + + + +/** + * cf. http://www.codesourcery.com/cxx-abi/abi.html#mangling + */ + + +/* Taille du bond pour les allocations */ +#define ITANIUM_ALLOC_CLUSTER 10 + + + +/* Décodeur de nom d'éléments selon la définition Intel */ +typedef struct _itanium_demangler +{ + name_demangler common; /* A laisser en premier */ + + char *identifier; /* Identifiant en construction */ + size_t id_allocated; /* Taille allouée en mémoire */ + size_t id_used; /* Longueur de la chaîne */ + +} itanium_demangler; + + +/* Indique si une chaîne peut être traitée par le décodeur. */ +bool can_be_itanium_demangled(itanium_demangler *, const char *); + +/* Procède au décodage d'une chaîne de caractères. */ +bin_routine *demangle_itanium_routine(itanium_demangler *, const char *); + + + +/* Réinitialise le constructeur d'identifiants. */ +void reset_itanium_identifier_building(itanium_demangler *); + +/* Construit à la volée un identifiant. */ +void build_itanium_identifier(itanium_demangler *, char); + + + + +/* Borne la longueur d'une chaîne à lire. */ +extern void set_itanium_text_length(unsigned int); + + + + + +char *strmerge(char *str1, const char *sep, char *str2); + char *strmerge(char *str1, const char *sep, char *str2) +{ + char *result; + + if (str1 == NULL) result = str2; + else if (str2 == NULL) result = str1; + else + { + result = (char *)calloc(strlen(str1) + strlen(sep) + strlen(str2) + 1, sizeof(char)); + + strcpy(result, str1); + strcat(result, sep); + strcat(result, str2); + + free(str1); + free(str2); + + } + + return result; + +} + + + +%} + + +%union { + + char car; + char *text; + unsigned int val; + short/*s16_t*/ s16_val; + + void/*simple_variable*/ *simple; + void/*complex_variable*/ *complex; + void/*variable*/ *var; + + int/*VariableQualifier*/ qual; + +} + +%parse-param { itanium_demangler *demangler } +%parse-param { bin_routine *routine } + + +%token ITANIUM_SIGNATURE + +%token EE NN II + +%token C1 C2 C3 D1 D2 D3 + +%token V W B C A H S T I J L M X Y N O F D E G Z DD DE DF DH DI DS U + +%token TP TR TO TC TG + +%token QR QV QK + +%token ST SA SB SS SI SO SD + + +%token NUMBER CHAR + + + + + + + + + +%token LPART MPART RPART + + +%token POSITION POSITION_ABS IMAGE + +%token RECT + +%token O_BRACKET C_BRACKET + +%token PATH +%token DEC_16 + +%token TEXT + + +%type TEXT PATH + +%type DEC_16 + + + + +%type name unscoped_name unscoped_template_name nested_name +%type unqualified_name +%type prefix source_name + + +%type type + +%type qualifiers + +%type builtin_type + +%type class_enum_type + + +%type template_args template_arg_list template_arg +%type substitution + + +%type CHAR +%type NUMBER + + +%{ + +/* De lexi.c... */ +/*int yylex(YYSTYPE *, YYLTYPE *);*/ +void yyrestart(FILE *); +typedef struct yy_buffer_state *YY_BUFFER_STATE; +extern YY_BUFFER_STATE yy_scan_string(const char *); +extern void yy_delete_buffer(YY_BUFFER_STATE); + + +/* Affiche un message d'erreur concernant l'analyse. */ +/*int yyerror(const YYLTYPE *, bool, char **, unsigned char *, char *);*/ + +%} + + +%% + + +input: + ITANIUM_SIGNATURE encoding + ; + +encoding: + name bare_function_type + ; + + + + +name: + nested_name { $$ = $1; set_binary_routine_name(routine, $1); } + | unscoped_name { $$ = $1; /*set_binary_routine_name(routine, $1);*/ } + | unscoped_template_name template_args { $$ = stradd($1, $2); /* TODO : merge -> free */ } + ; + +unscoped_name: + unqualified_name { $$ = $1; } + | ST unqualified_name { $$ = strprep($2, "std::"); } + ; + +unscoped_template_name: + unscoped_name { $$ = $1; } + | substitution { $$ = $1; } + ; + + + +nested_name: + NN prefix unqualified_name EE { $$ = ($3 != NULL ? strmerge($2, "::", $3) : $2); } + ; + + + +prefix: + /* vide */ { $$ = NULL; } + | prefix unqualified_name { $$ = ($2 != NULL ? strmerge($1, "::", $2) : $1); } + ; + + + + +unqualified_name: + ctor_dtor_name { $$ = NULL; } + | source_name { $$ = $1; } + ; + + + +source_name: + NUMBER { set_itanium_text_length($1); reset_itanium_identifier_building(demangler); } + identifier { $$ = strdup(demangler->identifier); } + ; + +identifier: + identifier CHAR { build_itanium_identifier(demangler, $2); } + | CHAR { build_itanium_identifier(demangler, $1); } + ; + +ctor_dtor_name: + C1 { set_binary_routine_type(routine, RTT_CONSTRUCTOR); } + | C2 { set_binary_routine_type(routine, RTT_CONSTRUCTOR); } + | C3 { set_binary_routine_type(routine, RTT_CONSTRUCTOR); } + | D1 { set_binary_routine_type(routine, RTT_DESTRUCTOR); } + | D2 { set_binary_routine_type(routine, RTT_DESTRUCTOR); } + | D3 { set_binary_routine_type(routine, RTT_DESTRUCTOR); } + ; + + +type: + builtin_type { $$ = create_var_from_simple_one($1); } + | class_enum_type { $$ = create_var_from_complex_one($1); } + | substitution { $$ = create_var_from_complex_one(create_class_enum_var($1)); } + | qualifiers type { $$ = $2; add_qualifier_to_var($2, $1); } + | TP type { $$ = create_var_from_complex_one(create_encapsulated_var(ECT_POINTER, $2)); } + | TR type { $$ = create_var_from_complex_one(create_encapsulated_var(ECT_REFERENCE, $2)); } + | TO type { $$ = create_var_from_complex_one(create_encapsulated_var(ECT_RVALUE_REF, $2)); } + | TC type { $$ = create_var_from_complex_one(create_encapsulated_var(ECT_COMPLEX, $2)); } + | TG type { $$ = create_var_from_complex_one(create_encapsulated_var(ECT_IMAGINARY, $2)); } + ; + +qualifiers: + QR { $$ = VQF_RESTRICT; } + | QV { $$ = VQF_VOLATILE; } + | QK { $$ = VQF_CONST; } + ; + + + +builtin_type: + V { $$ = create_typed_simple_var(BTP_VOID); } + | W { $$ = create_typed_simple_var(BTP_WCHAR_T); } + | B { $$ = create_typed_simple_var(BTP_BOOL); } + | C { $$ = create_typed_simple_var(BTP_CHAR); } + | A { $$ = create_typed_simple_var(BTP_SCHAR); } + | H { $$ = create_typed_simple_var(BTP_UCHAR); } + | S { $$ = create_typed_simple_var(BTP_SHORT); } + | T { $$ = create_typed_simple_var(BTP_USHORT); } + | I { $$ = create_typed_simple_var(BTP_INT); } + | J { $$ = create_typed_simple_var(BTP_UINT); } + | L { $$ = create_typed_simple_var(BTP_LONG); } + | M { $$ = create_typed_simple_var(BTP_ULONG); } + | X { $$ = create_typed_simple_var(BTP_LONG_LONG); } + | Y { $$ = create_typed_simple_var(BTP_ULONG_LONG); } + | N { $$ = create_typed_simple_var(BTP_INT128); } + | O { $$ = create_typed_simple_var(BTP_UINT128); } + | F { $$ = create_typed_simple_var(BTP_FLOAT); } + | D { $$ = create_typed_simple_var(BTP_DOUBLE); } + | E { $$ = create_typed_simple_var(BTP_LONG_DOUBLE); } + | G { $$ = create_typed_simple_var(BTP_FLOAT128); } + | Z { $$ = create_typed_simple_var(BTP_ELLIPSIS); } + | DD { $$ = create_typed_simple_var(BTP_754R_64); } + | DE { $$ = create_typed_simple_var(BTP_754R_128); } + | DF { $$ = create_typed_simple_var(BTP_754R_32); } + | DH { $$ = create_typed_simple_var(BTP_754R_16); } + | DI { $$ = create_typed_simple_var(BTP_CHAR32_T); } + | DS { $$ = create_typed_simple_var(BTP_CHAR16_T); } + | U source_name { $$ = create_typed_simple_var(BTP_OTHER); /* TODO */ ; free($2); } + ; + + + +bare_function_type: + bare_function_type type { add_arg_to_binary_routine(routine, $2); } + | type { add_arg_to_binary_routine(routine, $1); } + ; + +class_enum_type: + name { $$ = create_class_enum_var($1); } + ; + + + + +template_args: + II template_arg_list EE { $$ = stradd(strprep($2, "<"), ">"); } + ; + +template_arg_list: + template_arg_list template_arg { $$ = strmerge($1, ", ", $2); } + | template_arg { $$ = $1; } + ; + +template_arg: + type { $$ = var_to_string($1); delete_var($1); } + ; + +substitution: + ST { $$ = strdup("std::"); } + | SA { $$ = strdup("std::allocator"); } + | SB { $$ = strdup("std::basic_string"); } + | SS { $$ = strdup("std::string"); } + | SI { $$ = strdup("std::istream"); } + | SO { $$ = strdup("std::ostream"); } + | SD { $$ = strdup("std::iostream"); } + ; + + + + + + + +%% + + +/** + * Affiche un message d'erreur concernant l'analyse. + * @param yyloc informations concernant les coordonnées du soucis. + * @param hunt indique le type de passe réalisée. + * @param ucode code résultant compilé. + * @param index indice de commande à mettre à jour. + * @param msg indications humaines sur l'événement. + * @return 0. + */ +int yyerror(/*const YYLTYPE *yyloc, bool hunt, char **ucode, unsigned char *index, */char *msg) +{ + + + + fprintf(stderr, "ERREUR !\n"); + fprintf(stderr, "%s\n", msg); + + return -1; + +} + + + + + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Définit un décodeur répondant à la norme d'Intel. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +name_demangler *create_itanium_demangler(void) +{ + itanium_demangler *result; /* Structure à retourner */ + + result = (itanium_demangler *)calloc(1, sizeof(itanium_demangler)); + + NAME_DEMANGLER(result)->can_be_demangled = (can_be_demangled_fc)can_be_itanium_demangled; + NAME_DEMANGLER(result)->demangle_routine = (demangle_routine_fc)demangle_itanium_routine; + + return NAME_DEMANGLER(result); + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = décodeur à utiliser. * +* name = chaîne de caractères à analyser. * +* * +* Description : Indique si une chaîne peut être traitée par le décodeur. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool can_be_itanium_demangled(itanium_demangler *itanium, const char *name) +{ + return (strncmp(name, "_Z", 2) == 0); + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = décodeur à utiliser. * +* name = chaîne de caractères à décoder. * +* * +* Description : Procède au décodage d'une chaîne de caractères. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bin_routine *demangle_itanium_routine(itanium_demangler *demangler, const char *name) +{ + bin_routine *result; /* Construction à retourner */ + YY_BUFFER_STATE buffer; /* Tampon pour bison */ + int ret; /* Bilan de l'appel */ + + result = create_binary_routine(); + + buffer = yy_scan_string(name); + ret = yyparse(demangler, result); + yy_delete_buffer(buffer); + + if (ret != 0) + { + delete_binary_routine(result); + result = NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = décodeur à mettre à jour. * +* * +* Description : Réinitialise le constructeur d'identifiants. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_itanium_identifier_building(itanium_demangler *demangler) +{ + demangler->id_used = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : demangler = décodeur à mettre à jour. * +* value = caractère d'identifiant à mémoriser. * +* * +* Description : Construit à la volée un identifiant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void build_itanium_identifier(itanium_demangler *demangler, char value) +{ + if ((demangler->id_used + 2) > demangler->id_allocated) + { + demangler->id_allocated += ITANIUM_ALLOC_CLUSTER; + demangler->identifier = (char *)realloc(demangler->identifier, + demangler->id_allocated * sizeof(char)); + } + + demangler->identifier[demangler->id_used++] = value; + demangler->identifier[demangler->id_used] = 0; + +} diff --git a/src/format/mangling/itanium_tok.l b/src/format/mangling/itanium_tok.l new file mode 100644 index 0000000..5eef799 --- /dev/null +++ b/src/format/mangling/itanium_tok.l @@ -0,0 +1,116 @@ + +%{ + +#include "itanium_gram.h" + + +static unsigned int itanium_txt_length = 0; + + +/* Borne la longueur d'une chaîne à lire. */ +void set_itanium_text_length(unsigned int); + + +%} + + +%option noyywrap +%option yylineno + + +%x identifier + + +%% + + +_Z { return ITANIUM_SIGNATURE; } + +E { return EE; } +N { return NN; } +I { return II; } + +C1 { return C1; } +C2 { return C2; } +C3 { return C3; } +D0 { return C1; } +D1 { return D2; } +D2 { return D3; } + +v { return V; } +w { return W; } +b { return B; } +c { return C; } +a { return A; } +h { return H; } +s { return S; } +t { return T; } +i { return I; } +j { return J; } +l { return L; } +m { return M; } +x { return X; } +y { return Y; } +n { return N; } +o { return O; } +f { return F; } +d { return D; } +e { return E; } +g { return G; } +z { return Z; } +Dd { return DD; } +De { return DE; } +Df { return DF; } +Dh { return DH; } +Di { return DI; } +Ds { return DS; } +u { return U; } + +P { return TP; } +R { return TR; } +O { return TO; } +C { return TC; } +G { return TG; } + +r { return QR; } +V { return QV; } +K { return QK; } + +St { return ST; } +Sa { return SA; } +Sb { return SB; } +Ss { return SS; } +Si { return SI; } +So { return SO; } +Sd { return SD; } + + +[0-9]+ { yylval.val = atoi(yytext); return NUMBER; } + +. { if (--itanium_txt_length == 0) BEGIN(INITIAL); yylval.car = *yytext; return CHAR; } + +<*>. { printf("error : '%s'\n", yytext); } + + +%% + + +/****************************************************************************** +* * +* Paramètres : length = taille de chaîne à lire. * +* * +* Description : Borne la longueur d'une chaîne à lire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void set_itanium_text_length(unsigned int length) +{ + itanium_txt_length = length; + + BEGIN(identifier); + +} -- cgit v0.11.2-87-g4458