summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-07-04 10:24:39 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-07-04 10:24:39 (GMT)
commit1ade82e135d4e815db5b33c9ebd67632b74e5e1d (patch)
treeeafda5b3e4062922ee4f0b64e8f90695bfbde9c3
parent8dc83465a6ca2d5b94b983b39f6c06d37e4126a0 (diff)
Fixed various mistakes in Itanium C++ demangling.
-rw-r--r--plugins/itanium/abi.c59
-rw-r--r--plugins/itanium/component-int.h5
-rw-r--r--plugins/itanium/component.c63
-rw-r--r--plugins/itanium/component.h16
-rw-r--r--plugins/itanium/context.c43
-rw-r--r--plugins/itanium/context.h2
-rw-r--r--plugins/pychrysalide/analysis/types/array.c19
-rw-r--r--src/analysis/types/array.c33
-rw-r--r--src/analysis/types/array.h3
-rw-r--r--tests/mangling/itanium.py66
10 files changed, 212 insertions, 97 deletions
diff --git a/plugins/itanium/abi.c b/plugins/itanium/abi.c
index 5f76342..3f6f713 100644
--- a/plugins/itanium/abi.c
+++ b/plugins/itanium/abi.c
@@ -1954,6 +1954,7 @@ static itanium_component *itd_type(GItaniumDemangling *context)
{
builtin = g_class_enum_type_new(CET_UNKNOWN, itd_translate_component(vendor, NULL));
result = itd_make_type(builtin);
+ itd_set_type(result, ICT_VENDOR_TYPE);
itd_unref_comp(vendor);
sub = itd_type(context);
@@ -2483,10 +2484,10 @@ static itanium_component *itd_array_type(GItaniumDemangling *context)
{
itanium_component *result; /* Construction à retourner */
input_buffer *ibuf; /* Tampon de texte manipulé */
- char peek; /* Prochain caractère dispo. */
- itanium_component *dim_expr; /* Dimension via expression */
ssize_t dim_number; /* Dimension par un nombre */
itanium_component *type; /* Type du tableau */
+ itd_state saved; /* Position d'analyse courante */
+ itanium_component *dim_expr; /* Dimension via expression */
/**
* La règle traitée ici est la suivante :
@@ -2501,58 +2502,46 @@ static itanium_component *itd_array_type(GItaniumDemangling *context)
if (!check_input_buffer_char(ibuf, 'A'))
return NULL;
- peek = peek_input_buffer_char(ibuf);
-
- if (peek == '[')
+ if (itd_number(context, &dim_number))
{
- advance_input_buffer(ibuf, 1);
-
- dim_expr = itd_expression(context);
-
- if (dim_expr == NULL)
- return NULL;
-
- if (!check_input_buffer_char(ibuf, ']'))
- return NULL;
-
if (!check_input_buffer_char(ibuf, '_'))
return NULL;
type = itd_type(context);
if (type == NULL)
- {
- itd_unref_comp(dim_expr);
return NULL;
- }
- result = itd_make_array_with_dim_expr(dim_expr, type);
-
- if (result == NULL)
- {
- itd_unref_comp(dim_expr);
- itd_unref_comp(type);
- }
+ result = itd_make_array_with_dim_number(dim_number, type);
}
else
{
- if (!itd_number(context, &dim_number))
- return NULL;
+ g_itanium_demangling_push_state(context, &saved);
+
+ dim_expr = itd_expression(context);
+
+ if (dim_expr == NULL)
+ g_itanium_demangling_pop_state(context, &saved);
if (!check_input_buffer_char(ibuf, '_'))
+ {
+ if (dim_expr != NULL)
+ itd_unref_comp(dim_expr);
return NULL;
+ }
type = itd_type(context);
if (type == NULL)
+ {
+ if (dim_expr != NULL)
+ itd_unref_comp(dim_expr);
return NULL;
+ }
- result = itd_make_array_with_dim_number(dim_number, type);
-
- if (result == NULL)
- itd_unref_comp(type);
+ result = itd_make_array_with_dim_expr(dim_expr, type);
}
@@ -2660,6 +2649,9 @@ static itanium_component *itd_template_param(GItaniumDemangling *context)
result = g_itanium_demangling_get_template_arg(context, id);
+ if (result != NULL)
+ result = itd_make_unary(ICT_TEMPLATE_PARAM, result);
+
}
}
@@ -2761,6 +2753,8 @@ static itanium_component *itd_template_args(GItaniumDemangling *context)
result = itd_make_unary(ICT_TEMPLATE_ARGS, result);
+ g_itanium_demangling_add_template_args(context, result);
+
return result;
}
@@ -2817,9 +2811,6 @@ static itanium_component *itd_template_arg(GItaniumDemangling *context)
else
result = itd_type(context);
- if (result != NULL)
- g_itanium_demangling_add_template_arg(context, result);
-
return result;
}
diff --git a/plugins/itanium/component-int.h b/plugins/itanium/component-int.h
index fb8c423..20b2c8d 100644
--- a/plugins/itanium/component-int.h
+++ b/plugins/itanium/component-int.h
@@ -36,8 +36,6 @@ struct _itanium_component
unsigned int refcount; /* Compteur de références */
- fnv64_t hash; /* Empreinte en cache */
-
union
{
/* ICT_NAME */
@@ -66,8 +64,9 @@ struct _itanium_component
/* ICT_VIRTUAL_OFFSET */
ssize_t offset; /* Décalage de fonction */
- /* ICT_STD_SUBST */
/* ICT_TYPE */
+ /* ICT_VENDOR_TYPE */
+ /* ICT_STD_SUBST */
GDataType *dtype; /* Type instancié */
/* ICT_QUALIFIED_TYPE */
diff --git a/plugins/itanium/component.c b/plugins/itanium/component.c
index 6e580f6..d890a1b 100644
--- a/plugins/itanium/component.c
+++ b/plugins/itanium/component.c
@@ -48,9 +48,6 @@
typedef void (* visit_comp_fc) (itanium_component *);
-#define reset_comp_hash(c) c->hash = 0
-
-
/* Crée un composant de contexte Itanium complètement vierge. */
static itanium_component *itd_alloc(void);
@@ -191,6 +188,7 @@ static void visit_comp(itanium_component *comp, visit_comp_fc visitor)
break;
case ICT_TYPE:
+ case ICT_VENDOR_TYPE:
break;
case ICT_QUALIFIED_TYPE:
@@ -227,7 +225,7 @@ static void visit_comp(itanium_component *comp, visit_comp_fc visitor)
break;
case ICT_ARRAY:
- if (!comp->array.numbered_dim)
+ if (!comp->array.numbered_dim && comp->array.dim_expr != NULL)
visit_comp(comp->array.dim_expr, visitor);
visit_comp(comp->array.atype, visitor);
break;
@@ -237,6 +235,10 @@ static void visit_comp(itanium_component *comp, visit_comp_fc visitor)
visit_comp(comp->pmember.member, visitor);
break;
+ case ICT_TEMPLATE_PARAM:
+ visit_comp(comp->unary, visitor);
+ break;
+
case ICT_TEMPLATE_ARGS:
visit_comp(comp->unary, visitor);
break;
@@ -320,7 +322,7 @@ void itd_unref_comp(itanium_component *comp)
{
if (--comp->refcount == 0)
{
- if (comp->type == ICT_TYPE || comp->type == ICT_STD_SUBST)
+ if (comp->type == ICT_TYPE || comp->type == ICT_VENDOR_TYPE || comp->type == ICT_STD_SUBST)
g_object_unref(G_OBJECT(comp->dtype));
itd_free(comp);
@@ -336,34 +338,6 @@ void itd_unref_comp(itanium_component *comp)
/******************************************************************************
* *
-* Paramètres : comp = composant à manipuler. *
-* *
-* Description : Détermine ou fournit l'empreinte d'un composant. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-fnv64_t itd_hash_comp(itanium_component *comp)
-{
- char *desc; /* Description du composant */
-
- if (comp->hash == 0)
- {
- desc = itd_translate_component(comp, NULL);
- comp->hash = fnv_64a_hash(desc);
- free(desc);
- }
-
- return comp->hash;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : type = type à définir pour le composant. *
* *
* Description : Construit un composant dans un contexte Itanium. *
@@ -797,7 +771,7 @@ itanium_component *itd_append_right_to_binary(ItaniumComponentType type, itanium
if (parent != NULL)
{
for (iter = parent; iter->binary.right != NULL; iter = iter->binary.right)
- reset_comp_hash(iter);
+ ;
iter->binary.right = result;
}
@@ -854,8 +828,6 @@ void itd_set_type(itanium_component *comp, ItaniumComponentType type)
{
comp->type = type;
- reset_comp_hash(comp);
-
}
@@ -1025,6 +997,7 @@ char *itd_translate_component(const itanium_component *comp, char *base)
break;
case ICT_TYPE:
+ case ICT_VENDOR_TYPE:
name = g_data_type_to_string(comp->dtype, true);
result = stradd(base, name);
free(name);
@@ -1112,7 +1085,7 @@ char *itd_translate_component(const itanium_component *comp, char *base)
free(tmp);
}
- else
+ else if (comp->array.dim_expr != NULL)
result = itd_translate_component(comp->array.dim_expr, result);
result = stradd(result, "]");
@@ -1125,6 +1098,10 @@ char *itd_translate_component(const itanium_component *comp, char *base)
result = itd_translate_component(comp->pmember.member, result);
break;
+ case ICT_TEMPLATE_PARAM:
+ result = itd_translate_component(comp->unary, base);
+ break;
+
case ICT_TEMPLATE_ARGS:
result = stradd(base, "<");
result = itd_translate_component(comp->unary, result);
@@ -1543,6 +1520,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
break;
case ICT_TYPE:
+ case ICT_VENDOR_TYPE:
result = g_data_type_dup(comp->dtype);
break;
@@ -1631,9 +1609,12 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
if (comp->array.numbered_dim)
g_array_type_set_dimension_number(G_ARRAY_TYPE(result), comp->array.dim_number);
- else
+ else if (comp->array.dim_expr != NULL)
g_array_type_set_dimension_expression(G_ARRAY_TYPE(result),
- itd_translate_component(comp, NULL));
+ itd_translate_component(comp->array.dim_expr, NULL));
+
+ else
+ g_array_type_set_empty_dimension(G_ARRAY_TYPE(result));
}
@@ -1660,6 +1641,10 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp)
break;
+ case ICT_TEMPLATE_PARAM:
+ result = itd_translate_component_to_type(comp->unary);
+ break;
+
case ICT_TEMPLATE_ARGS:
assert(comp->unary->type == ICT_TYPES_LIST);
diff --git a/plugins/itanium/component.h b/plugins/itanium/component.h
index f921ff9..7012283 100644
--- a/plugins/itanium/component.h
+++ b/plugins/itanium/component.h
@@ -34,7 +34,6 @@
#include <analysis/routine.h>
#include <analysis/type.h>
-#include <common/fnv1a.h>
@@ -113,6 +112,12 @@ typedef enum _ItaniumComponentType
ICT_TYPE,
/**
+ * Simple distinction de ICT_TYPE, pour la distinction lors des candidatures
+ * aux substitutions.
+ */
+ ICT_VENDOR_TYPE,
+
+ /**
* Type qualifié ; les infos utilies sont explicitement
* conservées dans le champ qualified.
*/
@@ -154,6 +159,12 @@ typedef enum _ItaniumComponentType
ICT_POINTER_TO_MEMBER,
/**
+ * Argument de template. Utile pour les candidatures aux substitutions.
+ * 'unary' renvoie vers le composant utile.
+ */
+ ICT_TEMPLATE_PARAM,
+
+ /**
* Liste d'arguments pour templates, à encadrer par des chevrons.
* 'unary' pointe vers la liste des éléments.
*/
@@ -223,9 +234,6 @@ void itd_ref_comp(itanium_component *);
/* Décrémente le nombre d'utilisation du composant. */
void itd_unref_comp(itanium_component *);
-/* Détermine ou fournit l'empreinte d'un composant. */
-fnv64_t itd_hash_comp(itanium_component *);
-
/* Construit un composant dans un contexte Itanium. */
itanium_component *itd_make_with_type(ItaniumComponentType);
diff --git a/plugins/itanium/context.c b/plugins/itanium/context.c
index 1d2c365..c89f823 100644
--- a/plugins/itanium/context.c
+++ b/plugins/itanium/context.c
@@ -411,10 +411,12 @@ void g_itanium_demangling_pop_state(GItaniumDemangling *context, const itd_state
* *
******************************************************************************/
-void g_itanium_demangling_add_template_arg(GItaniumDemangling *context, itanium_component *comp)
+void g_itanium_demangling_add_template_args(GItaniumDemangling *context, itanium_component *comp)
{
assert(comp != NULL);
+ assert(itd_get_component_type(comp) == ICT_TEMPLATE_ARGS);
+
context->template_args[context->targs_count++] = comp;
itd_ref_comp(comp);
@@ -437,14 +439,37 @@ void g_itanium_demangling_add_template_arg(GItaniumDemangling *context, itanium_
itanium_component *g_itanium_demangling_get_template_arg(GItaniumDemangling *context, size_t index)
{
itanium_component *result; /* Composant à retourner */
+ itanium_component *targs; /* Racine des arguments */
+ itanium_component *iter; /* Boucle de parcours #1 */
+
+ if (context->targs_count == 0)
+ result = NULL;
- if (index < context->targs_count)
+ else
{
- result = context->template_args[index];
- itd_ref_comp(result);
+ targs = context->template_args[context->targs_count - 1];
+
+ for (iter = targs->unary; iter != NULL; iter = iter->binary.right)
+ {
+ assert(itd_get_component_type(iter) == ICT_TYPES_LIST);
+
+ if (index == 0)
+ break;
+
+ index--;
+
+ }
+
+ if (iter != NULL)
+ {
+ result = iter->binary.left;
+ itd_ref_comp(result);
+ }
+
+ else
+ result = NULL;
+
}
- else
- result = NULL;
return result;
@@ -466,15 +491,15 @@ itanium_component *g_itanium_demangling_get_template_arg(GItaniumDemangling *con
void g_itanium_demangling_add_substitution(GItaniumDemangling *context, itanium_component *comp)
{
- fnv64_t hash; /* Empreinte du candidat */
size_t i; /* Boucle de parcours */
assert(comp != NULL);
- hash = itd_hash_comp(comp);
+ if (itd_get_component_type(comp) == ICT_STD_SUBST)
+ return;
for (i = 0; i < context->subst_count; i++)
- if (cmp_fnv_64a(itd_hash_comp(context->substitutions[i]), hash) == 0)
+ if (comp == context->substitutions[i])
break;
if (i == context->subst_count)
diff --git a/plugins/itanium/context.h b/plugins/itanium/context.h
index 6ec65ae..d836afb 100644
--- a/plugins/itanium/context.h
+++ b/plugins/itanium/context.h
@@ -67,7 +67,7 @@ void g_itanium_demangling_push_state(const GItaniumDemangling *, itd_state *);
void g_itanium_demangling_pop_state(GItaniumDemangling *, const itd_state *);
/* Indexe un composant représentant un argument de modèle. */
-void g_itanium_demangling_add_template_arg(GItaniumDemangling *, itanium_component *);
+void g_itanium_demangling_add_template_args(GItaniumDemangling *, itanium_component *);
/* Fournit un composant représentant un argument de modèle. */
itanium_component *g_itanium_demangling_get_template_arg(GItaniumDemangling *, size_t);
diff --git a/plugins/pychrysalide/analysis/types/array.c b/plugins/pychrysalide/analysis/types/array.c
index d021e16..6f70b02 100644
--- a/plugins/pychrysalide/analysis/types/array.c
+++ b/plugins/pychrysalide/analysis/types/array.c
@@ -281,7 +281,14 @@ static PyObject *py_array_type_get_dimension_expression(PyObject *self, void *cl
dim = g_array_type_get_dimension_expression(type);
- result = PyUnicode_FromString(dim);
+ if (dim != NULL)
+ result = PyUnicode_FromString(dim);
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
return result;
@@ -306,15 +313,19 @@ static int py_array_type_set_dimension_expression(PyObject *self, PyObject *valu
{
GArrayType *type; /* Version GLib du type */
- if (!PyUnicode_Check(value))
+ if (!PyUnicode_Check(value) && value != Py_None)
{
- PyErr_SetString(PyExc_TypeError, _("The attribute value must be a string."));
+ PyErr_SetString(PyExc_TypeError, _("The attribute value must be a string or None."));
return -1;
}
type = G_ARRAY_TYPE(pygobject_get(self));
- g_array_type_set_dimension_expression(type, strdup(PyUnicode_DATA(value)));
+ if (value == Py_None)
+ g_array_type_set_empty_dimension(type);
+
+ else
+ g_array_type_set_dimension_expression(type, strdup(PyUnicode_DATA(value)));
return 0;
diff --git a/src/analysis/types/array.c b/src/analysis/types/array.c
index 714ab58..5aea07b 100644
--- a/src/analysis/types/array.c
+++ b/src/analysis/types/array.c
@@ -230,6 +230,9 @@ static GDataType *g_array_type_dup(const GArrayType *type)
else if (type->dim_expr != NULL)
g_array_type_set_dimension_expression(G_ARRAY_TYPE(result), strdup(type->dim_expr));
+ else
+ g_array_type_set_empty_dimension(G_ARRAY_TYPE(result));
+
return result;
}
@@ -268,7 +271,7 @@ static char *g_array_type_to_string(const GArrayType *type, bool include)
}
}
- else
+ else if (type->dim_expr != NULL)
result = stradd(result, type->dim_expr);
result = stradd(result, "]");
@@ -356,7 +359,7 @@ ssize_t g_array_type_get_dimension_number(const GArrayType *type)
/******************************************************************************
* *
-* Paramètres : type = type à consulter. *
+* Paramètres : type = type à traiter. *
* dim = dimension positive ou nulle. *
* *
* Description : Définit la dimension associée au tableau. *
@@ -406,7 +409,7 @@ const char *g_array_type_get_dimension_expression(const GArrayType *type)
/******************************************************************************
* *
-* Paramètres : type = type à consulter. *
+* Paramètres : type = type à traiter. *
* expr = expression de dimension. *
* *
* Description : Définit la dimension associée au tableau. *
@@ -427,3 +430,27 @@ void g_array_type_set_dimension_expression(GArrayType *type, char *expr)
type->dim_expr = expr;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type à traiter. *
+* *
+* Description : Définit une dimension vide pour le tableau. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_array_type_set_empty_dimension(GArrayType *type)
+{
+ if (!type->numbered && type->dim_expr != NULL)
+ free(type->dim_expr);
+
+ type->numbered = false;
+
+ type->dim_expr = NULL;
+
+}
diff --git a/src/analysis/types/array.h b/src/analysis/types/array.h
index d432c22..3bec2a0 100644
--- a/src/analysis/types/array.h
+++ b/src/analysis/types/array.h
@@ -71,6 +71,9 @@ const char *g_array_type_get_dimension_expression(const GArrayType *);
/* Définit la dimension associée au tableau. */
void g_array_type_set_dimension_expression(GArrayType *, char *);
+/* Définit une dimension vide pour le tableau. */
+void g_array_type_set_empty_dimension(GArrayType *);
+
#endif /* _ANALYSIS_TYPES_ARRAY_H */
diff --git a/tests/mangling/itanium.py b/tests/mangling/itanium.py
index 6bb49d3..a04c590 100644
--- a/tests/mangling/itanium.py
+++ b/tests/mangling/itanium.py
@@ -109,3 +109,69 @@ class TestItaniumMangling(ChrysalideTestCase):
demangled = demangler.decode_routine('_ZN1N1TIiiE2mfES0_IddE')
self.check_demangling(demangled, '??? N::T<int, int>::mf(N::T<double, double>)')
+
+
+ def testItaniumRoutineManglingExtra(self):
+ """Check extra Itanium routine demangling cases."""
+
+ # http://refspecs.linuxbase.org/cxxabi-1.83.html#linkage
+
+ demangler = ItaniumDemangler()
+
+ # A la lecture, il s'agit d'une référence sur un tableau, et non
+ # d'un tableau de références.
+ demangled = demangler.decode_routine('_Z3fooILi2EEvRAplT_Li1E_i')
+ self.check_demangling(demangled, 'void foo<2>(int[2+1] &)')
+
+
+ def testAFL(self):
+ """Tests from AFL."""
+
+ demangler = ItaniumDemangler()
+
+ demangled = demangler.decode_routine('_Z4makeI7FactoryiET_IT')
+ self.assertIsNone(demangled)
+
+ demangled = demangler.decode_routine('_Z4makeN7FactoryiET_IT0_Ev')
+ self.assertIsNone(demangled)
+
+ demangled = demangler.decode_routine('_Z4makeI7FactoryiET_I4makeIMGaptoryiET_T0_Ev')
+ self.assertIsNone(demangled)
+
+ demangled = demangler.decode_routine('_Z4maktoryiaS_ILNd')
+ self.assertIsNone(demangled)
+
+ # ?!
+ demangled = demangler.decode_routine('_Z4makeMVFactoryiES_')
+ self.assertIsNotNone(demangled)
+
+
+ def testOldRealWorldDemanglings(self):
+ """Check real world demangling cases from previous code."""
+
+ demangler = ItaniumDemangler()
+
+ demangled = demangler.decode_routine('_ZNSt6vectorItSaItEE6insertEN9__gnu_cxx17__normal_iteratorIPtS1_EERKt')
+ self.check_demangling(demangled, '??? 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 &)')
+
+ demangled = demangler.decode_routine('_ZSt26__uninitialized_fill_n_auxIP15CProfStringListiS0_ET_S2_T0_RKT1_12__false_type')
+ self.check_demangling(demangled, 'CProfStringList *std::__uninitialized_fill_n_aux<CProfStringList *, int, CProfStringList>(CProfStringList *, int, const CProfStringList &, __false_type)')
+
+
+ demangled = demangler.decode_routine('_ZN21IUDFSettingsValidator15IdNotIllegalStdEN13UDFParameters12UDF_STANDARDES1_')
+ self.check_demangling(demangled, '??? IUDFSettingsValidator::IdNotIllegalStd(UDFParameters::UDF_STANDARD, UDFParameters::UDF_STANDARD)')
+
+ demangled = demangler.decode_routine('_ZNSbI26NeroMediumFeatureSpecifierSt11char_traitsIS_ESaIS_EE4_Rep10_M_destroyERKS2_')
+ self.check_demangling(demangled, '??? std::basic_string<NeroMediumFeatureSpecifier, std::char_traits<NeroMediumFeatureSpecifier>, std::allocator<NeroMediumFeatureSpecifier>>::_Rep::_M_destroy(const std::allocator<NeroMediumFeatureSpecifier> &)')
+
+ demangled = demangler.decode_routine('_ZNSt6vectorIlSaIlEE6insertEN9__gnu_cxx17__normal_iteratorIPlS1_EERKl')
+ self.check_demangling(demangled, '??? std::vector<long, std::allocator<long>>::insert(__gnu_cxx::__normal_iterator<long *, std::vector<long, std::allocator<long>>>, const long &)')
+
+ demangled = demangler.decode_routine('_ZSt22__merge_without_bufferIN9__gnu_cxx17__normal_iteratorIP15CProfStringListSt6vectorIS2_SaIS2_EEEEiEvT_S8_S8_T0_S9_')
+ self.check_demangling(demangled, 'void std::__merge_without_buffer<__gnu_cxx::__normal_iterator<CProfStringList *, std::vector<CProfStringList, std::allocator<CProfStringList>>>, int>(__gnu_cxx::__normal_iterator<CProfStringList *, std::vector<CProfStringList, std::allocator<CProfStringList>>>, __gnu_cxx::__normal_iterator<CProfStringList *, std::vector<CProfStringList, std::allocator<CProfStringList>>>, __gnu_cxx::__normal_iterator<CProfStringList *, std::vector<CProfStringList, std::allocator<CProfStringList>>>, int, int)')
+
+ demangled = demangler.decode_routine('_ZSt11__push_heapIN9__gnu_cxx17__normal_iteratorIP8DRIVE_IDSt6vectorIS2_SaIS2_EEEEiS2_EvT_T0_S9_T1_')
+ self.check_demangling(demangled, 'void std::__push_heap<__gnu_cxx::__normal_iterator<DRIVE_ID *, std::vector<DRIVE_ID, std::allocator<DRIVE_ID>>>, int, DRIVE_ID>(__gnu_cxx::__normal_iterator<DRIVE_ID *, std::vector<DRIVE_ID, std::allocator<DRIVE_ID>>>, int, int, DRIVE_ID)')
+
+ 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<CPR_MAI_ADPTY_SectorSequence *, std::vector<CPR_MAI_ADPTY_SectorSequence, std::allocator<CPR_MAI_ADPTY_SectorSequence>>>>(__gnu_cxx::__normal_iterator<CPR_MAI_ADPTY_SectorSequence *, std::vector<CPR_MAI_ADPTY_SectorSequence, std::allocator<CPR_MAI_ADPTY_SectorSequence>>>, __gnu_cxx::__normal_iterator<CPR_MAI_ADPTY_SectorSequence *, std::vector<CPR_MAI_ADPTY_SectorSequence, std::allocator<CPR_MAI_ADPTY_SectorSequence>>>, __gnu_cxx::__normal_iterator<CPR_MAI_ADPTY_SectorSequence *, std::vector<CPR_MAI_ADPTY_SectorSequence, std::allocator<CPR_MAI_ADPTY_SectorSequence>>>)')