diff options
-rw-r--r-- | ChangeLog | 86 | ||||
-rw-r--r-- | libiberty/ChangeLog | 117 | ||||
-rwxr-xr-x | libiberty/configure | 1 | ||||
-rw-r--r-- | libiberty/configure.ac | 1 | ||||
-rw-r--r-- | libiberty/cp-demangle.c | 140 | ||||
-rw-r--r-- | libiberty/cp-demangle.h | 4 | ||||
-rw-r--r-- | libiberty/pex-win32.c | 2 | ||||
-rw-r--r-- | libiberty/rust-demangle.c | 1010 | ||||
-rw-r--r-- | libiberty/simple-object-elf.c | 11 | ||||
-rw-r--r-- | libiberty/strstr.c | 16 | ||||
-rw-r--r-- | libiberty/strverscmp.c | 2 | ||||
-rw-r--r-- | libiberty/testsuite/demangle-expected | 19 | ||||
-rw-r--r-- | libiberty/testsuite/rust-demangle-expected | 134 |
13 files changed, 1467 insertions, 76 deletions
@@ -1,3 +1,89 @@ +2021-01-05 Nick Clifton <nickc@redhat.com> + + * libiberty: Sync with gcc. Bring in: + 2021-01-04 Martin Liska <mliska@suse.cz> + + * strverscmp.c: Convert to utf8 from iso8859. + + 2020-12-22 Jason Merrill <jason@redhat.com> + + PR c++/67343 + * cp-demangle.h (struct d_info): Add unresolved_name_state. + * cp-demangle.c (d_prefix): Add subst parm. + (d_nested_name): Pass it. + (d_unresolved_name): Split out from... + (d_expression_1): ...here. + (d_demangle_callback): Maybe retry with old sr mangling. + * testsuite/demangle-expected: Add test. + + 2020-12-21 Jason Merrill <jason@redhat.com> + + * cp-demangle.c (d_expression_1): Recognize qualified-id + on RHS of dt/pt. + * testsuite/demangle-expected: Add test. + + 2020-12-21 Jason Merrill <jason@redhat.com> + + * cp-demangle.c (d_unqualified_name): Clear is_expression. + * testsuite/demangle-expected: Add tests. + + 2020-11-25 Matthew Malcomson <matthew.malcomson@arm.com> + + * configure: Regenerate. + * configure.ac: Avoid using sanitizer. + + 2020-11-13 Eduard-Mihai Burtescu <eddyb@lyken.rs> + + * rust-demangle.c (struct rust_demangler): Add + skipping_printing and bound_lifetime_depth fields. + (eat): Add (v0-only). + (parse_integer_62): Add (v0-only). + (parse_opt_integer_62): Add (v0-only). + (parse_disambiguator): Add (v0-only). + (struct rust_mangled_ident): Add punycode{,_len} fields. + (parse_ident): Support v0 identifiers. + (print_str): Respect skipping_printing. + (print_uint64): Add (v0-only). + (print_uint64_hex): Add (v0-only). + (print_ident): Respect skipping_printing, + Support v0 identifiers. + (print_lifetime_from_index): Add (v0-only). + (demangle_binder): Add (v0-only). + (demangle_path): Add (v0-only). + (demangle_generic_arg): Add (v0-only). + (demangle_type): Add (v0-only). + (demangle_path_maybe_open_generics): Add (v0-only). + (demangle_dyn_trait): Add (v0-only). + (demangle_const): Add (v0-only). + (demangle_const_uint): Add (v0-only). + (basic_type): Add (v0-only). + (rust_demangle_callback): Support v0 symbols. + * testsuite/rust-demangle-expected: Add v0 testcases. + + 2020-11-13 Seija Kijin <doremylover456@gmail.com> + + * strstr.c (strstr): Make implementation ANSI/POSIX compliant. + + 2020-11-11 Patrick Palka <ppalka@redhat.com> + + PR c++/88115 + * cp-demangle.c (d_print_comp_inner) + <case DEMANGLE_COMPONENT_EXTENDED_OPERATOR>: Don't print the + "operator " prefix for __alignof__. + <case DEMANGLE_COMPONENT_UNARY>: Always print parens around the + operand of __alignof__. + * testsuite/demangle-expected: Test demangling for __alignof__. + + 2020-11-09 Christophe Lyon <christophe.lyon@linaro.org> + + * pex-win32.c (pex_win32_exec_child): Initialize orig_err. + + 2020-10-06 Martin Liska <mliska@suse.cz> + + PR lto/97290 + * simple-object-elf.c (simple_object_elf_copy_lto_debug_sections): + Use sh_link of a .symtab_shndx section. + 2021-01-05 Alan Modra <amodra@gmail.com> * config.guess: Import from upstream. diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index abf836e..a6f82ef 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,23 +1,98 @@ -2020-09-23 Mark Wielaard <mark@klomp.org> +2021-01-04 Martin Liska <mliska@suse.cz> + + * strverscmp.c: Convert to utf8 from iso8859. + +2020-12-22 Jason Merrill <jason@redhat.com> + + PR c++/67343 + * cp-demangle.h (struct d_info): Add unresolved_name_state. + * cp-demangle.c (d_prefix): Add subst parm. + (d_nested_name): Pass it. + (d_unresolved_name): Split out from... + (d_expression_1): ...here. + (d_demangle_callback): Maybe retry with old sr mangling. + * testsuite/demangle-expected: Add test. + +2020-12-21 Jason Merrill <jason@redhat.com> + + * cp-demangle.c (d_expression_1): Recognize qualified-id + on RHS of dt/pt. + * testsuite/demangle-expected: Add test. + +2020-12-21 Jason Merrill <jason@redhat.com> + + * cp-demangle.c (d_unqualified_name): Clear is_expression. + * testsuite/demangle-expected: Add tests. + +2020-11-25 Matthew Malcomson <matthew.malcomson@arm.com> + + * configure: Regenerate. + * configure.ac: Avoid using sanitizer. + +2020-11-13 Eduard-Mihai Burtescu <eddyb@lyken.rs> + + * rust-demangle.c (struct rust_demangler): Add + skipping_printing and bound_lifetime_depth fields. + (eat): Add (v0-only). + (parse_integer_62): Add (v0-only). + (parse_opt_integer_62): Add (v0-only). + (parse_disambiguator): Add (v0-only). + (struct rust_mangled_ident): Add punycode{,_len} fields. + (parse_ident): Support v0 identifiers. + (print_str): Respect skipping_printing. + (print_uint64): Add (v0-only). + (print_uint64_hex): Add (v0-only). + (print_ident): Respect skipping_printing, + Support v0 identifiers. + (print_lifetime_from_index): Add (v0-only). + (demangle_binder): Add (v0-only). + (demangle_path): Add (v0-only). + (demangle_generic_arg): Add (v0-only). + (demangle_type): Add (v0-only). + (demangle_path_maybe_open_generics): Add (v0-only). + (demangle_dyn_trait): Add (v0-only). + (demangle_const): Add (v0-only). + (demangle_const_uint): Add (v0-only). + (basic_type): Add (v0-only). + (rust_demangle_callback): Support v0 symbols. + * testsuite/rust-demangle-expected: Add v0 testcases. + +2020-11-13 Seija Kijin <doremylover456@gmail.com> + + * strstr.c (strstr): Make implementation ANSI/POSIX compliant. + +2020-11-11 Patrick Palka <ppalka@redhat.com> + + PR c++/88115 + * cp-demangle.c (d_print_comp_inner) + <case DEMANGLE_COMPONENT_EXTENDED_OPERATOR>: Don't print the + "operator " prefix for __alignof__. + <case DEMANGLE_COMPONENT_UNARY>: Always print parens around the + operand of __alignof__. + * testsuite/demangle-expected: Test demangling for __alignof__. + +2020-11-09 Christophe Lyon <christophe.lyon@linaro.org> + + * pex-win32.c (pex_win32_exec_child): Initialize orig_err. + +2020-10-06 Martin Liska <mliska@suse.cz> + + PR lto/97290 + * simple-object-elf.c (simple_object_elf_copy_lto_debug_sections): + Use sh_link of a .symtab_shndx section. + +2020-09-24 Mark Wielaard <mark@klomp.org> - Sync with GCC * dwarfnames.c (get_DW_UT_name): Define using DW_UT_FIRST, DW_UT and DW_UT_END. -2020-09-11 Felix Willgerodt <felix.willgerodt@intel.com> - - Sync with GCC - 2020-09-08 Felix Willgerodt <felix.willgerodt@intel.com> +2020-09-08 Felix Willgerodt <felix.willgerodt@intel.com> * floatformat.c (floatformat_bfloat16_big): New. (floatformat_bfloat16_little): New. 2020-09-08 Alan Modra <amodra@gmail.com> - * configure: Regenerate. - - Sync from gcc - 2020-09-08 Alan Modra <amodra@gmail.com> * d-demangle.c: Include limits.h. (ULONG_MAX, UINT_MAX): Provide fall-back definition. (dlang_number): Simplify and correct overflow test. Only @@ -42,32 +117,42 @@ unsigned long variables. * testsuite/d-demangle-expected: Add new tests. - 2020-08-04 Iain Buclaw <ibuclaw@gdcproject.org> +2020-08-26 Iain Buclaw <ibuclaw@gdcproject.org> + * d-demangle.c (dlang_function_args): Handle 'in' and 'in ref' parameter storage classes. (dlang_type): Remove identifier type. * testsuite/d-demangle-expected: Update tests. - 2020-08-03 Richard Biener <rguenther@suse.de> +2020-08-03 Richard Biener <rguenther@suse.de> + PR lto/96385 * simple-object-elf.c (simple_object_elf_copy_lto_debug_sections): Localize global UNDEFs and reuse the prevailing name. - 2020-07-10 Ian Lance Taylor <iant@golang.org> +2020-07-30 H.J. Lu <hjl.tools@gmail.com> + + PR bootstrap/96202 + * configure: Regenerated. + +2020-07-14 Ian Lance Taylor <iant@golang.org> + PR demangler/96143 * cp-demangle.c (d_lambda): Don't add substitution candidate. * testsuite/demangle-expected: Update a few existing test cases accordingly, and add a new test case. - 2020-07-04 Jason Merrill <jason@redhat.com> +2020-07-10 Jason Merrill <jason@redhat.com> + * cp-demangle.c (cplus_demangle_operators): Add di, dx, dX. (d_expression_1): Handle di and dX. (is_designated_init, d_maybe_print_designated_init): New. (d_print_comp_inner): Use d_maybe_print_designated_init. * testsuite/demangle-expected: Add designator tests. - 2020-06-25 Nick Clifton <nickc@redhat.com> +2020-06-26 Nick Clifton <nickc@redhat.com> + * bsearch.c (bsearch): Remove use of register keyword. * bsearch_r.c (bsearch_r): Likewise. @@ -3296,7 +3381,7 @@ (find_executable): Likewise. (win32_spawn): Cast alloca return to (char**). Replace malloc with XNEWVEC. - bcopy.c (bcopy): Add explicit casts in assignments. + bcopy.c (bcopy): Add explict casts in assignments. 2006-10-25 Ben Elliston <bje@au.ibm.com> diff --git a/libiberty/configure b/libiberty/configure index ff93c9e..b6af9ba 100755 --- a/libiberty/configure +++ b/libiberty/configure @@ -5264,6 +5264,7 @@ fi NOASANFLAG= case " ${CFLAGS} " in *\ -fsanitize=address\ *) NOASANFLAG=-fno-sanitize=address ;; + *\ -fsanitize=hwaddress\ *) NOASANFLAG=-fno-sanitize=hwaddress ;; esac diff --git a/libiberty/configure.ac b/libiberty/configure.ac index 4e2599c..ad95296 100644 --- a/libiberty/configure.ac +++ b/libiberty/configure.ac @@ -240,6 +240,7 @@ AC_SUBST(PICFLAG) NOASANFLAG= case " ${CFLAGS} " in *\ -fsanitize=address\ *) NOASANFLAG=-fno-sanitize=address ;; + *\ -fsanitize=hwaddress\ *) NOASANFLAG=-fno-sanitize=hwaddress ;; esac AC_SUBST(NOASANFLAG) diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 4f709f4..d3e7984 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -429,7 +429,7 @@ static struct demangle_component *d_name (struct d_info *); static struct demangle_component *d_nested_name (struct d_info *); -static struct demangle_component *d_prefix (struct d_info *); +static struct demangle_component *d_prefix (struct d_info *, int); static struct demangle_component *d_unqualified_name (struct d_info *); @@ -1510,7 +1510,7 @@ d_nested_name (struct d_info *di) once we have something to attach it to. */ rqual = d_ref_qualifier (di, NULL); - *pret = d_prefix (di); + *pret = d_prefix (di, 1); if (*pret == NULL) return NULL; @@ -1536,10 +1536,12 @@ d_nested_name (struct d_info *di) <template-prefix> ::= <prefix> <(template) unqualified-name> ::= <template-param> ::= <substitution> -*/ + + SUBST is true if we should add substitutions (as normal), false + if not (in an unresolved-name). */ static struct demangle_component * -d_prefix (struct d_info *di) +d_prefix (struct d_info *di, int subst) { struct demangle_component *ret = NULL; @@ -1605,7 +1607,7 @@ d_prefix (struct d_info *di) else ret = d_make_comp (di, comb_type, ret, dc); - if (peek != 'S' && d_peek_char (di) != 'E') + if (peek != 'S' && d_peek_char (di) != 'E' && subst) { if (! d_add_substitution (di, ret)) return NULL; @@ -1632,9 +1634,15 @@ d_unqualified_name (struct d_info *di) ret = d_source_name (di); else if (IS_LOWER (peek)) { + int was_expr = di->is_expression; if (peek == 'o' && d_peek_next_char (di) == 'n') - d_advance (di, 2); + { + d_advance (di, 2); + /* Treat cv as naming a conversion operator. */ + di->is_expression = 0; + } ret = d_operator_name (di); + di->is_expression = was_expr; if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR) { di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2; @@ -3285,14 +3293,58 @@ op_is_new_cast (struct demangle_component *op) || code[0] == 'c' || code[0] == 'r')); } +/* <unresolved-name> ::= [gs] <base-unresolved-name> # x or (with "gs") ::x + ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x + # T::N::x /decltype(p)::N::x + ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name> + # A::x, N::y, A<T>::z; "gs" means leading "::" + ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name> + + "gs" is handled elsewhere, as a unary operator. */ + +static struct demangle_component * +d_unresolved_name (struct d_info *di) +{ + struct demangle_component *type; + struct demangle_component *name; + char peek; + + /* Consume the "sr". */ + d_advance (di, 2); + + peek = d_peek_char (di); + if (di->unresolved_name_state + && (IS_DIGIT (peek) + || IS_LOWER (peek) + || peek == 'C' + || peek == 'U' + || peek == 'L')) + { + /* The third production is ambiguous with the old unresolved-name syntax + of <type> <base-unresolved-name>; in the old mangling, A::x was mangled + as sr1A1x, now sr1AE1x. So we first try to demangle using the new + mangling, then with the old if that fails. */ + di->unresolved_name_state = -1; + type = d_prefix (di, 0); + if (d_peek_char (di) == 'E') + d_advance (di, 1); + } + else + type = cplus_demangle_type (di); + name = d_unqualified_name (di); + if (d_peek_char (di) == 'I') + name = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, + d_template_args (di)); + return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name); +} + /* <expression> ::= <(unary) operator-name> <expression> ::= <(binary) operator-name> <expression> <expression> ::= <(trinary) operator-name> <expression> <expression> <expression> ::= cl <expression>+ E ::= st <type> ::= <template-param> - ::= sr <type> <unqualified-name> - ::= sr <type> <unqualified-name> <template-args> + ::= <unresolved-name> ::= <expr-primary> <braced-expression> ::= <expression> @@ -3302,7 +3354,7 @@ op_is_new_cast (struct demangle_component *op) # [expr ... expr] = expr */ -static inline struct demangle_component * +static struct demangle_component * d_expression_1 (struct d_info *di) { char peek; @@ -3313,20 +3365,7 @@ d_expression_1 (struct d_info *di) else if (peek == 'T') return d_template_param (di); else if (peek == 's' && d_peek_next_char (di) == 'r') - { - struct demangle_component *type; - struct demangle_component *name; - - d_advance (di, 2); - type = cplus_demangle_type (di); - name = d_unqualified_name (di); - if (d_peek_char (di) != 'I') - return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name); - else - return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, - d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, - d_template_args (di))); - } + return d_unresolved_name (di); else if (peek == 's' && d_peek_next_char (di) == 'p') { d_advance (di, 2); @@ -3470,10 +3509,22 @@ d_expression_1 (struct d_info *di) right = d_exprlist (di, 'E'); else if (!strcmp (code, "dt") || !strcmp (code, "pt")) { - right = d_unqualified_name (di); - if (d_peek_char (di) == 'I') - right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, - right, d_template_args (di)); + peek = d_peek_char (di); + /* These codes start a qualified name. */ + if ((peek == 'g' && d_peek_next_char (di) == 's') + || (peek == 's' && d_peek_next_char (di) == 'r')) + right = d_expression_1 (di); + else + { + /* Otherwise it's an unqualified name. We use + d_unqualified_name rather than d_expression_1 here for + old mangled names that didn't add 'on' before operator + names. */ + right = d_unqualified_name (di); + if (d_peek_char (di) == 'I') + right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, + right, d_template_args (di)); + } } else right = d_expression_1 (di); @@ -5458,9 +5509,18 @@ d_print_comp_inner (struct d_print_info *dpi, int options, } case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: - d_append_string (dpi, "operator "); - d_print_comp (dpi, options, dc->u.s_extended_operator.name); - return; + { + struct demangle_component *name = dc->u.s_extended_operator.name; + if (name->type == DEMANGLE_COMPONENT_NAME + && !strncmp (name->u.s_name.s, "__alignof__", name->u.s_name.len)) + d_print_comp (dpi, options, dc->u.s_extended_operator.name); + else + { + d_append_string (dpi, "operator "); + d_print_comp (dpi, options, dc->u.s_extended_operator.name); + } + return; + } case DEMANGLE_COMPONENT_CONVERSION: d_append_string (dpi, "operator "); @@ -5525,8 +5585,14 @@ d_print_comp_inner (struct d_print_info *dpi, int options, if (code && !strcmp (code, "gs")) /* Avoid parens after '::'. */ d_print_comp (dpi, options, operand); - else if (code && !strcmp (code, "st")) - /* Always print parens for sizeof (type). */ + else if ((code && !strcmp (code, "st")) + || (op->type == DEMANGLE_COMPONENT_EXTENDED_OPERATOR + && (op->u.s_extended_operator.name->type + == DEMANGLE_COMPONENT_NAME) + && !strncmp (op->u.s_extended_operator.name->u.s_name.s, + "__alignof__", + op->u.s_extended_operator.name->u.s_name.len))) + /* Always print parens for sizeof (type) and __alignof__. */ { d_append_char (dpi, '('); d_print_comp (dpi, options, operand); @@ -6364,6 +6430,9 @@ d_demangle_callback (const char *mangled, int options, type = DCT_TYPE; } + di.unresolved_name_state = 1; + + again: cplus_demangle_init_info (mangled, options, strlen (mangled), &di); /* PR 87675 - Check for a mangled string that is so long @@ -6422,6 +6491,13 @@ d_demangle_callback (const char *mangled, int options, if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0') dc = NULL; + /* See discussion in d_unresolved_name. */ + if (dc == NULL && di.unresolved_name_state == -1) + { + di.unresolved_name_state = 0; + goto again; + } + #ifdef CP_DEMANGLE_DEBUG d_dump (dc, 0); #endif diff --git a/libiberty/cp-demangle.h b/libiberty/cp-demangle.h index 84eb5db..cb47bdf 100644 --- a/libiberty/cp-demangle.h +++ b/libiberty/cp-demangle.h @@ -122,6 +122,10 @@ struct d_info /* Non-zero if we are parsing the type operand of a conversion operator, but not when in an expression. */ int is_conversion; + /* 1: using new unresolved-name grammar. + -1: using new unresolved-name grammar and saw an unresolved-name. + 0: using old unresolved-name grammar. */ + int unresolved_name_state; /* If DMGL_NO_RECURSE_LIMIT is not active then this is set to the current recursion level. */ unsigned int recursion_level; diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c index 4be00f1..ecfe7f1 100644 --- a/libiberty/pex-win32.c +++ b/libiberty/pex-win32.c @@ -771,7 +771,7 @@ pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags, OSVERSIONINFO version_info; STARTUPINFO si; PROCESS_INFORMATION pi; - int orig_out, orig_in, orig_err; + int orig_out, orig_in, orig_err = 0; BOOL separate_stderr = !(flags & PEX_STDERR_TO_STDOUT); /* Ensure we have inheritable descriptors to pass to the child. */ diff --git a/libiberty/rust-demangle.c b/libiberty/rust-demangle.c index 5118976..6fd8f6a 100644 --- a/libiberty/rust-demangle.c +++ b/libiberty/rust-demangle.c @@ -1,6 +1,7 @@ /* Demangler for the Rust programming language Copyright (C) 2016-2021 Free Software Foundation, Inc. Written by David Tolnay (dtolnay@gmail.com). + Rewritten by Eduard-Mihai Burtescu (eddyb@lyken.rs) for v0 support. This file is part of the libiberty library. Libiberty is free software; you can redistribute it and/or @@ -64,11 +65,16 @@ struct rust_demangler /* Non-zero if any error occurred. */ int errored; + /* Non-zero if nothing should be printed. */ + int skipping_printing; + /* Non-zero if printing should be verbose (e.g. include hashes). */ int verbose; /* Rust mangling version, with legacy mangling being -1. */ int version; + + uint64_t bound_lifetime_depth; }; /* Parsing functions. */ @@ -81,6 +87,18 @@ peek (const struct rust_demangler *rdm) return 0; } +static int +eat (struct rust_demangler *rdm, char c) +{ + if (peek (rdm) == c) + { + rdm->next++; + return 1; + } + else + return 0; +} + static char next (struct rust_demangler *rdm) { @@ -92,11 +110,87 @@ next (struct rust_demangler *rdm) return c; } +static uint64_t +parse_integer_62 (struct rust_demangler *rdm) +{ + char c; + uint64_t x; + + if (eat (rdm, '_')) + return 0; + + x = 0; + while (!eat (rdm, '_')) + { + c = next (rdm); + x *= 62; + if (ISDIGIT (c)) + x += c - '0'; + else if (ISLOWER (c)) + x += 10 + (c - 'a'); + else if (ISUPPER (c)) + x += 10 + 26 + (c - 'A'); + else + { + rdm->errored = 1; + return 0; + } + } + return x + 1; +} + +static uint64_t +parse_opt_integer_62 (struct rust_demangler *rdm, char tag) +{ + if (!eat (rdm, tag)) + return 0; + return 1 + parse_integer_62 (rdm); +} + +static uint64_t +parse_disambiguator (struct rust_demangler *rdm) +{ + return parse_opt_integer_62 (rdm, 's'); +} + +static size_t +parse_hex_nibbles (struct rust_demangler *rdm, uint64_t *value) +{ + char c; + size_t hex_len; + + hex_len = 0; + *value = 0; + + while (!eat (rdm, '_')) + { + *value <<= 4; + + c = next (rdm); + if (ISDIGIT (c)) + *value |= c - '0'; + else if (c >= 'a' && c <= 'f') + *value |= 10 + (c - 'a'); + else + { + rdm->errored = 1; + return 0; + } + hex_len++; + } + + return hex_len; +} + struct rust_mangled_ident { /* ASCII part of the identifier. */ const char *ascii; size_t ascii_len; + + /* Punycode insertion codes for Unicode codepoints, if any. */ + const char *punycode; + size_t punycode_len; }; static struct rust_mangled_ident @@ -104,10 +198,16 @@ parse_ident (struct rust_demangler *rdm) { char c; size_t start, len; + int is_punycode = 0; struct rust_mangled_ident ident; ident.ascii = NULL; ident.ascii_len = 0; + ident.punycode = NULL; + ident.punycode_len = 0; + + if (rdm->version != -1) + is_punycode = eat (rdm, 'u'); c = next (rdm); if (!ISDIGIT (c)) @@ -121,6 +221,10 @@ parse_ident (struct rust_demangler *rdm) while (ISDIGIT (peek (rdm))) len = len * 10 + (next (rdm) - '0'); + /* Skip past the optional `_` separator (v0). */ + if (rdm->version != -1) + eat (rdm, '_'); + start = rdm->next; rdm->next += len; /* Check for overflows. */ @@ -133,6 +237,27 @@ parse_ident (struct rust_demangler *rdm) ident.ascii = rdm->sym + start; ident.ascii_len = len; + if (is_punycode) + { + ident.punycode_len = 0; + while (ident.ascii_len > 0) + { + ident.ascii_len--; + + /* The last '_' is a separator between ascii & punycode. */ + if (ident.ascii[ident.ascii_len] == '_') + break; + + ident.punycode_len++; + } + if (!ident.punycode_len) + { + rdm->errored = 1; + return ident; + } + ident.punycode = ident.ascii + (len - ident.punycode_len); + } + if (ident.ascii_len == 0) ident.ascii = NULL; @@ -144,12 +269,28 @@ parse_ident (struct rust_demangler *rdm) static void print_str (struct rust_demangler *rdm, const char *data, size_t len) { - if (!rdm->errored) + if (!rdm->errored && !rdm->skipping_printing) rdm->callback (data, len, rdm->callback_opaque); } #define PRINT(s) print_str (rdm, s, strlen (s)) +static void +print_uint64 (struct rust_demangler *rdm, uint64_t x) +{ + char s[21]; + snprintf (s, 21, "%" PRIu64, x); + PRINT (s); +} + +static void +print_uint64_hex (struct rust_demangler *rdm, uint64_t x) +{ + char s[17]; + snprintf (s, 17, "%" PRIx64, x); + PRINT (s); +} + /* Return a 0x0-0xf value if the char is 0-9a-f, and -1 otherwise. */ static int decode_lower_hex_nibble (char nibble) @@ -230,9 +371,14 @@ static void print_ident (struct rust_demangler *rdm, struct rust_mangled_ident ident) { char unescaped; - size_t len; - - if (rdm->errored) + uint8_t *out, *p, d; + size_t len, cap, punycode_pos, j; + /* Punycode parameters and state. */ + uint32_t c; + size_t base, t_min, t_max, skew, damp, bias, i; + size_t delta, w, k, t; + + if (rdm->errored || rdm->skipping_printing) return; if (rdm->version == -1) @@ -273,8 +419,7 @@ print_ident (struct rust_demangler *rdm, struct rust_mangled_ident ident) } else { - /* "." becomes "-" */ - PRINT ("-"); + PRINT ("."); len = 1; } } @@ -294,6 +439,830 @@ print_ident (struct rust_demangler *rdm, struct rust_mangled_ident ident) return; } + + if (!ident.punycode) + { + print_str (rdm, ident.ascii, ident.ascii_len); + return; + } + + len = 0; + cap = 4; + while (cap < ident.ascii_len) + { + cap *= 2; + /* Check for overflows. */ + if ((cap * 4) / 4 != cap) + { + rdm->errored = 1; + return; + } + } + + /* Store the output codepoints as groups of 4 UTF-8 bytes. */ + out = (uint8_t *)malloc (cap * 4); + if (!out) + { + rdm->errored = 1; + return; + } + + /* Populate initial output from ASCII fragment. */ + for (len = 0; len < ident.ascii_len; len++) + { + p = out + 4 * len; + p[0] = 0; + p[1] = 0; + p[2] = 0; + p[3] = ident.ascii[len]; + } + + /* Punycode parameters and initial state. */ + base = 36; + t_min = 1; + t_max = 26; + skew = 38; + damp = 700; + bias = 72; + i = 0; + c = 0x80; + + punycode_pos = 0; + while (punycode_pos < ident.punycode_len) + { + /* Read one delta value. */ + delta = 0; + w = 1; + k = 0; + do + { + k += base; + t = k < bias ? 0 : (k - bias); + if (t < t_min) + t = t_min; + if (t > t_max) + t = t_max; + + if (punycode_pos >= ident.punycode_len) + goto cleanup; + d = ident.punycode[punycode_pos++]; + + if (ISLOWER (d)) + d = d - 'a'; + else if (ISDIGIT (d)) + d = 26 + (d - '0'); + else + { + rdm->errored = 1; + goto cleanup; + } + + delta += d * w; + w *= base - t; + } + while (d >= t); + + /* Compute the new insert position and character. */ + len++; + i += delta; + c += i / len; + i %= len; + + /* Ensure enough space is available. */ + if (cap < len) + { + cap *= 2; + /* Check for overflows. */ + if ((cap * 4) / 4 != cap || cap < len) + { + rdm->errored = 1; + goto cleanup; + } + } + p = (uint8_t *)realloc (out, cap * 4); + if (!p) + { + rdm->errored = 1; + goto cleanup; + } + out = p; + + /* Move the characters after the insert position. */ + p = out + i * 4; + memmove (p + 4, p, (len - i - 1) * 4); + + /* Insert the new character, as UTF-8 bytes. */ + p[0] = c >= 0x10000 ? 0xf0 | (c >> 18) : 0; + p[1] = c >= 0x800 ? (c < 0x10000 ? 0xe0 : 0x80) | ((c >> 12) & 0x3f) : 0; + p[2] = (c < 0x800 ? 0xc0 : 0x80) | ((c >> 6) & 0x3f); + p[3] = 0x80 | (c & 0x3f); + + /* If there are no more deltas, decoding is complete. */ + if (punycode_pos == ident.punycode_len) + break; + + i++; + + /* Perform bias adaptation. */ + delta /= damp; + damp = 2; + + delta += delta / len; + k = 0; + while (delta > ((base - t_min) * t_max) / 2) + { + delta /= base - t_min; + k += base; + } + bias = k + ((base - t_min + 1) * delta) / (delta + skew); + } + + /* Remove all the 0 bytes to leave behind an UTF-8 string. */ + for (i = 0, j = 0; i < len * 4; i++) + if (out[i] != 0) + out[j++] = out[i]; + + print_str (rdm, (const char *)out, j); + +cleanup: + free (out); +} + +/* Print the lifetime according to the previously decoded index. + An index of `0` always refers to `'_`, but starting with `1`, + indices refer to late-bound lifetimes introduced by a binder. */ +static void +print_lifetime_from_index (struct rust_demangler *rdm, uint64_t lt) +{ + char c; + uint64_t depth; + + PRINT ("'"); + if (lt == 0) + { + PRINT ("_"); + return; + } + + depth = rdm->bound_lifetime_depth - lt; + /* Try to print lifetimes alphabetically first. */ + if (depth < 26) + { + c = 'a' + depth; + print_str (rdm, &c, 1); + } + else + { + /* Use `'_123` after running out of letters. */ + PRINT ("_"); + print_uint64 (rdm, depth); + } +} + +/* Demangling functions. */ + +static void demangle_binder (struct rust_demangler *rdm); +static void demangle_path (struct rust_demangler *rdm, int in_value); +static void demangle_generic_arg (struct rust_demangler *rdm); +static void demangle_type (struct rust_demangler *rdm); +static int demangle_path_maybe_open_generics (struct rust_demangler *rdm); +static void demangle_dyn_trait (struct rust_demangler *rdm); +static void demangle_const (struct rust_demangler *rdm); +static void demangle_const_uint (struct rust_demangler *rdm); +static void demangle_const_int (struct rust_demangler *rdm); +static void demangle_const_bool (struct rust_demangler *rdm); +static void demangle_const_char (struct rust_demangler *rdm); + +/* Optionally enter a binder ('G') for late-bound lifetimes, + printing e.g. `for<'a, 'b> `, and make those lifetimes visible + to the caller (via depth level, which the caller should reset). */ +static void +demangle_binder (struct rust_demangler *rdm) +{ + uint64_t i, bound_lifetimes; + + if (rdm->errored) + return; + + bound_lifetimes = parse_opt_integer_62 (rdm, 'G'); + if (bound_lifetimes > 0) + { + PRINT ("for<"); + for (i = 0; i < bound_lifetimes; i++) + { + if (i > 0) + PRINT (", "); + rdm->bound_lifetime_depth++; + print_lifetime_from_index (rdm, 1); + } + PRINT ("> "); + } +} + +static void +demangle_path (struct rust_demangler *rdm, int in_value) +{ + char tag, ns; + int was_skipping_printing; + size_t i, backref, old_next; + uint64_t dis; + struct rust_mangled_ident name; + + if (rdm->errored) + return; + + switch (tag = next (rdm)) + { + case 'C': + dis = parse_disambiguator (rdm); + name = parse_ident (rdm); + + print_ident (rdm, name); + if (rdm->verbose) + { + PRINT ("["); + print_uint64_hex (rdm, dis); + PRINT ("]"); + } + break; + case 'N': + ns = next (rdm); + if (!ISLOWER (ns) && !ISUPPER (ns)) + { + rdm->errored = 1; + return; + } + + demangle_path (rdm, in_value); + + dis = parse_disambiguator (rdm); + name = parse_ident (rdm); + + if (ISUPPER (ns)) + { + /* Special namespaces, like closures and shims. */ + PRINT ("::{"); + switch (ns) + { + case 'C': + PRINT ("closure"); + break; + case 'S': + PRINT ("shim"); + break; + default: + print_str (rdm, &ns, 1); + } + if (name.ascii || name.punycode) + { + PRINT (":"); + print_ident (rdm, name); + } + PRINT ("#"); + print_uint64 (rdm, dis); + PRINT ("}"); + } + else + { + /* Implementation-specific/unspecified namespaces. */ + + if (name.ascii || name.punycode) + { + PRINT ("::"); + print_ident (rdm, name); + } + } + break; + case 'M': + case 'X': + /* Ignore the `impl`'s own path.*/ + parse_disambiguator (rdm); + was_skipping_printing = rdm->skipping_printing; + rdm->skipping_printing = 1; + demangle_path (rdm, in_value); + rdm->skipping_printing = was_skipping_printing; + /* fallthrough */ + case 'Y': + PRINT ("<"); + demangle_type (rdm); + if (tag != 'M') + { + PRINT (" as "); + demangle_path (rdm, 0); + } + PRINT (">"); + break; + case 'I': + demangle_path (rdm, in_value); + if (in_value) + PRINT ("::"); + PRINT ("<"); + for (i = 0; !rdm->errored && !eat (rdm, 'E'); i++) + { + if (i > 0) + PRINT (", "); + demangle_generic_arg (rdm); + } + PRINT (">"); + break; + case 'B': + backref = parse_integer_62 (rdm); + if (!rdm->skipping_printing) + { + old_next = rdm->next; + rdm->next = backref; + demangle_path (rdm, in_value); + rdm->next = old_next; + } + break; + default: + rdm->errored = 1; + return; + } +} + +static void +demangle_generic_arg (struct rust_demangler *rdm) +{ + uint64_t lt; + if (eat (rdm, 'L')) + { + lt = parse_integer_62 (rdm); + print_lifetime_from_index (rdm, lt); + } + else if (eat (rdm, 'K')) + demangle_const (rdm); + else + demangle_type (rdm); +} + +static const char * +basic_type (char tag) +{ + switch (tag) + { + case 'b': + return "bool"; + case 'c': + return "char"; + case 'e': + return "str"; + case 'u': + return "()"; + case 'a': + return "i8"; + case 's': + return "i16"; + case 'l': + return "i32"; + case 'x': + return "i64"; + case 'n': + return "i128"; + case 'i': + return "isize"; + case 'h': + return "u8"; + case 't': + return "u16"; + case 'm': + return "u32"; + case 'y': + return "u64"; + case 'o': + return "u128"; + case 'j': + return "usize"; + case 'f': + return "f32"; + case 'd': + return "f64"; + case 'z': + return "!"; + case 'p': + return "_"; + case 'v': + return "..."; + + default: + return NULL; + } +} + +static void +demangle_type (struct rust_demangler *rdm) +{ + char tag; + size_t i, old_next, backref; + uint64_t lt, old_bound_lifetime_depth; + const char *basic; + struct rust_mangled_ident abi; + + if (rdm->errored) + return; + + tag = next (rdm); + + basic = basic_type (tag); + if (basic) + { + PRINT (basic); + return; + } + + switch (tag) + { + case 'R': + case 'Q': + PRINT ("&"); + if (eat (rdm, 'L')) + { + lt = parse_integer_62 (rdm); + if (lt) + { + print_lifetime_from_index (rdm, lt); + PRINT (" "); + } + } + if (tag != 'R') + PRINT ("mut "); + demangle_type (rdm); + break; + case 'P': + case 'O': + PRINT ("*"); + if (tag != 'P') + PRINT ("mut "); + else + PRINT ("const "); + demangle_type (rdm); + break; + case 'A': + case 'S': + PRINT ("["); + demangle_type (rdm); + if (tag == 'A') + { + PRINT ("; "); + demangle_const (rdm); + } + PRINT ("]"); + break; + case 'T': + PRINT ("("); + for (i = 0; !rdm->errored && !eat (rdm, 'E'); i++) + { + if (i > 0) + PRINT (", "); + demangle_type (rdm); + } + if (i == 1) + PRINT (","); + PRINT (")"); + break; + case 'F': + old_bound_lifetime_depth = rdm->bound_lifetime_depth; + demangle_binder (rdm); + + if (eat (rdm, 'U')) + PRINT ("unsafe "); + + if (eat (rdm, 'K')) + { + if (eat (rdm, 'C')) + { + abi.ascii = "C"; + abi.ascii_len = 1; + } + else + { + abi = parse_ident (rdm); + if (!abi.ascii || abi.punycode) + { + rdm->errored = 1; + goto restore; + } + } + + PRINT ("extern \""); + + /* If the ABI had any `-`, they were replaced with `_`, + so the parts between `_` have to be re-joined with `-`. */ + for (i = 0; i < abi.ascii_len; i++) + { + if (abi.ascii[i] == '_') + { + print_str (rdm, abi.ascii, i); + PRINT ("-"); + abi.ascii += i + 1; + abi.ascii_len -= i + 1; + i = 0; + } + } + print_str (rdm, abi.ascii, abi.ascii_len); + + PRINT ("\" "); + } + + PRINT ("fn("); + for (i = 0; !rdm->errored && !eat (rdm, 'E'); i++) + { + if (i > 0) + PRINT (", "); + demangle_type (rdm); + } + PRINT (")"); + + if (eat (rdm, 'u')) + { + /* Skip printing the return type if it's 'u', i.e. `()`. */ + } + else + { + PRINT (" -> "); + demangle_type (rdm); + } + + /* Restore `bound_lifetime_depth` to outside the binder. */ + restore: + rdm->bound_lifetime_depth = old_bound_lifetime_depth; + break; + case 'D': + PRINT ("dyn "); + + old_bound_lifetime_depth = rdm->bound_lifetime_depth; + demangle_binder (rdm); + + for (i = 0; !rdm->errored && !eat (rdm, 'E'); i++) + { + if (i > 0) + PRINT (" + "); + demangle_dyn_trait (rdm); + } + + /* Restore `bound_lifetime_depth` to outside the binder. */ + rdm->bound_lifetime_depth = old_bound_lifetime_depth; + + if (!eat (rdm, 'L')) + { + rdm->errored = 1; + return; + } + lt = parse_integer_62 (rdm); + if (lt) + { + PRINT (" + "); + print_lifetime_from_index (rdm, lt); + } + break; + case 'B': + backref = parse_integer_62 (rdm); + if (!rdm->skipping_printing) + { + old_next = rdm->next; + rdm->next = backref; + demangle_type (rdm); + rdm->next = old_next; + } + break; + default: + /* Go back to the tag, so `demangle_path` also sees it. */ + rdm->next--; + demangle_path (rdm, 0); + } +} + +/* A trait in a trait object may have some "existential projections" + (i.e. associated type bindings) after it, which should be printed + in the `<...>` of the trait, e.g. `dyn Trait<T, U, Assoc=X>`. + To this end, this method will keep the `<...>` of an 'I' path + open, by omitting the `>`, and return `Ok(true)` in that case. */ +static int +demangle_path_maybe_open_generics (struct rust_demangler *rdm) +{ + int open; + size_t i, old_next, backref; + + open = 0; + + if (rdm->errored) + return open; + + if (eat (rdm, 'B')) + { + backref = parse_integer_62 (rdm); + if (!rdm->skipping_printing) + { + old_next = rdm->next; + rdm->next = backref; + open = demangle_path_maybe_open_generics (rdm); + rdm->next = old_next; + } + } + else if (eat (rdm, 'I')) + { + demangle_path (rdm, 0); + PRINT ("<"); + open = 1; + for (i = 0; !rdm->errored && !eat (rdm, 'E'); i++) + { + if (i > 0) + PRINT (", "); + demangle_generic_arg (rdm); + } + } + else + demangle_path (rdm, 0); + return open; +} + +static void +demangle_dyn_trait (struct rust_demangler *rdm) +{ + int open; + struct rust_mangled_ident name; + + if (rdm->errored) + return; + + open = demangle_path_maybe_open_generics (rdm); + + while (eat (rdm, 'p')) + { + if (!open) + PRINT ("<"); + else + PRINT (", "); + open = 1; + + name = parse_ident (rdm); + print_ident (rdm, name); + PRINT (" = "); + demangle_type (rdm); + } + + if (open) + PRINT (">"); +} + +static void +demangle_const (struct rust_demangler *rdm) +{ + char ty_tag; + size_t old_next, backref; + + if (rdm->errored) + return; + + if (eat (rdm, 'B')) + { + backref = parse_integer_62 (rdm); + if (!rdm->skipping_printing) + { + old_next = rdm->next; + rdm->next = backref; + demangle_const (rdm); + rdm->next = old_next; + } + return; + } + + ty_tag = next (rdm); + switch (ty_tag) + { + /* Placeholder. */ + case 'p': + PRINT ("_"); + return; + + /* Unsigned integer types. */ + case 'h': + case 't': + case 'm': + case 'y': + case 'o': + case 'j': + demangle_const_uint (rdm); + break; + + /* Signed integer types. */ + case 'a': + case 's': + case 'l': + case 'x': + case 'n': + case 'i': + demangle_const_int (rdm); + break; + + /* Boolean. */ + case 'b': + demangle_const_bool (rdm); + break; + + /* Character. */ + case 'c': + demangle_const_char (rdm); + break; + + default: + rdm->errored = 1; + return; + } + + if (rdm->errored) + return; + + if (rdm->verbose) + { + PRINT (": "); + PRINT (basic_type (ty_tag)); + } +} + +static void +demangle_const_uint (struct rust_demangler *rdm) +{ + size_t hex_len; + uint64_t value; + + if (rdm->errored) + return; + + hex_len = parse_hex_nibbles (rdm, &value); + + if (hex_len > 16) + { + /* Print anything that doesn't fit in `uint64_t` verbatim. */ + PRINT ("0x"); + print_str (rdm, rdm->sym + (rdm->next - hex_len), hex_len); + } + else if (hex_len > 0) + print_uint64 (rdm, value); + else + rdm->errored = 1; +} + +static void +demangle_const_int (struct rust_demangler *rdm) +{ + if (eat (rdm, 'n')) + PRINT ("-"); + demangle_const_uint (rdm); +} + +static void +demangle_const_bool (struct rust_demangler *rdm) +{ + uint64_t value; + + if (parse_hex_nibbles (rdm, &value) != 1) + { + rdm->errored = 1; + return; + } + + if (value == 0) + PRINT ("false"); + else if (value == 1) + PRINT ("true"); + else + rdm->errored = 1; +} + +static void +demangle_const_char (struct rust_demangler *rdm) +{ + size_t hex_len; + uint64_t value; + + hex_len = parse_hex_nibbles (rdm, &value); + + if (hex_len == 0 || hex_len > 8) + { + rdm->errored = 1; + return; + } + + /* Match Rust's character "debug" output as best as we can. */ + PRINT ("'"); + if (value == '\t') + PRINT ("\\t"); + else if (value == '\r') + PRINT ("\\r"); + else if (value == '\n') + PRINT ("\\n"); + else if (value > ' ' && value < '~') + /* Rust also considers many non-ASCII codepoints to be printable, but + that logic is not easily ported to C. */ + print_str (rdm, (char *) &value, 1); + else + { + PRINT ("\\u{"); + print_uint64_hex (rdm, value); + PRINT ("}"); + } + PRINT ("'"); } /* A legacy hash is the prefix "h" followed by 16 lowercase hex digits. @@ -345,11 +1314,15 @@ rust_demangle_callback (const char *mangled, int options, rdm.next = 0; rdm.errored = 0; + rdm.skipping_printing = 0; rdm.verbose = (options & DMGL_VERBOSE) != 0; rdm.version = 0; + rdm.bound_lifetime_depth = 0; - /* Rust symbols always start with _ZN (legacy). */ - if (rdm.sym[0] == '_' && rdm.sym[1] == 'Z' && rdm.sym[2] == 'N') + /* Rust symbols always start with _R (v0) or _ZN (legacy). */ + if (rdm.sym[0] == '_' && rdm.sym[1] == 'R') + rdm.sym += 2; + else if (rdm.sym[0] == '_' && rdm.sym[1] == 'Z' && rdm.sym[2] == 'N') { rdm.sym += 3; rdm.version = -1; @@ -357,7 +1330,11 @@ rust_demangle_callback (const char *mangled, int options, else return 0; - /* Legacy Rust symbols use only [_0-9a-zA-Z.:$] characters. */ + /* Paths (v0) always start with uppercase characters. */ + if (rdm.version != -1 && !ISUPPER (rdm.sym[0])) + return 0; + + /* Rust symbols (v0) use only [_0-9a-zA-Z] characters. */ for (p = rdm.sym; *p; p++) { rdm.sym_len++; @@ -365,6 +1342,7 @@ rust_demangle_callback (const char *mangled, int options, if (*p == '_' || ISALNUM (*p)) continue; + /* Legacy Rust symbols can also contain [.:$] characters. */ if (rdm.version == -1 && (*p == '$' || *p == '.' || *p == ':')) continue; @@ -418,7 +1396,19 @@ rust_demangle_callback (const char *mangled, int options, while (rdm.next < rdm.sym_len); } else - return 0; + { + demangle_path (&rdm, 1); + + /* Skip instantiating crate. */ + if (!rdm.errored && rdm.next < rdm.sym_len) + { + rdm.skipping_printing = 1; + demangle_path (&rdm, 0); + } + + /* It's an error to not reach the end. */ + rdm.errored |= rdm.next != rdm.sym_len; + } return !rdm.errored; } diff --git a/libiberty/simple-object-elf.c b/libiberty/simple-object-elf.c index e37e334..a421177 100644 --- a/libiberty/simple-object-elf.c +++ b/libiberty/simple-object-elf.c @@ -1191,7 +1191,7 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, unsigned int sh_link; sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, shdr, sh_link, Elf_Word); - symtab_indices_shndx[sh_link - 1] = i; + symtab_indices_shndx[sh_link - 1] = i - 1; /* Always discard the extended index sections, after copying it will not be needed. This way we don't need to update it and deal with the ordering constraints of @@ -1372,19 +1372,22 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, { unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, shdr, sh_entsize, Elf_Addr); - unsigned strtab = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, - shdr, sh_link, Elf_Word); size_t prevailing_name_idx = 0; unsigned char *ent; unsigned *shndx_table = NULL; /* Read the section index table if present. */ if (symtab_indices_shndx[i - 1] != 0) { - unsigned char *sidxhdr = shdrs + (strtab - 1) * shdr_size; + unsigned char *sidxhdr = shdrs + symtab_indices_shndx[i - 1] * shdr_size; off_t sidxoff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, sidxhdr, sh_offset, Elf_Addr); size_t sidxsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, sidxhdr, sh_size, Elf_Addr); + unsigned int shndx_type + = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, + sidxhdr, sh_type, Elf_Word); + if (shndx_type != SHT_SYMTAB_SHNDX) + return "Wrong section type of a SYMTAB SECTION INDICES section"; shndx_table = (unsigned *)XNEWVEC (char, sidxsz); simple_object_internal_read (sobj->descriptor, sobj->offset + sidxoff, diff --git a/libiberty/strstr.c b/libiberty/strstr.c index 60902ea..c6f6849 100644 --- a/libiberty/strstr.c +++ b/libiberty/strstr.c @@ -16,26 +16,20 @@ length, the function returns @var{string}. */ - -/* FIXME: The above description is ANSI compiliant. This routine has not - been validated to comply with it. -fnf */ - #include <stddef.h> -extern char *strchr (const char *, int); -extern int strncmp (const void *, const void *, size_t); +extern int memcmp (const void *, const void *, size_t); extern size_t strlen (const char *); char * strstr (const char *s1, const char *s2) { - const char *p = s1; const size_t len = strlen (s2); - - for (; (p = strchr (p, *s2)) != 0; p++) + while (*s1) { - if (strncmp (p, s2, len) == 0) - return (char *)p; + if (!memcmp (s1, s2, len)) + return (char *)s1; + ++s1; } return (0); } diff --git a/libiberty/strverscmp.c b/libiberty/strverscmp.c index 6f3e8b4..57a71da 100644 --- a/libiberty/strverscmp.c +++ b/libiberty/strverscmp.c @@ -1,7 +1,7 @@ /* Compare strings while treating digits characters numerically. Copyright (C) 1997-2021 Free Software Foundation, Inc. This file is part of the libiberty library. - Contributed by Jean-Franηois Bignolles <bignolle@ecoledoc.ibp.fr>, 1997. + Contributed by Jean-FranΓ§ois Bignolles <bignolle@ecoledoc.ibp.fr>, 1997. Libiberty is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 0850db3..e6b5b64 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -1469,3 +1469,22 @@ f(A<X{.a.b[3 ... 4]=(1)}>) # PR 96143 _Z2F2IZ1FvEUlvE_EN1AIT_E1XES2_ A<F()::{lambda()#1}>::X F2<F()::{lambda()#1}>(F()::{lambda()#1}) + +# PR 88115 +_Z1fIiEvDTv111__alignof__T_E +void f<int>(decltype (__alignof__(int))) + +_Z1fIiEvDTv111__alignof__tlT_EE +void f<int>(decltype (__alignof__(int{}))) + +_Z1gI1AEv1SIXadsrT_oncviEE +void g<A>(S<&A::operator int>) + +_Z1jI1AEDTcldtfp_oncvPT_EES1_ +decltype (({parm#1}.(operator A*))()) j<A>(A) + +_Z1fI1AEDtdtfp_srT_1xES1_ +decltype ({parm#1}.A::x) f<A>(A) + +_Z2f6IP1AEDtptfp_gssr1A1BE1xET_ +decltype ({parm#1}->(::A::B::x)) f6<A*>(A*) diff --git a/libiberty/testsuite/rust-demangle-expected b/libiberty/testsuite/rust-demangle-expected index 7477479..7dca315 100644 --- a/libiberty/testsuite/rust-demangle-expected +++ b/libiberty/testsuite/rust-demangle-expected @@ -11,7 +11,7 @@ # ############ # -# Coverage Tests +# Coverage Tests (legacy) # # # Demangles as rust symbol. @@ -163,3 +163,135 @@ _ZN63_$LT$core..ptr..Unique$LT$T$GT$$u20$as$u20$core..ops..Deref$GT$5deref17h19f --format=rust _ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h059a991a004536adE issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo +--format=rust +_ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h000b1ad6c4f30bd6E +core::ops::function::FnOnce::call_once{{vtable.shim}} +# +############ +# +# Coverage Tests (v0) +# +# +# Crate with a leading digit. +--format=rust +_RNvC6_123foo3bar +123foo::bar +# UTF-8 identifiers. +--format=rust +_RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y +utf8_idents::α‘ααααααα_αααα αααα_α‘ααααα +# Closure path elements. +--format=rust +_RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_ +cc::spawn::{closure#0}::{closure#0} +# +--format=rust +_RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_ +<core::slice::Iter<u8> as core::iter::iterator::Iterator>::rposition::<core::slice::memchr::memrchr::{closure#1}>::{closure#0} +# dyn Trait ("trait object") types. +--format=rust +_RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std +alloc::alloc::box_free::<dyn alloc::boxed::FnBox<(), Output = ()>> +# Types with const generics parameters. +--format=rust +_RNvMC0INtC8arrayvec8ArrayVechKj7b_E3new +<arrayvec::ArrayVec<u8, 123>>::new +# +--format=rust +_RMCs4fqI2P2rA04_13const_genericINtB0_8UnsignedKhb_E +<const_generic::Unsigned<11>> +# +--format=rust +_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKs98_E +<const_generic::Signed<152>> +# +--format=rust +_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKanb_E +<const_generic::Signed<-11>> +# +--format=rust +_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb0_E +<const_generic::Bool<false>> +# +--format=rust +_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb1_E +<const_generic::Bool<true>> +# +--format=rust +_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc76_E +<const_generic::Char<'v'>> +# +--format=rust +_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKca_E +<const_generic::Char<'\n'>> +# +--format=rust +_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E +<const_generic::Char<'\u{2202}'>> +# +--format=rust +_RNvNvMCs4fqI2P2rA04_13const_genericINtB4_3FooKpE3foo3FOO +<const_generic::Foo<_>>::foo::FOO +# +# All of the tests above but in auto mode instead: +# +# Crate with a leading digit. +--format=auto +_RNvC6_123foo3bar +123foo::bar +# UTF-8 identifiers. +--format=auto +_RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y +utf8_idents::α‘ααααααα_αααα αααα_α‘ααααα +# Closure path elements. +--format=auto +_RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_ +cc::spawn::{closure#0}::{closure#0} +# +--format=auto +_RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_ +<core::slice::Iter<u8> as core::iter::iterator::Iterator>::rposition::<core::slice::memchr::memrchr::{closure#1}>::{closure#0} +# dyn Trait ("trait object") types. +--format=auto +_RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std +alloc::alloc::box_free::<dyn alloc::boxed::FnBox<(), Output = ()>> +# Types with const generics parameters. +--format=auto +_RNvMC0INtC8arrayvec8ArrayVechKj7b_E3new +<arrayvec::ArrayVec<u8, 123>>::new +# +--format=auto +_RMCs4fqI2P2rA04_13const_genericINtB0_8UnsignedKhb_E +<const_generic::Unsigned<11>> +# +--format=auto +_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKs98_E +<const_generic::Signed<152>> +# +--format=auto +_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKanb_E +<const_generic::Signed<-11>> +# +--format=auto +_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb0_E +<const_generic::Bool<false>> +# +--format=auto +_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb1_E +<const_generic::Bool<true>> +# +--format=auto +_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc76_E +<const_generic::Char<'v'>> +# +--format=auto +_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKca_E +<const_generic::Char<'\n'>> +# +--format=auto +_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E +<const_generic::Char<'\u{2202}'>> +# +--format=auto +_RNvNvMCs4fqI2P2rA04_13const_genericINtB4_3FooKpE3foo3FOO +<const_generic::Foo<_>>::foo::FOO |