From 797b8ecfe013d0b93352a06b292fdb0eb3a6ca08 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 8 Sep 2016 15:42:27 +0200 Subject: [PATCH] Update libiberty demangler. Update the libiberty demangler using the auxprogs/update-demangler script. There were various extensions and bug fixes since our last import. Add new D language demangler file d-demangle.c and update the vg_libciface.h header with some new constructs used (strtol, xmalloc_failed, xmemdup, XDELETEVEC, XDUPVEC). --- auxprogs/update-demangler | 6 +- coregrind/Makefile.am | 1 + coregrind/m_demangle/ansidecl.h | 22 +- coregrind/m_demangle/cp-demangle.c | 338 +++++++- coregrind/m_demangle/cp-demangle.h | 29 +- coregrind/m_demangle/cplus-dem.c | 140 ++- coregrind/m_demangle/d-demangle.c | 1618 +++++++++++++++++++++++++++++++++++ coregrind/m_demangle/demangle.h | 26 +- coregrind/m_demangle/dyn-string.h | 3 +- coregrind/m_demangle/safe-ctype.h | 2 +- coregrind/m_demangle/vg_libciface.h | 19 + 11 files changed, 2129 insertions(+), 75 deletions(-) create mode 100644 coregrind/m_demangle/d-demangle.c diff --git a/auxprogs/update-demangler b/auxprogs/update-demangler index 9a4a00a..18189b3 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=r181975 # the revision of the previous update -new_gcc_revision=r212125 # the revision for this update +old_gcc_revision=r212125 # the revision of the previous update +new_gcc_revision=r240068 # the revision for this update # Unless the organization of demangler related files has changed, no # changes below this line should be necessary. @@ -55,6 +55,7 @@ cp ../gcc-$old_gcc_revision/libiberty/cp-demangle.c . 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/safe-ctype.c . cd .. @@ -81,6 +82,7 @@ cp ../gcc-$new_gcc_revision/libiberty/cp-demangle.c . 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/safe-ctype.c . cd .. diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index d471224..d798015 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -357,6 +357,7 @@ COREGRIND_SOURCES_COMMON = \ m_demangle/cplus-dem.c \ m_demangle/demangle.c \ m_demangle/dyn-string.c \ + m_demangle/d-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 0fb23bb..6e4bfc2 100644 --- a/coregrind/m_demangle/ansidecl.h +++ b/coregrind/m_demangle/ansidecl.h @@ -1,7 +1,5 @@ /* ANSI and traditional C compatability macros - Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2013 - Free Software Foundation, Inc. + Copyright (C) 1991-2015 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 @@ -276,6 +274,15 @@ So instead we use the macro below and test it against specific values. */ # endif /* GNUC >= 4.3 */ #endif /* ATTRIBUTE_HOT */ +/* Attribute 'no_sanitize_undefined' was valid as of gcc 4.9. */ +#ifndef ATTRIBUTE_NO_SANITIZE_UNDEFINED +# if (GCC_VERSION >= 4009) +# define ATTRIBUTE_NO_SANITIZE_UNDEFINED __attribute__ ((no_sanitize_undefined)) +# else +# define ATTRIBUTE_NO_SANITIZE_UNDEFINED +# endif /* GNUC >= 4.9 */ +#endif /* ATTRIBUTE_NO_SANITIZE_UNDEFINED */ + /* We use __extension__ in some places to suppress -pedantic warnings about GCC extensions. This feature didn't work properly before gcc 2.8. */ @@ -306,6 +313,15 @@ 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 +#elif GCC_VERSION >= 4007 +#define GCC_FINAL __final +#else +#define GCC_FINAL +#endif + #ifdef __cplusplus } #endif diff --git a/coregrind/m_demangle/cp-demangle.c b/coregrind/m_demangle/cp-demangle.c index 381bd4d..a3f78ab 100644 --- a/coregrind/m_demangle/cp-demangle.c +++ b/coregrind/m_demangle/cp-demangle.c @@ -93,7 +93,11 @@ CP_DEMANGLE_DEBUG If defined, turns on debugging mode, which prints information on stdout about the mangled string. This is not generally useful. -*/ + + CHECK_DEMANGLER + If defined, additional sanity checks will be performed. It will + cause some slowdown, but will allow to catch out-of-bound access + errors earlier. This macro is intended for testing and debugging. */ #if 0 /* in valgrind */ #if defined (_AIX) && !defined (__GNUC__) @@ -135,6 +139,15 @@ extern char *alloca (); #endif /* ! in valgrind */ #if 0 /* in valgrind */ +#ifdef HAVE_LIMITS_H +#include +#endif +#endif /* ! in valgrind */ +#ifndef INT_MAX +# define INT_MAX (int)(((unsigned int) ~0) >> 1) /* 0x7FFFFFFF */ +#endif + +#if 0 /* in valgrind */ #include "ansidecl.h" #include "libiberty.h" #endif /* ! in valgrind */ @@ -348,7 +361,7 @@ struct d_print_info /* Set to 1 if we saw a demangling error. */ int demangle_failure; /* The current index into any template argument packs we are using - for printing. */ + for printing, or -1 to print the whole pack. */ int pack_index; /* Number of d_print_flush calls so far. */ unsigned long int flush_count; @@ -409,7 +422,7 @@ d_make_dtor (struct d_info *, enum gnu_v3_dtor_kinds, struct demangle_component *); static struct demangle_component * -d_make_template_param (struct d_info *, long); +d_make_template_param (struct d_info *, int); static struct demangle_component * d_make_sub (struct d_info *, const char *, int); @@ -432,7 +445,7 @@ static struct demangle_component *d_unqualified_name (struct d_info *); static struct demangle_component *d_source_name (struct d_info *); -static long d_number (struct d_info *); +static int d_number (struct d_info *); static struct demangle_component *d_identifier (struct d_info *, int); @@ -470,6 +483,7 @@ static struct demangle_component * d_template_param (struct d_info *); static struct demangle_component *d_template_args (struct d_info *); +static struct demangle_component *d_template_args_1 (struct d_info *); static struct demangle_component * d_template_arg (struct d_info *); @@ -553,8 +567,10 @@ d_print_array_type (struct d_print_info *, int, static void d_print_expr_op (struct d_print_info *, int, const struct demangle_component *); -static void -d_print_cast (struct d_print_info *, int, const struct demangle_component *); +static void d_print_cast (struct d_print_info *, int, + const struct demangle_component *); +static void d_print_conversion (struct d_print_info *, int, + const struct demangle_component *); static int d_demangle_callback (const char *, int, demangle_callbackref, void *); @@ -697,6 +713,9 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: printf ("rvalue reference this\n"); break; + case DEMANGLE_COMPONENT_TRANSACTION_SAFE: + printf ("transaction_safe this\n"); + break; case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: printf ("vendor type qualifier\n"); break; @@ -728,7 +747,9 @@ d_dump (struct demangle_component *dc, int indent) printf ("pointer to member type\n"); break; case DEMANGLE_COMPONENT_FIXED_TYPE: - printf ("fixed-point type\n"); + printf ("fixed-point type, accum? %d, sat? %d\n", + dc->u.s_fixed.accum, dc->u.s_fixed.sat); + d_dump (dc->u.s_fixed.length, indent + 2); break; case DEMANGLE_COMPONENT_ARGLIST: printf ("argument list\n"); @@ -742,6 +763,9 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_CAST: printf ("cast\n"); break; + case DEMANGLE_COMPONENT_CONVERSION: + printf ("conversion operator\n"); + break; case DEMANGLE_COMPONENT_NULLARY: printf ("nullary operator\n"); break; @@ -951,6 +975,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_IMAGINARY: case DEMANGLE_COMPONENT_VENDOR_TYPE: case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: case DEMANGLE_COMPONENT_JAVA_RESOURCE: case DEMANGLE_COMPONENT_DECLTYPE: case DEMANGLE_COMPONENT_PACK_EXPANSION: @@ -979,6 +1004,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, 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: @@ -1118,7 +1144,7 @@ d_make_dtor (struct d_info *di, enum gnu_v3_dtor_kinds kind, /* Add a new template parameter. */ static struct demangle_component * -d_make_template_param (struct d_info *di, long i) +d_make_template_param (struct d_info *di, int i) { struct demangle_component *p; @@ -1134,7 +1160,7 @@ d_make_template_param (struct d_info *di, long i) /* Add a new function parameter. */ static struct demangle_component * -d_make_function_param (struct d_info *di, long i) +d_make_function_param (struct d_info *di, int i) { struct demangle_component *p; @@ -1221,6 +1247,7 @@ has_return_type (struct demangle_component *dc) case DEMANGLE_COMPONENT_CONST_THIS: case DEMANGLE_COMPONENT_REFERENCE_THIS: case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: + case DEMANGLE_COMPONENT_TRANSACTION_SAFE: return has_return_type (d_left (dc)); } } @@ -1242,7 +1269,7 @@ is_ctor_dtor_or_conversion (struct demangle_component *dc) return is_ctor_dtor_or_conversion (d_right (dc)); case DEMANGLE_COMPONENT_CTOR: case DEMANGLE_COMPONENT_DTOR: - case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: return 1; } } @@ -1277,6 +1304,7 @@ 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); @@ -1293,6 +1321,7 @@ d_encoding (struct d_info *di, int top_level) 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) dcr = d_left (dcr); @@ -1315,7 +1344,12 @@ d_encoding (struct d_info *di, int top_level) static struct demangle_component * d_abi_tags (struct d_info *di, struct demangle_component *dc) { + struct demangle_component *hold_last_name; char peek; + + /* Preserve the last name, so the ABI tag doesn't clobber it. */ + hold_last_name = di->last_name; + while (peek = d_peek_char (di), peek == 'B') { @@ -1324,6 +1358,9 @@ d_abi_tags (struct d_info *di, struct demangle_component *dc) tag = d_source_name (di); dc = d_make_comp (di, DEMANGLE_COMPONENT_TAGGED_NAME, dc, tag); } + + di->last_name = hold_last_name; + return dc; } @@ -1608,7 +1645,7 @@ d_unqualified_name (struct d_info *di) static struct demangle_component * d_source_name (struct d_info *di) { - long len; + int len; struct demangle_component *ret; len = d_number (di); @@ -1621,12 +1658,12 @@ d_source_name (struct d_info *di) /* number ::= [n] <(non-negative decimal integer)> */ -static long +static int d_number (struct d_info *di) { int negative; char peek; - long ret; + int ret; negative = 0; peek = d_peek_char (di); @@ -1742,6 +1779,10 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "eO", NL ("^="), 2 }, { "eo", NL ("^"), 2 }, { "eq", NL ("=="), 2 }, + { "fL", NL ("..."), 3 }, + { "fR", NL ("..."), 3 }, + { "fl", NL ("..."), 2 }, + { "fr", NL ("..."), 2 }, { "ge", NL (">="), 2 }, { "gs", NL ("::"), 1 }, { "gt", NL (">"), 2 }, @@ -1776,6 +1817,8 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "rc", NL ("reinterpret_cast"), 2 }, { "rm", NL ("%"), 2 }, { "rs", NL (">>"), 2 }, + { "sP", NL ("sizeof..."), 1 }, + { "sZ", NL ("sizeof..."), 1 }, { "sc", NL ("static_cast"), 2 }, { "st", NL ("sizeof "), 1 }, { "sz", NL ("sizeof "), 1 }, @@ -1798,11 +1841,16 @@ d_operator_name (struct d_info *di) { struct demangle_component *type; int was_conversion = di->is_conversion; + struct demangle_component *res; di->is_conversion = ! di->is_expression; type = cplus_demangle_type (di); + if (di->is_conversion) + res = d_make_comp (di, DEMANGLE_COMPONENT_CONVERSION, type, NULL); + else + res = d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL); di->is_conversion = was_conversion; - return d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL); + return res; } else { @@ -1853,7 +1901,7 @@ d_java_resource (struct d_info *di) { struct demangle_component *p = NULL; struct demangle_component *next = NULL; - long len, i; + int len, i; char c; const char *str; @@ -1995,7 +2043,7 @@ d_special_name (struct d_info *di) case 'C': { struct demangle_component *derived_type; - long offset; + int offset; struct demangle_component *base_type; derived_type = cplus_demangle_type (di); @@ -2282,7 +2330,8 @@ cplus_demangle_type (struct d_info *di) names. */ peek = d_peek_char (di); - if (peek == 'r' || peek == 'V' || peek == 'K') + if (peek == 'r' || peek == 'V' || peek == 'K' + || (peek == 'D' && d_peek_next_char (di) == 'x')) { struct demangle_component **pret; @@ -2483,6 +2532,9 @@ cplus_demangle_type (struct d_info *di) case 'U': d_advance (di, 1); ret = d_source_name (di); + if (d_peek_char (di) == 'I') + ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, + d_template_args (di)); ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL, cplus_demangle_type (di), ret); break; @@ -2590,7 +2642,7 @@ cplus_demangle_type (struct d_info *di) return ret; } -/* ::= [r] [V] [K] */ +/* ::= [r] [V] [K] [Dx] */ static struct demangle_component ** d_cv_qualifiers (struct d_info *di, @@ -2601,7 +2653,8 @@ d_cv_qualifiers (struct d_info *di, pstart = pret; peek = d_peek_char (di); - while (peek == 'r' || peek == 'V' || peek == 'K') + while (peek == 'r' || peek == 'V' || peek == 'K' + || (peek == 'D' && d_peek_next_char (di) == 'x')) { enum demangle_component_type t; @@ -2620,13 +2673,19 @@ d_cv_qualifiers (struct d_info *di, : DEMANGLE_COMPONENT_VOLATILE); di->expansion += sizeof "volatile"; } - else + else if (peek == 'K') { t = (member_fn ? DEMANGLE_COMPONENT_CONST_THIS : DEMANGLE_COMPONENT_CONST); di->expansion += sizeof "const"; } + else + { + t = DEMANGLE_COMPONENT_TRANSACTION_SAFE; + di->expansion += sizeof "transaction_safe"; + d_advance (di, 1); + } *pret = d_make_comp (di, t, NULL, NULL); if (*pret == NULL) @@ -2692,7 +2751,7 @@ d_ref_qualifier (struct d_info *di, struct demangle_component *sub) return ret; } -/* ::= F [Y] [] E */ +/* ::= F [Y] [] [T] E */ static struct demangle_component * d_function_type (struct d_info *di) @@ -2918,10 +2977,10 @@ d_pointer_to_member_type (struct d_info *di) /* _ */ -static long +static int d_compact_number (struct d_info *di) { - long num; + int num; if (d_peek_char (di) == '_') num = 0; else if (d_peek_char (di) == 'n') @@ -2929,7 +2988,7 @@ d_compact_number (struct d_info *di) else num = d_number (di) + 1; - if (! d_check_char (di, '_')) + if (num < 0 || ! d_check_char (di, '_')) return -1; return num; } @@ -2941,7 +3000,7 @@ d_compact_number (struct d_info *di) static struct demangle_component * d_template_param (struct d_info *di) { - long param; + int param; if (! d_check_char (di, 'T')) return NULL; @@ -2960,6 +3019,19 @@ d_template_param (struct d_info *di) static struct demangle_component * d_template_args (struct d_info *di) { + if (d_peek_char (di) != 'I' + && d_peek_char (di) != 'J') + return NULL; + d_advance (di, 1); + + return d_template_args_1 (di); +} + +/* * E */ + +static struct demangle_component * +d_template_args_1 (struct d_info *di) +{ struct demangle_component *hold_last_name; struct demangle_component *al; struct demangle_component **pal; @@ -2969,11 +3041,6 @@ d_template_args (struct d_info *di) constructor or destructor. */ hold_last_name = di->last_name; - if (d_peek_char (di) != 'I' - && d_peek_char (di) != 'J') - return NULL; - d_advance (di, 1); - if (d_peek_char (di) == 'E') { /* An argument pack can be empty. */ @@ -3143,9 +3210,10 @@ d_expression_1 (struct d_info *di) } else { - index = d_compact_number (di) + 1; - if (index == 0) + index = d_compact_number (di); + if (index == INT_MAX || index == -1) return NULL; + index++; } return d_make_function_param (di, index); } @@ -3176,6 +3244,8 @@ d_expression_1 (struct d_info *di) struct demangle_component *type = NULL; if (peek == 't') type = cplus_demangle_type (di); + if (!d_peek_next_char (di)) + return NULL; d_advance (di, 2); return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST, type, d_exprlist (di, 'E')); @@ -3232,6 +3302,8 @@ d_expression_1 (struct d_info *di) if (op->type == DEMANGLE_COMPONENT_CAST && d_check_char (di, '_')) operand = d_exprlist (di, 'E'); + else if (code && !strcmp (code, "sP")) + operand = d_template_args_1 (di); else operand = d_expression_1 (di); @@ -3250,8 +3322,13 @@ d_expression_1 (struct d_info *di) struct demangle_component *left; struct demangle_component *right; + if (code == NULL) + return NULL; if (op_is_new_cast (op)) left = cplus_demangle_type (di); + else if (code[0] == 'f') + /* fold-expression. */ + left = d_operator_name (di); else left = d_expression_1 (di); if (!strcmp (code, "cl")) @@ -3277,13 +3354,22 @@ d_expression_1 (struct d_info *di) struct demangle_component *second; struct demangle_component *third; - if (!strcmp (code, "qu")) + if (code == NULL) + return NULL; + else if (!strcmp (code, "qu")) { /* ?: expression. */ first = d_expression_1 (di); second = d_expression_1 (di); third = d_expression_1 (di); } + else if (code[0] == 'f') + { + /* fold-expression. */ + first = d_operator_name (di); + second = d_expression_1 (di); + third = d_expression_1 (di); + } else if (code[0] == 'n') { /* new-expression. */ @@ -3468,7 +3554,7 @@ d_local_name (struct d_info *di) static int d_discriminator (struct d_info *di) { - long discrim; + int discrim; if (d_peek_char (di) != '_') return 1; @@ -3524,7 +3610,7 @@ static struct demangle_component * d_unnamed_type (struct d_info *di) { struct demangle_component *ret; - long num; + int num; if (! d_check_char (di, 'U')) return NULL; @@ -3700,6 +3786,7 @@ d_substitution (struct d_info *di, int prefix) { const char *s; int len; + struct demangle_component *dc; if (p->set_last_name != NULL) di->last_name = d_make_sub (di, p->set_last_name, @@ -3715,7 +3802,15 @@ d_substitution (struct d_info *di, int prefix) len = p->simple_len; } di->expansion += len; - return d_make_sub (di, s, len); + dc = d_make_sub (di, s, len); + if (d_peek_char (di) == 'B') + { + /* If there are ABI tags on the abbreviation, it becomes + a substitution candidate. */ + dc = d_abi_tags (di, dc); + d_add_substitution (di, dc); + } + return dc; } } @@ -3882,6 +3977,7 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, case DEMANGLE_COMPONENT_CONST_THIS: case DEMANGLE_COMPONENT_REFERENCE_THIS: case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: + case DEMANGLE_COMPONENT_TRANSACTION_SAFE: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_COMPLEX: @@ -3890,12 +3986,12 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, case DEMANGLE_COMPONENT_FUNCTION_TYPE: case DEMANGLE_COMPONENT_ARRAY_TYPE: case DEMANGLE_COMPONENT_PTRMEM_TYPE: - case DEMANGLE_COMPONENT_FIXED_TYPE: case DEMANGLE_COMPONENT_VECTOR_TYPE: case DEMANGLE_COMPONENT_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: case DEMANGLE_COMPONENT_INITIALIZER_LIST: case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: case DEMANGLE_COMPONENT_NULLARY: case DEMANGLE_COMPONENT_UNARY: case DEMANGLE_COMPONENT_BINARY: @@ -3935,6 +4031,11 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, dc->u.s_extended_operator.name); break; + case DEMANGLE_COMPONENT_FIXED_TYPE: + d_count_templates_scopes (num_templates, num_scopes, + dc->u.s_fixed.length); + break; + case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: d_count_templates_scopes (num_templates, num_scopes, @@ -4037,10 +4138,10 @@ d_append_string (struct d_print_info *dpi, const char *s) } static inline void -d_append_num (struct d_print_info *dpi, long l) +d_append_num (struct d_print_info *dpi, int l) { char buf[25]; - sprintf (buf,"%ld", l); + sprintf (buf,"%d", l); d_append_string (dpi, buf); } @@ -4072,8 +4173,12 @@ cplus_demangle_print_callback (int options, { #if 0 /* in valgrind */ #ifdef CP_DYNAMIC_ARRAYS - __extension__ struct d_saved_scope scopes[dpi.num_saved_scopes ?: 1]; - __extension__ struct d_print_template temps[dpi.num_copy_templates ?: 1]; + /* Avoid zero-length VLAs, which are prohibited by the C99 standard + and flagged as errors by Address Sanitizer. */ + __extension__ struct d_saved_scope scopes[(dpi.num_saved_scopes > 0) + ? dpi.num_saved_scopes : 1]; + __extension__ struct d_print_template temps[(dpi.num_copy_templates > 0) + ? dpi.num_copy_templates : 1]; dpi.saved_scopes = scopes; dpi.copy_templates = temps; @@ -4138,13 +4243,17 @@ cplus_demangle_print (int options, const struct demangle_component *dc, } /* Returns the I'th element of the template arglist ARGS, or NULL on - failure. */ + failure. If I is negative, return the entire arglist. */ static struct demangle_component * d_index_template_argument (struct demangle_component *args, int i) { struct demangle_component *a; + if (i < 0) + /* Print the whole argument pack. */ + return args; + for (a = args; a != NULL; a = d_right (a)) @@ -4209,6 +4318,9 @@ d_find_pack (struct d_print_info *dpi, case DEMANGLE_COMPONENT_CHARACTER: case DEMANGLE_COMPONENT_FUNCTION_PARAM: case DEMANGLE_COMPONENT_UNNAMED_TYPE: + case DEMANGLE_COMPONENT_FIXED_TYPE: + case DEMANGLE_COMPONENT_DEFAULT_ARG: + case DEMANGLE_COMPONENT_NUMBER: return NULL; case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: @@ -4241,6 +4353,30 @@ d_pack_length (const struct demangle_component *dc) return count; } +/* Returns the number of template args in DC, expanding any pack expansions + found there. */ + +static int +d_args_length (struct d_print_info *dpi, const struct demangle_component *dc) +{ + int count = 0; + for (; dc && dc->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST; + dc = d_right (dc)) + { + struct demangle_component *elt = d_left (dc); + if (elt == NULL) + break; + if (elt->type == DEMANGLE_COMPONENT_PACK_EXPANSION) + { + struct demangle_component *a = d_find_pack (dpi, d_left (elt)); + count += d_pack_length (a); + } + else + ++count; + } + return count; +} + /* DC is a component of a mangled expression. Print it, wrapped in parens if needed. */ @@ -4317,6 +4453,70 @@ d_get_saved_scope (struct d_print_info *dpi, return NULL; } +/* If DC is a C++17 fold-expression, print it and return true; otherwise + return false. */ + +static int +d_maybe_print_fold_expression (struct d_print_info *dpi, int options, + const struct demangle_component *dc) +{ + const struct demangle_component *ops, *operator_, *op1, *op2; + int save_idx; + + const char *fold_code = d_left (dc)->u.s_operator.op->code; + if (fold_code[0] != 'f') + return 0; + + ops = d_right (dc); + operator_ = d_left (ops); + op1 = d_right (ops); + op2 = 0; + if (op1->type == DEMANGLE_COMPONENT_TRINARY_ARG2) + { + op2 = d_right (op1); + op1 = d_left (op1); + } + + /* Print the whole pack. */ + save_idx = dpi->pack_index; + dpi->pack_index = -1; + + switch (fold_code[1]) + { + /* Unary left fold, (... + X). */ + case 'l': + d_append_string (dpi, "(..."); + d_print_expr_op (dpi, options, operator_); + d_print_subexpr (dpi, options, op1); + d_append_char (dpi, ')'); + break; + + /* Unary right fold, (X + ...). */ + case 'r': + d_append_char (dpi, '('); + d_print_subexpr (dpi, options, op1); + d_print_expr_op (dpi, options, operator_); + d_append_string (dpi, "...)"); + break; + + /* Binary left fold, (42 + ... + X). */ + case 'L': + /* Binary right fold, (X + ... + 42). */ + case 'R': + d_append_char (dpi, '('); + d_print_subexpr (dpi, options, op1); + d_print_expr_op (dpi, options, operator_); + d_append_string (dpi, "..."); + d_print_expr_op (dpi, options, operator_); + d_print_subexpr (dpi, options, op2); + d_append_char (dpi, ')'); + break; + } + + dpi->pack_index = save_idx; + return 1; +} + /* Subroutine to handle components. */ static void @@ -4412,6 +4612,7 @@ d_print_comp_inner (struct d_print_info *dpi, int options, && 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) break; @@ -4444,10 +4645,16 @@ d_print_comp_inner (struct d_print_info *dpi, int options, local_name = d_right (typed_name); if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG) local_name = local_name->u.s_unary_num.sub; + if (local_name == NULL) + { + 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)) { @@ -4783,6 +4990,7 @@ d_print_comp_inner (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_COMPLEX: case DEMANGLE_COMPONENT_IMAGINARY: + case DEMANGLE_COMPONENT_TRANSACTION_SAFE: modifier: { /* We keep a list of modifiers on the stack. */ @@ -5032,9 +5240,9 @@ d_print_comp_inner (struct d_print_info *dpi, int options, d_print_comp (dpi, options, dc->u.s_extended_operator.name); return; - case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: d_append_string (dpi, "operator "); - d_print_cast (dpi, options, dc); + d_print_conversion (dpi, options, dc); return; case DEMANGLE_COMPONENT_NULLARY: @@ -5069,6 +5277,21 @@ d_print_comp_inner (struct d_print_info *dpi, int options, } } + /* For sizeof..., just print the pack length. */ + if (code && !strcmp (code, "sZ")) + { + struct demangle_component *a = d_find_pack (dpi, operand); + int len = d_pack_length (a); + d_append_num (dpi, len); + return; + } + else if (code && !strcmp (code, "sP")) + { + int len = d_args_length (dpi, operand); + d_append_num (dpi, len); + return; + } + if (op->type != DEMANGLE_COMPONENT_CAST) d_print_expr_op (dpi, options, op); else @@ -5110,6 +5333,9 @@ d_print_comp_inner (struct d_print_info *dpi, int options, return; } + if (d_maybe_print_fold_expression (dpi, options, dc)) + return; + /* We wrap an expression which uses the greater-than operator in an extra layer of parens so that it does not get confused with the '>' which ends the template parameters. */ @@ -5165,6 +5391,8 @@ d_print_comp_inner (struct d_print_info *dpi, int options, d_print_error (dpi); return; } + if (d_maybe_print_fold_expression (dpi, options, dc)) + return; { struct demangle_component *op = d_left (dc); struct demangle_component *first = d_left (d_right (dc)); @@ -5471,6 +5699,7 @@ d_print_mod_list (struct d_print_info *dpi, int options, || 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)))) { @@ -5529,6 +5758,7 @@ d_print_mod_list (struct d_print_info *dpi, int options, || 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) dc = d_left (dc); @@ -5565,6 +5795,9 @@ d_print_mod (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_CONST_THIS: d_append_string (dpi, " const"); return; + case DEMANGLE_COMPONENT_TRANSACTION_SAFE: + d_append_string (dpi, " transaction_safe"); + return; case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: d_append_char (dpi, ' '); d_print_comp (dpi, options, d_right (mod)); @@ -5577,11 +5810,13 @@ d_print_mod (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_REFERENCE_THIS: /* For the ref-qualifier, put a space before the &. */ d_append_char (dpi, ' '); + /* FALLTHRU */ case DEMANGLE_COMPONENT_REFERENCE: d_append_char (dpi, '&'); return; case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: d_append_char (dpi, ' '); + /* FALLTHRU */ case DEMANGLE_COMPONENT_RVALUE_REFERENCE: d_append_string (dpi, "&&"); return; @@ -5655,6 +5890,7 @@ d_print_function_type (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_CONST_THIS: case DEMANGLE_COMPONENT_REFERENCE_THIS: case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: + case DEMANGLE_COMPONENT_TRANSACTION_SAFE: break; default: break; @@ -5767,11 +6003,20 @@ 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) + const struct demangle_component *dc) +{ + d_print_comp (dpi, options, d_left (dc)); +} + +/* Print a conversion operator. */ + +static void +d_print_conversion (struct d_print_info *dpi, int options, + const struct demangle_component *dc) { struct d_print_template dpt; - /* For a cast operator, we need the template parameters from + /* For a conversion operator, we need the template parameters from the enclosing template in scope for processing the type. */ if (dpi->current_template != NULL) { @@ -6206,6 +6451,7 @@ 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 6fce025..197883e 100644 --- a/coregrind/m_demangle/cp-demangle.h +++ b/coregrind/m_demangle/cp-demangle.h @@ -135,12 +135,37 @@ struct d_info - call d_check_char(di, '\0') Everything else is safe. */ #define d_peek_char(di) (*((di)->n)) -#define d_peek_next_char(di) ((di)->n[1]) -#define d_advance(di, i) ((di)->n += (i)) +#ifndef CHECK_DEMANGLER +# define d_peek_next_char(di) ((di)->n[1]) +# define d_advance(di, i) ((di)->n += (i)) +#endif #define d_check_char(di, c) (d_peek_char(di) == c ? ((di)->n++, 1) : 0) #define d_next_char(di) (d_peek_char(di) == '\0' ? '\0' : *((di)->n++)) #define d_str(di) ((di)->n) +#ifdef CHECK_DEMANGLER +static inline char +d_peek_next_char (const struct d_info *di) +{ + if (!di->n[0]) + abort (); + return di->n[1]; +} + +static inline void +d_advance (struct d_info *di, int i) +{ + if (i < 0) + abort (); + while (i--) + { + if (!di->n[0]) + abort (); + di->n++; + } +} +#endif + /* Functions and arrays in cp-demangle.c which are referenced by functions in cp-demint.c. */ #ifdef IN_GLIBCPP_V3 diff --git a/coregrind/m_demangle/cplus-dem.c b/coregrind/m_demangle/cplus-dem.c index 46cc3b5..d00f79f 100644 --- a/coregrind/m_demangle/cplus-dem.c +++ b/coregrind/m_demangle/cplus-dem.c @@ -65,6 +65,15 @@ void * realloc (); #endif /* ! in valgrind */ #if 0 /* in valgrind */ +#ifdef HAVE_LIMITS_H +#include +#endif +#endif /* ! in valgrind */ +#ifndef INT_MAX +# define INT_MAX (int)(((unsigned int) ~0) >> 1) /* 0x7FFFFFFF */ +#endif + +#if 0 /* in valgrind */ #include #undef CURRENT_DEMANGLING_STYLE #define CURRENT_DEMANGLING_STYLE work->options @@ -155,6 +164,9 @@ struct work_stuff string* previous_argument; /* The last function argument demangled. */ int nrepeats; /* The number of times to repeat the previous argument. */ + int *proctypevec; /* Indices of currently processed remembered typevecs. */ + int proctypevec_size; + int nproctypes; }; #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) @@ -255,6 +267,7 @@ typedef enum type_kind_t tk_none, tk_pointer, tk_reference, + tk_rvalue_reference, tk_integral, tk_bool, tk_char, @@ -324,6 +337,12 @@ const struct demangler_engine libiberty_demanglers[] = } , { + DLANG_DEMANGLING_STYLE_STRING, + dlang_demangling, + "DLANG style demangling" + } + , + { NULL, unknown_demangling, NULL } }; @@ -439,6 +458,10 @@ iterate_demangle_function (struct work_stuff *, static void remember_type (struct work_stuff *, const char *, int); +static void push_processed_type (struct work_stuff *, int); + +static void pop_processed_type (struct work_stuff *); + static void remember_Btype (struct work_stuff *, const char *, int, int); static int register_Btype (struct work_stuff *); @@ -887,6 +910,13 @@ ML_(cplus_demangle) (const char *mangled, int options) if (GNAT_DEMANGLING) return ada_demangle (mangled, options); + if (DLANG_DEMANGLING) + { + ret = dlang_demangle (mangled, options); + if (ret) + return ret; + } + ret = internal_cplus_demangle (work, mangled); squangle_mop_up (work); return (ret); @@ -1241,11 +1271,13 @@ squangle_mop_up (struct work_stuff *work) { free ((char *) work -> btypevec); work->btypevec = NULL; + work->bsize = 0; } if (work -> ktypevec != NULL) { free ((char *) work -> ktypevec); work->ktypevec = NULL; + work->ksize = 0; } } @@ -1296,6 +1328,10 @@ work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from) memcpy (to->btypevec[i], from->btypevec[i], len); } + if (from->proctypevec) + to->proctypevec = + XDUPVEC (int, from->proctypevec, from->proctypevec_size); + if (from->ntmpl_args) to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args); @@ -1324,11 +1360,17 @@ delete_non_B_K_work_stuff (struct work_stuff *work) /* Discard the remembered types, if any. */ forget_types (work); - if (work -> typevec != NULL) + if (work->typevec != NULL) { - free ((char *) work -> typevec); - work -> typevec = NULL; - work -> typevec_size = 0; + free ((char *) work->typevec); + work->typevec = NULL; + work->typevec_size = 0; + } + if (work->proctypevec != NULL) + { + free (work->proctypevec); + work->proctypevec = NULL; + work->proctypevec_size = 0; } if (work->tmpl_argvec) { @@ -2037,7 +2079,8 @@ demangle_template_value_parm (struct work_stuff *work, const char **mangled, } else if (tk == tk_real) success = demangle_real_value (work, mangled, s); - else if (tk == tk_pointer || tk == tk_reference) + else if (tk == tk_pointer || tk == tk_reference + || tk == tk_rvalue_reference) { if (**mangled == 'Q') success = demangle_qualified (work, mangled, s, @@ -2046,7 +2089,8 @@ demangle_template_value_parm (struct work_stuff *work, const char **mangled, else { int symbol_len = consume_count (mangled); - if (symbol_len == -1) + if (symbol_len == -1 + || symbol_len > (long) strlen (*mangled)) return -1; if (symbol_len == 0) string_appendn (s, "0", 1); @@ -3003,6 +3047,11 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp) success = 1; break; } + else if (n == -1) + { + success = 0; + break; + } } else { @@ -3542,6 +3591,8 @@ static int do_type (struct work_stuff *work, const char **mangled, string *result) { int n; + int i; + int is_proctypevec; int done; int success; string decl; @@ -3554,6 +3605,7 @@ do_type (struct work_stuff *work, const char **mangled, string *result) done = 0; success = 1; + is_proctypevec = 0; while (success && !done) { int member; @@ -3578,6 +3630,14 @@ do_type (struct work_stuff *work, const char **mangled, string *result) tk = tk_reference; break; + /* An rvalue reference type */ + case 'O': + (*mangled)++; + string_prepend (&decl, "&&"); + if (tk == tk_none) + tk = tk_rvalue_reference; + break; + /* An array */ case 'A': { @@ -3601,13 +3661,20 @@ do_type (struct work_stuff *work, const char **mangled, string *result) /* A back reference to a previously seen type */ case 'T': (*mangled)++; - if (!get_count (mangled, &n) || n >= work -> ntypes) + if (!get_count (mangled, &n) || n < 0 || n >= work -> ntypes) { success = 0; } else - { - remembered_type = work -> typevec[n]; + for (i = 0; i < work->nproctypes; i++) + if (work -> proctypevec [i] == n) + success = 0; + + if (success) + { + is_proctypevec = 1; + push_processed_type (work, n); + remembered_type = work->typevec[n]; mangled = &remembered_type; } break; @@ -3635,7 +3702,6 @@ do_type (struct work_stuff *work, const char **mangled, string *result) break; case 'M': - case 'O': { type_quals = TYPE_UNQUALIFIED; @@ -3779,7 +3845,7 @@ do_type (struct work_stuff *work, const char **mangled, string *result) /* A back reference to a previously seen squangled type */ case 'B': (*mangled)++; - if (!get_count (mangled, &n) || n >= work -> numb) + if (!get_count (mangled, &n) || n < 0 || n >= work -> numb) success = 0; else string_append (result, work->btypevec[n]); @@ -3830,6 +3896,9 @@ do_type (struct work_stuff *work, const char **mangled, string *result) string_delete (result); string_delete (&decl); + if (is_proctypevec) + pop_processed_type (work); + if (success) /* Assume an integral type, if we're not sure. */ return (int) ((tk == tk_none) ? tk_integral : tk); @@ -4127,7 +4196,8 @@ do_hpacc_template_literal (struct work_stuff *work, const char **mangled, literal_len = consume_count (mangled); - if (literal_len <= 0) + if (literal_len <= 0 + || literal_len > (long) strlen (*mangled)) return 0; /* Literal parameters are names of arrays, functions, etc. and the @@ -4249,6 +4319,41 @@ do_arg (struct work_stuff *work, const char **mangled, string *result) } static void +push_processed_type (struct work_stuff *work, int typevec_index) +{ + if (work->nproctypes >= work->proctypevec_size) + { + if (!work->proctypevec_size) + { + work->proctypevec_size = 4; + work->proctypevec = XNEWVEC (int, work->proctypevec_size); + } + else + { + if (work->proctypevec_size < 16) + /* Double when small. */ + work->proctypevec_size *= 2; + else + { + /* Grow slower when large. */ + if (work->proctypevec_size > (INT_MAX / 3) * 2) + xmalloc_failed (INT_MAX); + work->proctypevec_size = (work->proctypevec_size * 3 / 2); + } + work->proctypevec + = XRESIZEVEC (int, work->proctypevec, work->proctypevec_size); + } + } + work->proctypevec [work->nproctypes++] = typevec_index; +} + +static void +pop_processed_type (struct work_stuff *work) +{ + work->nproctypes--; +} + +static void remember_type (struct work_stuff *work, const char *start, int len) { char *tem; @@ -4265,6 +4370,8 @@ remember_type (struct work_stuff *work, const char *start, int len) } else { + if (work -> typevec_size > INT_MAX / 2) + xmalloc_failed (INT_MAX); work -> typevec_size *= 2; work -> typevec = XRESIZEVEC (char *, work->typevec, work->typevec_size); @@ -4292,6 +4399,8 @@ remember_Ktype (struct work_stuff *work, const char *start, int len) } else { + if (work -> ksize > INT_MAX / 2) + xmalloc_failed (INT_MAX); work -> ksize *= 2; work -> ktypevec = XRESIZEVEC (char *, work->ktypevec, work->ksize); @@ -4321,6 +4430,8 @@ register_Btype (struct work_stuff *work) } else { + if (work -> bsize > INT_MAX / 2) + xmalloc_failed (INT_MAX); work -> bsize *= 2; work -> btypevec = XRESIZEVEC (char *, work->btypevec, work->bsize); @@ -4506,10 +4617,13 @@ demangle_args (struct work_stuff *work, const char **mangled, { string_append (declp, ", "); } + push_processed_type (work, t); if (!do_arg (work, &tem, &arg)) { + pop_processed_type (work); return (0); } + pop_processed_type (work); if (PRINT_ARG_TYPES) { string_appends (declp, &arg); @@ -4791,6 +4905,8 @@ string_need (string *s, int n) else if (s->e - s->p < n) { tem = s->p - s->b; + if (n > INT_MAX / 2 - tem) + xmalloc_failed (INT_MAX); n += tem; n *= 2; s->b = XRESIZEVEC (char, s->b, n); diff --git a/coregrind/m_demangle/d-demangle.c b/coregrind/m_demangle/d-demangle.c new file mode 100644 index 0000000..129999c --- /dev/null +++ b/coregrind/m_demangle/d-demangle.c @@ -0,0 +1,1618 @@ +/* Demangler for the D programming language + Copyright 2014, 2015, 2016 Free Software Foundation, Inc. + Written by Iain Buclaw (ibuclaw@gdcproject.org) + +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 . */ + +/* This file exports one function; dlang_demangle. + + This file imports strtol for decoding mangled literals. */ + +#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_STDLIB_H +#include +#else +extern long strtol (const char *nptr, char **endptr, int base); +#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" + +/* A mini string-handling package */ + +typedef struct string /* Beware: these aren't required to be */ +{ /* '\0' terminated. */ + char *b; /* pointer to start of string */ + char *p; /* pointer after last character */ + char *e; /* pointer after end of allocated space */ +} string; + +static void +string_need (string *s, int n) +{ + int tem; + + if (s->b == NULL) + { + if (n < 32) + { + n = 32; + } + s->p = s->b = XNEWVEC (char, n); + s->e = s->b + n; + } + else if (s->e - s->p < n) + { + tem = s->p - s->b; + n += tem; + n *= 2; + s->b = XRESIZEVEC (char, s->b, n); + s->p = s->b + tem; + s->e = s->b + n; + } +} + +static void +string_delete (string *s) +{ + if (s->b != NULL) + { + XDELETEVEC (s->b); + s->b = s->e = s->p = NULL; + } +} + +static void +string_init (string *s) +{ + s->b = s->p = s->e = NULL; +} + +static int +string_length (string *s) +{ + if (s->p == s->b) + { + return 0; + } + return s->p - s->b; +} + +static void +string_setlength (string *s, int n) +{ + if (n - string_length (s) < 0) + { + s->p = s->b + n; + } +} + +static void +string_append (string *p, const char *s) +{ + int n = strlen (s); + string_need (p, n); + memcpy (p->p, s, n); + p->p += n; +} + +static void +string_appendn (string *p, const char *s, int n) +{ + if (n != 0) + { + string_need (p, n); + memcpy (p->p, s, n); + p->p += n; + } +} + +static void +string_prependn (string *p, const char *s, int n) +{ + char *q; + + if (n != 0) + { + string_need (p, n); + for (q = p->p - 1; q >= p->b; q--) + { + q[n] = q[0]; + } + memcpy (p->b, s, n); + p->p += n; + } +} + +static void +string_prepend (string *p, const char *s) +{ + if (s != NULL && *s != '\0') + { + string_prependn (p, s, strlen (s)); + } +} + +/* What kinds of symbol we could be parsing. */ +enum dlang_symbol_kinds +{ + /* Top-level symbol, needs it's type checked. */ + dlang_top_level, + /* Function symbol, needs it's type checked. */ + dlang_function, + /* Strongly typed name, such as for classes, structs and enums. */ + dlang_type_name, + /* Template identifier. */ + dlang_template_ident, + /* Template symbol parameter. */ + dlang_template_param +}; + +/* Prototypes for forward referenced functions */ +static const char *dlang_function_args (string *, const char *); + +static const char *dlang_type (string *, const char *); + +static const char *dlang_value (string *, const char *, const char *, char); + +static const char *dlang_parse_symbol (string *, const char *, + enum dlang_symbol_kinds); + +static const char *dlang_parse_tuple (string *, const char *); + +static const char *dlang_parse_template (string *, const char *, long); + + +/* Demangle the calling convention from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_call_convention (string *decl, const char *mangled) +{ + if (mangled == NULL || *mangled == '\0') + return NULL; + + switch (*mangled) + { + case 'F': /* (D) */ + mangled++; + break; + case 'U': /* (C) */ + mangled++; + string_append (decl, "extern(C) "); + break; + case 'W': /* (Windows) */ + mangled++; + string_append (decl, "extern(Windows) "); + break; + case 'V': /* (Pascal) */ + mangled++; + string_append (decl, "extern(Pascal) "); + break; + case 'R': /* (C++) */ + mangled++; + string_append (decl, "extern(C++) "); + break; + case 'Y': /* (Objective-C) */ + mangled++; + string_append (decl, "extern(Objective-C) "); + break; + default: + return NULL; + } + + return mangled; +} + +/* Extract the type modifiers from MANGLED and append them to DECL. + Returns the remaining signature on success or NULL on failure. */ +static const char * +dlang_type_modifiers (string *decl, const char *mangled) +{ + if (mangled == NULL || *mangled == '\0') + return NULL; + + switch (*mangled) + { + case 'x': /* const */ + mangled++; + string_append (decl, " const"); + return mangled; + case 'y': /* immutable */ + mangled++; + string_append (decl, " immutable"); + return mangled; + case 'O': /* shared */ + mangled++; + string_append (decl, " shared"); + return dlang_type_modifiers (decl, mangled); + case 'N': + mangled++; + if (*mangled == 'g') /* wild */ + { + mangled++; + string_append (decl, " inout"); + return dlang_type_modifiers (decl, mangled); + } + else + return NULL; + + default: + return mangled; + } +} + +/* Demangle the D function attributes from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_attributes (string *decl, const char *mangled) +{ + if (mangled == NULL || *mangled == '\0') + return NULL; + + while (*mangled == 'N') + { + mangled++; + switch (*mangled) + { + case 'a': /* pure */ + mangled++; + string_append (decl, "pure "); + continue; + case 'b': /* nothrow */ + mangled++; + string_append (decl, "nothrow "); + continue; + case 'c': /* ref */ + mangled++; + string_append (decl, "ref "); + continue; + case 'd': /* @property */ + mangled++; + string_append (decl, "@property "); + continue; + case 'e': /* @trusted */ + mangled++; + string_append (decl, "@trusted "); + continue; + case 'f': /* @safe */ + mangled++; + string_append (decl, "@safe "); + continue; + case 'g': + case 'h': + case 'k': + /* inout parameter is represented as 'Ng'. + vector parameter is represented as 'Nh'. + return paramenter is represented as 'Nk'. + If we see this, then we know we're really in the + parameter list. Rewind and break. */ + mangled--; + break; + case 'i': /* @nogc */ + mangled++; + string_append (decl, "@nogc "); + continue; + case 'j': /* return */ + mangled++; + string_append (decl, "return "); + continue; + + default: /* unknown attribute */ + return NULL; + } + break; + } + + return mangled; +} + +/* Demangle the function type from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_function_type (string *decl, const char *mangled) +{ + string attr, args, type; + size_t szattr, szargs, sztype; + + if (mangled == NULL || *mangled == '\0') + return NULL; + + /* The order of the mangled string is: + CallConvention FuncAttrs Arguments ArgClose Type + + The demangled string is re-ordered as: + CallConvention Type Arguments FuncAttrs + */ + string_init (&attr); + string_init (&args); + string_init (&type); + + /* Function call convention. */ + mangled = dlang_call_convention (decl, mangled); + + /* Function attributes. */ + mangled = dlang_attributes (&attr, mangled); + szattr = string_length (&attr); + + /* Function arguments. */ + mangled = dlang_function_args (&args, mangled); + szargs = string_length (&args); + + /* Function return type. */ + mangled = dlang_type (&type, mangled); + sztype = string_length (&type); + + /* Append to decl in order. */ + string_appendn (decl, type.b, sztype); + string_append (decl, "("); + string_appendn (decl, args.b, szargs); + string_append (decl, ") "); + string_appendn (decl, attr.b, szattr); + + string_delete (&attr); + string_delete (&args); + string_delete (&type); + return mangled; +} + +/* Demangle the argument list from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_function_args (string *decl, const char *mangled) +{ + size_t n = 0; + + while (mangled && *mangled != '\0') + { + switch (*mangled) + { + case 'X': /* (variadic T t...) style. */ + mangled++; + string_append (decl, "..."); + return mangled; + case 'Y': /* (variadic T t, ...) style. */ + mangled++; + if (n != 0) + string_append (decl, ", "); + string_append (decl, "..."); + return mangled; + case 'Z': /* Normal function. */ + mangled++; + return mangled; + } + + if (n++) + string_append (decl, ", "); + + if (*mangled == 'M') /* scope(T) */ + { + mangled++; + string_append (decl, "scope "); + } + + if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */ + { + mangled += 2; + string_append (decl, "return "); + } + + switch (*mangled) + { + case 'J': /* out(T) */ + mangled++; + string_append (decl, "out "); + break; + case 'K': /* ref(T) */ + mangled++; + string_append (decl, "ref "); + break; + case 'L': /* lazy(T) */ + mangled++; + string_append (decl, "lazy "); + break; + } + mangled = dlang_type (decl, mangled); + } + + return mangled; +} + +/* Demangle the type from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_type (string *decl, const char *mangled) +{ + if (mangled == NULL || *mangled == '\0') + return NULL; + + switch (*mangled) + { + case 'O': /* shared(T) */ + mangled++; + string_append (decl, "shared("); + mangled = dlang_type (decl, mangled); + string_append (decl, ")"); + return mangled; + case 'x': /* const(T) */ + mangled++; + string_append (decl, "const("); + mangled = dlang_type (decl, mangled); + string_append (decl, ")"); + return mangled; + case 'y': /* immutable(T) */ + mangled++; + string_append (decl, "immutable("); + mangled = dlang_type (decl, mangled); + string_append (decl, ")"); + return mangled; + case 'N': + mangled++; + if (*mangled == 'g') /* wild(T) */ + { + mangled++; + string_append (decl, "inout("); + mangled = dlang_type (decl, mangled); + string_append (decl, ")"); + return mangled; + } + else if (*mangled == 'h') /* vector(T) */ + { + mangled++; + string_append (decl, "__vector("); + mangled = dlang_type (decl, mangled); + string_append (decl, ")"); + return mangled; + } + else + return NULL; + case 'A': /* dynamic array (T[]) */ + mangled++; + mangled = dlang_type (decl, mangled); + string_append (decl, "[]"); + return mangled; + case 'G': /* static array (T[N]) */ + { + const char *numptr; + size_t num = 0; + mangled++; + + numptr = mangled; + while (ISDIGIT (*mangled)) + { + num++; + mangled++; + } + mangled = dlang_type (decl, mangled); + string_append (decl, "["); + string_appendn (decl, numptr, num); + string_append (decl, "]"); + return mangled; + } + case 'H': /* associative array (T[T]) */ + { + string type; + size_t sztype; + mangled++; + + string_init (&type); + mangled = dlang_type (&type, mangled); + sztype = string_length (&type); + + mangled = dlang_type (decl, mangled); + string_append (decl, "["); + string_appendn (decl, type.b, sztype); + string_append (decl, "]"); + + string_delete (&type); + return mangled; + } + case 'P': /* pointer (T*) */ + mangled++; + /* Function pointer types don't include the trailing asterisk. */ + switch (*mangled) + { + case 'F': case 'U': case 'W': + case 'V': case 'R': case 'Y': + mangled = dlang_function_type (decl, mangled); + string_append (decl, "function"); + return mangled; + } + mangled = dlang_type (decl, mangled); + string_append (decl, "*"); + return mangled; + case 'I': /* ident T */ + case 'C': /* class T */ + case 'S': /* struct T */ + case 'E': /* enum T */ + case 'T': /* typedef T */ + mangled++; + return dlang_parse_symbol (decl, mangled, dlang_type_name); + case 'D': /* delegate T */ + { + string mods; + size_t szmods; + mangled++; + + string_init (&mods); + mangled = dlang_type_modifiers (&mods, mangled); + szmods = string_length (&mods); + + mangled = dlang_function_type (decl, mangled); + string_append (decl, "delegate"); + string_appendn (decl, mods.b, szmods); + + string_delete (&mods); + return mangled; + } + case 'B': /* tuple T */ + mangled++; + return dlang_parse_tuple (decl, mangled); + + /* Basic types */ + case 'n': + mangled++; + string_append (decl, "none"); + return mangled; + case 'v': + mangled++; + string_append (decl, "void"); + return mangled; + case 'g': + mangled++; + string_append (decl, "byte"); + return mangled; + case 'h': + mangled++; + string_append (decl, "ubyte"); + return mangled; + case 's': + mangled++; + string_append (decl, "short"); + return mangled; + case 't': + mangled++; + string_append (decl, "ushort"); + return mangled; + case 'i': + mangled++; + string_append (decl, "int"); + return mangled; + case 'k': + mangled++; + string_append (decl, "uint"); + return mangled; + case 'l': + mangled++; + string_append (decl, "long"); + return mangled; + case 'm': + mangled++; + string_append (decl, "ulong"); + return mangled; + case 'f': + mangled++; + string_append (decl, "float"); + return mangled; + case 'd': + mangled++; + string_append (decl, "double"); + return mangled; + case 'e': + mangled++; + string_append (decl, "real"); + return mangled; + + /* Imaginary and Complex types */ + case 'o': + mangled++; + string_append (decl, "ifloat"); + return mangled; + case 'p': + mangled++; + string_append (decl, "idouble"); + return mangled; + case 'j': + mangled++; + string_append (decl, "ireal"); + return mangled; + case 'q': + mangled++; + string_append (decl, "cfloat"); + return mangled; + case 'r': + mangled++; + string_append (decl, "cdouble"); + return mangled; + case 'c': + mangled++; + string_append (decl, "creal"); + return mangled; + + /* Other types */ + case 'b': + mangled++; + string_append (decl, "bool"); + return mangled; + case 'a': + mangled++; + string_append (decl, "char"); + return mangled; + case 'u': + mangled++; + string_append (decl, "wchar"); + return mangled; + case 'w': + mangled++; + string_append (decl, "dchar"); + return mangled; + case 'z': + mangled++; + switch (*mangled) + { + case 'i': + mangled++; + string_append (decl, "cent"); + return mangled; + case 'k': + mangled++; + string_append (decl, "ucent"); + return mangled; + } + return NULL; + + default: /* unhandled */ + return NULL; + } +} + +/* Extract the identifier from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_identifier (string *decl, const char *mangled, + enum dlang_symbol_kinds kind) +{ + char *endptr; + long len; + + if (mangled == NULL || *mangled == '\0') + return NULL; + + len = strtol (mangled, &endptr, 10); + + if (endptr == NULL || len <= 0) + return NULL; + + /* In template parameter symbols, the first character of the mangled + name can be a digit. This causes ambiguity issues because the + digits of the two numbers are adjacent. */ + if (kind == dlang_template_param) + { + long psize = len; + char *pend; + int saved = string_length (decl); + + /* Work backwards until a match is found. */ + for (pend = endptr; endptr != NULL; pend--) + { + mangled = pend; + + /* Reached the beginning of the pointer to the name length, + try parsing the entire symbol. */ + if (psize == 0) + { + psize = len; + pend = endptr; + endptr = NULL; + } + + /* Check whether template parameter is a function with a valid + return type or an untyped identifier. */ + if (ISDIGIT (*mangled)) + mangled = dlang_parse_symbol (decl, mangled, dlang_template_ident); + else if (strncmp (mangled, "_D", 2) == 0) + { + mangled += 2; + mangled = dlang_parse_symbol (decl, mangled, dlang_function); + } + + /* Check for name length mismatch. */ + if (mangled && (mangled - pend) == psize) + return mangled; + + psize /= 10; + string_setlength (decl, saved); + } + + /* No match on any combinations. */ + return NULL; + } + else + { + if (strlen (endptr) < (size_t) len) + return NULL; + + mangled = endptr; + + /* May be a template instance. */ + if (len >= 5 && strncmp (mangled, "__T", 3) == 0) + { + /* Template symbol. */ + if (ISDIGIT (mangled[3]) && mangled[3] != '0') + return dlang_parse_template (decl, mangled, len); + + return NULL; + } + + switch (len) + { + case 6: + if (strncmp (mangled, "__ctor", len) == 0) + { + /* Constructor symbol for a class/struct. */ + string_append (decl, "this"); + mangled += len; + return mangled; + } + else if (strncmp (mangled, "__dtor", len) == 0) + { + /* Destructor symbol for a class/struct. */ + string_append (decl, "~this"); + mangled += len; + return mangled; + } + else if (strncmp (mangled, "__initZ", len+1) == 0) + { + /* The static initialiser for a given symbol. */ + string_append (decl, "init$"); + mangled += len; + return mangled; + } + else if (strncmp (mangled, "__vtblZ", len+1) == 0) + { + /* The vtable symbol for a given class. */ + string_prepend (decl, "vtable for "); + string_setlength (decl, string_length (decl) - 1); + mangled += len; + return mangled; + } + break; + + case 7: + if (strncmp (mangled, "__ClassZ", len+1) == 0) + { + /* The classinfo symbol for a given class. */ + string_prepend (decl, "ClassInfo for "); + string_setlength (decl, string_length (decl) - 1); + mangled += len; + return mangled; + } + break; + + case 10: + if (strncmp (mangled, "__postblitMFZ", len+3) == 0) + { + /* Postblit symbol for a struct. */ + string_append (decl, "this(this)"); + mangled += len + 3; + return mangled; + } + break; + + case 11: + if (strncmp (mangled, "__InterfaceZ", len+1) == 0) + { + /* The interface symbol for a given class. */ + string_prepend (decl, "Interface for "); + string_setlength (decl, string_length (decl) - 1); + mangled += len; + return mangled; + } + break; + + case 12: + if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0) + { + /* The ModuleInfo symbol for a given module. */ + string_prepend (decl, "ModuleInfo for "); + string_setlength (decl, string_length (decl) - 1); + mangled += len; + return mangled; + } + break; + } + + string_appendn (decl, mangled, len); + mangled += len; + } + + return mangled; +} + +/* Extract the integer value from MANGLED and append it to DECL, + where TYPE is the type it should be represented as. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_parse_integer (string *decl, const char *mangled, char type) +{ + if (type == 'a' || type == 'u' || type == 'w') + { + /* Parse character value. */ + char value[10]; + int pos = 10; + int width = 0; + char *endptr; + long val = strtol (mangled, &endptr, 10); + + if (endptr == NULL || val < 0) + return NULL; + + string_append (decl, "'"); + + if (type == 'a' && val >= 0x20 && val < 0x7F) + { + /* Represent as a character literal. */ + char c = (char) val; + string_appendn (decl, &c, 1); + } + else + { + /* Represent as a hexadecimal value. */ + switch (type) + { + case 'a': /* char */ + string_append (decl, "\\x"); + width = 2; + break; + case 'u': /* wchar */ + string_append (decl, "\\u"); + width = 4; + break; + case 'w': /* dchar */ + string_append (decl, "\\U"); + width = 8; + break; + } + + while (val > 0) + { + int digit = val % 16; + + if (digit < 10) + value[--pos] = (char)(digit + '0'); + else + value[--pos] = (char)((digit - 10) + 'a'); + + val /= 16; + width--; + } + + for (; width > 0; width--) + value[--pos] = '0'; + + string_appendn (decl, &(value[pos]), 10 - pos); + } + string_append (decl, "'"); + mangled = endptr; + } + else if (type == 'b') + { + /* Parse boolean value. */ + char *endptr; + long val = strtol (mangled, &endptr, 10); + + if (endptr == NULL || val < 0) + return NULL; + + string_append (decl, val ? "true" : "false"); + mangled = endptr; + } + else + { + /* Parse integer value. */ + const char *numptr = mangled; + size_t num = 0; + + while (ISDIGIT (*mangled)) + { + num++; + mangled++; + } + string_appendn (decl, numptr, num); + + /* Append suffix. */ + switch (type) + { + case 'h': /* ubyte */ + case 't': /* ushort */ + case 'k': /* uint */ + string_append (decl, "u"); + break; + case 'l': /* long */ + string_append (decl, "L"); + break; + case 'm': /* ulong */ + string_append (decl, "uL"); + break; + } + } + + return mangled; +} + +/* Extract the floating-point value from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_parse_real (string *decl, const char *mangled) +{ + char buffer[64]; + int len = 0; + + /* Handle NAN and +-INF. */ + if (strncmp (mangled, "NAN", 3) == 0) + { + string_append (decl, "NaN"); + mangled += 3; + return mangled; + } + else if (strncmp (mangled, "INF", 3) == 0) + { + string_append (decl, "Inf"); + mangled += 3; + return mangled; + } + else if (strncmp (mangled, "NINF", 4) == 0) + { + string_append (decl, "-Inf"); + mangled += 4; + return mangled; + } + + /* Hexadecimal prefix and leading bit. */ + if (*mangled == 'N') + { + buffer[len++] = '-'; + mangled++; + } + + if (!ISXDIGIT (*mangled)) + return NULL; + + buffer[len++] = '0'; + buffer[len++] = 'x'; + buffer[len++] = *mangled; + buffer[len++] = '.'; + mangled++; + + /* Significand. */ + while (ISXDIGIT (*mangled)) + { + buffer[len++] = *mangled; + mangled++; + } + + /* Exponent. */ + if (*mangled != 'P') + return NULL; + + buffer[len++] = 'p'; + mangled++; + + if (*mangled == 'N') + { + buffer[len++] = '-'; + mangled++; + } + + while (ISDIGIT (*mangled)) + { + buffer[len++] = *mangled; + mangled++; + } + + /* Write out the demangled hexadecimal, rather than trying to + convert the buffer into a floating-point value. */ + buffer[len] = '\0'; + len = strlen (buffer); + string_appendn (decl, buffer, len); + return mangled; +} + +/* Convert VAL from an ascii hexdigit to value. */ +static char +ascii2hex (char val) +{ + if (val >= 'a' && val <= 'f') + return (val - 'a' + 10); + + if (val >= 'A' && val <= 'F') + return (val - 'A' + 10); + + if (val >= '0' && val <= '9') + return (val - '0'); + + return 0; +} + +/* Extract the string value from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_parse_string (string *decl, const char *mangled) +{ + char type = *mangled; + char *endptr; + long len; + + mangled++; + len = strtol (mangled, &endptr, 10); + + if (endptr == NULL || len < 0) + return NULL; + + mangled = endptr; + if (*mangled != '_') + return NULL; + + mangled++; + string_append (decl, "\""); + while (len--) + { + if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1])) + { + char a = ascii2hex (mangled[0]); + char b = ascii2hex (mangled[1]); + char val = (a << 4) | b; + + /* Sanitize white and non-printable characters. */ + switch (val) + { + case ' ': + string_append (decl, " "); + break; + case '\t': + string_append (decl, "\\t"); + break; + case '\n': + string_append (decl, "\\n"); + break; + case '\r': + string_append (decl, "\\r"); + break; + case '\f': + string_append (decl, "\\f"); + break; + case '\v': + string_append (decl, "\\v"); + break; + + default: + if (ISPRINT (val)) + string_appendn (decl, &val, 1); + else + { + string_append (decl, "\\x"); + string_appendn (decl, mangled, 2); + } + } + } + else + return NULL; + + mangled += 2; + } + string_append (decl, "\""); + + if (type != 'a') + string_appendn (decl, &type, 1); + + return mangled; +} + +/* Extract the static array value from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_parse_arrayliteral (string *decl, const char *mangled) +{ + char *endptr; + long elements = strtol (mangled, &endptr, 10); + + if (endptr == NULL || elements < 0) + return NULL; + + mangled = endptr; + string_append (decl, "["); + while (elements--) + { + mangled = dlang_value (decl, mangled, NULL, '\0'); + if (elements != 0) + string_append (decl, ", "); + } + + string_append (decl, "]"); + return mangled; +} + +/* Extract the associative array value from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_parse_assocarray (string *decl, const char *mangled) +{ + char *endptr; + long elements = strtol (mangled, &endptr, 10); + + if (endptr == NULL || elements < 0) + return NULL; + + mangled = endptr; + string_append (decl, "["); + while (elements--) + { + mangled = dlang_value (decl, mangled, NULL, '\0'); + string_append (decl, ":"); + mangled = dlang_value (decl, mangled, NULL, '\0'); + + if (elements != 0) + string_append (decl, ", "); + } + + string_append (decl, "]"); + return mangled; +} + +/* Extract the struct literal value for NAME from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_parse_structlit (string *decl, const char *mangled, const char *name) +{ + char *endptr; + long args = strtol (mangled, &endptr, 10); + + if (endptr == NULL || args < 0) + return NULL; + + mangled = endptr; + if (name != NULL) + string_append (decl, name); + + string_append (decl, "("); + while (args--) + { + mangled = dlang_value (decl, mangled, NULL, '\0'); + if (args != 0) + string_append (decl, ", "); + } + + string_append (decl, ")"); + return mangled; +} + +/* Extract the value from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_value (string *decl, const char *mangled, const char *name, char type) +{ + if (mangled == NULL || *mangled == '\0') + return NULL; + + switch (*mangled) + { + /* Null value. */ + case 'n': + mangled++; + string_append (decl, "null"); + break; + + /* Integral values. */ + case 'N': + mangled++; + string_append (decl, "-"); + mangled = dlang_parse_integer (decl, mangled, type); + break; + + case 'i': + mangled++; + if (*mangled < '0' || *mangled > '9') + return NULL; + /* Fall through */ + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + mangled = dlang_parse_integer (decl, mangled, type); + break; + + /* Real value. */ + case 'e': + mangled++; + mangled = dlang_parse_real (decl, mangled); + break; + + /* Complex value. */ + case 'c': + mangled++; + mangled = dlang_parse_real (decl, mangled); + string_append (decl, "+"); + if (mangled == NULL || *mangled != 'c') + return NULL; + mangled++; + mangled = dlang_parse_real (decl, mangled); + string_append (decl, "i"); + break; + + /* String values. */ + case 'a': /* UTF8 */ + case 'w': /* UTF16 */ + case 'd': /* UTF32 */ + mangled = dlang_parse_string (decl, mangled); + break; + + /* Array values. */ + case 'A': + mangled++; + if (type == 'H') + mangled = dlang_parse_assocarray (decl, mangled); + else + mangled = dlang_parse_arrayliteral (decl, mangled); + break; + + /* Struct values. */ + case 'S': + mangled++; + mangled = dlang_parse_structlit (decl, mangled, name); + break; + + default: + return NULL; + } + + return mangled; +} + +/* Extract the type modifiers from MANGLED and return the string + length that it consumes in MANGLED on success or 0 on failure. */ +static int +dlang_type_modifier_p (const char *mangled) +{ + int i; + + switch (*mangled) + { + case 'x': case 'y': + return 1; + + case 'O': + mangled++; + i = dlang_type_modifier_p (mangled); + return i + 1; + + case 'N': + mangled++; + if (*mangled == 'g') + { + mangled++; + i = dlang_type_modifier_p (mangled); + return i + 2; + } + } + + return 0; +} + +/* Extract the function calling convention from MANGLED and + return 1 on success or 0 on failure. */ +static int +dlang_call_convention_p (const char *mangled) +{ + /* Prefix for functions needing 'this' */ + if (*mangled == 'M') + { + mangled++; + /* Also skip over any type modifiers. */ + mangled += dlang_type_modifier_p (mangled); + } + + switch (*mangled) + { + case 'F': case 'U': case 'V': + case 'W': case 'R': case 'Y': + return 1; + + default: + return 0; + } +} + +/* Extract and demangle the symbol in MANGLED and append it to DECL. + Returns the remaining signature on success or NULL on failure. */ +static const char * +dlang_parse_symbol (string *decl, const char *mangled, + enum dlang_symbol_kinds kind) +{ + int saved; + size_t n = 0; + do + { + if (n++) + string_append (decl, "."); + + mangled = dlang_identifier (decl, mangled, kind); + + if (mangled && dlang_call_convention_p (mangled)) + { + string mods; + const char *start = NULL; + int checkpoint = 0; + + /* Skip over 'this' parameter. */ + if (*mangled == 'M') + mangled++; + + /* We have reached here because we expect an extern(Pascal) function. + However this is so rare, that it is more likely a template value + parameter. Since this can't be assumed, first attempt parsing + the symbol as a function, and then back out on failure. */ + if (*mangled == 'V') + { + start = mangled; + checkpoint = string_length (decl); + } + + /* Save the type modifiers for appending at the end. */ + string_init (&mods); + mangled = dlang_type_modifiers (&mods, mangled); + + /* Skip over calling convention and attributes in qualified name. */ + saved = string_length (decl); + mangled = dlang_call_convention (decl, mangled); + mangled = dlang_attributes (decl, mangled); + string_setlength (decl, saved); + + string_append (decl, "("); + mangled = dlang_function_args (decl, mangled); + string_append (decl, ")"); + + /* Add any const/immutable/shared modifier. */ + string_appendn (decl, mods.b, string_length (&mods)); + string_delete (&mods); + + if (mangled == NULL && checkpoint != 0) + { + mangled = start; + string_setlength (decl, checkpoint); + } + } + } + while (mangled && ISDIGIT (*mangled)); + + /* Only top-level symbols or function template parameters have + a type that needs checking. */ + if (kind == dlang_top_level || kind == dlang_function) + { + /* Artificial symbols end with 'Z' and have no type. */ + if (mangled && *mangled == 'Z') + mangled++; + else + { + saved = string_length (decl); + mangled = dlang_type (decl, mangled); + string_setlength (decl, saved); + } + + /* Check that the entire symbol was successfully demangled. */ + if (kind == dlang_top_level) + { + if (mangled == NULL || *mangled != '\0') + return NULL; + } + } + + return mangled; +} + +/* Demangle the tuple from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_parse_tuple (string *decl, const char *mangled) +{ + char *endptr; + long elements = strtol (mangled, &endptr, 10); + + if (endptr == NULL || elements < 0) + return NULL; + + mangled = endptr; + string_append (decl, "Tuple!("); + + while (elements--) + { + mangled = dlang_type (decl, mangled); + if (elements != 0) + string_append (decl, ", "); + } + + string_append (decl, ")"); + return mangled; +} + +/* Demangle the argument list from MANGLED and append it to DECL. + Return the remaining string on success or NULL on failure. */ +static const char * +dlang_template_args (string *decl, const char *mangled) +{ + size_t n = 0; + + while (mangled && *mangled != '\0') + { + switch (*mangled) + { + case 'Z': /* End of parameter list. */ + mangled++; + return mangled; + } + + if (n++) + string_append (decl, ", "); + + /* Skip over specialised template prefix. */ + if (*mangled == 'H') + mangled++; + + switch (*mangled) + { + case 'S': /* Symbol parameter. */ + mangled++; + mangled = dlang_parse_symbol (decl, mangled, dlang_template_param); + break; + case 'T': /* Type parameter. */ + mangled++; + mangled = dlang_type (decl, mangled); + break; + case 'V': /* Value parameter. */ + { + string name; + char type; + + /* Peek at the type. */ + mangled++; + type = *mangled; + + /* In the few instances where the type is actually desired in + the output, it should precede the value from dlang_value. */ + string_init (&name); + mangled = dlang_type (&name, mangled); + string_need (&name, 1); + *(name.p) = '\0'; + + mangled = dlang_value (decl, mangled, name.b, type); + string_delete (&name); + break; + } + + default: + return NULL; + } + } + + return mangled; +} + +/* Extract and demangle the template symbol in MANGLED, expected to + be made up of LEN characters, and append it to DECL. + Returns the remaining signature on success or NULL on failure. */ +static const char * +dlang_parse_template (string *decl, const char *mangled, long len) +{ + const char *start = mangled; + + /* Template instance names have the types and values of its parameters + encoded into it. + + TemplateInstanceName: + Number __T LName TemplateArgs Z + ^ + The start pointer should be at the above location, and LEN should be + the value of the decoded number. + */ + if (strncmp (mangled, "__T", 3) != 0) + return NULL; + + mangled += 3; + + /* Template identifier. */ + mangled = dlang_identifier (decl, mangled, dlang_template_ident); + + /* Template arguments. */ + string_append (decl, "!("); + mangled = dlang_template_args (decl, mangled); + string_append (decl, ")"); + + /* Check for template name length mismatch. */ + if (mangled && (mangled - start) != len) + return NULL; + + return mangled; +} + +/* Extract and demangle the symbol in MANGLED. Returns the demangled + signature on success or NULL on failure. */ + +char * +dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) +{ + string decl; + char *demangled = NULL; + + if (mangled == NULL || *mangled == '\0') + return NULL; + + if (strncmp (mangled, "_D", 2) != 0) + return NULL; + + string_init (&decl); + + if (strcmp (mangled, "_Dmain") == 0) + { + string_append (&decl, "D main"); + } + else + { + mangled += 2; + + if (dlang_parse_symbol (&decl, mangled, dlang_top_level) == NULL) + string_delete (&decl); + } + + if (string_length (&decl) > 0) + { + string_need (&decl, 1); + *(decl.p) = '\0'; + demangled = decl.b; + } + + return demangled; +} + diff --git a/coregrind/m_demangle/demangle.h b/coregrind/m_demangle/demangle.h index 129d856..b3439d9 100644 --- a/coregrind/m_demangle/demangle.h +++ b/coregrind/m_demangle/demangle.h @@ -1,7 +1,6 @@ /* Defs for interface to demanglers. - Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, - 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. - + Copyright (C) 1992-2015 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 as published by the Free Software Foundation; either version 2, or @@ -65,9 +64,10 @@ extern "C" { #define DMGL_EDG (1 << 13) #define DMGL_GNU_V3 (1 << 14) #define DMGL_GNAT (1 << 15) +#define DMGL_DLANG (1 << 16) /* 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) +#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) /* Enumeration of possible demangling styles. @@ -89,7 +89,8 @@ extern enum demangling_styles edg_demangling = DMGL_EDG, gnu_v3_demangling = DMGL_GNU_V3, java_demangling = DMGL_JAVA, - gnat_demangling = DMGL_GNAT + gnat_demangling = DMGL_GNAT, + dlang_demangling = DMGL_DLANG } current_demangling_style; /* Define string names for the various demangling styles. */ @@ -104,6 +105,7 @@ extern enum demangling_styles #define GNU_V3_DEMANGLING_STYLE_STRING "gnu-v3" #define JAVA_DEMANGLING_STYLE_STRING "java" #define GNAT_DEMANGLING_STYLE_STRING "gnat" +#define DLANG_DEMANGLING_STYLE_STRING "dlang" /* Some macros to test what demangling style is active. */ @@ -117,6 +119,7 @@ extern enum demangling_styles #define GNU_V3_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_V3) #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) /* Provide information about the available demangle styles. This code is pulled from gdb into libiberty because it is useful to binutils also. */ @@ -142,10 +145,10 @@ cplus_mangle_opname (const char *opname, int options); extern void set_cplus_marker_for_demangling (int ch); -extern enum demangling_styles +extern enum demangling_styles cplus_demangle_set_style (enum demangling_styles style); -extern enum demangling_styles +extern enum demangling_styles cplus_demangle_name_to_style (const char *name); /* Callback typedef for allocation-less demangler interfaces. */ @@ -171,6 +174,9 @@ java_demangle_v3 (const char *mangled); char * ada_demangle (const char *mangled, int options); +extern char * +dlang_demangle (const char *mangled, int options); + enum gnu_v3_ctor_kinds { gnu_v3_complete_object_ctor = 1, gnu_v3_base_object_ctor, @@ -375,6 +381,10 @@ enum demangle_component_type /* A typecast, represented as a unary operator. The one subtree is the type to which the argument should be cast. */ DEMANGLE_COMPONENT_CAST, + /* A conversion operator, represented as a unary operator. The one + subtree is the type to which the argument should be converted + to. */ + DEMANGLE_COMPONENT_CONVERSION, /* A nullary expression. The left subtree is the operator. */ DEMANGLE_COMPONENT_NULLARY, /* A unary expression. The left subtree is the operator, and the @@ -438,6 +448,8 @@ enum demangle_component_type DEMANGLE_COMPONENT_PACK_EXPANSION, /* A name with an ABI tag. */ DEMANGLE_COMPONENT_TAGGED_NAME, + /* A transaction-safe function type. */ + DEMANGLE_COMPONENT_TRANSACTION_SAFE, /* A cloned function. */ DEMANGLE_COMPONENT_CLONE }; diff --git a/coregrind/m_demangle/dyn-string.h b/coregrind/m_demangle/dyn-string.h index 2b14727..7c3684b 100644 --- a/coregrind/m_demangle/dyn-string.h +++ b/coregrind/m_demangle/dyn-string.h @@ -1,6 +1,5 @@ /* An abstract string datatype. - Copyright (C) 1998, 1999, 2000, 2002, 2004, 2005, 2009 - Free Software Foundation, Inc. + Copyright (C) 1998-2015 Free Software Foundation, Inc. Contributed by Mark Mitchell (mark@markmitchell.com). This file is part of GCC. diff --git a/coregrind/m_demangle/safe-ctype.h b/coregrind/m_demangle/safe-ctype.h index 3b16827..1f4465b 100644 --- a/coregrind/m_demangle/safe-ctype.h +++ b/coregrind/m_demangle/safe-ctype.h @@ -1,6 +1,6 @@ /* replacement macros. - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000-2015 Free Software Foundation, Inc. Contributed by Zack Weinberg . This file is part of the libiberty library. diff --git a/coregrind/m_demangle/vg_libciface.h b/coregrind/m_demangle/vg_libciface.h index 8832500..dd57fca 100644 --- a/coregrind/m_demangle/vg_libciface.h +++ b/coregrind/m_demangle/vg_libciface.h @@ -64,16 +64,30 @@ #define strpbrk(_ss,_aa) VG_(strpbrk)((_ss),(_aa)) #define strspn(_ss,_aa) VG_(strspn)((_ss),(_aa)) #define strstr(_hh,_nn) VG_(strstr)((_hh),(_nn)) +/* strtol supports base 16 or else assumes it is base 10 */ +#define strtol(s,r,b) ((b) == 16 ? \ + VG_(strtoll16) ((s),(r)) \ + : VG_(strtoll10) ((s),(r))) + #define size_t SizeT #define xmalloc(_nn) \ VG_(arena_malloc)(VG_AR_DEMANGLE, "m_demangle.xmalloc", (_nn)) +#define xmalloc_failed(_sz) abort() #define xrealloc(_pt,_sz) \ VG_(arena_realloc)(VG_AR_DEMANGLE,"m_demangle.xrealloc",(_pt),(_sz)) #define xstrdup(_str) \ VG_(arena_strdup)(VG_AR_DEMANGLE,"m_demangle.xstrdup",(_str)) +static inline void *xmemdup(const void *in, size_t c_size, size_t a_size) { + void *dst; + dst = VG_(arena_malloc)(VG_AR_DEMANGLE, "m_demangle.xmemdup", a_size); + if (a_size > c_size) + memset ((char *) dst + c_size, 0, a_size - c_size); + return memcpy (dst, in, c_size); +} + /* Required by safe-ctype.h */ #undef EOF @@ -96,6 +110,11 @@ #define XNEW(_Ty) \ ((_Ty *) xmalloc(sizeof (_Ty))) +#define XDELETEVEC(P) \ + free ((void*) (P)) + +#define XDUPVEC(T, P, N) \ + ((T *) xmemdup ((P), sizeof (T) * (N), sizeof (T) * (N))) /*--------------------------------------------------------------------*/ /*--- end vg_libciface.h ---*/ -- 1.8.3.1