%{ #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. */ GBinRoutine *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 { GBinRoutine *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; g_binary_routine_set_name(routine, $1); } | unscoped_name { $$ = $1; /*g_binary_routine_set_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 { g_binary_routine_set_type(routine, RTT_CONSTRUCTOR); } | C2 { g_binary_routine_set_type(routine, RTT_CONSTRUCTOR); } | C3 { g_binary_routine_set_type(routine, RTT_CONSTRUCTOR); } | D1 { g_binary_routine_set_type(routine, RTT_DESTRUCTOR); } | D2 { g_binary_routine_set_type(routine, RTT_DESTRUCTOR); } | D3 { g_binary_routine_set_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 { g_binary_routine_add_arg(routine, $2); } | type { g_binary_routine_add_arg(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 : - * * * ******************************************************************************/ GBinRoutine *demangle_itanium_routine(itanium_demangler *demangler, const char *name) { GBinRoutine *result; /* Construction à retourner */ YY_BUFFER_STATE buffer; /* Tampon pour bison */ int ret; /* Bilan de l'appel */ result = g_binary_routine_new(); buffer = yy_scan_string(name); ret = yyparse(demangler, result); yy_delete_buffer(buffer); if (ret != 0) { /*delete_binary_routine(result); FIXME */ 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; }