diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2010-08-10 00:17:32 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2010-08-10 00:17:32 (GMT) |
commit | 088a489002fd1c9a62d5cafe693dc73cc271ee18 (patch) | |
tree | a147acd77fab3b66d541326349d08dae29ec0e8c /src/format/mangling/itanium_gram.y | |
parent | bcfcb4ec8b4cf9a35b77e93d172e7dae81e8872a (diff) |
Improved Itanium demangling.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@179 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/format/mangling/itanium_gram.y')
-rw-r--r-- | src/format/mangling/itanium_gram.y | 395 |
1 files changed, 356 insertions, 39 deletions
diff --git a/src/format/mangling/itanium_gram.y b/src/format/mangling/itanium_gram.y index f8c02a2..ab59ac7 100644 --- a/src/format/mangling/itanium_gram.y +++ b/src/format/mangling/itanium_gram.y @@ -38,11 +38,13 @@ struct _GItaniumDContext size_t id_allocated; /* Taille allouée en mémoire */ size_t id_used; /* Longueur de la chaîne */ - bool use_templates; /* Utilisation des gabarits */ GSList *routines; /* Routines en cours de maj */ GSList *substitutions; /* Empilement des types créés */ + bool start_args; /* Début de définitions d'args */ + unsigned int template_level; /* Compteur d'imbrications */ + }; /* Contexte de décodage Itanium (classe) */ @@ -66,6 +68,12 @@ static void g_itanium_dcontext_class_init(GItaniumDContextClass *); /* Initialise une instance de contexte pour décodage. */ static void g_itanium_dcontext_init(GItaniumDContext *); +/* Supprime toutes les références externes. */ +static void g_itanium_dcontext_dispose(GItaniumDContext *); + +/* Procède à la libération totale de la mémoire. */ +static void g_itanium_dcontext_finalize(GItaniumDContext *); + /* Réinitialise le constructeur d'identifiants. */ static void g_itanium_dcontext_reset_identifier(GItaniumDContext *); @@ -84,9 +92,19 @@ static void g_itanium_dcontext_add_item(GItaniumDContext *, GOpenidaType *); /* Fournit le nième élément d'une liste de substitutions. */ static GOpenidaType *g_itanium_dcontext_get_item(GItaniumDContext *, guint); +/* Autorise ou non le dépilement des opérateurs. */ +static void g_itanium_dcontext_update(GItaniumDContext *); + + + +/* ------------------------ TRAITEMENT DE L'ENCODAGE ITANIUM ------------------------ */ +/* Fait sauter le premier argument en faveur du type de retour. */ +static void compute_routine_itanium_ret_type(GBinRoutine *); +/* Recherche et fait sauter les premiers arguments rencontrés. */ +static void update_itanium_ret_type(GOpenidaType *); @@ -99,6 +117,13 @@ static GOpenidaType *g_itanium_dcontext_get_item(GItaniumDContext *, guint); /* Borne la longueur d'une chaîne à lire. */ extern void set_itanium_text_length(unsigned int); +/* Autorise la lecture des opérateurs. */ +extern void allow_itanium_operators(void); + +/* Autorise la lecture des opérateurs. */ +extern void exclude_itanium_operators(void); + + @@ -234,8 +259,14 @@ char *strmerge(char *str1, const char *sep, char *str2); %type <templtype> unscoped_template_name %type <text> unqualified_name operator_name -%type <text> prefix template_prefix source_name +%type <text> registered_prefix + +%type <type> prefix + +%type <text> template_prefix source_name + +%type <type> registered_template_prefix %type <type> template_param template_template_param @@ -251,7 +282,7 @@ char *strmerge(char *str1, const char *sep, char *str2); %type <slist> template_args template_arg_list %type <type> template_arg expr_primary -%type <text> substitution +%type <type> substitution %type <car> CHAR @@ -279,7 +310,7 @@ extern void yy_delete_buffer(YY_BUFFER_STATE); input: - ITANIUM_SIGNATURE encoding + ITANIUM_SIGNATURE encoding ; encoding: @@ -293,7 +324,34 @@ encoding: name: nested_name { $$.type = $1; $$.is_string = false; } | unscoped_name { $$.str = $1; $$.is_string = true; } - | unscoped_template_name template_args { $$.type = $1; $$.is_string = false; g_template_type_add_params($1, $2); } + | unscoped_template_name template_args { + + if (G_IS_TEMPLATE_TYPE($1)) + { + g_template_type_add_params($1, $2); + + $$.type = $1; + $$.is_string = false; + + } + + else + { + char *tmp; + + tmp = g_openida_type_to_string($1); + + $$.type = g_template_type_new(tmp, $2); + $$.is_string = false; + + free(tmp); + g_object_unref(G_OBJECT($1)); + + } + + //g_template_type_add_params($1, $2); + printf(" [name tmp:: %s]\n", g_openida_type_to_string($$.type)); + } ; unscoped_name: @@ -303,42 +361,68 @@ unscoped_name: unscoped_template_name: unscoped_name { $$ = g_template_type_new($1, NULL); g_itanium_dcontext_add_item(context, $$); } - | substitution { - $$ = NULL;/*g_openida_type_to_string($1)*/; - /*printf("unscoped sub name :: %s\n", $$); - g_object_unref(G_OBJECT($1));*/ - } + | substitution { $$ = $1; } ; - nested_name: - NN prefix unqualified_name EE { - $$ = ($3 != NULL ? strmerge($2, "::", $3) : $2); - $$ = g_class_enum_type_new(CET_UNKNOWN, $$); + NN registered_prefix unqualified_name EE { + $$ = ($3 != NULL ? strmerge($2, "::", $3) : $2); printf("passage nested p+uq = '%s'\n", $$); + $$ = g_class_enum_type_new(CET_UNKNOWN, $$); g_itanium_dcontext_add_item(context, $$); } - | NN template_prefix template_args EE { $$ = g_template_type_new($2, $3); } + | NN qualifiers registered_prefix unqualified_name EE { + $$ = ($4 != NULL ? strmerge($3, "::", $4) : $3); printf("passage nested p+uq = '%s'\n", $$); + $$ = g_class_enum_type_new(CET_UNKNOWN, $$); g_itanium_dcontext_add_item(context, $$); + } + | NN registered_template_prefix template_args EE { $$ = $2; g_template_type_add_params($2, $3); printf(" [nested tmp:: %s]\n", g_openida_type_to_string($$)); } + | NN qualifiers registered_template_prefix template_args EE { $$ = $3; g_template_type_add_params($3, $4); printf(" [nested tmp:: %s]\n", g_openida_type_to_string($$)); } ; -prefix: - /* vide */ { $$ = NULL; /*printf("passage E\n")*/; } - | prefix unqualified_name { $$ = ($2 != NULL ? strmerge($1, "::", $2) : $1); } - | template_prefix template_args { $$ = g_template_type_new($1, $2); $$ = g_openida_type_to_string($$); /* FIXME : retourner un type ! */} +registered_prefix: + prefix { + if ($1 == NULL) $$ = NULL; + else + { + g_itanium_dcontext_add_item(context, $1); + $$ = g_openida_type_to_string($1); + } + } | substitution { $$ = g_openida_type_to_string($1); - printf("prefix substi :: %s\n", $$); - g_object_unref(G_OBJECT($1)); + printf("prefix substi :: %s\n", g_openida_type_to_string($1)); } ; +prefix: + /* vide */ { $$ = NULL; } + | registered_prefix unqualified_name { $$ = ($2 != NULL ? g_class_enum_type_new(CET_CLASS, strmerge($1, "::", $2)) : $1); printf("passage p+uq = '%s'\n", g_openida_type_to_string($$)); } + | registered_template_prefix template_args { $$ = $1; g_template_type_add_params($1, $2); printf("passage p_tmp = '%s'\n", g_openida_type_to_string($$)); } + ; + +registered_template_prefix: + template_prefix { $$ = g_template_type_new($1, NULL); /*g_itanium_dcontext_add_item(context, $$);*/ } + ; + template_prefix: - prefix unqualified_name { $$ = ($2 != NULL ? strmerge($1, "::", $2) : $1); } + registered_prefix unqualified_name { + if ($1 != NULL) printf("$1 == '%s'\n", $1); + //if ($1 != NULL) if (strcmp($1, "std") != 0) g_itanium_dcontext_add_item(context, g_class_enum_type_new(CET_CLASS, $1)); + $$ = ($2 != NULL ? strmerge($1, "::", $2) : $1); + printf("$$ == '%s'\n", $$); + g_itanium_dcontext_add_item(context, g_class_enum_type_new(CET_CLASS, $$)); + } | template_param { $$ = g_openida_type_to_string($1); + printf("[[ tmp param %s ]]\n", $$); g_object_unref(G_OBJECT($1)); } + | substitution { + $$ = g_openida_type_to_string($1); + printf("template_prefix substi :: %s\n", $$); + g_object_unref(G_OBJECT($1)); + } ; @@ -428,7 +512,11 @@ ctor_dtor_name: function_type: - FF { routine = g_itanium_dcontext_push_routine(context, routine); } + FF { + routine = g_itanium_dcontext_push_routine(context, routine); + context->start_args = true; + g_itanium_dcontext_update(context); + } bare_function_type EE { $$ = g_encapsulated_type_new(ECT_ROUTINE, routine); routine = g_itanium_dcontext_pop_routine(context); @@ -439,13 +527,14 @@ function_type: type: builtin_type { $$ = $1; printf("builtin '%s'\n", g_openida_type_to_string($1)); } - | class_enum_type { $$ = $1; g_itanium_dcontext_add_item(context, $1); } + | class_enum_type { $$ = $1; printf("type :: %p\n", $1); fflush(NULL); g_itanium_dcontext_add_item(context, $1); } | substitution { $$ = $1; } | template_param { $$ = $1; } | template_template_param template_args { $$ = g_template_type_new(g_openida_type_to_string($1), NULL); g_object_unref($1); g_template_type_add_params($$, $2); + printf(" [type tmp:: %s]\n", g_openida_type_to_string($$)); } | function_type { $$ = $1; } | qualifiers type { @@ -502,17 +591,12 @@ builtin_type: bare_function_type: - bare_function_type type { g_binary_routine_add_arg(routine, g_binary_variable_new($2)); } - | type { - if (context->use_templates) - g_binary_routine_set_return_type(routine, $1); - else - g_binary_routine_add_arg(routine, g_binary_variable_new($1)); - } + bare_function_type type { g_binary_routine_add_arg(routine, g_binary_variable_new($2))/*TODO unref*/; } + | type { g_binary_routine_add_arg(routine, g_binary_variable_new($1))/*TODO unref*/; } ; class_enum_type: - name { $$ = $1.is_string ? g_class_enum_type_new(CET_UNKNOWN, $1.str) : $1.type; } + name { printf("is str ?? %d (%p)\n", $1.is_string, $1.type); fflush(NULL); $$ = $1.is_string ? g_class_enum_type_new(CET_UNKNOWN, $1.str) : $1.type; } ; @@ -524,14 +608,14 @@ template_param: if (G_IS_TEMPLATE_TYPE(type)) $$ = g_template_type_get_param(G_TEMPLATE_TYPE(type), 0); else $$ = NULL; - if ($$ == NULL) YYERROR; + if ($$ == NULL) YYERROR; if (!G_IS_BASIC_TYPE($$)) g_itanium_dcontext_add_item(context, $$); } | TPARAM_N { const GOpenidaType *type = g_binary_routine_get_type_from_name(routine); if (G_IS_TEMPLATE_TYPE(type)) $$ = g_template_type_get_param(G_TEMPLATE_TYPE(type), $1 + 1); else $$ = NULL; - if ($$ == NULL) YYERROR; + if ($$ == NULL) YYERROR; if (!G_IS_BASIC_TYPE($$)) g_itanium_dcontext_add_item(context, $$); } ; @@ -541,17 +625,23 @@ template_template_param: ; template_args: - use_templates template_arg_list EE { $$ = $2; } + use_templates template_arg_list EE { $$ = $2; + context->template_level--; + g_itanium_dcontext_update(context); + } ; use_templates: - II { printf("new template !!!\n"); context->use_templates = true; } + II { printf("new template !!!\n"); /* FIXME : régle désormais inutile ! -> remme */ + context->template_level++; + g_itanium_dcontext_update(context); + } ; template_arg_list: template_arg_list template_arg { $$ = g_slist_prepend($1, $2); } | template_arg { $$ = g_slist_prepend(NULL, $1); } - | template_args { g_class_enum_type_new(CET_UNKNOWN, "template params"); } + | template_args { g_class_enum_type_new(CET_UNKNOWN, "template params"); printf("??? tmp list\n"); } ; template_arg: @@ -610,6 +700,12 @@ G_DEFINE_TYPE(GItaniumDContext, g_itanium_dcontext, G_TYPE_DEMANGLING_CONTEXT); static void g_itanium_dcontext_class_init(GItaniumDContextClass *klass) { + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = g_itanium_dcontext_dispose; + object->finalize = g_itanium_dcontext_finalize; } @@ -635,6 +731,66 @@ static void g_itanium_dcontext_init(GItaniumDContext *context) /****************************************************************************** * * +* Paramètres : context = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_itanium_dcontext_dispose(GItaniumDContext *context) +{ + gpointer data; /* Type à détacher */ + GBinRoutine *routine; /* Routine à détacher */ + gpointer obj_class; /* Classe parente */ + + while ((data = g_slist_nth_data(context->substitutions, 0)) != NULL) + { + g_object_unref(G_OBJECT(data)); + context->substitutions = g_slist_remove(context->substitutions, data); + } + + while ((routine = g_itanium_dcontext_pop_routine(context)) != NULL) + g_object_unref(G_OBJECT(routine)); + + obj_class = g_type_class_peek_parent(G_ITANIUM_DCONTEXT_GET_CLASS(context)); + + G_OBJECT_CLASS(obj_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_dcontext_finalize(GItaniumDContext *context) +{ + gpointer obj_class; /* Classe parente */ + + if (context->identifier != NULL) + free(context->identifier); + + obj_class = g_type_class_peek_parent(G_ITANIUM_DCONTEXT_GET_CLASS(context)); + + G_OBJECT_CLASS(obj_class)->finalize(G_OBJECT(context)); + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Prépare de quoi effectuer un décodage Itanium. * @@ -777,7 +933,7 @@ static void g_itanium_dcontext_add_item(GItaniumDContext *context, GOpenidaType { g_object_ref(G_OBJECT(type)); - printf("push %p\n", type); + printf(" [[ %u ]] PUSH '%s' (%p)\n", g_slist_length(context->substitutions) - 1, g_openida_type_to_string(type), type); context->substitutions = g_slist_append(context->substitutions, type); @@ -806,6 +962,28 @@ static GOpenidaType *g_itanium_dcontext_get_item(GItaniumDContext *context, guin } +/****************************************************************************** +* * +* Paramètres : context = décodeur à consulter. * +* * +* Description : Autorise ou non le dépilement des opérateurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_itanium_dcontext_update(GItaniumDContext *context) +{ + if (context->start_args || context->template_level > 0) + exclude_itanium_operators(); + + else allow_itanium_operators(); + +} + + /* ---------------------------------------------------------------------------------- */ /* TRAITEMENT DE L'ENCODAGE ITANIUM */ @@ -891,13 +1069,152 @@ bool can_be_itanium_demangled(const char *desc) bool demangle_itanium_routine(GItaniumDContext *context, const char *desc) { + GBinRoutine *routine; /* Routine à construire */ YY_BUFFER_STATE buffer; /* Tampon pour bison */ int ret; /* Bilan de l'appel */ + GOpenidaType *name_type; /* Nom basé sur un type ? */ + + routine = g_demangling_context_get_decoded_routine(G_DEMANGLING_CONTEXT(context)); + + allow_itanium_operators(); buffer = yy_scan_string(desc); - ret = yyparse(context, g_demangling_context_get_decoded_routine(G_DEMANGLING_CONTEXT(context))); + ret = yyparse(context, routine); yy_delete_buffer(buffer); + if (ret == 0) + { + name_type = g_binary_routine_get_type_from_name(routine); + + if (name_type != NULL && G_IS_TEMPLATE_TYPE(name_type)) + compute_routine_itanium_ret_type(routine); + + } + return (ret == 0); } + + +/****************************************************************************** +* * +* Paramètres : routine = routine à traiter si ce n'est pas déjà fait. * +* * +* Description : Fait sauter le premier argument en faveur du type de retour. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void compute_routine_itanium_ret_type(GBinRoutine *routine) +{ + size_t count; /* Nombre d'arguments présents */ + size_t i; /* Boucle de parcours */ + GBinVariable *arg; /* Argument de la routine */ + GOpenidaType *type; /* Type associé à l'argument */ + + /* Traitement récursif des arguments */ + + type = g_binary_routine_get_type_from_name(routine); + + if (type != NULL) + { + update_itanium_ret_type(type); + + /* On force une actualisation au cas où... */ + g_binary_routine_set_name(routine, NULL); + + } + + count = g_binary_routine_get_args_count(routine); + if (count == 0) return; + + for (i = 0; i < count; i++) + { + arg = g_binary_routine_get_arg(routine, i); + type = g_binary_variable_get_vtype(arg); + + update_itanium_ret_type(type); + + } + + /* Basculement du premier argument */ + + /** + * Avec les références de type partagées, il + * se peut que la fonction soit déjà traitée. + */ + if (g_binary_routine_get_return_type(routine) != NULL) + return; + + arg = g_binary_routine_get_arg(routine, 0); + + type = g_binary_variable_get_vtype(arg); + g_object_ref(G_OBJECT(type)); + + g_binary_routine_remove_arg(routine, 0); + + g_binary_routine_set_return_type(routine, type); + +} + + +/****************************************************************************** +* * +* Paramètres : type = type à traiter si ce n'est pas déjà fait. * +* * +* Description : Recherche et fait sauter les premiers arguments rencontrés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void update_itanium_ret_type(GOpenidaType *type) +{ + GTemplateType *template; /* Gabarit à analyser */ + size_t max; /* Nombre d'itérations */ + size_t i; /* Boucle de parcours */ + GOpenidaType *subtype; /* Type à traiter */ + GEncapsulatedType *encaps; /* Encapsulation quelconque */ + GBinRoutine *routine; /* Routine à traiter */ + + /* Gabarits */ + if (G_IS_TEMPLATE_TYPE(type)) + { + template = G_TEMPLATE_TYPE(type); + max = g_template_type_count_param(template); + + for (i = 0; i < max; i++) + { + subtype = g_template_type_get_param(template, i); + update_itanium_ret_type(subtype); + } + + } + + /* Encapsulations */ + else if (G_IS_ENCAPSULATED_TYPE(type)) + { + encaps = G_ENCAPSULATED_TYPE(type); + + switch (g_encapsulated_type_get_etype(encaps)) + { + case ECT_ROUTINE: + g_encapsulated_type_get_item(encaps, &routine); + compute_routine_itanium_ret_type(routine); + break; + + default: + g_encapsulated_type_get_item(encaps, &subtype); + update_itanium_ret_type(subtype); + break; + + } + + } + +} |