From d0314437fcad499f45a4bdb93d085100cee2c70b Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 4 Mar 2020 00:32:42 +0100 Subject: Handled destructors properly when demangling C++ Itanium names. --- plugins/itanium/abi.c | 2 +- plugins/itanium/component.c | 86 +++++++++++++++++++++++++++------------------ plugins/itanium/component.h | 4 +-- plugins/itanium/context.c | 2 +- src/analysis/routine.c | 33 ++++++++++++----- src/analysis/type.c | 23 ++++++++++++ src/analysis/type.h | 3 ++ tests/mangling/itanium.py | 9 +++++ 8 files changed, 115 insertions(+), 47 deletions(-) diff --git a/plugins/itanium/abi.c b/plugins/itanium/abi.c index c2e56e1..7094aa4 100644 --- a/plugins/itanium/abi.c +++ b/plugins/itanium/abi.c @@ -1772,7 +1772,7 @@ static itanium_component *itd_ctor_dtor_name(GItaniumDemangling *context) if (next == 'C') type = ICT_CONSTRUCTOR; else if (next == 'D') - type = ICT_DESSTRUCTOR; + type = ICT_DESTRUCTOR; else return NULL; diff --git a/plugins/itanium/component.c b/plugins/itanium/component.c index 1b2c33c..3474639 100644 --- a/plugins/itanium/component.c +++ b/plugins/itanium/component.c @@ -43,7 +43,6 @@ - /* Procédure à appliquer sur un composant visité */ typedef void (* visit_comp_fc) (itanium_component *); @@ -187,7 +186,7 @@ static void visit_comp(itanium_component *comp, visit_comp_fc visitor) break; case ICT_CONSTRUCTOR: - case ICT_DESSTRUCTOR: + case ICT_DESTRUCTOR: break; case ICT_TYPE: @@ -1019,7 +1018,7 @@ char *itd_translate_component(const itanium_component *comp, char *base) result = stradd(base, ""); break; - case ICT_DESSTRUCTOR: + case ICT_DESTRUCTOR: result = stradd(base, ""); break; @@ -1339,7 +1338,8 @@ static void itd_prepend_namespace_to_type(GDataType *type, GDataType *ns) /****************************************************************************** * * -* Paramètres : comp = composant Itanium à traduire en type. * +* Paramètres : comp = composant Itanium à traduire en type. * +* rtype = type de l'éventuelle routine en construction. * * * * Description : Traduit les composants de contexte Itanium en type. * * * @@ -1349,7 +1349,7 @@ static void itd_prepend_namespace_to_type(GDataType *type, GDataType *ns) * * ******************************************************************************/ -GDataType *itd_translate_component_to_type(const itanium_component *comp) +GDataType *itd_translate_component_to_type(const itanium_component *comp, RoutineType *rtype) { GDataType *result; /* Type à retourner */ char *name; /* Attribution finale */ @@ -1373,7 +1373,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) break; case ICT_STD_UNSCOPED_NAME: - result = itd_translate_component_to_type(comp->unary); + result = itd_translate_component_to_type(comp->unary, rtype); if (result != NULL) { ns = g_class_enum_type_new(CET_NAMESPACE, strdup("std")); @@ -1396,7 +1396,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) { if (comp->binary.left != NULL) { - ns = itd_translate_component_to_type(comp->binary.left); + ns = itd_translate_component_to_type(comp->binary.left, rtype); if (ns == NULL) { result = NULL; @@ -1406,7 +1406,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) else ns = NULL; - result = itd_translate_component_to_type(comp->binary.right); + result = itd_translate_component_to_type(comp->binary.right, rtype); if (result != NULL) { @@ -1416,8 +1416,12 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) else { - if (ns != NULL) + if (*rtype != RTT_CLASSIC) + result = ns; + + else if (ns != NULL) g_object_unref(G_OBJECT(ns)); + } } @@ -1426,11 +1430,11 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) case ICT_TEMPLATE_NAME_ARGS: - result = itd_translate_component_to_type(comp->binary.right); + result = itd_translate_component_to_type(comp->binary.right, rtype); if (result != NULL) { - sub = itd_translate_component_to_type(comp->binary.left); + sub = itd_translate_component_to_type(comp->binary.left, rtype); if (sub == NULL) { @@ -1471,14 +1475,14 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) else { - ns = itd_translate_component_to_type(comp->binary.left); + ns = itd_translate_component_to_type(comp->binary.left, rtype); if (ns == NULL) { result = NULL; break; } - result = itd_translate_component_to_type(comp->binary.right); + result = itd_translate_component_to_type(comp->binary.right, rtype); if (result != NULL) itd_prepend_namespace_to_type(result, ns); @@ -1502,7 +1506,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) { if (comp->binary.left != NULL) { - ns = itd_translate_component_to_type(comp->binary.left); + ns = itd_translate_component_to_type(comp->binary.left, rtype); if (ns == NULL) { result = NULL; @@ -1513,7 +1517,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) else ns = NULL; - result = itd_translate_component_to_type(comp->binary.right); + result = itd_translate_component_to_type(comp->binary.right, rtype); if (result != NULL) { @@ -1536,7 +1540,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) case ICT_SPECIAL_NAME_VTABLE: - ns = itd_translate_component_to_type(comp->unary); + ns = itd_translate_component_to_type(comp->unary, rtype); if (ns == NULL) result = NULL; @@ -1551,7 +1555,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) case ICT_SPECIAL_NAME_VSTRUCT: - ns = itd_translate_component_to_type(comp->unary); + ns = itd_translate_component_to_type(comp->unary, rtype); if (ns == NULL) result = NULL; @@ -1578,7 +1582,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) break; } - result = itd_translate_component_to_type(comp->binary.left); + result = itd_translate_component_to_type(comp->binary.left, rtype); if (result != NULL) result = g_override_type_new(result, &off0); @@ -1599,7 +1603,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) break; } - result = itd_translate_component_to_type(comp->ternary.first); + result = itd_translate_component_to_type(comp->ternary.first, rtype); if (result != NULL) result = g_override_type_new_with_covariant(result, &off0, &off1); @@ -1607,7 +1611,14 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) break; case ICT_CONSTRUCTOR: - case ICT_DESSTRUCTOR: + if (rtype != NULL) + *rtype = RTT_CONSTRUCTOR; + result = NULL; + break; + + case ICT_DESTRUCTOR: + if (rtype != NULL) + *rtype = RTT_DESTRUCTOR; result = NULL; break; @@ -1617,37 +1628,37 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) break; case ICT_QUALIFIED_TYPE: - result = itd_translate_component_to_type(comp->qualified.sub); + result = itd_translate_component_to_type(comp->qualified.sub, rtype); if (result != NULL) g_data_type_add_qualifier(result, comp->qualified.qualifier); break; case ICT_POINTER_TO: - result = itd_translate_component_to_type(comp->unary); + result = itd_translate_component_to_type(comp->unary, rtype); if (result != NULL && !G_IS_PROTO_TYPE(result)) result = g_encapsulated_type_new(ECT_POINTER, result); break; case ICT_REFERENCE_TO: - result = itd_translate_component_to_type(comp->unary); + result = itd_translate_component_to_type(comp->unary, rtype); if (result != NULL) result = g_encapsulated_type_new(ECT_REFERENCE, result); break; case ICT_RVALUE_REFERENCE_TO: - result = itd_translate_component_to_type(comp->unary); + result = itd_translate_component_to_type(comp->unary, rtype); if (result != NULL) result = g_encapsulated_type_new(ECT_RVALUE_REF, result); break; case ICT_COMPLEX_PAIR: - result = itd_translate_component_to_type(comp->unary); + result = itd_translate_component_to_type(comp->unary, rtype); if (result != NULL) result = g_encapsulated_type_new(ECT_COMPLEX, result); break; case ICT_IMAGINARY: - result = itd_translate_component_to_type(comp->unary); + result = itd_translate_component_to_type(comp->unary, rtype); if (result != NULL) result = g_encapsulated_type_new(ECT_IMAGINARY, result); break; @@ -1662,7 +1673,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) { assert(iter->type == ICT_TYPES_LIST); - arg = itd_translate_component_to_type(iter->binary.left); + arg = itd_translate_component_to_type(iter->binary.left, rtype); if (arg == NULL) { @@ -1689,7 +1700,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) case ICT_ARRAY: - members = itd_translate_component_to_type(comp->array.atype); + members = itd_translate_component_to_type(comp->array.atype, rtype); if (members == NULL) result = NULL; @@ -1714,14 +1725,14 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) case ICT_POINTER_TO_MEMBER: - ns = itd_translate_component_to_type(comp->pmember.class); + ns = itd_translate_component_to_type(comp->pmember.class, rtype); if (ns == NULL) result = NULL; else { - result = itd_translate_component_to_type(comp->pmember.member); + result = itd_translate_component_to_type(comp->pmember.member, rtype); if (result == NULL) g_object_unref(G_OBJECT(ns)); @@ -1734,7 +1745,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) break; case ICT_TEMPLATE_PARAM: - result = itd_translate_component_to_type(comp->unary); + result = itd_translate_component_to_type(comp->unary, rtype); break; case ICT_TEMPLATE_ARGS: @@ -1747,7 +1758,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) { assert(iter->type == ICT_TYPES_LIST); - param = itd_translate_component_to_type(iter->binary.left); + param = itd_translate_component_to_type(iter->binary.left, rtype); if (param == NULL) { @@ -1816,8 +1827,9 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp) GBinRoutine *itd_translate_component_to_routine(const itanium_component *comp) { GBinRoutine *result; /* Routine à retourner */ - bool has_ret; /* Type de retour présent ? */ itanium_component *name; /* Désignation de la routine */ + RoutineType rtype; /* Type déclaré de routine */ + bool has_ret; /* Type de retour présent ? */ char *desc; /* Description humaine */ GDataType *ns; /* Espace de noms de la routine*/ itanium_component *args; /* Liste de ses arguments */ @@ -1834,6 +1846,8 @@ GBinRoutine *itd_translate_component_to_routine(const itanium_component *comp) name = comp->binary.left; + rtype = RTT_CLASSIC; + /** * A la fin de § 5.1.3 ("Operator Encodings") est précisé : * @@ -1857,7 +1871,7 @@ GBinRoutine *itd_translate_component_to_routine(const itanium_component *comp) case ICT_STD_UNSCOPED_NAME: case ICT_NAME: - type = itd_translate_component_to_type(name); + type = itd_translate_component_to_type(name, &rtype); if (type == NULL) goto unsupported_encoding; ns = g_data_type_get_namespace(type); @@ -1892,6 +1906,8 @@ GBinRoutine *itd_translate_component_to_routine(const itanium_component *comp) } + g_binary_routine_set_type(result, rtype); + /* Liste d'arguments */ args = comp->binary.right; @@ -1901,7 +1917,7 @@ GBinRoutine *itd_translate_component_to_routine(const itanium_component *comp) for (iter = args; iter != NULL; iter = iter->binary.right) { - type = itd_translate_component_to_type(iter->binary.left); + type = itd_translate_component_to_type(iter->binary.left, NULL); if (type == NULL) goto unsupported_encoding; diff --git a/plugins/itanium/component.h b/plugins/itanium/component.h index a2dc607..36852d9 100644 --- a/plugins/itanium/component.h +++ b/plugins/itanium/component.h @@ -104,7 +104,7 @@ typedef enum _ItaniumComponentType * Constructeur ou destructeur, sans plus de détail. */ ICT_CONSTRUCTOR, - ICT_DESSTRUCTOR, + ICT_DESTRUCTOR, /** * Type instanciable dans le programme. @@ -295,7 +295,7 @@ ItaniumComponentType itd_get_component_type(const itanium_component *); char *itd_translate_component(const itanium_component *, char *); /* Traduit les composants de contexte Itanium en type. */ -GDataType *itd_translate_component_to_type(const itanium_component *); +GDataType *itd_translate_component_to_type(const itanium_component *, RoutineType *); /* Traduit les composants de contexte Itanium en routine. */ GBinRoutine *itd_translate_component_to_routine(const itanium_component *); diff --git a/plugins/itanium/context.c b/plugins/itanium/context.c index 315131e..6a79a40 100644 --- a/plugins/itanium/context.c +++ b/plugins/itanium/context.c @@ -289,7 +289,7 @@ static GDataType *g_itanium_demangling_decode_type(GItaniumDemangling *context) else { - result = itd_translate_component_to_type(comp); + result = itd_translate_component_to_type(comp, NULL); itd_unref_comp(comp); diff --git a/src/analysis/routine.c b/src/analysis/routine.c index 8c38ff1..240004f 100644 --- a/src/analysis/routine.c +++ b/src/analysis/routine.c @@ -826,12 +826,11 @@ char *g_binary_routine_to_string(const GBinRoutine *routine, bool include) { case RTT_CONSTRUCTOR: result = g_binary_routine_get_label(routine); - result = stradd(result, "." /* FIXME */); + result = stradd(result, " *"); break; case RTT_DESTRUCTOR: - result = g_binary_routine_get_label(routine); - result = stradd(result, "::~"); + result = strdup("void "); break; default: /* Pour gcc */ @@ -863,17 +862,35 @@ char *g_binary_routine_to_string(const GBinRoutine *routine, bool include) } if (routine->full_name != NULL) - { name = g_data_type_to_string(routine->full_name, true); - result = stradd(result, name); + else if (routine->name != NULL) + name = routine->name; - free(name); + switch (routine->type) + { + case RTT_CONSTRUCTOR: + result = stradd(result, name); + result = stradd(result, routine->ns_sep); + result = stradd(result, name); + break; + + case RTT_DESTRUCTOR: + result = stradd(result, name); + result = stradd(result, routine->ns_sep); + result = stradd(result, "~"); + result = stradd(result, name); + break; + + default: /* Pour gcc */ + case RTT_CLASSIC: + result = stradd(result, name); + break; } - else if (routine->name != NULL) - result = stradd(result, routine->name); + if (routine->full_name != NULL) + free(name); /* Liste des arguments */ diff --git a/src/analysis/type.c b/src/analysis/type.c index ddc068f..5bcb0e2 100644 --- a/src/analysis/type.c +++ b/src/analysis/type.c @@ -281,6 +281,29 @@ GDataType *g_data_type_get_namespace(const GDataType *type) /****************************************************************************** * * +* Paramètres : type = type à consulter. * +* * +* Description : Fournit la chaîne de séparation entre deux entités. * +* * +* Retour : Eventuelle chaîne de séparation ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_data_type_get_namespace_separator(const GDataType *type) +{ + char *result; /* Séparateur à retourner */ + + result = type->ns_sep; + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : type = instance à mettre à jour. * * qualifiers = nouveaux qualificatifs pour la variable. * * * diff --git a/src/analysis/type.h b/src/analysis/type.h index 96c8835..431c080 100644 --- a/src/analysis/type.h +++ b/src/analysis/type.h @@ -75,6 +75,9 @@ void g_data_type_set_namespace(GDataType *, GDataType *, char *); /* Fournit le groupe d'appartenance d'un type donné. */ GDataType *g_data_type_get_namespace(const GDataType *); +/* Fournit la chaîne de séparation entre deux entités. */ +const char *g_data_type_get_namespace_separator(const GDataType *); + /* Définit l'ensemble des qualificatifs d'une instance de type. */ void g_data_type_set_qualifiers(GDataType *, TypeQualifier); diff --git a/tests/mangling/itanium.py b/tests/mangling/itanium.py index a04c590..2d13d77 100644 --- a/tests/mangling/itanium.py +++ b/tests/mangling/itanium.py @@ -175,3 +175,12 @@ class TestItaniumMangling(ChrysalideTestCase): demangled = demangler.decode_routine('_ZSt12partial_sortIN9__gnu_cxx17__normal_iteratorIP28CPR_MAI_ADPTY_SectorSequenceSt6vectorIS2_SaIS2_EEEEEvT_S8_S8_') self.check_demangling(demangled, 'void std::partial_sort<__gnu_cxx::__normal_iterator>>>(__gnu_cxx::__normal_iterator>>, __gnu_cxx::__normal_iterator>>, __gnu_cxx::__normal_iterator>>)') + + + def testAndroidSystem(self): + """Check Itanium routine demangling from Android system cases.""" + + demangler = ItaniumDemangler() + + demangled = demangler.decode_routine('_ZN7android7String8D1Ev') + self.check_demangling(demangled, 'void android::String8::~String8(void)') -- cgit v0.11.2-87-g4458