diff options
-rw-r--r-- | include/ChangeLog | 18 | ||||
-rw-r--r-- | include/demangle.h | 11 | ||||
-rw-r--r-- | include/libiberty.h | 14 | ||||
-rw-r--r-- | include/longlong.h | 3 | ||||
-rw-r--r-- | libiberty/ChangeLog | 43 | ||||
-rw-r--r-- | libiberty/Makefile.in | 12 | ||||
-rw-r--r-- | libiberty/cp-demangle.c | 21 | ||||
-rw-r--r-- | libiberty/cplus-dem.c | 13 | ||||
-rw-r--r-- | libiberty/d-demangle.c | 1338 | ||||
-rw-r--r-- | libiberty/pex-common.c | 8 | ||||
-rw-r--r-- | libiberty/pex-common.h | 2 | ||||
-rw-r--r-- | libiberty/pex-djgpp.c | 6 | ||||
-rw-r--r-- | libiberty/pex-unix.c | 7 | ||||
-rw-r--r-- | libiberty/pex-win32.c | 6 | ||||
-rw-r--r-- | libiberty/simple-object-elf.c | 38 | ||||
-rw-r--r-- | libiberty/testsuite/Makefile.in | 14 | ||||
-rw-r--r-- | libiberty/testsuite/d-demangle-expected | 936 | ||||
-rw-r--r-- | libiberty/testsuite/demangle-expected | 8 | ||||
-rw-r--r-- | libiberty/testsuite/demangler-fuzzer.c | 108 |
19 files changed, 2576 insertions, 30 deletions
diff --git a/include/ChangeLog b/include/ChangeLog index f13af30..7acd73d 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,21 @@ +2014-09-26 Max Ostapenko <m.ostapenko@partner.samsung.com> + + * libiberty.h (PEX_STDOUT_APPEND): New flag. + (PEX_STDERR_APPEND): Likewise. + +2014-09-23 Iain Buclaw <ibuclaw@gdcproject.org> + + * demangle.h (DMGL_DLANG): New macro. + (DMGL_STYLE_MASK): Add DMGL_DLANG. + (demangling_styles): Add dlang_demangling. + (DLANG_DEMANGLING_STYLE_STRING): New macro. + (DLANG_DEMANGLING): New macro. + (dlang_demangle): New prototype. + +2014-09-15 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> + + * longlong.h: Add __udiv_w_sdiv prototype. + 2014-08-12 Alan Modra <amodra@gmail.com> * bfdlink.h (struct bfd_link_callbacks <notice>): Remove "string" diff --git a/include/demangle.h b/include/demangle.h index bbad71b..d2a6731 100644 --- a/include/demangle.h +++ b/include/demangle.h @@ -63,9 +63,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. @@ -87,7 +88,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. */ @@ -102,6 +104,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. */ @@ -115,6 +118,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. */ @@ -169,6 +173,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, diff --git a/include/libiberty.h b/include/libiberty.h index 78c42eb..bcc1f9a 100644 --- a/include/libiberty.h +++ b/include/libiberty.h @@ -106,7 +106,10 @@ extern int countargv (char**); to find the declaration so provide a fully prototyped one. If it is 1, we found it so don't provide any declaration at all. */ #if !HAVE_DECL_BASENAME -#if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__) || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__MINGW32__) || defined (HAVE_DECL_BASENAME) +#if defined (__GNU_LIBRARY__ ) || defined (__linux__) \ + || defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) \ + || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__MINGW32__) \ + || defined (__DragonFly__) || defined (HAVE_DECL_BASENAME) extern char *basename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1); #else /* Do not allow basename to be used if there is no prototype seen. We @@ -442,6 +445,11 @@ extern struct pex_obj *pex_init (int flags, const char *pname, on Unix. */ #define PEX_BINARY_ERROR 0x80 +/* Append stdout to existing file instead of truncating it. */ +#define PEX_STDOUT_APPEND 0x100 + +/* Thes same as PEX_STDOUT_APPEND, but for STDERR. */ +#define PEX_STDERR_APPEND 0x200 /* Execute one program. Returns NULL on success. On error returns an error string (typically just the name of a system call); the error @@ -633,6 +641,10 @@ extern int snprintf (char *, size_t, const char *, ...) ATTRIBUTE_PRINTF_3; extern int vsnprintf (char *, size_t, const char *, va_list) ATTRIBUTE_PRINTF(3,0); #endif +#if defined (HAVE_DECL_STRNLEN) && !HAVE_DECL_STRNLEN +extern size_t strnlen (const char *, size_t); +#endif + #if defined(HAVE_DECL_STRVERSCMP) && !HAVE_DECL_STRVERSCMP /* Compare version strings. */ extern int strverscmp (const char *, const char *); diff --git a/include/longlong.h b/include/longlong.h index 31f88cb..42c68dd 100644 --- a/include/longlong.h +++ b/include/longlong.h @@ -1687,7 +1687,8 @@ extern UHItype __stormy16_count_leading_zeros (UHItype); #if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) #define udiv_qrnnd(q, r, nh, nl, d) \ do { \ - USItype __r; \ + extern UWtype __udiv_w_sdiv (UWtype *, UWtype, UWtype, UWtype); \ + UWtype __r; \ (q) = __udiv_w_sdiv (&__r, nh, nl, d); \ (r) = __r; \ } while (0) diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index ddd96cc..829f684 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,46 @@ +2014-09-26 Jason Merrill <jason@redhat.com> + + * cp-demangle.c (d_substitution): Handle abi tags on abbreviation. + +2014-09-26 Max Ostapenko <m.ostapenko@partner.samsung.com> + + * pex-common.h (struct pex_funcs): Add new parameter for open_write field. + * pex-unix.c (pex_unix_open_write): Add support for new parameter. + * pex-djgpp.c (pex_djgpp_open_write): Likewise. + * pex-win32.c (pex_win32_open_write): Likewise. + * pex-common.c (pex_run_in_environment): Likewise. + +2014-09-23 Iain Buclaw <ibuclaw@gdcproject.org> + + * Makefile.in (CFILES): Add d-demangle.c. + (REQUIRED_OFILES): Add d-demangle.o. + * cplus-dem.c (libiberty_demanglers): Add dlang_demangling case. + (cplus_demangle): Likewise. + * d-demangle.c: New file. + * testsuite/Makefile.in (really-check): Add check-d-demangle. + * testsuite/d-demangle-expected: New file. + +2014-09-19 Ian Lance Taylor <iant@google.com> + + * simple-object-elf.c (simple_object_elf_write_ehdr): Correctly + handle objects with more than SHN_LORESERVE sections. + (simple_object_elf_write_shdr): Add sh_link parameter. + (simple_object_elf_write_to_file): Correctly handle objects with + more than SHN_LORESERVE sections. + +2014-08-29 Andrew Burgess <aburgess@broadcom.com> + + * cp-demangle.c (d_dump): Only access field from s_fixed part of + the union for DEMANGLE_COMPONENT_FIXED_TYPE. + (d_count_templates_scopes): Likewise. + +2014-08-13 Gary Benson <gbenson@redhat.com> + + * testsuite/demangler-fuzzer.c: New file. + * testsuite/Makefile.in (fuzz-demangler): New rule. + (demangler-fuzzer): Likewise. + (mostlyclean): Clean up demangler fuzzer. + 2014-06-11 Andrew Burgess <aburgess@broadcom.com> * cplus-dem.c (do_type): Call string_delete even if the call to diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in index 44e340f..9b87720 100644 --- a/libiberty/Makefile.in +++ b/libiberty/Makefile.in @@ -127,7 +127,7 @@ CFILES = alloca.c argv.c asprintf.c atexit.c \ basename.c bcmp.c bcopy.c bsearch.c bzero.c \ calloc.c choose-temp.c clock.c concat.c cp-demangle.c \ cp-demint.c cplus-dem.c crc32.c \ - dwarfnames.c dyn-string.c \ + d-demangle.c dwarfnames.c dyn-string.c \ fdmatch.c ffs.c fibheap.c filename_cmp.c floatformat.c \ fnmatch.c fopen_unlocked.c \ getcwd.c getopt.c getopt1.c getpagesize.c getpwd.c getruntime.c \ @@ -167,7 +167,7 @@ REQUIRED_OFILES = \ ./md5.$(objext) ./sha1.$(objext) ./alloca.$(objext) \ ./argv.$(objext) \ ./choose-temp.$(objext) ./concat.$(objext) \ - ./cp-demint.$(objext) ./crc32.$(objext) \ + ./cp-demint.$(objext) ./crc32.$(objext) ./d-demangle.$(objext) \ ./dwarfnames.$(objext) ./dyn-string.$(objext) \ ./fdmatch.$(objext) ./fibheap.$(objext) \ ./filename_cmp.$(objext) ./floatformat.$(objext) \ @@ -714,6 +714,14 @@ $(CONFIGURED_OFILES): stamp-picdir stamp-noasandir else true; fi $(COMPILE.c) $(srcdir)/dyn-string.c $(OUTPUT_OPTION) +./d-demangle.$(objext): $(srcdir)/d-demangle.c config.h $(INCDIR)/ansidecl.h \ + $(srcdir)/cp-demangle.h $(INCDIR)/demangle.h \ + $(INCDIR)/dyn-string.h $(INCDIR)/getopt.h $(INCDIR)/libiberty.h + if [ x"$(PICFLAG)" != x ]; then \ + $(COMPILE.c) $(PICFLAG) $(srcdir)/d-demangle.c -o pic/$@; \ + else true; fi + $(COMPILE.c) $(srcdir)/d-demangle.c $(OUTPUT_OPTION) + ./fdmatch.$(objext): $(srcdir)/fdmatch.c config.h $(INCDIR)/ansidecl.h \ $(INCDIR)/libiberty.h if [ x"$(PICFLAG)" != x ]; then \ diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index c0d2ffe..77c2cee9 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -713,7 +713,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"); @@ -3685,6 +3687,7 @@ d_substitution (struct d_info *di, int prefix) { const char *s; int len; + struct demangle_component *c; if (p->set_last_name != NULL) di->last_name = d_make_sub (di, p->set_last_name, @@ -3700,7 +3703,15 @@ d_substitution (struct d_info *di, int prefix) len = p->simple_len; } di->expansion += len; - return d_make_sub (di, s, len); + c = 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. */ + c = d_abi_tags (di, c); + d_add_substitution (di, c); + } + return c; } } @@ -3875,7 +3886,6 @@ 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: @@ -3920,6 +3930,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, diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c index 52767cc..c68b981 100644 --- a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -306,6 +306,12 @@ const struct demangler_engine libiberty_demanglers[] = } , { + DLANG_DEMANGLING_STYLE_STRING, + dlang_demangling, + "DLANG style demangling" + } + , + { NULL, unknown_demangling, NULL } }; @@ -870,6 +876,13 @@ 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); diff --git a/libiberty/d-demangle.c b/libiberty/d-demangle.c new file mode 100644 index 0000000..d31bf94 --- /dev/null +++ b/libiberty/d-demangle.c @@ -0,0 +1,1338 @@ +/* Demangler for the D programming language + Copyright 2014 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 <http://www.gnu.org/licenses/>. */ + +/* This file exports one function; dlang_demangle. + + This file imports strtol and strtold for decoding mangled literals. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "safe-ctype.h" + +#include <sys/types.h> +#include <string.h> +#include <stdio.h> + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#else +extern long strtol (const char *nptr, char **endptr, int base); +extern long double strtold (const char *nptr, char **endptr); +#endif + +#include <demangle.h> +#include "libiberty.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)); + } +} + +/* 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 *); + +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 mangled; + + 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; + default: + return NULL; + } + + 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 mangled; + + 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': + /* inout parameter is represented as 'Ng'. + vector parameter is represented as 'Nh'. + 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; + } + 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 mangled; + + /* 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++; + 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 "); + } + + 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 mangled; + + 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++; + 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); + case 'D': /* delegate T */ + mangled++; + mangled = dlang_function_type (decl, mangled); + string_append (decl, "delegate"); + return mangled; + case 'B': /* tuple T */ + mangled++; + return dlang_parse_tuple (decl, mangled); + + /* Function types */ + case 'F': case 'U': case 'W': + case 'V': case 'R': + mangled = dlang_function_type (decl, mangled); + string_append (decl, "function"); + return 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; + + 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) +{ + if (mangled == NULL || *mangled == '\0') + return mangled; + + if (ISDIGIT (*mangled)) + { + char *endptr; + long i = strtol (mangled, &endptr, 10); + + if (endptr == NULL || i <= 0 || strlen (endptr) < (size_t) i) + return NULL; + + mangled = endptr; + + /* May be a template instance. */ + if (i >= 5 && strncmp (mangled, "__T", 3) == 0) + { + /* Template symbol. */ + if (ISDIGIT (mangled[3]) && mangled[3] != '0') + return dlang_parse_template (decl, mangled, i); + + return NULL; + } + + if (strncmp (mangled, "__ctor", i) == 0) + { + /* Constructor symbol for a class/struct. */ + string_append (decl, "this"); + mangled += i; + return mangled; + } + else if (strncmp (mangled, "__dtor", i) == 0) + { + /* Destructor symbol for a class/struct. */ + string_append (decl, "~this"); + mangled += i; + return mangled; + } + else if (strncmp (mangled, "__postblit", i) == 0) + { + /* Postblit symbol for a struct. */ + string_append (decl, "this(this)"); + mangled += i; + return mangled; + } + else if (strncmp (mangled, "__initZ", i+1) == 0) + { + /* The static initialiser for a given symbol. */ + string_append (decl, "init$"); + mangled += i + 1; + return mangled; + } + else if (strncmp (mangled, "__ClassZ", i+1) == 0) + { + /* The classinfo symbol for a given class. */ + string_prepend (decl, "ClassInfo for "); + string_setlength (decl, string_length (decl) - 1); + mangled += i + 1; + return mangled; + } + else if (strncmp (mangled, "__vtblZ", i+1) == 0) + { + /* The vtable symbol for a given class. */ + string_prepend (decl, "vtable for "); + string_setlength (decl, string_length (decl) - 1); + mangled += i + 1; + return mangled; + } + else if (strncmp (mangled, "__InterfaceZ", i+1) == 0) + { + /* The interface symbol for a given class. */ + string_prepend (decl, "Interface for "); + string_setlength (decl, string_length (decl) - 1); + mangled += i + 1; + return mangled; + } + else if (strncmp (mangled, "__ModuleInfoZ", i+1) == 0) + { + /* The ModuleInfo symbol for a given module. */ + string_prepend (decl, "ModuleInfo for "); + string_setlength (decl, string_length (decl) - 1); + mangled += i + 1; + return mangled; + } + + string_appendn (decl, mangled, i); + mangled += i; + } + else + return NULL; + + 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; + long double value; + char *endptr; + + /* 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++; + } + + /* Convert buffer from hexadecimal to floating-point. */ + buffer[len] = '\0'; + value = strtold (buffer, &endptr); + + if (endptr == NULL || endptr != (buffer + len)) + return NULL; + + len = snprintf (buffer, sizeof(buffer), "%#Lg", value); + 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; + string_appendn (decl, &val, 1); + } + 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 mangled; + + 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; +} + +static int +dlang_call_convention_p (const char *mangled) +{ + size_t i; + + switch (*mangled) + { + case 'F': case 'U': case 'V': + case 'W': case 'R': + return 1; + + case 'M': /* Prefix for functions needing 'this' */ + i = 1; + if (mangled[i] == 'x') + i++; + + switch (mangled[i]) + { + case 'F': case 'U': case 'V': + case 'W': case 'R': + 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) +{ + size_t n = 0; + do + { + if (n++) + string_append (decl, "."); + + mangled = dlang_identifier (decl, mangled); + + if (mangled && dlang_call_convention_p (mangled)) + { + int saved; + + /* Skip over 'this' parameter. */ + if (*mangled == 'M') + mangled += (mangled[1] == 'x') ? 2 : 1; + + /* 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, ")"); + + /* Demangle the function return type as a kind of sanity test. */ + if (mangled && !ISDIGIT (*mangled)) + { + saved = string_length (decl); + mangled = dlang_type (decl, mangled); + string_setlength (decl, saved); + } + } + } + while (mangled && ISDIGIT (*mangled)); + + 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, ", "); + + switch (*mangled) + { + case 'S': /* Symbol parameter. */ + mangled++; + mangled = dlang_parse_symbol (decl, mangled); + 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); + + /* 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) == NULL) + string_delete (&decl); + } + + if (string_length (&decl) > 0) + { + string_need (&decl, 1); + *(decl.p) = '\0'; + demangled = decl.b; + } + + return demangled; +} + diff --git a/libiberty/pex-common.c b/libiberty/pex-common.c index 6fd3fde..146010a 100644 --- a/libiberty/pex-common.c +++ b/libiberty/pex-common.c @@ -267,7 +267,8 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable, if (out < 0) { out = obj->funcs->open_write (obj, outname, - (flags & PEX_BINARY_OUTPUT) != 0); + (flags & PEX_BINARY_OUTPUT) != 0, + (flags & PEX_STDOUT_APPEND) != 0); if (out < 0) { *err = errno; @@ -319,8 +320,9 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable, } else { - errdes = obj->funcs->open_write (obj, errname, - (flags & PEX_BINARY_ERROR) != 0); + errdes = obj->funcs->open_write (obj, errname, + (flags & PEX_BINARY_ERROR) != 0, + (flags & PEX_STDERR_APPEND) != 0); if (errdes < 0) { *err = errno; diff --git a/libiberty/pex-common.h b/libiberty/pex-common.h index af338e6..b6db248 100644 --- a/libiberty/pex-common.h +++ b/libiberty/pex-common.h @@ -104,7 +104,7 @@ struct pex_funcs /* Open file NAME for writing. If BINARY is non-zero, open in binary mode. Return >= 0 on success, -1 on error. */ int (*open_write) (struct pex_obj *, const char */* name */, - int /* binary */); + int /* binary */, int /* append */); /* Execute a child process. FLAGS, EXECUTABLE, ARGV, ERR are from pex_run. IN, OUT, ERRDES, TOCLOSE are all descriptors, from open_read, open_write, or pipe, or they are one of STDIN_FILE_NO, diff --git a/libiberty/pex-djgpp.c b/libiberty/pex-djgpp.c index 0721139..b014ffa 100644 --- a/libiberty/pex-djgpp.c +++ b/libiberty/pex-djgpp.c @@ -43,7 +43,7 @@ extern int errno; #endif static int pex_djgpp_open_read (struct pex_obj *, const char *, int); -static int pex_djgpp_open_write (struct pex_obj *, const char *, int); +static int pex_djgpp_open_write (struct pex_obj *, const char *, int, int); static pid_t pex_djgpp_exec_child (struct pex_obj *, int, const char *, char * const *, char * const *, int, int, int, int, @@ -90,10 +90,12 @@ pex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, static int pex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, - const char *name, int binary) + const char *name, int binary, int append) { /* Note that we can't use O_EXCL here because gcc may have already created the temporary file via make_temp_file. */ + if (append) + return -1; return open (name, (O_WRONLY | O_CREAT | O_TRUNC | (binary ? O_BINARY : O_TEXT)), diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c index addf8ee..0715115 100644 --- a/libiberty/pex-unix.c +++ b/libiberty/pex-unix.c @@ -301,7 +301,7 @@ pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time) static void pex_child_error (struct pex_obj *, const char *, const char *, int) ATTRIBUTE_NORETURN; static int pex_unix_open_read (struct pex_obj *, const char *, int); -static int pex_unix_open_write (struct pex_obj *, const char *, int); +static int pex_unix_open_write (struct pex_obj *, const char *, int, int); static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *, char * const *, char * const *, int, int, int, int, @@ -350,11 +350,12 @@ pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, static int pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, - int binary ATTRIBUTE_UNUSED) + int binary ATTRIBUTE_UNUSED, int append) { /* Note that we can't use O_EXCL here because gcc may have already created the temporary file via make_temp_file. */ - return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE); + return open (name, O_WRONLY | O_CREAT + | (append ? O_APPEND : O_TRUNC), PUBLIC_MODE); } /* Close a file. */ diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c index 8b9d4f0..66d2f11 100644 --- a/libiberty/pex-win32.c +++ b/libiberty/pex-win32.c @@ -78,7 +78,7 @@ backslashify (char *s) } static int pex_win32_open_read (struct pex_obj *, const char *, int); -static int pex_win32_open_write (struct pex_obj *, const char *, int); +static int pex_win32_open_write (struct pex_obj *, const char *, int, int); static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *, char * const *, char * const *, int, int, int, int, @@ -126,10 +126,12 @@ pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, static int pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, - int binary) + int binary, int append) { /* Note that we can't use O_EXCL here because gcc may have already created the temporary file via make_temp_file. */ + if (append) + return -1; return _open (name, (_O_WRONLY | _O_CREAT | _O_TRUNC | (binary ? _O_BINARY : _O_TEXT)), diff --git a/libiberty/simple-object-elf.c b/libiberty/simple-object-elf.c index 4196c53..8594cf9 100644 --- a/libiberty/simple-object-elf.c +++ b/libiberty/simple-object-elf.c @@ -698,6 +698,7 @@ simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor, unsigned char buf[sizeof (Elf64_External_Ehdr)]; simple_object_write_section *section; unsigned int shnum; + unsigned int shstrndx; fns = attrs->type_functions; cl = attrs->ei_class; @@ -743,9 +744,17 @@ simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor, (cl == ELFCLASS32 ? sizeof (Elf32_External_Shdr) : sizeof (Elf64_External_Shdr))); - ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half, shnum); - ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half, - shnum == 0 ? 0 : shnum - 1); + ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half, + shnum >= SHN_LORESERVE ? 0 : shnum); + if (shnum == 0) + shstrndx = 0; + else + { + shstrndx = shnum - 1; + if (shstrndx >= SHN_LORESERVE) + shstrndx = SHN_XINDEX; + } + ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half, shstrndx); return simple_object_internal_write (descriptor, 0, buf, ehdr_size, errmsg, err); @@ -758,8 +767,8 @@ simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor, off_t offset, unsigned int sh_name, unsigned int sh_type, unsigned int sh_flags, unsigned int sh_offset, unsigned int sh_size, - unsigned int sh_addralign, const char **errmsg, - int *err) + unsigned int sh_link, unsigned int sh_addralign, + const char **errmsg, int *err) { struct simple_object_elf_attributes *attrs = (struct simple_object_elf_attributes *) sobj->data; @@ -781,7 +790,7 @@ simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor, ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags); ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset); ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size); - /* sh_link left as zero. */ + ELF_SET_FIELD (fns, cl, Shdr, buf, sh_link, Elf_Word, sh_link); /* sh_info left as zero. */ ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign); /* sh_entsize left as zero. */ @@ -812,6 +821,8 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, unsigned int shnum; size_t shdr_offset; size_t sh_offset; + unsigned int first_sh_size; + unsigned int first_sh_link; size_t sh_name; unsigned char zero; @@ -842,8 +853,17 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, shdr_offset = ehdr_size; sh_offset = shdr_offset + shnum * shdr_size; + if (shnum < SHN_LORESERVE) + first_sh_size = 0; + else + first_sh_size = shnum; + if (shnum - 1 < SHN_LORESERVE) + first_sh_link = 0; + else + first_sh_link = shnum - 1; if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, - 0, 0, 0, 0, 0, 0, &errmsg, err)) + 0, 0, 0, 0, first_sh_size, first_sh_link, + 0, &errmsg, err)) return errmsg; shdr_offset += shdr_size; @@ -887,7 +907,7 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, sh_name, SHT_PROGBITS, 0, sh_offset, - sh_size, 1U << section->align, + sh_size, 0, 1U << section->align, &errmsg, err)) return errmsg; @@ -898,7 +918,7 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, sh_name, SHT_STRTAB, 0, sh_offset, - sh_name + strlen (".shstrtab") + 1, + sh_name + strlen (".shstrtab") + 1, 0, 1, &errmsg, err)) return errmsg; diff --git a/libiberty/testsuite/Makefile.in b/libiberty/testsuite/Makefile.in index 69ac1f5..bb2db67 100644 --- a/libiberty/testsuite/Makefile.in +++ b/libiberty/testsuite/Makefile.in @@ -45,12 +45,15 @@ all: # CHECK is set to "really_check" or the empty string by configure. check: @CHECK@ -really-check: check-cplus-dem check-pexecute check-expandargv +really-check: check-cplus-dem check-d-demangle check-pexecute check-expandargv # Run some tests of the demangler. check-cplus-dem: test-demangle $(srcdir)/demangle-expected ./test-demangle < $(srcdir)/demangle-expected +check-d-demangle: test-demangle $(srcdir)/d-demangle-expected + ./test-demangle < $(srcdir)/d-demangle-expected + # Check the pexecute code. check-pexecute: test-pexecute ./test-pexecute @@ -59,6 +62,10 @@ check-pexecute: test-pexecute check-expandargv: test-expandargv ./test-expandargv +# Run the demangler fuzzer +fuzz-demangler: demangler-fuzzer + ./demangler-fuzzer + TEST_COMPILE = $(CC) @DEFS@ $(LIBCFLAGS) -I.. -I$(INCDIR) $(HDEFINES) test-demangle: $(srcdir)/test-demangle.c ../libiberty.a $(TEST_COMPILE) -o test-demangle \ @@ -72,6 +79,10 @@ test-expandargv: $(srcdir)/test-expandargv.c ../libiberty.a $(TEST_COMPILE) -DHAVE_CONFIG_H -I.. -o test-expandargv \ $(srcdir)/test-expandargv.c ../libiberty.a +demangler-fuzzer: $(srcdir)/demangler-fuzzer.c ../libiberty.a + $(TEST_COMPILE) -o demangler-fuzzer \ + $(srcdir)/demangler-fuzzer.c ../libiberty.a + # Standard (either GNU or Cygnus) rules we don't use. html install-html info install-info clean-info dvi pdf install-pdf \ install etags tags installcheck: @@ -81,6 +92,7 @@ mostlyclean: rm -f test-demangle rm -f test-pexecute rm -f test-expandargv + rm -f demangler-fuzzer rm -f core clean: mostlyclean distclean: clean diff --git a/libiberty/testsuite/d-demangle-expected b/libiberty/testsuite/d-demangle-expected new file mode 100644 index 0000000..2aeacb8 --- /dev/null +++ b/libiberty/testsuite/d-demangle-expected @@ -0,0 +1,936 @@ +# This file holds test cases for the D demangler. +# Each test case looks like this: +# options +# input to be demangled +# expected output +# +# See demangle-expected for documentation of supported options. +# +# A line starting with `#' is ignored. +# However, blank lines in this file are NOT ignored. +# +############ +# +# Coverage Tests +# +--format=dlang +_Dmain +D main +# +--format=dlang +_D8demangle4testPFLAiYi +demangle.test +# +--format=dlang +_D8demangle4testFaZv +demangle.test(char) +# +--format=dlang +_D8demangle4testFbZv +demangle.test(bool) +# +--format=dlang +_D8demangle4testFcZv +demangle.test(creal) +# +--format=dlang +_D8demangle4testFdZv +demangle.test(double) +# +--format=dlang +_D8demangle4testFeZv +demangle.test(real) +# +--format=dlang +_D8demangle4testFfZv +demangle.test(float) +# +--format=dlang +_D8demangle4testFgZv +demangle.test(byte) +# +--format=dlang +_D8demangle4testFhZv +demangle.test(ubyte) +# +--format=dlang +_D8demangle4testFiZv +demangle.test(int) +# +--format=dlang +_D8demangle4testFjZv +demangle.test(ireal) +# +--format=dlang +_D8demangle4testFkZv +demangle.test(uint) +# +--format=dlang +_D8demangle4testFlZv +demangle.test(long) +# +--format=dlang +_D8demangle4testFmZv +demangle.test(ulong) +# +--format=dlang +_D8demangle4testFnZv +demangle.test(none) +# +--format=dlang +_D8demangle4testFoZv +demangle.test(ifloat) +# +--format=dlang +_D8demangle4testFpZv +demangle.test(idouble) +# +--format=dlang +_D8demangle4testFqZv +demangle.test(cfloat) +# +--format=dlang +_D8demangle4testFrZv +demangle.test(cdouble) +# +--format=dlang +_D8demangle4testFsZv +demangle.test(short) +# +--format=dlang +_D8demangle4testFtZv +demangle.test(ushort) +# +--format=dlang +_D8demangle4testFuZv +demangle.test(wchar) +# +--format=dlang +_D8demangle4testFvZv +demangle.test(void) +# +--format=dlang +_D8demangle4testFwZv +demangle.test(dchar) +# +--format=dlang +_D8demangle4testFOaZv +demangle.test(shared(char)) +# +--format=dlang +_D8demangle4testFxaZv +demangle.test(const(char)) +# +--format=dlang +_D8demangle4testFyaZv +demangle.test(immutable(char)) +# +--format=dlang +_D8demangle4testFNgaZv +demangle.test(inout(char)) +# +--format=dlang +_D8demangle4testFOxaZv +demangle.test(shared(const(char))) +# +--format=dlang +_D8demangle4testFONgaZv +demangle.test(shared(inout(char))) +# +--format=dlang +_D8demangle4testFAaZv +demangle.test(char[]) +# +--format=dlang +_D8demangle4testFAAaZv +demangle.test(char[][]) +# +--format=dlang +_D8demangle4testFAAAaZv +demangle.test(char[][][]) +# +--format=dlang +_D8demangle4testFG42aZv +demangle.test(char[42]) +# +--format=dlang +_D8demangle4testFG42G42aZv +demangle.test(char[42][42]) +# +--format=dlang +_D8demangle4testFG42G42G42aZv +demangle.test(char[42][42][42]) +# +--format=dlang +_D8demangle4testFG1234567890aZv +demangle.test(char[1234567890]) +# +--format=dlang +_D8demangle4testFHaaZv +demangle.test(char[char]) +# +--format=dlang +_D8demangle4testFHHaaaZv +demangle.test(char[char[char]]) +# +--format=dlang +_D8demangle4testFPaZv +demangle.test(char*) +# +--format=dlang +_D8demangle4testFPPaZv +demangle.test(char**) +# +--format=dlang +_D8demangle4testFPPPaZv +demangle.test(char***) +# +--format=dlang +_D8demangle4testFNhG8gZv +demangle.test(__vector(byte[8])) +# +--format=dlang +_D8demangle4testFNhG16gZv +demangle.test(__vector(byte[16])) +# +--format=dlang +_D8demangle4testFNhG32gZv +demangle.test(__vector(byte[32])) +# +--format=dlang +_D8demangle4testFNhG4sZv +demangle.test(__vector(short[4])) +# +--format=dlang +_D8demangle4testFNhG8sZv +demangle.test(__vector(short[8])) +# +--format=dlang +_D8demangle4testFNhG16sZv +demangle.test(__vector(short[16])) +# +--format=dlang +_D8demangle4testFNhG2iZv +demangle.test(__vector(int[2])) +# +--format=dlang +_D8demangle4testFNhG4iZv +demangle.test(__vector(int[4])) +# +--format=dlang +_D8demangle4testFNhG8iZv +demangle.test(__vector(int[8])) +# +--format=dlang +_D8demangle4testFNhG1lZv +demangle.test(__vector(long[1])) +# +--format=dlang +_D8demangle4testFNhG2lZv +demangle.test(__vector(long[2])) +# +--format=dlang +_D8demangle4testFNhG4lZv +demangle.test(__vector(long[4])) +# +--format=dlang +_D8demangle4testFNhG2fZv +demangle.test(__vector(float[2])) +# +--format=dlang +_D8demangle4testFNhG4fZv +demangle.test(__vector(float[4])) +# +--format=dlang +_D8demangle4testFNhG8fZv +demangle.test(__vector(float[8])) +# +--format=dlang +_D8demangle4testFNhG1dZv +demangle.test(__vector(double[1])) +# +--format=dlang +_D8demangle4testFNhG2dZv +demangle.test(__vector(double[2])) +# +--format=dlang +_D8demangle4testFNhG4dZv +demangle.test(__vector(double[4])) +# +--format=dlang +_D8demangle4testFI5identZv +demangle.test(ident) +# +--format=dlang +_D8demangle4testFI5ident4testZv +demangle.test(ident.test) +# +--format=dlang +_D8demangle4testFC5classZv +demangle.test(class) +# +--format=dlang +_D8demangle4testFC5class4testZv +demangle.test(class.test) +# +--format=dlang +_D8demangle4testFS6structZv +demangle.test(struct) +# +--format=dlang +_D8demangle4testFS6struct4testZv +demangle.test(struct.test) +# +--format=dlang +_D8demangle4testFE4enumZv +demangle.test(enum) +# +--format=dlang +_D8demangle4testFE4enum4testZv +demangle.test(enum.test) +# +--format=dlang +_D8demangle4testFT7typedefZv +demangle.test(typedef) +# +--format=dlang +_D8demangle4testFT7typedef4testZv +demangle.test(typedef.test) +# +--format=dlang +_D8demangle4testFJaZv +demangle.test(out char) +# +--format=dlang +_D8demangle4testFKaZv +demangle.test(ref char) +# +--format=dlang +_D8demangle4testFLaZv +demangle.test(lazy char) +# +--format=dlang +_D8demangle4testFMaZv +demangle.test(scope char) +# +--format=dlang +_D8demangle4testFaXv +demangle.test(char...) +# +--format=dlang +_D8demangle4testFaYv +demangle.test(char, ...) +# +--format=dlang +_D8demangle4testFaaYv +demangle.test(char, char, ...) +# +--format=dlang +_D8demangle4testFaaZv +demangle.test(char, char) +# +--format=dlang +_D8demangle4testFB0Zv +demangle.test(Tuple!()) +# +--format=dlang +_D8demangle4testFB1aZv +demangle.test(Tuple!(char)) +# +--format=dlang +_D8demangle4testFB2aaZv +demangle.test(Tuple!(char, char)) +# +--format=dlang +_D8demangle4testFB3aaaZv +demangle.test(Tuple!(char, char, char)) +# +--format=dlang +_D8demangle4testFB2OaaZv +demangle.test(Tuple!(shared(char), char)) +# +--format=dlang +_D8demangle4testFB3aDFZaaZv +demangle.test(Tuple!(char, char() delegate, char)) +# +--format=dlang +_D8demangle4testFDFZaZv +demangle.test(char() delegate) +# +--format=dlang +_D8demangle4testFDUZaZv +demangle.test(extern(C) char() delegate) +# +--format=dlang +_D8demangle4testFDWZaZv +demangle.test(extern(Windows) char() delegate) +# +--format=dlang +_D8demangle4testFDVZaZv +demangle.test(extern(Pascal) char() delegate) +# +--format=dlang +_D8demangle4testFDRZaZv +demangle.test(extern(C++) char() delegate) +# +--format=dlang +_D8demangle4testFFZaZv +demangle.test(char() function) +# +--format=dlang +_D8demangle4testFUZaZv +demangle.test(extern(C) char() function) +# +--format=dlang +_D8demangle4testFWZaZv +demangle.test(extern(Windows) char() function) +# +--format=dlang +_D8demangle4testFVZaZv +demangle.test(extern(Pascal) char() function) +# +--format=dlang +_D8demangle4testFRZaZv +demangle.test(extern(C++) char() function) +# +--format=dlang +_D8demangle4testFDFNaZaZv +demangle.test(char() pure delegate) +# +--format=dlang +_D8demangle4testFDFNbZaZv +demangle.test(char() nothrow delegate) +# +--format=dlang +_D8demangle4testFDFNcZaZv +demangle.test(char() ref delegate) +# +--format=dlang +_D8demangle4testFDFNdZaZv +demangle.test(char() @property delegate) +# +--format=dlang +_D8demangle4testFDFNeZaZv +demangle.test(char() @trusted delegate) +# +--format=dlang +_D8demangle4testFDFNfZaZv +demangle.test(char() @safe delegate) +# +--format=dlang +_D8demangle4testFDFNiZaZv +demangle.test(char() @nogc delegate) +# +--format=dlang +_D8demangle4testFDFNaNbZaZv +demangle.test(char() pure nothrow delegate) +# +--format=dlang +_D8demangle4testFDFNbNaZaZv +demangle.test(char() nothrow pure delegate) +# +--format=dlang +_D8demangle4testFDFNdNfNaZaZv +demangle.test(char() @property @safe pure delegate) +# +--format=dlang +_D8demangle4testFFNaZaZv +demangle.test(char() pure function) +# +--format=dlang +_D8demangle4testFFNbZaZv +demangle.test(char() nothrow function) +# +--format=dlang +_D8demangle4testFFNcZaZv +demangle.test(char() ref function) +# +--format=dlang +_D8demangle4testFFNdZaZv +demangle.test(char() @property function) +# +--format=dlang +_D8demangle4testFFNeZaZv +demangle.test(char() @trusted function) +# +--format=dlang +_D8demangle4testFFNfZaZv +demangle.test(char() @safe function) +# +--format=dlang +_D8demangle4testFFNiZaZv +demangle.test(char() @nogc function) +# +--format=dlang +_D8demangle4testFFNaNbZaZv +demangle.test(char() pure nothrow function) +# +--format=dlang +_D8demangle4testFFNbNaZaZv +demangle.test(char() nothrow pure function) +# +--format=dlang +_D8demangle4testFFNdNfNaZaZv +demangle.test(char() @property @safe pure function) +# +--format=dlang +_D8demangle4test6__initZ +demangle.test.init$ +# +--format=dlang +_D8demangle4test6__vtblZ +vtable for demangle.test +# +--format=dlang +_D8demangle4test7__ClassZ +ClassInfo for demangle.test +# +--format=dlang +_D8demangle4test11__InterfaceZ +Interface for demangle.test +# +--format=dlang +_D8demangle4test12__ModuleInfoZ +ModuleInfo for demangle.test +# +--format=dlang +_D8demangle4test6__ctorMFZv +demangle.test.this() +# +--format=dlang +_D8demangle4test6__dtorMFZv +demangle.test.~this() +# +--format=dlang +_D8demangle4test6__postblitMFZv +demangle.test.this(this) +# +--format=dlang +_D8demangle4testFHAbaZv +demangle.test(char[bool[]]) +# +--format=dlang +_D8demangle4testFHG42caZv +demangle.test(char[creal[42]]) +# +--format=dlang +_D8demangle4testFAiXv +demangle.test(int[]...) +# +--format=dlang +_D8demangle4testFLAiXv +demangle.test(lazy int[]...) +# +--format=dlang +_D8demangle4testFAiYv +demangle.test(int[], ...) +# +--format=dlang +_D8demangle4testFLAiYv +demangle.test(lazy int[], ...) +# +--format=dlang +_D8demangle4testFLilZv +demangle.test(lazy int, long) +# +--format=dlang +_D8demangle4testFLliZv +demangle.test(lazy long, int) +# +--format=dlang +_D8demangle4testFLC6ObjectLDFLiZiZi +demangle.test(lazy Object, lazy int(lazy int) delegate) +# +--format=dlang +_D8demangle9__T4testZv +demangle.test!() +# +--format=dlang +_D8demangle11__T4testTaZv +demangle.test!(char) +# +--format=dlang +_D8demangle13__T4testTaTaZv +demangle.test!(char, char) +# +--format=dlang +_D8demangle15__T4testTaTaTaZv +demangle.test!(char, char, char) +# +--format=dlang +_D8demangle16__T4testTaTOiTaZv +demangle.test!(char, shared(int), char) +# +--format=dlang +_D8demangle17__T4testS6symbolZv +demangle.test!(symbol) +# +--format=dlang +_D8demangle21__T4testS6symbol3fooZv +demangle.test!(symbol.foo) +# +--format=dlang +_D8demangle25__T4testS6symbol3foo3barZv +demangle.test!(symbol.foo.bar) +# +--format=dlang +_D8demangle19__T4testTaS6symbolZv +demangle.test!(char, symbol) +# +--format=dlang +_D8demangle19__T4testS6symbolTaZv +demangle.test!(symbol, char) +# +--format=dlang +_D8demangle13__T4testVPinZv +demangle.test!(null) +# +--format=dlang +_D8demangle14__T4testVg123Zv +demangle.test!(123) +# +--format=dlang +_D8demangle14__T4testVi123Zv +demangle.test!(123) +# +--format=dlang +_D8demangle14__T4testVs123Zv +demangle.test!(123) +# +--format=dlang +_D8demangle14__T4testVh123Zv +demangle.test!(123u) +# +--format=dlang +_D8demangle14__T4testVk123Zv +demangle.test!(123u) +# +--format=dlang +_D8demangle14__T4testVt123Zv +demangle.test!(123u) +# +--format=dlang +_D8demangle14__T4testVl123Zv +demangle.test!(123L) +# +--format=dlang +_D8demangle14__T4testVm123Zv +demangle.test!(123uL) +# +--format=dlang +_D8demangle15__T4testViN123Zv +demangle.test!(-123) +# +--format=dlang +_D8demangle15__T4testVkN123Zv +demangle.test!(-123u) +# +--format=dlang +_D8demangle15__T4testVlN123Zv +demangle.test!(-123L) +# +--format=dlang +_D8demangle15__T4testVmN123Zv +demangle.test!(-123uL) +# +--format=dlang +_D8demangle12__T4testVb1Zv +demangle.test!(true) +# +--format=dlang +_D8demangle12__T4testVb0Zv +demangle.test!(false) +# +--format=dlang +_D8demangle13__T4testVa10Zv +demangle.test!('\x0a') +# +--format=dlang +_D8demangle13__T4testVa32Zv +demangle.test!(' ') +# +--format=dlang +_D8demangle13__T4testVa65Zv +demangle.test!('A') +# +--format=dlang +_D8demangle14__T4testVa126Zv +demangle.test!('~') +# +--format=dlang +_D8demangle15__T4testVu1000Zv +demangle.test!('\u03e8') +# +--format=dlang +_D8demangle17__T4testVw100000Zv +demangle.test!('\U000186a0') +# +--format=dlang +_D8demangle17__T4testVde0A8P6Zv +demangle.test!(42.0000) +# +--format=dlang +_D8demangle16__T4testVdeA8P2Zv +demangle.test!(42.0000) +# +--format=dlang +_D8demangle18__T4testVdeN0A8P6Zv +demangle.test!(-42.0000) +# +--format=dlang +_D8demangle31__T4testVde0F6E978D4FDF3B646P7Zv +demangle.test!(123.456) +# +--format=dlang +_D8demangle15__T4testVdeNANZv +demangle.test!(NaN) +# +--format=dlang +_D8demangle15__T4testVdeINFZv +demangle.test!(Inf) +# +--format=dlang +_D8demangle16__T4testVdeNINFZv +demangle.test!(-Inf) +# +--format=dlang +_D8demangle23__T4testVfe0FFFFFFP128Zv +demangle.test!(3.40282e+38) +# +--format=dlang +_D8demangle32__T4testVde0FFFFFFFFFFFFF8P1024Zv +demangle.test!(1.79769e+308) +# +--format=dlang +_D8demangle19__T4testVfe08PN125Zv +demangle.test!(1.17549e-38) +# +--format=dlang +_D8demangle20__T4testVde08PN1021Zv +demangle.test!(2.22507e-308) +# +--format=dlang +_D8demangle51__T4testVrc0C4CCCCCCCCCCCCCDP4c0B666666666666666P6Zv +demangle.test!(12.3000+45.6000i) +# +--format=dlang +_D8demangle52__T4testVrcN0C4CCCCCCCCCCCCCDP4c0B666666666666666P6Zv +demangle.test!(-12.3000+45.6000i) +# +--format=dlang +_D8demangle22__T4testVG3ua3_616263Zv +demangle.test!("abc") +# +--format=dlang +_D8demangle22__T4testVG3ud3_616263Zv +demangle.test!("abc"d) +# +--format=dlang +_D8demangle22__T4testVG3uw3_616263Zv +demangle.test!("abc"w) +# +--format=dlang +_D8demangle22__T4testVAiA4i1i2i3i4Zv +demangle.test!([1, 2, 3, 4]) +# +--format=dlang +_D8demangle25__T4testVAdA2e08P1eN08P1Zv +demangle.test!([1.00000, -1.00000]) +# +--format=dlang +_D8demangle23__T4testVHiiA2i1i2i3i4Zv +demangle.test!([1:2, 3:4]) +# +--format=dlang +_D8demangle39__T4testVHAxaiA2a3_616263i1a3_646566i2Zv +demangle.test!(["abc":1, "def":2]) +# +--format=dlang +_D8demangle28__T4testVS8demangle1SS2i1i2Zv +demangle.test!(demangle.S(1, 2)) +# +--format=dlang +_D8demangle35__T4testVS8demangle1SS2i1a3_616263Zv +demangle.test!(demangle.S(1, "abc")) +# +# Unittests +# +--format=dlang +printf +printf +# +--format=dlang +_foo +_foo +# +--format=dlang +_D88 +_D88 +# +--format=dlang +_D5__T1aZv +_D5__T1aZv +# +--format=dlang +_D4test3fooAa +test.foo +# +--format=dlang +_D8demangle8demangleFAaZAa +demangle.demangle(char[]) +# +--format=dlang +_D6object6Object8opEqualsFC6ObjectZi +object.Object.opEquals(Object) +# +--format=dlang +_D6object6Object8opAssignFC6ObjectZi +object.Object.opAssign(Object) +# +--format=dlang +_D4test2dgDFiYd +test.dg +# +--format=dlang +_D1a1bi +a.b +# +--format=dlang +_D1a1bPFiZi +a.b +# +--format=dlang +_D4test34__T3barVG3uw3_616263VG3wd3_646566Z1xi +test.bar!("abc"w, "def"d).x +# +--format=dlang +_D6plugin8generateFiiZAya +plugin.generate(int, int) +# +--format=dlang +_D6plugin8generateFiiZAxa +plugin.generate(int, int) +# +--format=dlang +_D6plugin8generateFiiZAOa +plugin.generate(int, int) +# +--format=dlang +_D8demangle3fnAFZv3fnBMFZv +demangle.fnA().fnB() +# +--format=dlang +_D8demangle4mainFZv1S3fnCFZv +demangle.main().S.fnC() +# +--format=dlang +_D8demangle4mainFZv1S3fnDMFZv +demangle.main().S.fnD() +# +--format=dlang +_D8demangle4mainFZv5localMFZi +demangle.main().local() +# +--format=dlang +_D3std5ascii9uppercaseyAa +std.ascii.uppercase +# +--format=dlang +_D3std6stream9BOMEndianyG5E3std6system6Endian +std.stream.BOMEndian +# +--format=dlang +_D3std8internal7uni_tab10unicodeNkoyS3std8internal3uni12CodepointSet +std.internal.uni_tab.unicodeNko +# +--format=dlang +_D2gc2gc2GC6addrOfMFPvZPv +gc.gc.GC.addrOf(void*) +# +--format=dlang +_D3std7process10setCLOEXECFibZv +std.process.setCLOEXEC(int, bool) +# +--format=dlang +_D3std6digest2md3MD53putMFNaNbNeMAxhXv +std.digest.md.MD5.put(scope const(ubyte)[]...) +# +--format=dlang +_D3std6mmfile6MmFile13opIndexAssignMFhmZh +std.mmfile.MmFile.opIndexAssign(ubyte, ulong) +# +--format=dlang +_D3std7process18escapeShellCommandFxAAaXAya +std.process.escapeShellCommand(const(char[][])...) +# +--format=dlang +_D4core4sync5mutex5Mutex6__ctorMFC6ObjectZC4core4sync5mutex5Mutex +core.sync.mutex.Mutex.this(Object) +# +--format=dlang +_D6object14TypeInfo_Array8argTypesMFNbNfJC8TypeInfoJC8TypeInfoZi +object.TypeInfo_Array.argTypes(out TypeInfo, out TypeInfo) +# +--format=dlang +_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZi7tryExecMFMDFZvZv +rt.dmain2._d_run_main(int, char**, extern(C) int(char[][]) function*).tryExec(scope void() delegate) +# +--format=dlang +_D6object9Exception6__ctorMFNaNbNfAyaAyamC6object9ThrowableZC9Exception +object.Exception.this(immutable(char)[], immutable(char)[], ulong, object.Throwable) +# +--format=dlang +_D3gcc3deh17parse_lsda_headerFPS3gcc6unwind7generic15_Unwind_ContextPhPS3gcc3deh16lsda_header_infoZPh +gcc.deh.parse_lsda_header(gcc.unwind.generic._Unwind_Context*, ubyte*, gcc.deh.lsda_header_info*) +# +--format=dlang +_D3std6socket23UnknownAddressReference6__ctorMFPS4core3sys5posix3sys6socket8sockaddrkZC3std6socket23UnknownAddressReference +std.socket.UnknownAddressReference.this(core.sys.posix.sys.socket.sockaddr*, uint) +# +--format=dlang +_D8demangle20__T2fnVAiA4i1i2i3i4Z2fnFZv +demangle.fn!([1, 2, 3, 4]).fn() +# +--format=dlang +_D8demangle10__T2fnVi1Z2fnFZv +demangle.fn!(1).fn() +# +--format=dlang +_D8demangle26__T2fnVS8demangle1SS2i1i2Z2fnFZv +demangle.fn!(demangle.S(1, 2)).fn() +# +--format=dlang +_D8demangle13__T2fnVeeNANZ2fnFZv +demangle.fn!(NaN).fn() +# +--format=dlang +_D8demangle14__T2fnVeeNINFZ2fnFZv +demangle.fn!(-Inf).fn() +# +--format=dlang +_D8demangle13__T2fnVeeINFZ2fnFZv +demangle.fn!(Inf).fn() +# +--format=dlang +_D8demangle21__T2fnVHiiA2i1i2i3i4Z2fnFZv +demangle.fn!([1:2, 3:4]).fn() +# +--format=dlang +_D8demangle2fnFNgiZNgi +demangle.fn(inout(int)) +# +--format=dlang +_D8demangle29__T2fnVa97Va9Va0Vu257Vw65537Z2fnFZv +demangle.fn!('a', '\x09', '\x00', '\u0101', '\U00010001').fn() +# +--format=dlang +_D2gc11gctemplates56__T8mkBitmapTS3std5range13__T4iotaTiTiZ4iotaFiiZ6ResultZ8mkBitmapFNbNiNfPmmZv +gc.gctemplates.mkBitmap!(std.range.iota!(int, int).iota(int, int).Result).mkBitmap(ulong*, ulong) +# +--format=dlang +_D8serenity9persister6Sqlite70__T15SqlitePersisterTS8serenity9persister6Sqlite11__unittest6FZv4TestZ15SqlitePersister12__T7opIndexZ7opIndexMFmZS8serenity9persister6Sqlite11__unittest6FZv4Test +serenity.persister.Sqlite.SqlitePersister!(serenity.persister.Sqlite.__unittest6().Test).SqlitePersister.opIndex!().opIndex(ulong) +# +--format=dlang +_D4test4mainFZv5localMFZi +test.main().local() diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 864ee7e..a030685 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -4343,8 +4343,16 @@ cereal::detail::InputBindingMap<cereal::JSONInputArchive>::Serializers cereal::p --format=gnu-v3 _ZNSt9_Any_data9_M_accessIPZ4postISt8functionIFvvEEEvOT_EUlvE_EERS5_v void post<std::function<void ()> >(std::function<void ()>&&)::{lambda()#1}*& std::_Any_data::_M_access<void post<std::function<void ()> >(void post<std::function<void ()> >(std::function<void ()>&&)::{lambda()#1}*&&)::{lambda()#1}*>() +# +--format=auto --no-params +_Z3xxxDFyuVb +xxx(unsigned long long _Fract, bool volatile) +xxx # https://sourceware.org/bugzilla/show_bug.cgi?id=16817 --format=auto --no-params _QueueNotification_QueueController__$4PPPPPPPM_A_INotice___Z _QueueNotification_QueueController__$4PPPPPPPM_A_INotice___Z _QueueNotification_QueueController__$4PPPPPPPM_A_INotice___Z +--format=gnu-v3 +_Z1fSsB3fooS_ +f(std::string[abi:foo], std::string[abi:foo]) diff --git a/libiberty/testsuite/demangler-fuzzer.c b/libiberty/testsuite/demangler-fuzzer.c new file mode 100644 index 0000000..aff7024 --- /dev/null +++ b/libiberty/testsuite/demangler-fuzzer.c @@ -0,0 +1,108 @@ +/* Demangler fuzzer. + + Copyright (C) 2014 Free Software Foundation, Inc. + + This file is part of GNU libiberty. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include "demangle.h" + +#define MAXLEN 253 +#define ALPMIN 33 +#define ALPMAX 127 + +static char *program_name; + +#define DEFAULT_MAXCOUNT 7500000 + +static void +print_usage (FILE *fp, int exit_value) +{ + fprintf (fp, "Usage: %s [OPTION]...\n", program_name); + fprintf (fp, "Options:\n"); + fprintf (fp, " -h Display this message.\n"); + fprintf (fp, " -s SEED Select the random seed to be used.\n"); + fprintf (fp, " The default is to base one on the"); + fprintf (fp, " current time.\n"); + fprintf (fp, " -m MAXCOUNT Exit after MAXCOUNT symbols.\n"); + fprintf (fp, " The default is %d.", DEFAULT_MAXCOUNT); + fprintf (fp, " Set to `-1' for no limit.\n"); + + exit (exit_value); +} + +int +main (int argc, char *argv[]) +{ + char symbol[2 + MAXLEN + 1] = "_Z"; + int seed = -1, seed_set = 0; + int count = 0, maxcount = DEFAULT_MAXCOUNT; + int optchr; + + program_name = argv[0]; + + do + { + optchr = getopt (argc, argv, "hs:m:t:"); + switch (optchr) + { + case '?': /* Unrecognized option. */ + print_usage (stderr, 1); + break; + + case 'h': + print_usage (stdout, 0); + break; + + case 's': + seed = atoi (optarg); + seed_set = 1; + break; + + case 'm': + maxcount = atoi (optarg); + break; + } + } + while (optchr != -1); + + if (!seed_set) + seed = time (NULL); + srand (seed); + printf ("%s: seed = %d\n", program_name, seed); + + while (maxcount < 0 || count < maxcount) + { + char *buffer = symbol + 2; + int length, i; + + length = rand () % MAXLEN; + for (i = 0; i < length; i++) + *buffer++ = (rand () % (ALPMAX - ALPMIN)) + ALPMIN; + + *buffer++ = '\0'; + + cplus_demangle (symbol, DMGL_AUTO | DMGL_ANSI | DMGL_PARAMS); + + count++; + } + + printf ("%s: successfully demangled %d symbols\n", program_name, count); + exit (0); +} |