From 088a489002fd1c9a62d5cafe693dc73cc271ee18 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 10 Aug 2010 00:17:32 +0000 Subject: Improved Itanium demangling. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@179 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 17 ++ src/analysis/routine.c | 90 ++++++++- src/analysis/routine.h | 14 +- src/analysis/type.c | 82 +++++++- src/analysis/type.h | 9 + src/format/mangling/demangler.c | 50 ++++- src/format/mangling/itanium_gram.y | 395 +++++++++++++++++++++++++++++++++---- src/format/mangling/itanium_tok.l | 58 +++++- 8 files changed, 667 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index bf7801f..f2f5a9f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +10-08-10 Cyrille Bagard + + * src/analysis/routine.c: + * src/analysis/routine.h: + Improve the code. + + * src/analysis/type.c: + * src/analysis/type.h: + Fix one warning, one bug in templates and improve the code. + + * src/format/mangling/demangler.c: + Extend the test suite. + + * src/format/mangling/itanium_gram.y: + * src/format/mangling/itanium_tok.l: + Improve Itanium demangling. + 10-08-01 Cyrille Bagard * src/format/elf/helper_x86.c: diff --git a/src/analysis/routine.c b/src/analysis/routine.c index 7709fa4..0c8d83a 100644 --- a/src/analysis/routine.c +++ b/src/analysis/routine.c @@ -437,7 +437,7 @@ void g_binary_routine_set_name_from_type(GBinRoutine *routine, GOpenidaType *typ * * ******************************************************************************/ -const GOpenidaType *g_binary_routine_get_type_from_name(const GBinRoutine *routine) +GOpenidaType *g_binary_routine_get_type_from_name(const GBinRoutine *routine) { return routine->full_name; @@ -472,6 +472,25 @@ void g_binary_routine_set_return_type(GBinRoutine *routine, GOpenidaType *type) /****************************************************************************** * * +* Paramètres : routine = routine à consulter. * +* * +* Description : Fournit le type de retour d'une routine. * +* * +* Retour : Indication sur le type de retour en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GOpenidaType *g_binary_routine_get_return_type(const GBinRoutine *routine) +{ + return routine->ret_type; + +} + + +/****************************************************************************** +* * * Paramètres : routine = routine à mettre à jour. * * var = variable représentant un argument supplémentaire. * * * @@ -490,6 +509,7 @@ void g_binary_routine_add_arg(GBinRoutine *routine, GBinVariable *var) routine->args = (GBinVariable **)realloc(routine->args, routine->args_count * sizeof(GBinVariable *)); + g_object_ref(G_OBJECT(var)); routine->args[routine->args_count - 1] = var; } @@ -497,6 +517,74 @@ void g_binary_routine_add_arg(GBinRoutine *routine, GBinVariable *var) /****************************************************************************** * * +* Paramètres : routine = routine à mettre à consulter. * +* * +* Description : Indique le nombre d'arguments associés à une routine. * +* * +* Retour : Nombre d'arguments présents. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_binary_routine_get_args_count(const GBinRoutine *routine) +{ + return routine->args_count; + +} + + +/****************************************************************************** +* * +* Paramètres : routine = routine à consulter. * +* index = indice de l'argument demandé. * +* * +* Description : Fournit un argument d'une routine. * +* * +* Retour : Argument demandé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBinVariable *g_binary_routine_get_arg(GBinRoutine *routine, size_t index) +{ + return routine->args[index]; + +} + + +/****************************************************************************** +* * +* Paramètres : routine = routine à mettre à jour. * +* index = indice de l'argument à retirer; * +* * +* Description : Retire un argument d'une routine. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_binary_routine_remove_arg(GBinRoutine *routine, size_t index) +{ + g_object_unref(G_OBJECT(routine->args[index])); + + if ((index + 1) < routine->args_count) + memmove(&routine->args[index], &routine->args[index + 1], + (routine->args_count - index - 1) * sizeof(GBinVariable *)); + + routine->args_count--; + + routine->args = (GBinVariable **)realloc(routine->args, + routine->args_count * sizeof(GBinVariable *)); + +} + + +/****************************************************************************** +* * * Paramètres : routine = routine à mettre à jour. * * offset = position abstraite à retrouver. * * local = indique le type de variable à manipuler. * diff --git a/src/analysis/routine.h b/src/analysis/routine.h index cd17bf3..e2ea1cc 100644 --- a/src/analysis/routine.h +++ b/src/analysis/routine.h @@ -112,14 +112,26 @@ const char *g_binary_routine_get_name(const GBinRoutine *); void g_binary_routine_set_name_from_type(GBinRoutine *, GOpenidaType *); /* Fournit le type construisant le nom humain d'une routine. */ -const GOpenidaType *g_binary_routine_get_type_from_name(const GBinRoutine *); +GOpenidaType *g_binary_routine_get_type_from_name(const GBinRoutine *); /* Définit le type de retour d'une routine. */ void g_binary_routine_set_return_type(GBinRoutine *, GOpenidaType *); +/* Fournit le type de retour d'une routine. */ +GOpenidaType *g_binary_routine_get_return_type(const GBinRoutine *); + /* Ajoute un argument à une routine. */ void g_binary_routine_add_arg(GBinRoutine *, GBinVariable *); +/* Indique le nombre d'arguments associés à une routine. */ +size_t g_binary_routine_get_args_count(const GBinRoutine *); + +/* Fournit un argument d'une routine. */ +GBinVariable *g_binary_routine_get_arg(GBinRoutine *, size_t); + +/* Retire un argument d'une routine. */ +void g_binary_routine_remove_arg(GBinRoutine *, size_t); + /* S'assure qu'une variable est bien associée à une routine. */ void g_binary_routine_register_if_needed(GBinRoutine *, size_t, bool); diff --git a/src/analysis/type.c b/src/analysis/type.c index d16917f..0cd021e 100644 --- a/src/analysis/type.c +++ b/src/analysis/type.c @@ -888,6 +888,7 @@ static char *g_encapsulated_type_to_string(const GEncapsulatedType *type) result = stradd(result, " imaginary"); break; + case ECT_ROUTINE: /* Pour GCC */ default: break; @@ -898,6 +899,65 @@ static char *g_encapsulated_type_to_string(const GEncapsulatedType *type) } +/****************************************************************************** +* * +* Paramètres : type = type à consulter. * +* * +* Description : Fournit le type d'encapsulation gérée par le type. * +* * +* Retour : Type d'encapsulation gérée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +EncapsulationType g_encapsulated_type_get_etype(const GEncapsulatedType *type) +{ + return type->type; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type à consulter. * +* ... = sous-type ou routine encapsulée dans le type. [OUT] * +* * +* Description : Fournit la routine encapsulée dans le type. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_encapsulated_type_get_item(const GEncapsulatedType *type, ...) +{ + va_list ap; /* Liste variable d'arguments */ + GOpenidaType **child; /* Adresse pour sous-type */ + GBinRoutine **routine; /* Adresse pour routine */ + + va_start(ap, type); + + switch (type->type) + { + case ECT_ROUTINE: + routine = va_arg(ap, GBinRoutine **); + *routine = type->routine; + break; + + default: + child = va_arg(ap, GOpenidaType **); + *child = type->child; + break; + + } + + va_end(ap); + +} + + /* ---------------------------------------------------------------------------------- */ /* CLASSES / STRUCTURES ET ENUMERATIONS */ @@ -1125,8 +1185,6 @@ static GOpenidaType *g_template_type_dup(const GTemplateType *type) result = g_template_type_new(G_CLASS_ENUM_TYPE(type)->name, list); - g_slist_free(list); - return G_OPENIDA_TYPE(result); } @@ -1171,7 +1229,6 @@ static char *g_template_type_to_string(const GTemplateType *type) } - /****************************************************************************** * * * Paramètres : type = type à mettre à jour. * @@ -1204,6 +1261,25 @@ void g_template_type_add_params(GTemplateType *type, GSList *list) /****************************************************************************** * * +* Paramètres : type = type à consulter. * +* * +* Description : Indique le nombre de paramètres associés du gabarit. * +* * +* Retour : Nombre de paramètres inclus dans le gabarit. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_template_type_count_param(const GTemplateType *type) +{ + return type->models_count; + +} + + +/****************************************************************************** +* * * Paramètres : type = type à consulter. * * index = indice du paramètre à retourner. * * * diff --git a/src/analysis/type.h b/src/analysis/type.h index ac17235..77f3ace 100644 --- a/src/analysis/type.h +++ b/src/analysis/type.h @@ -183,6 +183,12 @@ GType g_encapsulated_type_get_type(void); /* Crée une représentation de variable dérivée. */ GOpenidaType *g_encapsulated_type_new(EncapsulationType, ...); +/* Fournit le type d'encapsulation gérée par le type. */ +EncapsulationType g_encapsulated_type_get_etype(const GEncapsulatedType *); + +/* Fournit la routine encapsulée dans le type. */ +void g_encapsulated_type_get_item(const GEncapsulatedType *, ...); + /* ---------------------- CLASSES / STRUCTURES ET ENUMERATIONS ---------------------- */ @@ -249,6 +255,9 @@ GOpenidaType *g_template_type_new(const char *, GSList *); /* Ajoute une série de paramètres à un gabarit. */ void g_template_type_add_params(GTemplateType *, GSList *); +/* Indique le nombre de paramètres associés du gabarit. */ +size_t g_template_type_count_param(const GTemplateType *); + /* Fournit un paramètre donné du gabarit. */ GOpenidaType *g_template_type_get_param(const GTemplateType *, size_t); diff --git a/src/format/mangling/demangler.c b/src/format/mangling/demangler.c index dec4cb5..786005d 100644 --- a/src/format/mangling/demangler.c +++ b/src/format/mangling/demangler.c @@ -95,8 +95,18 @@ GBinRoutine *try_to_demangle_routine(const char *desc) GBinRoutine *result; /* Construction à remonter */ DemanglerType i; /* Boucle de parcours */ + static int counter = 0; + result = NULL; + if (strcmp(desc, "_ZN21IUDFSettingsValidator15IdNotIllegalStdEN13UDFParameters12UDF_STANDARDES1_") == 0 + || strcmp(desc, "_ZSt12partial_sortIN9__gnu_cxx17__normal_iteratorIP28CPR_MAI_ADPTY_SectorSequenceSt6vectorIS2_SaIS2_EEEEEvT_S8_S8_") == 0 + || strcmp(desc, "_ZSt22__merge_without_bufferIN9__gnu_cxx17__normal_iteratorIP15CProfStringListSt6vectorIS2_SaIS2_EEEEiEvT_S8_S8_T0_S9_") == 0 + || strcmp(desc, "_ZSt11__push_heapIN9__gnu_cxx17__normal_iteratorIP8DRIVE_IDSt6vectorIS2_SaIS2_EEEEiS2_EvT_T0_S9_T1_") == 0 // Intéressant + //|| strcmp(desc, "") == 0 + ) + goto exit; + for (i = 0; i < DGT_COUNT; i++) { if (demanglers[i].can_demangle == NULL) @@ -105,7 +115,7 @@ GBinRoutine *try_to_demangle_routine(const char *desc) if (!demanglers[i].can_demangle(desc)) continue; - printf("++ routine :: %s\n", desc); + printf("++ [%d] routine :: %s\n", ++counter, desc); fflush(NULL); result = demangle_routine(i, desc); @@ -114,14 +124,21 @@ GBinRoutine *try_to_demangle_routine(const char *desc) if (result == NULL) { printf("++failed :: %s\n", desc); - exit(-1); + + if (strcmp(desc, "_ZN21IUDFSettingsValidator15IdNotIllegalStdEN13UDFParameters12UDF_STANDARDES1_") != 0 + && strcmp(desc, "_ZSt12partial_sortIN9__gnu_cxx17__normal_iteratorIP28CPR_MAI_ADPTY_SectorSequenceSt6vectorIS2_SaIS2_EEEEEvT_S8_S8_") != 0 + ) + exit(-1); + } - else printf(" -->> '%s'\n", g_binary_routine_get_name(result)); + else printf(" -->> '%s'\n\n", g_binary_routine_get_name(result)); if (result != NULL) break; } + exit: + if (result == NULL) { result = g_binary_routine_new(); @@ -253,6 +270,8 @@ void test_itanium_demangling(void) } \ while (0) + //goto last; + /** * Tests de : * http://www.codesourcery.com/public/cxx-abi/abi-examples.html#mangling @@ -290,6 +309,31 @@ void test_itanium_demangling(void) //TEST_ITANIUM_MANGLING("", ""); + /** + * Tests de : + * http://www.codesourcery.com/public/cxx-abi/abi.html#mangling + */ + + TEST_ITANIUM_MANGLING("_ZN1N1TIiiE2mfES0_IddE", "??? N::T::mf(N::T)"); + + /** + * Tests de : + * (nero.so). + */ + + TEST_ITANIUM_MANGLING("_ZNSt6vectorItSaItEE6insertEN9__gnu_cxx17__normal_iteratorIPtS1_EERKt", "??? std::vector>::insert(__gnu_cxx::__normal_iterator>>, const unsigned short &)"); + + TEST_ITANIUM_MANGLING("_ZSt26__uninitialized_fill_n_auxIP15CProfStringListiS0_ET_S2_T0_RKT1_12__false_type", "CProfStringList *std::__uninitialized_fill_n_aux(CProfStringList *, int, const CProfStringList &, __false_type)"); + + // TODO TEST_ITANIUM_MANGLING("_ZN21IUDFSettingsValidator15IdNotIllegalStdEN13UDFParameters12UDF_STANDARDES1_", ""); + + TEST_ITANIUM_MANGLING("_ZNSbI26NeroMediumFeatureSpecifierSt11char_traitsIS_ESaIS_EE4_Rep10_M_destroyERKS2_", "??? std::basic_string, std::allocator>::_Rep::_M_destroy(const std::allocator &)"); + + last: + + /* 80 */ + TEST_ITANIUM_MANGLING("_ZNSt6vectorIlSaIlEE6insertEN9__gnu_cxx17__normal_iteratorIPlS1_EERKl", "??? std::vector>::insert(__gnu_cxx::__normal_iterator>>, const long &)"); + end_of_test: ; 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 unscoped_template_name %type unqualified_name operator_name -%type prefix template_prefix source_name +%type registered_prefix + +%type prefix + +%type template_prefix source_name + +%type registered_template_prefix %type template_param template_template_param @@ -251,7 +282,7 @@ char *strmerge(char *str1, const char *sep, char *str2); %type template_args template_arg_list %type template_arg expr_primary -%type substitution +%type substitution %type 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; + + } + + } + +} diff --git a/src/format/mangling/itanium_tok.l b/src/format/mangling/itanium_tok.l index e8fb7f1..a4c330b 100644 --- a/src/format/mangling/itanium_tok.l +++ b/src/format/mangling/itanium_tok.l @@ -10,6 +10,13 @@ static unsigned int itanium_txt_length = 0; /* Borne la longueur d'une chaîne à lire. */ void set_itanium_text_length(unsigned int); +/* Autorise la lecture des opérateurs. */ +void allow_itanium_operators(void); + +/* Autorise la lecture des opérateurs. */ +void exclude_itanium_operators(void); + + %} @@ -19,11 +26,14 @@ void set_itanium_text_length(unsigned int); %x identifier +%x operators %% +{ + _Z { return ITANIUM_SIGNATURE; } E { return EE; } @@ -86,6 +96,9 @@ Si { return SI; } So { return SO; } Sd { return SD; } +} /* INITIAL,operators> */ + +{ nw { return OPER_NEW; } na { return OPER_NEW_ARRAY; } @@ -134,6 +147,9 @@ pt { return OPER_POINTER_TO; } cl { return OPER_CLASS; } ix { return OPER_INDEX; } +} /* operators */ + +{ S_ { return SUBSTI_FIRST; } S[0-9a-z]_ { yylval.val = atoi(yytext + 1); return SUBSTI_N; } @@ -145,9 +161,11 @@ T[0-9]*_ { yylval.val = atoi(yytext + 1); return TPARAM_N; } [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); } @@ -173,3 +191,41 @@ void set_itanium_text_length(unsigned int length) BEGIN(identifier); } + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Autorise la lecture des opérateurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void allow_itanium_operators(void) +{ + BEGIN(operators); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Autorise la lecture des opérateurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void exclude_itanium_operators(void) +{ + BEGIN(INITIAL); + +} -- cgit v0.11.2-87-g4458