From: Mark Wielaard Date: Wed, 12 Apr 2017 13:01:29 +0000 (+0000) Subject: Update libiberty demangler. X-Git-Tag: svn/VALGRIND_3_13_0~132 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=db52ecc03652a37b8c08c81fb5f6868ab73d4c1d;p=thirdparty%2Fvalgrind.git Update libiberty demangler. Update the libiberty demangler using the auxprogs/update-demangler script to the gcc svn r246502 revision. Replaces our rust demangling with the upstream variant (which is basically the same code in a separate file). Adds handling of inheriting constructor. Handle noexcept and throw-spec. Demangle Dc as decltype(auto). And various (crasher) bug fixes. Bug 378673. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@16302 --- diff --git a/NEWS b/NEWS index a5392eef24..24c38e03c8 100644 --- a/NEWS +++ b/NEWS @@ -155,6 +155,7 @@ where XXXXXX is the bug number as listed below. 377717 Fix massive space leak when reading compressed debuginfo sections 377930 fcntl syscall wrapper is missing flock structure check 378535 Valgrind reports INTERNAL ERROR in execve syscall wrapper +378673 Update libiberty demangler Release 3.12.0 (20 October 2016) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/auxprogs/update-demangler b/auxprogs/update-demangler index 18189b3b75..8c1bbaa403 100755 --- a/auxprogs/update-demangler +++ b/auxprogs/update-demangler @@ -17,8 +17,8 @@ set -e #--------------------------------------------------------------------- # You need to modify these revision numbers for your update. -old_gcc_revision=r212125 # the revision of the previous update -new_gcc_revision=r240068 # the revision for this update +old_gcc_revision=r240068 # the revision of the previous update +new_gcc_revision=r246502 # the revision for this update # Unless the organization of demangler related files has changed, no # changes below this line should be necessary. @@ -56,6 +56,7 @@ cp ../gcc-$old_gcc_revision/libiberty/cp-demangle.h . cp ../gcc-$old_gcc_revision/libiberty/cplus-dem.c . cp ../gcc-$old_gcc_revision/libiberty/dyn-string.c . cp ../gcc-$old_gcc_revision/libiberty/d-demangle.c . +cp ../gcc-$old_gcc_revision/libiberty/rust-demangle.c . cp ../gcc-$old_gcc_revision/libiberty/safe-ctype.c . cd .. @@ -83,6 +84,7 @@ cp ../gcc-$new_gcc_revision/libiberty/cp-demangle.h . cp ../gcc-$new_gcc_revision/libiberty/cplus-dem.c . cp ../gcc-$new_gcc_revision/libiberty/dyn-string.c . cp ../gcc-$new_gcc_revision/libiberty/d-demangle.c . +cp ../gcc-$new_gcc_revision/libiberty/rust-demangle.c . cp ../gcc-$new_gcc_revision/libiberty/safe-ctype.c . cd .. diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index 41c5ef4931..f3e49169c3 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -362,6 +362,7 @@ COREGRIND_SOURCES_COMMON = \ m_demangle/demangle.c \ m_demangle/dyn-string.c \ m_demangle/d-demangle.c \ + m_demangle/rust-demangle.c \ m_demangle/safe-ctype.c \ m_dispatch/dispatch-x86-linux.S \ m_dispatch/dispatch-amd64-linux.S \ diff --git a/coregrind/m_demangle/ansidecl.h b/coregrind/m_demangle/ansidecl.h index 6e4bfc21f2..6c0c837bf2 100644 --- a/coregrind/m_demangle/ansidecl.h +++ b/coregrind/m_demangle/ansidecl.h @@ -1,5 +1,5 @@ /* ANSI and traditional C compatability macros - Copyright (C) 1991-2015 Free Software Foundation, Inc. + Copyright (C) 1991-2017 Free Software Foundation, Inc. This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify @@ -313,13 +313,39 @@ So instead we use the macro below and test it against specific values. */ #define ENUM_BITFIELD(TYPE) unsigned int #endif - /* This is used to mark a class or virtual function as final. */ -#if __cplusplus >= 201103L -#define GCC_FINAL final +/* C++11 adds the ability to add "override" after an implementation of a + virtual function in a subclass, to: + (A) document that this is an override of a virtual function + (B) allow the compiler to issue a warning if it isn't (e.g. a mismatch + of the type signature). + + Similarly, it allows us to add a "final" to indicate that no subclass + may subsequently override the vfunc. + + Provide OVERRIDE and FINAL as macros, allowing us to get these benefits + when compiling with C++11 support, but without requiring C++11. + + For gcc, use "-std=c++11" to enable C++11 support; gcc 6 onwards enables + this by default (actually GNU++14). */ + +#if __cplusplus >= 201103 +/* C++11 claims to be available: use it. final/override were only + implemented in 4.7, though. */ +# if GCC_VERSION < 4007 +# define OVERRIDE +# define FINAL +# else +# define OVERRIDE override +# define FINAL final +# endif #elif GCC_VERSION >= 4007 -#define GCC_FINAL __final +/* G++ 4.7 supports __final in C++98. */ +# define OVERRIDE +# define FINAL __final #else -#define GCC_FINAL +/* No C++11 support; leave the macros empty: */ +# define OVERRIDE +# define FINAL #endif #ifdef __cplusplus diff --git a/coregrind/m_demangle/cp-demangle.c b/coregrind/m_demangle/cp-demangle.c index a3f78ab108..4a3fa5d167 100644 --- a/coregrind/m_demangle/cp-demangle.c +++ b/coregrind/m_demangle/cp-demangle.c @@ -1,6 +1,5 @@ /* Demangler for g++ V3 ABI. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014 - Free Software Foundation, Inc. + Copyright (C) 2003-2017 Free Software Foundation, Inc. Written by Ian Lance Taylor . This file is part of the libiberty library, which is part of GCC. @@ -190,10 +189,10 @@ static struct demangle_component *d_mangled_name (struct d_info *, int); static struct demangle_component *d_type (struct d_info *); #define cplus_demangle_print d_print -static char *d_print (int, const struct demangle_component *, int, size_t *); +static char *d_print (int, struct demangle_component *, int, size_t *); #define cplus_demangle_print_callback d_print_callback -static int d_print_callback (int, const struct demangle_component *, +static int d_print_callback (int, struct demangle_component *, demangle_callbackref, void *); #define cplus_demangle_init_info d_init_info @@ -282,7 +281,7 @@ struct d_print_mod in which they appeared in the mangled string. */ struct d_print_mod *next; /* The modifier. */ - const struct demangle_component *mod; + struct demangle_component *mod; /* Whether this modifier was printed. */ int printed; /* The list of templates which applies to this modifier. */ @@ -360,6 +359,9 @@ struct d_print_info struct d_print_mod *modifiers; /* Set to 1 if we saw a demangling error. */ int demangle_failure; + /* Non-zero if we're printing a lambda argument. A template + parameter reference actually means 'auto'. */ + int is_lambda_arg; /* The current index into any template argument packs we are using for printing, or -1 to print the whole pack. */ int pack_index; @@ -453,6 +455,8 @@ static struct demangle_component *d_operator_name (struct d_info *); static struct demangle_component *d_special_name (struct d_info *); +static struct demangle_component *d_parmlist (struct d_info *); + static int d_call_offset (struct d_info *, int); static struct demangle_component *d_ctor_dtor_name (struct d_info *); @@ -543,7 +547,7 @@ static inline void d_append_string (struct d_print_info *, const char *); static inline char d_last_char (struct d_print_info *); static void -d_print_comp (struct d_print_info *, int, const struct demangle_component *); +d_print_comp (struct d_print_info *, int, struct demangle_component *); static void d_print_java_identifier (struct d_print_info *, const char *, int); @@ -552,30 +556,56 @@ static void d_print_mod_list (struct d_print_info *, int, struct d_print_mod *, int); static void -d_print_mod (struct d_print_info *, int, const struct demangle_component *); +d_print_mod (struct d_print_info *, int, struct demangle_component *); static void d_print_function_type (struct d_print_info *, int, - const struct demangle_component *, + struct demangle_component *, struct d_print_mod *); static void d_print_array_type (struct d_print_info *, int, - const struct demangle_component *, + struct demangle_component *, struct d_print_mod *); static void -d_print_expr_op (struct d_print_info *, int, const struct demangle_component *); +d_print_expr_op (struct d_print_info *, int, struct demangle_component *); static void d_print_cast (struct d_print_info *, int, - const struct demangle_component *); + struct demangle_component *); static void d_print_conversion (struct d_print_info *, int, - const struct demangle_component *); + struct demangle_component *); static int d_demangle_callback (const char *, int, demangle_callbackref, void *); static char *d_demangle (const char *, int, size_t *); +/* True iff TYPE is a demangling component representing a + function-type-qualifier. */ + +static int +is_fnqual_component_type (enum demangle_component_type type) +{ + return (type == DEMANGLE_COMPONENT_RESTRICT_THIS + || type == DEMANGLE_COMPONENT_VOLATILE_THIS + || type == DEMANGLE_COMPONENT_CONST_THIS + || type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS + || type == DEMANGLE_COMPONENT_TRANSACTION_SAFE + || type == DEMANGLE_COMPONENT_NOEXCEPT + || type == DEMANGLE_COMPONENT_THROW_SPEC + || type == DEMANGLE_COMPONENT_REFERENCE_THIS); +} + +#define FNQUAL_COMPONENT_CASE \ + case DEMANGLE_COMPONENT_RESTRICT_THIS: \ + case DEMANGLE_COMPONENT_VOLATILE_THIS: \ + case DEMANGLE_COMPONENT_CONST_THIS: \ + case DEMANGLE_COMPONENT_REFERENCE_THIS: \ + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: \ + case DEMANGLE_COMPONENT_TRANSACTION_SAFE: \ + case DEMANGLE_COMPONENT_NOEXCEPT: \ + case DEMANGLE_COMPONENT_THROW_SPEC + #ifdef CP_DEMANGLE_DEBUG static void @@ -841,6 +871,7 @@ cplus_demangle_fill_name (struct demangle_component *p, const char *s, int len) { if (p == NULL || s == NULL || len == 0) return 0; + p->d_printing = 0; p->type = DEMANGLE_COMPONENT_NAME; p->u.s_name.s = s; p->u.s_name.len = len; @@ -856,6 +887,7 @@ cplus_demangle_fill_extended_operator (struct demangle_component *p, int args, { if (p == NULL || args < 0 || name == NULL) return 0; + p->d_printing = 0; p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR; p->u.s_extended_operator.args = args; p->u.s_extended_operator.name = name; @@ -875,6 +907,7 @@ cplus_demangle_fill_ctor (struct demangle_component *p, || (int) kind < gnu_v3_complete_object_ctor || (int) kind > gnu_v3_object_ctor_group) return 0; + p->d_printing = 0; p->type = DEMANGLE_COMPONENT_CTOR; p->u.s_ctor.kind = kind; p->u.s_ctor.name = name; @@ -894,6 +927,7 @@ cplus_demangle_fill_dtor (struct demangle_component *p, || (int) kind < gnu_v3_deleting_dtor || (int) kind > gnu_v3_object_dtor_group) return 0; + p->d_printing = 0; p->type = DEMANGLE_COMPONENT_DTOR; p->u.s_dtor.kind = kind; p->u.s_dtor.name = name; @@ -910,6 +944,7 @@ d_make_empty (struct d_info *di) if (di->next_comp >= di->num_comps) return NULL; p = &di->comps[di->next_comp]; + p->d_printing = 0; ++di->next_comp; return p; } @@ -1001,14 +1036,9 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_RESTRICT: case DEMANGLE_COMPONENT_VOLATILE: case DEMANGLE_COMPONENT_CONST: - case DEMANGLE_COMPONENT_RESTRICT_THIS: - case DEMANGLE_COMPONENT_VOLATILE_THIS: - case DEMANGLE_COMPONENT_CONST_THIS: - case DEMANGLE_COMPONENT_TRANSACTION_SAFE: - case DEMANGLE_COMPONENT_REFERENCE_THIS: - case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: case DEMANGLE_COMPONENT_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: + FNQUAL_COMPONENT_CASE: break; /* Other types should not be seen here. */ @@ -1242,12 +1272,7 @@ has_return_type (struct demangle_component *dc) return 0; case DEMANGLE_COMPONENT_TEMPLATE: return ! is_ctor_dtor_or_conversion (d_left (dc)); - case DEMANGLE_COMPONENT_RESTRICT_THIS: - case DEMANGLE_COMPONENT_VOLATILE_THIS: - case DEMANGLE_COMPONENT_CONST_THIS: - case DEMANGLE_COMPONENT_REFERENCE_THIS: - case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: - case DEMANGLE_COMPONENT_TRANSACTION_SAFE: + FNQUAL_COMPONENT_CASE: return has_return_type (d_left (dc)); } } @@ -1304,13 +1329,12 @@ d_encoding (struct d_info *di, int top_level) while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS || dc->type == DEMANGLE_COMPONENT_CONST_THIS - || dc->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) dc = d_left (dc); /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then - there may be CV-qualifiers on its right argument which + there may be function-qualifiers on its right argument which really apply here; this happens when parsing a class which is local to a function. */ if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME) @@ -1318,12 +1342,7 @@ d_encoding (struct d_info *di, int top_level) struct demangle_component *dcr; dcr = d_right (dc); - while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS - || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS - || dcr->type == DEMANGLE_COMPONENT_CONST_THIS - || dcr->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE - || dcr->type == DEMANGLE_COMPONENT_REFERENCE_THIS - || dcr->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) + while (is_fnqual_component_type (dcr->type)) dcr = d_left (dcr); dc->u.s_binary.right = dcr; } @@ -1597,6 +1616,8 @@ d_unqualified_name (struct d_info *di) ret = d_source_name (di); else if (IS_LOWER (peek)) { + if (peek == 'o' && d_peek_next_char (di) == 'n') + d_advance (di, 2); ret = d_operator_name (di); if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR) { @@ -2185,6 +2206,13 @@ d_ctor_dtor_name (struct d_info *di) case 'C': { enum gnu_v3_ctor_kinds kind; + int inheriting = 0; + + if (d_peek_next_char (di) == 'I') + { + inheriting = 1; + d_advance (di, 1); + } switch (d_peek_next_char (di)) { @@ -2206,7 +2234,12 @@ d_ctor_dtor_name (struct d_info *di) default: return NULL; } + d_advance (di, 2); + + if (inheriting) + cplus_demangle_type (di); + return d_make_ctor (di, kind, di->last_name); } @@ -2244,6 +2277,24 @@ d_ctor_dtor_name (struct d_info *di) } } +/* True iff we're looking at an order-insensitive type-qualifier, including + function-type-qualifiers. */ + +static int +next_is_type_qual (struct d_info *di) +{ + char peek = d_peek_char (di); + if (peek == 'r' || peek == 'V' || peek == 'K') + return 1; + if (peek == 'D') + { + peek = d_peek_next_char (di); + if (peek == 'x' || peek == 'o' || peek == 'O' || peek == 'w') + return 1; + } + return 0; +} + /* ::= ::= ::= @@ -2329,9 +2380,7 @@ cplus_demangle_type (struct d_info *di) __vector, and it treats it as order-sensitive when mangling names. */ - peek = d_peek_char (di); - if (peek == 'r' || peek == 'V' || peek == 'K' - || (peek == 'D' && d_peek_next_char (di) == 'x')) + if (next_is_type_qual (di)) { struct demangle_component **pret; @@ -2366,6 +2415,7 @@ cplus_demangle_type (struct d_info *di) can_subst = 1; + peek = d_peek_char (di); switch (peek) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': @@ -2566,7 +2616,11 @@ cplus_demangle_type (struct d_info *di) /* auto */ ret = d_make_name (di, "auto", 4); break; - + case 'c': + /* decltype(auto) */ + ret = d_make_name (di, "decltype(auto)", 14); + break; + case 'f': /* 32-bit decimal floating point */ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[26]); @@ -2653,10 +2707,10 @@ d_cv_qualifiers (struct d_info *di, pstart = pret; peek = d_peek_char (di); - while (peek == 'r' || peek == 'V' || peek == 'K' - || (peek == 'D' && d_peek_next_char (di) == 'x')) + while (next_is_type_qual (di)) { enum demangle_component_type t; + struct demangle_component *right = NULL; d_advance (di, 1); if (peek == 'r') @@ -2682,12 +2736,41 @@ d_cv_qualifiers (struct d_info *di, } else { - t = DEMANGLE_COMPONENT_TRANSACTION_SAFE; - di->expansion += sizeof "transaction_safe"; - d_advance (di, 1); + peek = d_next_char (di); + if (peek == 'x') + { + t = DEMANGLE_COMPONENT_TRANSACTION_SAFE; + di->expansion += sizeof "transaction_safe"; + } + else if (peek == 'o' + || peek == 'O') + { + t = DEMANGLE_COMPONENT_NOEXCEPT; + di->expansion += sizeof "noexcept"; + if (peek == 'O') + { + right = d_expression (di); + if (right == NULL) + return NULL; + if (! d_check_char (di, 'E')) + return NULL; + } + } + else if (peek == 'w') + { + t = DEMANGLE_COMPONENT_THROW_SPEC; + di->expansion += sizeof "throw"; + right = d_parmlist (di); + if (right == NULL) + return NULL; + if (! d_check_char (di, 'E')) + return NULL; + } + else + return NULL; } - *pret = d_make_comp (di, t, NULL, NULL); + *pret = d_make_comp (di, t, NULL, right); if (*pret == NULL) return NULL; pret = &d_left (*pret); @@ -3362,6 +3445,8 @@ d_expression_1 (struct d_info *di) first = d_expression_1 (di); second = d_expression_1 (di); third = d_expression_1 (di); + if (third == NULL) + return NULL; } else if (code[0] == 'f') { @@ -3369,6 +3454,8 @@ d_expression_1 (struct d_info *di) first = d_operator_name (di); second = d_expression_1 (di); third = d_expression_1 (di); + if (third == NULL) + return NULL; } else if (code[0] == 'n') { @@ -3546,7 +3633,11 @@ d_local_name (struct d_info *di) } } -/* ::= _ <(non-negative) number> +/* ::= _ # when number < 10 + ::= __ _ # when number >= 10 + + ::= _ # when number >=10 + is also accepted to support gcc versions that wrongly mangled that way. We demangle the discriminator, but we don't print it out. FIXME: We should print it out in verbose mode. */ @@ -3554,14 +3645,28 @@ d_local_name (struct d_info *di) static int d_discriminator (struct d_info *di) { - int discrim; + int discrim, num_underscores = 1; if (d_peek_char (di) != '_') return 1; d_advance (di, 1); + if (d_peek_char (di) == '_') + { + ++num_underscores; + d_advance (di, 1); + } + discrim = d_number (di); if (discrim < 0) return 0; + if (num_underscores > 1 && discrim >= 10) + { + if (d_peek_char (di) == '_') + d_advance (di, 1); + else + return 0; + } + return 1; } @@ -3978,6 +4083,8 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, case DEMANGLE_COMPONENT_REFERENCE_THIS: case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: case DEMANGLE_COMPONENT_TRANSACTION_SAFE: + case DEMANGLE_COMPONENT_NOEXCEPT: + case DEMANGLE_COMPONENT_THROW_SPEC: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_COMPLEX: @@ -4067,6 +4174,7 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback, dpi->opaque = opaque; dpi->demangle_failure = 0; + dpi->is_lambda_arg = 0; dpi->component_stack = NULL; @@ -4163,7 +4271,7 @@ d_last_char (struct d_print_info *dpi) CP_STATIC_IF_GLIBCPP_V3 int cplus_demangle_print_callback (int options, - const struct demangle_component *dc, + struct demangle_component *dc, demangle_callbackref callback, void *opaque) { struct d_print_info dpi; @@ -4222,7 +4330,7 @@ cplus_demangle_print_callback (int options, CP_STATIC_IF_GLIBCPP_V3 char * -cplus_demangle_print (int options, const struct demangle_component *dc, +cplus_demangle_print (int options, struct demangle_component *dc, int estimate, size_t *palc) { struct d_growable_string dgs; @@ -4382,7 +4490,7 @@ d_args_length (struct d_print_info *dpi, const struct demangle_component *dc) static void d_print_subexpr (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { int simple = 0; if (dc->type == DEMANGLE_COMPONENT_NAME @@ -4458,9 +4566,9 @@ d_get_saved_scope (struct d_print_info *dpi, static int d_maybe_print_fold_expression (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { - const struct demangle_component *ops, *operator_, *op1, *op2; + struct demangle_component *ops, *operator_, *op1, *op2; int save_idx; const char *fold_code = d_left (dc)->u.s_operator.op->code; @@ -4521,11 +4629,11 @@ d_maybe_print_fold_expression (struct d_print_info *dpi, int options, static void d_print_comp_inner (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { /* Magic variable to let reference smashing skip over the next modifier without needing to modify *dc. */ - const struct demangle_component *mod_inner = NULL; + struct demangle_component *mod_inner = NULL; /* Variable used to store the current templates while a previously captured scope is used. */ @@ -4608,12 +4716,7 @@ d_print_comp_inner (struct d_print_info *dpi, int options, adpm[i].templates = dpi->templates; ++i; - if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS - && typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS - && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS - && typed_name->type != DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS - && typed_name->type != DEMANGLE_COMPONENT_TRANSACTION_SAFE - && typed_name->type != DEMANGLE_COMPONENT_REFERENCE_THIS) + if (!is_fnqual_component_type (typed_name->type)) break; typed_name = d_left (typed_name); @@ -4650,13 +4753,7 @@ d_print_comp_inner (struct d_print_info *dpi, int options, d_print_error (dpi); return; } - while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS - || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS - || local_name->type == DEMANGLE_COMPONENT_CONST_THIS - || local_name->type == DEMANGLE_COMPONENT_REFERENCE_THIS - || local_name->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE - || (local_name->type - == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)) + while (is_fnqual_component_type (local_name->type)) { if (i >= sizeof adpm / sizeof adpm[0]) { @@ -4751,33 +4848,41 @@ d_print_comp_inner (struct d_print_info *dpi, int options, } case DEMANGLE_COMPONENT_TEMPLATE_PARAM: - { - struct d_print_template *hold_dpt; - struct demangle_component *a = d_lookup_template_argument (dpi, dc); - - if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) - a = d_index_template_argument (a, dpi->pack_index); + if (dpi->is_lambda_arg) + { + /* Show the template parm index, as that's how g++ displays + these, and future proofs us against potential + '[] (T *a, T *b) {...}'. */ + d_append_buffer (dpi, "auto:", 5); + d_append_num (dpi, dc->u.s_number.number + 1); + } + else + { + struct d_print_template *hold_dpt; + struct demangle_component *a = d_lookup_template_argument (dpi, dc); - if (a == NULL) - { - d_print_error (dpi); - return; - } + if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) + a = d_index_template_argument (a, dpi->pack_index); - /* While processing this parameter, we need to pop the list of - templates. This is because the template parameter may - itself be a reference to a parameter of an outer - template. */ + if (a == NULL) + { + d_print_error (dpi); + return; + } - hold_dpt = dpi->templates; - dpi->templates = hold_dpt->next; + /* While processing this parameter, we need to pop the list + of templates. This is because the template parameter may + itself be a reference to a parameter of an outer + template. */ - d_print_comp (dpi, options, a); + hold_dpt = dpi->templates; + dpi->templates = hold_dpt->next; - dpi->templates = hold_dpt; + d_print_comp (dpi, options, a); - return; - } + dpi->templates = hold_dpt; + } + return; case DEMANGLE_COMPONENT_CTOR: d_print_comp (dpi, options, dc->u.s_ctor.name); @@ -4913,8 +5018,9 @@ d_print_comp_inner (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_RVALUE_REFERENCE: { /* Handle reference smashing: & + && = &. */ - const struct demangle_component *sub = d_left (dc); - if (sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM) + struct demangle_component *sub = d_left (dc); + if (!dpi->is_lambda_arg + && sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM) { struct d_saved_scope *scope = d_get_saved_scope (dpi, sub); struct demangle_component *a; @@ -4981,16 +5087,11 @@ d_print_comp_inner (struct d_print_info *dpi, int options, } /* Fall through. */ - case DEMANGLE_COMPONENT_RESTRICT_THIS: - case DEMANGLE_COMPONENT_VOLATILE_THIS: - case DEMANGLE_COMPONENT_CONST_THIS: - case DEMANGLE_COMPONENT_REFERENCE_THIS: - case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_COMPLEX: case DEMANGLE_COMPONENT_IMAGINARY: - case DEMANGLE_COMPONENT_TRANSACTION_SAFE: + FNQUAL_COMPONENT_CASE: modifier: { /* We keep a list of modifiers on the stack. */ @@ -5589,7 +5690,11 @@ d_print_comp_inner (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_LAMBDA: d_append_string (dpi, "{lambda("); + /* Generic lambda auto parms are mangled as the template type + parm they are. */ + dpi->is_lambda_arg++; d_print_comp (dpi, options, dc->u.s_unary_num.sub); + dpi->is_lambda_arg--; d_append_string (dpi, ")#"); d_append_num (dpi, dc->u.s_unary_num.num + 1); d_append_char (dpi, '}'); @@ -5616,9 +5721,16 @@ d_print_comp_inner (struct d_print_info *dpi, int options, static void d_print_comp (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { struct d_component_stack self; + if (dc == NULL || dc->d_printing > 1) + { + d_print_error (dpi); + return; + } + else + dc->d_printing++; self.dc = dc; self.parent = dpi->component_stack; @@ -5627,6 +5739,7 @@ d_print_comp (struct d_print_info *dpi, int options, d_print_comp_inner (dpi, options, dc); dpi->component_stack = self.parent; + dc->d_printing--; } /* Print a Java dentifier. For Java we try to handle encoded extended @@ -5695,13 +5808,7 @@ d_print_mod_list (struct d_print_info *dpi, int options, if (mods->printed || (! suffix - && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS - || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS - || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS - || mods->mod->type == DEMANGLE_COMPONENT_REFERENCE_THIS - || mods->mod->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE - || (mods->mod->type - == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)))) + && (is_fnqual_component_type (mods->mod->type)))) { d_print_mod_list (dpi, options, mods->next, suffix); return; @@ -5754,12 +5861,7 @@ d_print_mod_list (struct d_print_info *dpi, int options, dc = dc->u.s_unary_num.sub; } - while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS - || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS - || dc->type == DEMANGLE_COMPONENT_CONST_THIS - || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS - || dc->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE - || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) + while (is_fnqual_component_type (dc->type)) dc = d_left (dc); d_print_comp (dpi, options, dc); @@ -5779,7 +5881,7 @@ d_print_mod_list (struct d_print_info *dpi, int options, static void d_print_mod (struct d_print_info *dpi, int options, - const struct demangle_component *mod) + struct demangle_component *mod) { switch (mod->type) { @@ -5798,6 +5900,24 @@ d_print_mod (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_TRANSACTION_SAFE: d_append_string (dpi, " transaction_safe"); return; + case DEMANGLE_COMPONENT_NOEXCEPT: + d_append_string (dpi, " noexcept"); + if (d_right (mod)) + { + d_append_char (dpi, '('); + d_print_comp (dpi, options, d_right (mod)); + d_append_char (dpi, ')'); + } + return; + case DEMANGLE_COMPONENT_THROW_SPEC: + d_append_string (dpi, " throw"); + if (d_right (mod)) + { + d_append_char (dpi, '('); + d_print_comp (dpi, options, d_right (mod)); + d_append_char (dpi, ')'); + } + return; case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: d_append_char (dpi, ' '); d_print_comp (dpi, options, d_right (mod)); @@ -5853,7 +5973,7 @@ d_print_mod (struct d_print_info *dpi, int options, static void d_print_function_type (struct d_print_info *dpi, int options, - const struct demangle_component *dc, + struct demangle_component *dc, struct d_print_mod *mods) { int need_paren; @@ -5885,12 +6005,7 @@ d_print_function_type (struct d_print_info *dpi, int options, need_space = 1; need_paren = 1; break; - case DEMANGLE_COMPONENT_RESTRICT_THIS: - case DEMANGLE_COMPONENT_VOLATILE_THIS: - case DEMANGLE_COMPONENT_CONST_THIS: - case DEMANGLE_COMPONENT_REFERENCE_THIS: - case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: - case DEMANGLE_COMPONENT_TRANSACTION_SAFE: + FNQUAL_COMPONENT_CASE: break; default: break; @@ -5936,7 +6051,7 @@ d_print_function_type (struct d_print_info *dpi, int options, static void d_print_array_type (struct d_print_info *dpi, int options, - const struct demangle_component *dc, + struct demangle_component *dc, struct d_print_mod *mods) { int need_space; @@ -5990,7 +6105,7 @@ d_print_array_type (struct d_print_info *dpi, int options, static void d_print_expr_op (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { if (dc->type == DEMANGLE_COMPONENT_OPERATOR) d_append_buffer (dpi, dc->u.s_operator.op->name, @@ -6003,7 +6118,7 @@ d_print_expr_op (struct d_print_info *dpi, int options, static void d_print_cast (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { d_print_comp (dpi, options, d_left (dc)); } @@ -6012,7 +6127,7 @@ d_print_cast (struct d_print_info *dpi, int options, static void d_print_conversion (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { struct d_print_template dpt; @@ -6451,7 +6566,6 @@ is_ctor_or_dtor (const char *mangled, case DEMANGLE_COMPONENT_CONST_THIS: case DEMANGLE_COMPONENT_REFERENCE_THIS: case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: - case DEMANGLE_COMPONENT_TRANSACTION_SAFE: default: dc = NULL; break; diff --git a/coregrind/m_demangle/cp-demangle.h b/coregrind/m_demangle/cp-demangle.h index 197883e256..a2657755f1 100644 --- a/coregrind/m_demangle/cp-demangle.h +++ b/coregrind/m_demangle/cp-demangle.h @@ -1,6 +1,5 @@ /* Internal demangler interface for g++ V3 ABI. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 - Free Software Foundation, Inc. + Copyright (C) 2003-2017 Free Software Foundation, Inc. Written by Ian Lance Taylor . This file is part of the libiberty library, which is part of GCC. diff --git a/coregrind/m_demangle/cplus-dem.c b/coregrind/m_demangle/cplus-dem.c index d00f79fa54..9cdf40ba94 100644 --- a/coregrind/m_demangle/cplus-dem.c +++ b/coregrind/m_demangle/cplus-dem.c @@ -1,6 +1,5 @@ /* Demangler for GNU C++ - Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2010 Free Software Foundation, Inc. + Copyright (C) 1989-2017 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.uucp) Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling Modified by Satish Pai (pai@apollo.hp.com) for HP demangling @@ -342,6 +341,12 @@ const struct demangler_engine libiberty_demanglers[] = "DLANG style demangling" } , + { + RUST_DEMANGLING_STYLE_STRING, + rust_demangling, + "Rust style demangling" + } + , { NULL, unknown_demangling, NULL } @@ -893,10 +898,26 @@ ML_(cplus_demangle) (const char *mangled, int options) work->options |= (int) current_demangling_style & DMGL_STYLE_MASK; /* The V3 ABI demangling is implemented elsewhere. */ - if (GNU_V3_DEMANGLING || AUTO_DEMANGLING) + if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING) { ret = cplus_demangle_v3 (mangled, work->options); - if (ret || GNU_V3_DEMANGLING) + if (GNU_V3_DEMANGLING) + return ret; + + if (ret) + { + /* Rust symbols are GNU_V3 mangled plus some extra subtitutions. + The subtitutions are always smaller, so do in place changes. */ + if (rust_is_mangled (ret)) + rust_demangle_sym (ret); + else if (RUST_DEMANGLING) + { + free (ret); + ret = NULL; + } + } + + if (ret || RUST_DEMANGLING) return ret; } @@ -922,6 +943,27 @@ ML_(cplus_demangle) (const char *mangled, int options) return (ret); } +char * +rust_demangle (const char *mangled, int options) +{ + /* Rust symbols are GNU_V3 mangled plus some extra subtitutions. */ + char *ret = cplus_demangle_v3 (mangled, options); + + /* The Rust subtitutions are always smaller, so do in place changes. */ + if (ret != NULL) + { + if (rust_is_mangled (ret)) + rust_demangle_sym (ret); + else + { + free (ret); + ret = NULL; + } + } + + return ret; +} + /* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */ char * @@ -930,7 +972,7 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) int len0; const char* p; char *d; - char *demangled; + char *demangled = NULL; /* Discard leading _ada_, which is used for library level subprograms. */ if (strncmp (mangled, "_ada_", 5) == 0) @@ -1175,6 +1217,7 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) return demangled; unknown: + XDELETEVEC (demangled); len0 = strlen (mangled); demangled = XNEWVEC (char, len0 + 3); @@ -1672,12 +1715,13 @@ demangle_signature (struct work_stuff *work, 0); if (!(work->constructor & 1)) expect_return_type = 1; - (*mangled)++; + if (!**mangled) + success = 0; + else + (*mangled)++; break; } - else - /* fall through */ - {;} + /* fall through */ default: if (AUTO_DEMANGLING || GNU_DEMANGLING) @@ -2153,6 +2197,8 @@ demangle_template (struct work_stuff *work, const char **mangled, { int idx; (*mangled)++; + if (**mangled == '\0') + return (0); (*mangled)++; idx = consume_count_with_underscores (mangled); @@ -2997,7 +3043,7 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp) int success = 1; const char *p; - if ((*mangled)[0] == '_' + if ((*mangled)[0] == '_' && (*mangled)[1] != '\0' && strchr (cplus_markers, (*mangled)[1]) != NULL && (*mangled)[2] == '_') { @@ -3011,7 +3057,7 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp) && (*mangled)[3] == 't' && (*mangled)[4] == '_') || ((*mangled)[1] == 'v' - && (*mangled)[2] == 't' + && (*mangled)[2] == 't' && (*mangled)[3] != '\0' && strchr (cplus_markers, (*mangled)[3]) != NULL))) { /* Found a GNU style virtual table, get past "_vt" @@ -3781,11 +3827,12 @@ do_type (struct work_stuff *work, const char **mangled, string *result) break; } - if (*(*mangled)++ != 'F') + if (*(*mangled) != 'F') { success = 0; break; } + (*mangled)++; } if ((member && !demangle_nested_args (work, mangled, &decl)) || **mangled != '_') @@ -4042,6 +4089,7 @@ demangle_fund_type (struct work_stuff *work, success = 0; break; } + /* fall through */ case 'I': (*mangled)++; if (**mangled == '_') diff --git a/coregrind/m_demangle/d-demangle.c b/coregrind/m_demangle/d-demangle.c index 129999cbf3..f9a7f1df8d 100644 --- a/coregrind/m_demangle/d-demangle.c +++ b/coregrind/m_demangle/d-demangle.c @@ -1,5 +1,5 @@ /* Demangler for the D programming language - Copyright 2014, 2015, 2016 Free Software Foundation, Inc. + Copyright (C) 2014-2017 Free Software Foundation, Inc. Written by Iain Buclaw (ibuclaw@gdcproject.org) This file is part of the libiberty library. diff --git a/coregrind/m_demangle/demangle.c b/coregrind/m_demangle/demangle.c index c8a9ca5d05..4a0967b57d 100644 --- a/coregrind/m_demangle/demangle.c +++ b/coregrind/m_demangle/demangle.c @@ -43,10 +43,6 @@ #include "vg_libciface.h" #include "demangle.h" -/* fwds */ -static Bool rust_is_mangled ( const HChar* ); -static void rust_demangle_sym ( HChar* ); - /*------------------------------------------------------------*/ /*--- ---*/ @@ -408,297 +404,6 @@ Bool VG_(maybe_Z_demangle) ( const HChar* sym, } -/*------------------------------------------------------------*/ -/*--- DEMANGLE RUST NAMES ---*/ -/*------------------------------------------------------------*/ - -/* - * Mangled Rust symbols look like this: - * - * _$LT$std..sys..fd..FileDesc$u20$as$u20$core..ops..Drop$GT$::drop::hc68340e1baa4987a - * - * The original symbol is: - * - * ::drop - * - * The last component of the path is a 64-bit hash in lowercase hex, prefixed - * with "h". Rust does not have a global namespace between crates, an illusion - * which Rust maintains by using the hash to distinguish things that would - * otherwise have the same symbol. - * - * Any path component not starting with a XID_Start character is prefixed with - * "_". - * - * The following escape sequences are used: - * - * "," => $C$ - * "@" => $SP$ - * "*" => $BP$ - * "&" => $RF$ - * "<" => $LT$ - * ">" => $GT$ - * "(" => $LP$ - * ")" => $RP$ - * " " => $u20$ - * "\"" => $u22$ - * "'" => $u27$ - * "+" => $u2b$ - * ";" => $u3b$ - * "[" => $u5b$ - * "]" => $u5d$ - * "{" => $u7b$ - * "}" => $u7d$ - * "~" => $u7e$ - * - * A double ".." means "::" and a single "." means "-". - * - * The only characters allowed in the mangled symbol are a-zA-Z0-9 and _.:$ - */ - -static const HChar *hash_prefix = "::h"; -static const SizeT hash_prefix_len = 3; -static const SizeT hash_len = 16; - -static Bool is_prefixed_hash(const HChar *start); -static Bool looks_like_rust(const HChar *sym, SizeT len); -static Bool unescape(const HChar **in, HChar **out, - const HChar *seq, HChar value); - -/* - * INPUT: - * sym: symbol that has been through BFD-demangling - * - * This function looks for the following indicators: - * - * 1. The hash must consist of "h" followed by 16 lowercase hex digits. - * - * 2. As a sanity check, the hash must use between 5 and 15 of the 16 possible - * hex digits. This is true of 99.9998% of hashes so once in your life you - * may see a false negative. The point is to notice path components that - * could be Rust hashes but are probably not, like "haaaaaaaaaaaaaaaa". In - * this case a false positive (non-Rust symbol has an important path - * component removed because it looks like a Rust hash) is worse than a - * false negative (the rare Rust symbol is not demangled) so this sets the - * balance in favor of false negatives. - * - * 3. There must be no characters other than a-zA-Z0-9 and _.:$ - * - * 4. There must be no unrecognized $-sign sequences. - * - * 5. There must be no sequence of three or more dots in a row ("..."). - */ -static Bool rust_is_mangled(const HChar *sym) -{ - SizeT len, len_without_hash; - - if (!sym) - return False; - - len = VG_(strlen)(sym); - if (len <= hash_prefix_len + hash_len) - /* Not long enough to contain "::h" + hash + something else */ - return False; - - len_without_hash = len - (hash_prefix_len + hash_len); - if (!is_prefixed_hash(sym + len_without_hash)) - return False; - - return looks_like_rust(sym, len_without_hash); -} - -/* - * A hash is the prefix "::h" followed by 16 lowercase hex digits. The hex - * digits must comprise between 5 and 15 (inclusive) distinct digits. - */ -static Bool is_prefixed_hash(const HChar *str) -{ - const HChar *end; - Bool seen[16]; - SizeT i; - Int count; - - if (VG_(strncmp)(str, hash_prefix, hash_prefix_len)) - return False; - str += hash_prefix_len; - - VG_(memset)(seen, False, sizeof(seen)); - for (end = str + hash_len; str < end; str++) - if (*str >= '0' && *str <= '9') - seen[*str - '0'] = True; - else if (*str >= 'a' && *str <= 'f') - seen[*str - 'a' + 10] = True; - else - return False; - - /* Count how many distinct digits seen */ - count = 0; - for (i = 0; i < 16; i++) - if (seen[i]) - count++; - - return count >= 5 && count <= 15; -} - -static Bool looks_like_rust(const HChar *str, SizeT len) -{ - const HChar *end = str + len; - - while (str < end) { - switch (*str) { - case '$': - if (!VG_(strncmp)(str, "$C$", 3)) - str += 3; - else if (!VG_(strncmp)(str, "$SP$", 4) - || !VG_(strncmp)(str, "$BP$", 4) - || !VG_(strncmp)(str, "$RF$", 4) - || !VG_(strncmp)(str, "$LT$", 4) - || !VG_(strncmp)(str, "$GT$", 4) - || !VG_(strncmp)(str, "$LP$", 4) - || !VG_(strncmp)(str, "$RP$", 4)) - str += 4; - else if (!VG_(strncmp)(str, "$u20$", 5) - || !VG_(strncmp)(str, "$u22$", 5) - || !VG_(strncmp)(str, "$u27$", 5) - || !VG_(strncmp)(str, "$u2b$", 5) - || !VG_(strncmp)(str, "$u3b$", 5) - || !VG_(strncmp)(str, "$u5b$", 5) - || !VG_(strncmp)(str, "$u5d$", 5) - || !VG_(strncmp)(str, "$u7b$", 5) - || !VG_(strncmp)(str, "$u7d$", 5) - || !VG_(strncmp)(str, "$u7e$", 5)) - str += 5; - else - return False; - break; - case '.': - /* Do not allow three or more consecutive dots */ - if (!VG_(strncmp)(str, "...", 3)) - return False; - /* Fall through */ - case 'a' ... 'z': - case 'A' ... 'Z': - case '0' ... '9': - case '_': - case ':': - str++; - break; - default: - return False; - } - } - - return True; -} - -/* - * INPUT: - * sym: symbol for which rust_is_mangled(sym) returns True - * - * The input is demangled in-place because the mangled name is always longer - * than the demangled one. - */ -static void rust_demangle_sym(HChar *sym) -{ - const HChar *in; - HChar *out; - const HChar *end; - - if (!sym) - return; - - const SizeT sym_len = VG_(strlen)(sym); - const HChar* never_after = sym + sym_len; - - in = sym; - out = sym; - end = sym + sym_len - (hash_prefix_len + hash_len); - - while (in < end) { - switch (*in) { - case '$': - if (!(unescape(&in, &out, "$C$", ',') - || unescape(&in, &out, "$SP$", '@') - || unescape(&in, &out, "$BP$", '*') - || unescape(&in, &out, "$RF$", '&') - || unescape(&in, &out, "$LT$", '<') - || unescape(&in, &out, "$GT$", '>') - || unescape(&in, &out, "$LP$", '(') - || unescape(&in, &out, "$RP$", ')') - || unescape(&in, &out, "$u20$", ' ') - || unescape(&in, &out, "$u22$", '\"') - || unescape(&in, &out, "$u27$", '\'') - || unescape(&in, &out, "$u2b$", '+') - || unescape(&in, &out, "$u3b$", ';') - || unescape(&in, &out, "$u5b$", '[') - || unescape(&in, &out, "$u5d$", ']') - || unescape(&in, &out, "$u7b$", '{') - || unescape(&in, &out, "$u7d$", '}') - || unescape(&in, &out, "$u7e$", '~'))) { - goto fail; - } - break; - case '_': - /* - * If this is the start of a path component and the next - * character is an escape sequence, ignore the - * underscore. The mangler inserts an underscore to make - * sure the path component begins with a XID_Start - * character. - */ - if ((in == sym || in[-1] == ':') && in[1] == '$') - in++; - else - *out++ = *in++; - break; - case '.': - if (in[1] == '.') { - /* ".." becomes "::" */ - *out++ = ':'; - *out++ = ':'; - in += 2; - } else { - /* "." becomes "-" */ - *out++ = '-'; - in++; - } - break; - case 'a' ... 'z': - case 'A' ... 'Z': - case '0' ... '9': - case ':': - *out++ = *in++; - break; - default: - goto fail; - } - } - goto done; - - fail: - *out++ = '?'; /* This is pretty lame, but it's hard to do better. */ - done: - *out++ = '\0'; - - vg_assert(out <= never_after); -} - -static Bool unescape(const HChar **in, HChar **out, - const HChar *seq, HChar value) -{ - SizeT len = VG_(strlen)(seq); - - if (VG_(strncmp)(*in, seq, len)) - return False; - - **out = value; - - *in += len; - *out += 1; - - return True; -} - - /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ diff --git a/coregrind/m_demangle/demangle.h b/coregrind/m_demangle/demangle.h index b3439d9577..f5a214362d 100644 --- a/coregrind/m_demangle/demangle.h +++ b/coregrind/m_demangle/demangle.h @@ -1,5 +1,5 @@ /* Defs for interface to demanglers. - Copyright (C) 1992-2015 Free Software Foundation, Inc. + Copyright (C) 1992-2017 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License @@ -65,9 +65,10 @@ extern "C" { #define DMGL_GNU_V3 (1 << 14) #define DMGL_GNAT (1 << 15) #define DMGL_DLANG (1 << 16) +#define DMGL_RUST (1 << 17) /* Rust wraps GNU_V3 style mangling. */ /* If none of these are set, use 'current_demangling_style' as the default. */ -#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG) +#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST) /* Enumeration of possible demangling styles. @@ -90,7 +91,8 @@ extern enum demangling_styles gnu_v3_demangling = DMGL_GNU_V3, java_demangling = DMGL_JAVA, gnat_demangling = DMGL_GNAT, - dlang_demangling = DMGL_DLANG + dlang_demangling = DMGL_DLANG, + rust_demangling = DMGL_RUST } current_demangling_style; /* Define string names for the various demangling styles. */ @@ -106,6 +108,7 @@ extern enum demangling_styles #define JAVA_DEMANGLING_STYLE_STRING "java" #define GNAT_DEMANGLING_STYLE_STRING "gnat" #define DLANG_DEMANGLING_STYLE_STRING "dlang" +#define RUST_DEMANGLING_STYLE_STRING "rust" /* Some macros to test what demangling style is active. */ @@ -120,6 +123,7 @@ extern enum demangling_styles #define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA) #define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT) #define DLANG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_DLANG) +#define RUST_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_RUST) /* Provide information about the available demangle styles. This code is pulled from gdb into libiberty because it is useful to binutils also. */ @@ -177,6 +181,27 @@ ada_demangle (const char *mangled, int options); extern char * dlang_demangle (const char *mangled, int options); +/* Returns non-zero iff MANGLED is a rust mangled symbol. MANGLED must + already have been demangled through cplus_demangle_v3. If this function + returns non-zero then MANGLED can be demangled (in-place) using + RUST_DEMANGLE_SYM. */ +extern int +rust_is_mangled (const char *mangled); + +/* Demangles SYM (in-place) if RUST_IS_MANGLED returned non-zero for SYM. + If RUST_IS_MANGLED returned zero for SYM then RUST_DEMANGLE_SYM might + replace characters that cannot be demangled with '?' and might truncate + SYM. After calling RUST_DEMANGLE_SYM SYM might be shorter, but never + larger. */ +extern void +rust_demangle_sym (char *sym); + +/* Demangles MANGLED if it was GNU_V3 and then RUST mangled, otherwise + returns NULL. Uses CPLUS_DEMANGLE_V3, RUST_IS_MANGLED and + RUST_DEMANGLE_SYM. Returns a new string that is owned by the caller. */ +extern char * +rust_demangle (const char *mangled, int options); + enum gnu_v3_ctor_kinds { gnu_v3_complete_object_ctor = 1, gnu_v3_base_object_ctor, @@ -451,7 +476,9 @@ enum demangle_component_type /* A transaction-safe function type. */ DEMANGLE_COMPONENT_TRANSACTION_SAFE, /* A cloned function. */ - DEMANGLE_COMPONENT_CLONE + DEMANGLE_COMPONENT_CLONE, + DEMANGLE_COMPONENT_NOEXCEPT, + DEMANGLE_COMPONENT_THROW_SPEC }; /* Types which are only used internally. */ @@ -469,6 +496,11 @@ struct demangle_component /* The type of this component. */ enum demangle_component_type type; + /* Guard against recursive component printing. + Initialize to zero. Private to d_print_comp. + All other fields are final after initialization. */ + int d_printing; + union { /* For DEMANGLE_COMPONENT_NAME. */ @@ -663,7 +695,7 @@ cplus_demangle_v3_components (const char *mangled, int options, void **mem); extern char * cplus_demangle_print (int options, - const struct demangle_component *tree, + struct demangle_component *tree, int estimated_length, size_t *p_allocated_size); @@ -683,7 +715,7 @@ cplus_demangle_print (int options, extern int cplus_demangle_print_callback (int options, - const struct demangle_component *tree, + struct demangle_component *tree, demangle_callbackref callback, void *opaque); #ifdef __cplusplus diff --git a/coregrind/m_demangle/dyn-string.c b/coregrind/m_demangle/dyn-string.c index 0dbb3ac889..9beba6e468 100644 --- a/coregrind/m_demangle/dyn-string.c +++ b/coregrind/m_demangle/dyn-string.c @@ -1,5 +1,5 @@ /* An abstract string datatype. - Copyright (C) 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 1998-2017 Free Software Foundation, Inc. Contributed by Mark Mitchell (mark@markmitchell.com). This file is part of GNU CC. diff --git a/coregrind/m_demangle/dyn-string.h b/coregrind/m_demangle/dyn-string.h index 7c3684b7cf..6c0accc724 100644 --- a/coregrind/m_demangle/dyn-string.h +++ b/coregrind/m_demangle/dyn-string.h @@ -1,5 +1,5 @@ /* An abstract string datatype. - Copyright (C) 1998-2015 Free Software Foundation, Inc. + Copyright (C) 1998-2017 Free Software Foundation, Inc. Contributed by Mark Mitchell (mark@markmitchell.com). This file is part of GCC. diff --git a/coregrind/m_demangle/rust-demangle.c b/coregrind/m_demangle/rust-demangle.c new file mode 100644 index 0000000000..3bfde6d750 --- /dev/null +++ b/coregrind/m_demangle/rust-demangle.c @@ -0,0 +1,363 @@ +/* Demangler for the Rust programming language + Copyright (C) 2016-2017 Free Software Foundation, Inc. + Written by David Tolnay (dtolnay@gmail.com). + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +In addition to the permissions in the GNU Library General Public +License, the Free Software Foundation gives you unlimited permission +to link the compiled version of this file into combinations with other +programs, and to distribute those combinations without any restriction +coming from the use of this file. (The Library Public License +restrictions do apply in other respects; for example, they cover +modification of the file, and distribution when not linked into a +combined executable.) + +Libiberty is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. +If not, see . */ + + +#if 0 /* in valgrind */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#endif /* ! in valgrind */ + +#if 0 /* in valgrind */ +#include "safe-ctype.h" +#endif /* ! in valgrind */ + +#if 0 /* in valgrind */ +#include +#include +#include +#endif /* ! in valgrind */ + +#if 0 /* in valgrind */ +#ifdef HAVE_STRING_H +#include +#else +extern size_t strlen(const char *s); +extern int strncmp(const char *s1, const char *s2, size_t n); +extern void *memset(void *s, int c, size_t n); +#endif +#endif /* ! in valgrind */ + +#if 0 /* in valgrind */ +#include +#include "libiberty.h" +#endif /* ! in valgrind */ + +#include "vg_libciface.h" + +#include "ansidecl.h" +#include "demangle.h" +#include "safe-ctype.h" + +/* Mangled Rust symbols look like this: + _$LT$std..sys..fd..FileDesc$u20$as$u20$core..ops..Drop$GT$::drop::hc68340e1baa4987a + + The original symbol is: + ::drop + + The last component of the path is a 64-bit hash in lowercase hex, + prefixed with "h". Rust does not have a global namespace between + crates, an illusion which Rust maintains by using the hash to + distinguish things that would otherwise have the same symbol. + + Any path component not starting with a XID_Start character is + prefixed with "_". + + The following escape sequences are used: + + "," => $C$ + "@" => $SP$ + "*" => $BP$ + "&" => $RF$ + "<" => $LT$ + ">" => $GT$ + "(" => $LP$ + ")" => $RP$ + " " => $u20$ + "\"" => $u22$ + "'" => $u27$ + "+" => $u2b$ + ";" => $u3b$ + "[" => $u5b$ + "]" => $u5d$ + "{" => $u7b$ + "}" => $u7d$ + "~" => $u7e$ + + A double ".." means "::" and a single "." means "-". + + The only characters allowed in the mangled symbol are a-zA-Z0-9 and _.:$ */ + +static const char *hash_prefix = "::h"; +static const size_t hash_prefix_len = 3; +static const size_t hash_len = 16; + +static int is_prefixed_hash (const char *start); +static int looks_like_rust (const char *sym, size_t len); +static int unescape (const char **in, char **out, const char *seq, char value); + +/* INPUT: sym: symbol that has been through C++ (gnu v3) demangling + + This function looks for the following indicators: + + 1. The hash must consist of "h" followed by 16 lowercase hex digits. + + 2. As a sanity check, the hash must use between 5 and 15 of the 16 + possible hex digits. This is true of 99.9998% of hashes so once + in your life you may see a false negative. The point is to + notice path components that could be Rust hashes but are + probably not, like "haaaaaaaaaaaaaaaa". In this case a false + positive (non-Rust symbol has an important path component + removed because it looks like a Rust hash) is worse than a false + negative (the rare Rust symbol is not demangled) so this sets + the balance in favor of false negatives. + + 3. There must be no characters other than a-zA-Z0-9 and _.:$ + + 4. There must be no unrecognized $-sign sequences. + + 5. There must be no sequence of three or more dots in a row ("..."). */ + +int +rust_is_mangled (const char *sym) +{ + size_t len, len_without_hash; + + if (!sym) + return 0; + + len = strlen (sym); + if (len <= hash_prefix_len + hash_len) + /* Not long enough to contain "::h" + hash + something else */ + return 0; + + len_without_hash = len - (hash_prefix_len + hash_len); + if (!is_prefixed_hash (sym + len_without_hash)) + return 0; + + return looks_like_rust (sym, len_without_hash); +} + +/* A hash is the prefix "::h" followed by 16 lowercase hex digits. The + hex digits must comprise between 5 and 15 (inclusive) distinct + digits. */ + +static int +is_prefixed_hash (const char *str) +{ + const char *end; + char seen[16]; + size_t i; + int count; + + if (strncmp (str, hash_prefix, hash_prefix_len)) + return 0; + str += hash_prefix_len; + + memset (seen, 0, sizeof(seen)); + for (end = str + hash_len; str < end; str++) + if (*str >= '0' && *str <= '9') + seen[*str - '0'] = 1; + else if (*str >= 'a' && *str <= 'f') + seen[*str - 'a' + 10] = 1; + else + return 0; + + /* Count how many distinct digits seen */ + count = 0; + for (i = 0; i < 16; i++) + if (seen[i]) + count++; + + return count >= 5 && count <= 15; +} + +static int +looks_like_rust (const char *str, size_t len) +{ + const char *end = str + len; + + while (str < end) + switch (*str) + { + case '$': + if (!strncmp (str, "$C$", 3)) + str += 3; + else if (!strncmp (str, "$SP$", 4) + || !strncmp (str, "$BP$", 4) + || !strncmp (str, "$RF$", 4) + || !strncmp (str, "$LT$", 4) + || !strncmp (str, "$GT$", 4) + || !strncmp (str, "$LP$", 4) + || !strncmp (str, "$RP$", 4)) + str += 4; + else if (!strncmp (str, "$u20$", 5) + || !strncmp (str, "$u22$", 5) + || !strncmp (str, "$u27$", 5) + || !strncmp (str, "$u2b$", 5) + || !strncmp (str, "$u3b$", 5) + || !strncmp (str, "$u5b$", 5) + || !strncmp (str, "$u5d$", 5) + || !strncmp (str, "$u7b$", 5) + || !strncmp (str, "$u7d$", 5) + || !strncmp (str, "$u7e$", 5)) + str += 5; + else + return 0; + break; + case '.': + /* Do not allow three or more consecutive dots */ + if (!strncmp (str, "...", 3)) + return 0; + /* Fall through */ + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + case '_': + case ':': + str++; + break; + default: + return 0; + } + + return 1; +} + +/* + INPUT: sym: symbol for which rust_is_mangled(sym) returned 1. + + The input is demangled in-place because the mangled name is always + longer than the demangled one. */ + +void +rust_demangle_sym (char *sym) +{ + const char *in; + char *out; + const char *end; + + if (!sym) + return; + + in = sym; + out = sym; + end = sym + strlen (sym) - (hash_prefix_len + hash_len); + + while (in < end) + switch (*in) + { + case '$': + if (!(unescape (&in, &out, "$C$", ',') + || unescape (&in, &out, "$SP$", '@') + || unescape (&in, &out, "$BP$", '*') + || unescape (&in, &out, "$RF$", '&') + || unescape (&in, &out, "$LT$", '<') + || unescape (&in, &out, "$GT$", '>') + || unescape (&in, &out, "$LP$", '(') + || unescape (&in, &out, "$RP$", ')') + || unescape (&in, &out, "$u20$", ' ') + || unescape (&in, &out, "$u22$", '\"') + || unescape (&in, &out, "$u27$", '\'') + || unescape (&in, &out, "$u2b$", '+') + || unescape (&in, &out, "$u3b$", ';') + || unescape (&in, &out, "$u5b$", '[') + || unescape (&in, &out, "$u5d$", ']') + || unescape (&in, &out, "$u7b$", '{') + || unescape (&in, &out, "$u7d$", '}') + || unescape (&in, &out, "$u7e$", '~'))) { + /* unexpected escape sequence, not looks_like_rust. */ + goto fail; + } + break; + case '_': + /* If this is the start of a path component and the next + character is an escape sequence, ignore the underscore. The + mangler inserts an underscore to make sure the path + component begins with a XID_Start character. */ + if ((in == sym || in[-1] == ':') && in[1] == '$') + in++; + else + *out++ = *in++; + break; + case '.': + if (in[1] == '.') + { + /* ".." becomes "::" */ + *out++ = ':'; + *out++ = ':'; + in += 2; + } + else + { + /* "." becomes "-" */ + *out++ = '-'; + in++; + } + break; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + case ':': + *out++ = *in++; + break; + default: + /* unexpected character in symbol, not looks_like_rust. */ + goto fail; + } + goto done; + +fail: + *out++ = '?'; /* This is pretty lame, but it's hard to do better. */ +done: + *out = '\0'; +} + +static int +unescape (const char **in, char **out, const char *seq, char value) +{ + size_t len = strlen (seq); + + if (strncmp (*in, seq, len)) + return 0; + + **out = value; + + *in += len; + *out += 1; + + return 1; +} diff --git a/coregrind/m_demangle/safe-ctype.c b/coregrind/m_demangle/safe-ctype.c index 7ac1c7a843..d3247eddb8 100644 --- a/coregrind/m_demangle/safe-ctype.c +++ b/coregrind/m_demangle/safe-ctype.c @@ -1,7 +1,6 @@ /* replacement macros. - Copyright (C) 2000, 2001, 2002, 2003, 2004, - 2005 Free Software Foundation, Inc. + Copyright (C) 2000-2017 Free Software Foundation, Inc. Contributed by Zack Weinberg . This file is part of the libiberty library. diff --git a/coregrind/m_demangle/safe-ctype.h b/coregrind/m_demangle/safe-ctype.h index 1f4465bf5a..472c897826 100644 --- a/coregrind/m_demangle/safe-ctype.h +++ b/coregrind/m_demangle/safe-ctype.h @@ -1,6 +1,6 @@ /* replacement macros. - Copyright (C) 2000-2015 Free Software Foundation, Inc. + Copyright (C) 2000-2017 Free Software Foundation, Inc. Contributed by Zack Weinberg . This file is part of the libiberty library.