summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2010-08-10 00:17:32 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2010-08-10 00:17:32 (GMT)
commit088a489002fd1c9a62d5cafe693dc73cc271ee18 (patch)
treea147acd77fab3b66d541326349d08dae29ec0e8c
parentbcfcb4ec8b4cf9a35b77e93d172e7dae81e8872a (diff)
Improved Itanium demangling.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@179 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r--ChangeLog17
-rw-r--r--src/analysis/routine.c90
-rw-r--r--src/analysis/routine.h14
-rw-r--r--src/analysis/type.c82
-rw-r--r--src/analysis/type.h9
-rw-r--r--src/format/mangling/demangler.c50
-rw-r--r--src/format/mangling/itanium_gram.y395
-rw-r--r--src/format/mangling/itanium_tok.l58
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 <nocbos@gmail.com>
+
+ * 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 <nocbos@gmail.com>
* 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<int, int>::mf(N::T<double, double>)");
+
+ /**
+ * Tests de :
+ * (nero.so).
+ */
+
+ TEST_ITANIUM_MANGLING("_ZNSt6vectorItSaItEE6insertEN9__gnu_cxx17__normal_iteratorIPtS1_EERKt", "??? std::vector<unsigned short, std::allocator<unsigned short>>::insert(__gnu_cxx::__normal_iterator<unsigned short *, std::vector<unsigned short, std::allocator<unsigned short>>>, 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, CProfStringList>(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<NeroMediumFeatureSpecifier, std::char_traits<NeroMediumFeatureSpecifier>, std::allocator<NeroMediumFeatureSpecifier>>::_Rep::_M_destroy(const std::allocator<NeroMediumFeatureSpecifier> &)");
+
+ last:
+
+ /* 80 */
+ TEST_ITANIUM_MANGLING("_ZNSt6vectorIlSaIlEE6insertEN9__gnu_cxx17__normal_iteratorIPlS1_EERKl", "??? std::vector<long, std::allocator<long>>::insert(__gnu_cxx::__normal_iterator<long *, std::vector<long, std::allocator<long>>>, 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 <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;
+
+ }
+
+ }
+
+}
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
%%
+<INITIAL,operators>{
+
_Z { return ITANIUM_SIGNATURE; }
E { return EE; }
@@ -86,6 +96,9 @@ Si { return SI; }
So { return SO; }
Sd { return SD; }
+} /* INITIAL,operators> */
+
+<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 */
+
+<INITIAL,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; }
+} /* <INITIAL,operators> */
+
<identifier>. { if (--itanium_txt_length == 0) BEGIN(INITIAL); yylval.car = *yytext; return CHAR; }
-<*>[ ]
+<INITIAL,operators>[ ]
<*>. { 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);
+
+}