mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
Synchronize libiberty with gcc and add --no-recruse-limit option to tools that support name demangling.
This patch addresses the multitude of bug reports about resource exhaustion in libiberty's name demangling code. It adds a limit to the amount of recursion that is allowed, before an error is triggered. It also adds a new demangling option to disable this limit. (The limit is enabled by default). PR 87681 PR 87675 PR 87636 PR 87335 libiberty * cp-demangle.h (struct d_info): Add recursion_limit field. * cp-demangle.c (d_function_type): If the recursion limit is enabled and reached, return with a failure result. (d_demangle_callback): If the recursion limit is enabled, check for a mangled string that is so long that there is not enough stack space for the local arrays. * cplus-dem.c (struct work): Add recursion_level field. (demangle_nested_args): If the recursion limit is enabled and reached, return with a failure result. include * demangle.h (DMGL_RECURSE_LIMIT): Define. (DEMANGLE_RECURSION_LIMIT): Prototype. binutuils * addr2line.c (demangle_flags): New static variable. (long_options): Add --recurse-limit and --no-recurse-limit. (translate_address): Pass demangle_flags to bfd_demangle. (main): Handle --recurse-limit and --no-recurse-limit options. * cxxfilt.c (flags): Add DMGL_RECURSE_LIMIT. (long_options): Add --recurse-limit and --no-recurse-limit. (main): Handle new options. * dlltool.c (gen_def_file): Include DMGL_RECURSE_LIMIT in flags passed to cplus_demangle. * nm.c (demangle_flags): New static variable. (long_options): Add --recurse-limit and --no-recurse-limit. (main): Handle new options. * objdump.c (demangle_flags): New static variable. (usage): Add --recurse-limit and --no-recurse-limit. (long_options): Likewise. (objdump_print_symname): Pass demangle_flags to bfd_demangle. (disassemble_section): Likewise. (dump_dymbols): Likewise. (main): Handle new options. * prdbg.c (demangle_flags): New static variable. (tg_variable): Pass demangle_flags to demangler. (tg_start_function): Likewise. * stabs.c (demangle_flags): New static variable. (stab_demangle_template): Pass demangle_flags to demangler. (stab_demangle_v3_argtypes): Likewise. (stab_demangle_v3_arg): Likewise. * doc/binutuls.texi: Document new command line options. * NEWS: Mention the new feature. * testsuite/config/default.exp (CXXFILT): Define if not already defined. (CXXFILTFLAGS): Likewise. * testsuite/binutils-all/cxxfilt.exp: New file. Runs a few simple tests of the cxxfilt program.
This commit is contained in:
parent
67bb16f345
commit
af03af8f55
@ -1,3 +1,37 @@
|
||||
2018-12-07 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* addr2line.c (demangle_flags): New static variable.
|
||||
(long_options): Add --recurse-limit and --no-recurse-limit.
|
||||
(translate_address): Pass demangle_flags to bfd_demangle.
|
||||
(main): Handle --recurse-limit and --no-recurse-limit options.
|
||||
* cxxfilt.c: (long_options): Add --recurse-limit and
|
||||
--no-recurse-limit.
|
||||
(main): Handle new options.
|
||||
* nm.c (demangle_flags): New static variable.
|
||||
(long_options): Add --recurse-limit and --no-recurse-limit.
|
||||
(main): Handle new options.
|
||||
* objdump.c (demangle_flags): New static variable.
|
||||
(usage): Add --recurse-limit and --no-recurse-limit.
|
||||
(long_options): Likewise.
|
||||
(objdump_print_symname): Pass demangle_flags to bfd_demangle.
|
||||
(disassemble_section): Likewise.
|
||||
(dump_dymbols): Likewise.
|
||||
(main): Handle new options.
|
||||
* prdbg.c (demangle_flags): New static variable.
|
||||
(tg_variable): Pass demangle_flags to demangler.
|
||||
(tg_start_function): Likewise.
|
||||
* stabs.c (demangle_flags): New static variable.
|
||||
(stab_demangle_template): Pass demangle_flags to demangler.
|
||||
(stab_demangle_v3_argtypes): Likewise.
|
||||
(stab_demangle_v3_arg): Likewise.
|
||||
* doc/binutuls.texi: Document new command line options.
|
||||
* NEWS: Mention the new feature.
|
||||
* testsuite/config/default.exp (CXXFILT): Define if not already
|
||||
defined.
|
||||
(CXXFILTFLAGS): Likewise.
|
||||
* testsuite/binutils-all/cxxfilt.exp: New file. Runs a few
|
||||
simple tests of the cxxfilt program.
|
||||
|
||||
2018-12-03 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR 23941
|
||||
|
@ -1,5 +1,16 @@
|
||||
-*- text -*-
|
||||
|
||||
* The addr2line, c++filt, nm and objdump tools now have a limit on the
|
||||
maximum amount of recursion that is allowed whilst demangling strings.
|
||||
The value for this limit is defined by the DEMANGLE_RECRUSE_LIMIT
|
||||
constant declared in the include/demangle.h header file. At the time
|
||||
of writing this constant has the value of 1024.
|
||||
|
||||
The --no-recurse-limit option can be used to remove the limit, restoring
|
||||
the behaviour of earlier versions of these tools. This may be needed in
|
||||
order to dmangle truly complicated names, but it also leaves the tools
|
||||
vulnerable to stack exhaustion from maliciously constructed mangled names.
|
||||
|
||||
* Objdump's --disassemble option can now take a parameter, specifying the
|
||||
starting symbol for disassembly. Disassembly will continue from this
|
||||
symbol up to the next symbol.
|
||||
|
@ -45,6 +45,9 @@ static bfd_boolean do_demangle; /* -C, demangle names. */
|
||||
static bfd_boolean pretty_print; /* -p, print on one line. */
|
||||
static bfd_boolean base_names; /* -s, strip directory names. */
|
||||
|
||||
/* Flags passed to the name demangler. */
|
||||
static int demangle_flags = DMGL_PARAMS | DMGL_ANSI;
|
||||
|
||||
static int naddr; /* Number of addresses to process. */
|
||||
static char **addr; /* Hex addresses to process. */
|
||||
|
||||
@ -59,6 +62,10 @@ static struct option long_options[] =
|
||||
{"functions", no_argument, NULL, 'f'},
|
||||
{"inlines", no_argument, NULL, 'i'},
|
||||
{"pretty-print", no_argument, NULL, 'p'},
|
||||
{"recurse-limit", no_argument, NULL, 'R'},
|
||||
{"recursion-limit", no_argument, NULL, 'R'},
|
||||
{"no-recurse-limit", no_argument, NULL, 'r'},
|
||||
{"no-recursion-limit", no_argument, NULL, 'r'},
|
||||
{"section", required_argument, NULL, 'j'},
|
||||
{"target", required_argument, NULL, 'b'},
|
||||
{"help", no_argument, NULL, 'H'},
|
||||
@ -91,6 +98,8 @@ usage (FILE *stream, int status)
|
||||
-s --basenames Strip directory names\n\
|
||||
-f --functions Show function names\n\
|
||||
-C --demangle[=style] Demangle function names\n\
|
||||
-R --recurse-limit Enable a limit on recursion whilst demangling. [Default]\n\
|
||||
-r --no-recurse-limit Disable a limit on recursion whilst demangling\n\
|
||||
-h --help Display this information\n\
|
||||
-v --version Display the program's version\n\
|
||||
\n"));
|
||||
@ -289,7 +298,7 @@ translate_addresses (bfd *abfd, asection *section)
|
||||
name = "??";
|
||||
else if (do_demangle)
|
||||
{
|
||||
alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
|
||||
alloc = bfd_demangle (abfd, name, demangle_flags);
|
||||
if (alloc != NULL)
|
||||
name = alloc;
|
||||
}
|
||||
@ -442,7 +451,7 @@ main (int argc, char **argv)
|
||||
file_name = NULL;
|
||||
section_name = NULL;
|
||||
target = NULL;
|
||||
while ((c = getopt_long (argc, argv, "ab:Ce:sfHhij:pVv", long_options, (int *) 0))
|
||||
while ((c = getopt_long (argc, argv, "ab:Ce:rRsfHhij:pVv", long_options, (int *) 0))
|
||||
!= EOF)
|
||||
{
|
||||
switch (c)
|
||||
@ -469,6 +478,12 @@ main (int argc, char **argv)
|
||||
cplus_demangle_set_style (style);
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
demangle_flags |= DMGL_NO_RECURSE_LIMIT;
|
||||
break;
|
||||
case 'R':
|
||||
demangle_flags &= ~ DMGL_NO_RECURSE_LIMIT;
|
||||
break;
|
||||
case 'e':
|
||||
file_name = optarg;
|
||||
break;
|
||||
|
@ -42,6 +42,10 @@ static const struct option long_options[] =
|
||||
{"no-verbose", no_argument, NULL, 'i'},
|
||||
{"types", no_argument, NULL, 't'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"recurse-limit", no_argument, NULL, 'R'},
|
||||
{"recursion-limit", no_argument, NULL, 'R'},
|
||||
{"no-recurse-limit", no_argument, NULL, 'r'},
|
||||
{"no-recursion-limit", no_argument, NULL, 'r'},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
|
||||
@ -102,6 +106,8 @@ Options are:\n\
|
||||
fprintf (stream, "\
|
||||
[-p|--no-params] Do not display function arguments\n\
|
||||
[-i|--no-verbose] Do not show implementation details (if any)\n\
|
||||
[-R|--recurse-limit] Enable a limit on recursion whilst demangling. [Default]\n\
|
||||
]-r|--no-recurse-limit] Disable a limit on recursion whilst demangling\n\
|
||||
[-t|--types] Also attempt to demangle type encodings\n\
|
||||
[-s|--format ");
|
||||
print_demangler_list (stream);
|
||||
@ -180,7 +186,7 @@ main (int argc, char **argv)
|
||||
|
||||
expandargv (&argc, &argv);
|
||||
|
||||
while ((c = getopt_long (argc, argv, "_hinps:tv", long_options, (int *) 0)) != EOF)
|
||||
while ((c = getopt_long (argc, argv, "_hinprRs:tv", long_options, (int *) 0)) != EOF)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
@ -195,6 +201,12 @@ main (int argc, char **argv)
|
||||
case 'p':
|
||||
flags &= ~ DMGL_PARAMS;
|
||||
break;
|
||||
case 'r':
|
||||
flags |= DMGL_NO_RECURSE_LIMIT;
|
||||
break;
|
||||
case 'R':
|
||||
flags &= ~ DMGL_NO_RECURSE_LIMIT;
|
||||
break;
|
||||
case 't':
|
||||
flags |= DMGL_TYPES;
|
||||
break;
|
||||
|
@ -769,7 +769,9 @@ nm [@option{-A}|@option{-o}|@option{--print-file-name}] [@option{-a}|@option{--d
|
||||
[@option{-s}|@option{--print-armap}] [@option{-t} @var{radix}|@option{--radix=}@var{radix}]
|
||||
[@option{-u}|@option{--undefined-only}] [@option{-V}|@option{--version}]
|
||||
[@option{-X 32_64}] [@option{--defined-only}] [@option{--no-demangle}]
|
||||
[@option{--plugin} @var{name}] [@option{--size-sort}] [@option{--special-syms}]
|
||||
[@option{--plugin} @var{name}]
|
||||
[@option{--no-recurse-limit}|@option{--recurse-limit}]]
|
||||
[@option{--size-sort}] [@option{--special-syms}]
|
||||
[@option{--synthetic}] [@option{--with-symbol-versions}] [@option{--target=}@var{bfdname}]
|
||||
[@var{objfile}@dots{}]
|
||||
@c man end
|
||||
@ -939,6 +941,22 @@ for more information on demangling.
|
||||
@item --no-demangle
|
||||
Do not demangle low-level symbol names. This is the default.
|
||||
|
||||
@item --recurse-limit
|
||||
@itemx --no-recurse-limit
|
||||
@itemx --recursion-limit
|
||||
@itemx --no-recursion-limit
|
||||
Enables or disables a limit on the amount of recursion performed
|
||||
whilst demangling strings. Since the name mangling formats allow for
|
||||
an inifinite level of recursion it is possible to create strings whose
|
||||
decoding will exhaust the amount of stack space available on the host
|
||||
machine, triggering a memory fault. The limit tries to prevent this
|
||||
from happening by restricting recursion to 1024 levels of nesting.
|
||||
|
||||
The default is for this limit to be enabled, but disabling it may be
|
||||
necessary in order to demangle truly complicated names. Note however
|
||||
that if the recursion limit is disabled then stack exhaustion is
|
||||
possible and any bug reports about such an event will be rejected.
|
||||
|
||||
@item -D
|
||||
@itemx --dynamic
|
||||
@cindex dynamic symbols
|
||||
@ -2098,6 +2116,7 @@ objdump [@option{-a}|@option{--archive-headers}]
|
||||
[@option{--adjust-vma=}@var{offset}]
|
||||
[@option{--dwarf-depth=@var{n}}]
|
||||
[@option{--dwarf-start=@var{n}}]
|
||||
[@option{--no-recurse-limit}|@option{--recurse-limit}]
|
||||
[@option{--special-syms}]
|
||||
[@option{--prefix=}@var{prefix}]
|
||||
[@option{--prefix-strip=}@var{level}]
|
||||
@ -2174,6 +2193,22 @@ mangling styles. The optional demangling style argument can be used to
|
||||
choose an appropriate demangling style for your compiler. @xref{c++filt},
|
||||
for more information on demangling.
|
||||
|
||||
@item --recurse-limit
|
||||
@itemx --no-recurse-limit
|
||||
@itemx --recursion-limit
|
||||
@itemx --no-recursion-limit
|
||||
Enables or disables a limit on the amount of recursion performed
|
||||
whilst demangling strings. Since the name mangling formats allow for
|
||||
an inifinite level of recursion it is possible to create strings whose
|
||||
decoding will exhaust the amount of stack space available on the host
|
||||
machine, triggering a memory fault. The limit tries to prevent this
|
||||
from happening by restricting recursion to 1024 levels of nesting.
|
||||
|
||||
The default is for this limit to be enabled, but disabling it may be
|
||||
necessary in order to demangle truly complicated names. Note however
|
||||
that if the recursion limit is disabled then stack exhaustion is
|
||||
possible and any bug reports about such an event will be rejected.
|
||||
|
||||
@item -g
|
||||
@itemx --debugging
|
||||
Display debugging information. This attempts to parse STABS
|
||||
@ -3403,6 +3438,8 @@ c++filt [@option{-_}|@option{--strip-underscore}]
|
||||
[@option{-p}|@option{--no-params}]
|
||||
[@option{-t}|@option{--types}]
|
||||
[@option{-i}|@option{--no-verbose}]
|
||||
[@option{-r}|@option{--no-recurse-limit}]
|
||||
[@option{-R}|@option{--recurse-limit}]
|
||||
[@option{-s} @var{format}|@option{--format=}@var{format}]
|
||||
[@option{--help}] [@option{--version}] [@var{symbol}@dots{}]
|
||||
@c man end
|
||||
@ -3507,6 +3544,28 @@ demangled to ``signed char''.
|
||||
Do not include implementation details (if any) in the demangled
|
||||
output.
|
||||
|
||||
@item -r
|
||||
@itemx -R
|
||||
@itemx --recurse-limit
|
||||
@itemx --no-recurse-limit
|
||||
@itemx --recursion-limit
|
||||
@itemx --no-recursion-limit
|
||||
Enables or disables a limit on the amount of recursion performed
|
||||
whilst demangling strings. Since the name mangling formats allow for
|
||||
an inifinite level of recursion it is possible to create strings whose
|
||||
decoding will exhaust the amount of stack space available on the host
|
||||
machine, triggering a memory fault. The limit tries to prevent this
|
||||
from happening by restricting recursion to 1024 levels of nesting.
|
||||
|
||||
The default is for this limit to be enabled, but disabling it may be
|
||||
necessary in order to demangle truly complicated names. Note however
|
||||
that if the recursion limit is disabled then stack exhaustion is
|
||||
possible and any bug reports about such an event will be rejected.
|
||||
|
||||
The @option{-r} option is a synonym for the
|
||||
@option{--no-recurse-limit} option. The @option{-R} option is a
|
||||
synonym for the @option{--recurse-limit} option.
|
||||
|
||||
@item -s @var{format}
|
||||
@itemx --format=@var{format}
|
||||
@command{c++filt} can decode various methods of mangling, used by
|
||||
@ -3580,6 +3639,8 @@ c++filt @var{option} @var{symbol}
|
||||
addr2line [@option{-a}|@option{--addresses}]
|
||||
[@option{-b} @var{bfdname}|@option{--target=}@var{bfdname}]
|
||||
[@option{-C}|@option{--demangle}[=@var{style}]]
|
||||
[@option{-r}|@option{--no-recurse-limit}]
|
||||
[@option{-R}|@option{--recurse-limit}]
|
||||
[@option{-e} @var{filename}|@option{--exe=}@var{filename}]
|
||||
[@option{-f}|@option{--functions}] [@option{-s}|@option{--basename}]
|
||||
[@option{-i}|@option{--inlines}]
|
||||
@ -3705,6 +3766,32 @@ Read offsets relative to the specified section instead of absolute addresses.
|
||||
Make the output more human friendly: each location are printed on one line.
|
||||
If option @option{-i} is specified, lines for all enclosing scopes are
|
||||
prefixed with @samp{(inlined by)}.
|
||||
|
||||
@item -r
|
||||
@itemx -R
|
||||
@itemx --recurse-limit
|
||||
@itemx --no-recurse-limit
|
||||
@itemx --recursion-limit
|
||||
@itemx --no-recursion-limit
|
||||
Enables or disables a limit on the amount of recursion performed
|
||||
whilst demangling strings. Since the name mangling formats allow for
|
||||
an inifinite level of recursion it is possible to create strings whose
|
||||
decoding will exhaust the amount of stack space available on the host
|
||||
machine, triggering a memory fault. The limit tries to prevent this
|
||||
from happening by restricting recursion to 1024 levels of nesting.
|
||||
|
||||
The default is for this limit to be enabled, but disabling it may be
|
||||
necessary in order to demangle truly complicated names. Note however
|
||||
that if the recursion limit is disabled then stack exhaustion is
|
||||
possible and any bug reports about such an event will be rejected.
|
||||
|
||||
The @option{-r} option is a synonym for the
|
||||
@option{--no-recurse-limit} option. The @option{-R} option is a
|
||||
synonym for the @option{--recurse-limit} option.
|
||||
|
||||
Note this option is only effective if the @option{-C} or
|
||||
@option{--demangle} option has been enabled.
|
||||
|
||||
@end table
|
||||
|
||||
@c man end
|
||||
|
@ -162,6 +162,8 @@ static int line_numbers = 0; /* Print line numbers for symbols. */
|
||||
static int allow_special_symbols = 0; /* Allow special symbols. */
|
||||
static int with_symbol_versions = 0; /* Include symbol version information in the output. */
|
||||
|
||||
static int demangle_flags = DMGL_ANSI | DMGL_PARAMS;
|
||||
|
||||
/* When to print the names of files. Not mutually exclusive in SYSV format. */
|
||||
static int filename_per_file = 0; /* Once per file, on its own line. */
|
||||
static int filename_per_symbol = 0; /* Once per symbol, at start of line. */
|
||||
@ -194,9 +196,14 @@ static const char *plugin_target = NULL;
|
||||
static bfd *lineno_cache_bfd;
|
||||
static bfd *lineno_cache_rel_bfd;
|
||||
|
||||
#define OPTION_TARGET 200
|
||||
#define OPTION_PLUGIN (OPTION_TARGET + 1)
|
||||
#define OPTION_SIZE_SORT (OPTION_PLUGIN + 1)
|
||||
enum long_option_values
|
||||
{
|
||||
OPTION_TARGET = 200,
|
||||
OPTION_PLUGIN,
|
||||
OPTION_SIZE_SORT,
|
||||
OPTION_RECURSE_LIMIT,
|
||||
OPTION_NO_RECURSE_LIMIT
|
||||
};
|
||||
|
||||
static struct option long_options[] =
|
||||
{
|
||||
@ -209,6 +216,8 @@ static struct option long_options[] =
|
||||
{"line-numbers", no_argument, 0, 'l'},
|
||||
{"no-cplus", no_argument, &do_demangle, 0}, /* Linux compatibility. */
|
||||
{"no-demangle", no_argument, &do_demangle, 0},
|
||||
{"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
|
||||
{"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
|
||||
{"no-sort", no_argument, 0, 'p'},
|
||||
{"numeric-sort", no_argument, 0, 'n'},
|
||||
{"plugin", required_argument, 0, OPTION_PLUGIN},
|
||||
@ -217,6 +226,8 @@ static struct option long_options[] =
|
||||
{"print-file-name", no_argument, 0, 'o'},
|
||||
{"print-size", no_argument, 0, 'S'},
|
||||
{"radix", required_argument, 0, 't'},
|
||||
{"recurse-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
|
||||
{"recursion-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
|
||||
{"reverse-sort", no_argument, &reverse_sort, 1},
|
||||
{"size-sort", no_argument, 0, OPTION_SIZE_SORT},
|
||||
{"special-syms", no_argument, &allow_special_symbols, 1},
|
||||
@ -245,6 +256,8 @@ usage (FILE *stream, int status)
|
||||
`gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
|
||||
or `gnat'\n\
|
||||
--no-demangle Do not demangle low-level symbol names\n\
|
||||
--recurse-limit Enable a demangling recursion limit. This is the default.\n\
|
||||
--no-recurse-limit Disable a demangling recursion limit.\n\
|
||||
-D, --dynamic Display dynamic symbols instead of normal symbols\n\
|
||||
--defined-only Display only defined symbols\n\
|
||||
-e (ignored)\n\
|
||||
@ -407,7 +420,7 @@ print_symname (const char *form, const char *name, bfd *abfd)
|
||||
{
|
||||
if (do_demangle && *name)
|
||||
{
|
||||
char *res = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
|
||||
char *res = bfd_demangle (abfd, name, demangle_flags);
|
||||
|
||||
if (res != NULL)
|
||||
{
|
||||
@ -1687,6 +1700,12 @@ main (int argc, char **argv)
|
||||
cplus_demangle_set_style (style);
|
||||
}
|
||||
break;
|
||||
case OPTION_RECURSE_LIMIT:
|
||||
demangle_flags &= ~ DMGL_NO_RECURSE_LIMIT;
|
||||
break;
|
||||
case OPTION_NO_RECURSE_LIMIT:
|
||||
demangle_flags |= DMGL_NO_RECURSE_LIMIT;
|
||||
break;
|
||||
case 'D':
|
||||
dynamic = 1;
|
||||
break;
|
||||
|
@ -120,6 +120,8 @@ static size_t prefix_length;
|
||||
static bfd_boolean unwind_inlines; /* --inlines. */
|
||||
static const char * disasm_sym; /* Disassembly start symbol. */
|
||||
|
||||
static int demangle_flags = DMGL_ANSI | DMGL_PARAMS;
|
||||
|
||||
/* A structure to record the sections mentioned in -j switches. */
|
||||
struct only
|
||||
{
|
||||
@ -252,6 +254,8 @@ usage (FILE *stream, int status)
|
||||
The STYLE, if specified, can be `auto', `gnu',\n\
|
||||
`lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
|
||||
or `gnat'\n\
|
||||
--recurse-limit Enable a limit on recursion whilst demangling. [Default]\n\
|
||||
--no-recurse-limit Disable a limit on recursion whilst demangling\n\
|
||||
-w, --wide Format output for more than 80 columns\n\
|
||||
-z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n\
|
||||
--start-address=ADDR Only process data whose address is >= ADDR\n\
|
||||
@ -302,6 +306,8 @@ enum option_values
|
||||
OPTION_DWARF_DEPTH,
|
||||
OPTION_DWARF_CHECK,
|
||||
OPTION_DWARF_START,
|
||||
OPTION_RECURSE_LIMIT,
|
||||
OPTION_NO_RECURSE_LIMIT,
|
||||
OPTION_INLINES
|
||||
};
|
||||
|
||||
@ -333,6 +339,10 @@ static struct option long_options[]=
|
||||
{"line-numbers", no_argument, NULL, 'l'},
|
||||
{"no-show-raw-insn", no_argument, &show_raw_insn, -1},
|
||||
{"prefix-addresses", no_argument, &prefix_addresses, 1},
|
||||
{"recurse-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
|
||||
{"recursion-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
|
||||
{"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
|
||||
{"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
|
||||
{"reloc", no_argument, NULL, 'r'},
|
||||
{"section", required_argument, NULL, 'j'},
|
||||
{"section-headers", no_argument, NULL, 'h'},
|
||||
@ -884,7 +894,7 @@ objdump_print_symname (bfd *abfd, struct disassemble_info *inf,
|
||||
if (do_demangle && name[0] != '\0')
|
||||
{
|
||||
/* Demangle the name. */
|
||||
alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
|
||||
alloc = bfd_demangle (abfd, name, demangle_flags);
|
||||
if (alloc != NULL)
|
||||
name = alloc;
|
||||
}
|
||||
@ -2290,7 +2300,7 @@ disassemble_section (bfd *abfd, asection *section, void *inf)
|
||||
if (do_demangle && name[0] != '\0')
|
||||
{
|
||||
/* Demangle the name. */
|
||||
alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
|
||||
alloc = bfd_demangle (abfd, name, demangle_flags);
|
||||
if (alloc != NULL)
|
||||
name = alloc;
|
||||
}
|
||||
@ -3268,7 +3278,7 @@ dump_symbols (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean dynamic)
|
||||
/* If we want to demangle the name, we demangle it
|
||||
here, and temporarily clobber it while calling
|
||||
bfd_print_symbol. FIXME: This is a gross hack. */
|
||||
alloc = bfd_demangle (cur_bfd, name, DMGL_ANSI | DMGL_PARAMS);
|
||||
alloc = bfd_demangle (cur_bfd, name, demangle_flags);
|
||||
if (alloc != NULL)
|
||||
(*current)->name = alloc;
|
||||
bfd_print_symbol (cur_bfd, stdout, *current,
|
||||
@ -3927,6 +3937,12 @@ main (int argc, char **argv)
|
||||
cplus_demangle_set_style (style);
|
||||
}
|
||||
break;
|
||||
case OPTION_RECURSE_LIMIT:
|
||||
demangle_flags &= ~ DMGL_NO_RECURSE_LIMIT;
|
||||
break;
|
||||
case OPTION_NO_RECURSE_LIMIT:
|
||||
demangle_flags |= DMGL_NO_RECURSE_LIMIT;
|
||||
break;
|
||||
case 'w':
|
||||
do_wide = wide_output = TRUE;
|
||||
break;
|
||||
|
@ -286,6 +286,8 @@ static const struct debug_write_fns tg_fns =
|
||||
pr_end_function, /* Same, does nothing. */
|
||||
tg_lineno
|
||||
};
|
||||
|
||||
static int demangle_flags = DMGL_ANSI | DMGL_PARAMS;
|
||||
|
||||
/* Print out the generic debugging information recorded in dhandle. */
|
||||
|
||||
@ -2600,7 +2602,7 @@ tg_variable (void *p, const char *name, enum debug_var_kind kind,
|
||||
|
||||
dname = NULL;
|
||||
if (info->demangler)
|
||||
dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS);
|
||||
dname = info->demangler (info->abfd, name, demangle_flags);
|
||||
|
||||
from_class = NULL;
|
||||
if (dname != NULL)
|
||||
@ -2661,7 +2663,7 @@ tg_start_function (void *p, const char *name, bfd_boolean global)
|
||||
|
||||
dname = NULL;
|
||||
if (info->demangler)
|
||||
dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS);
|
||||
dname = info->demangler (info->abfd, name, demangle_flags);
|
||||
|
||||
if (! substitute_type (info, dname ? dname : name))
|
||||
return FALSE;
|
||||
|
@ -215,6 +215,8 @@ static debug_type stab_demangle_v3_arg
|
||||
(void *, struct stab_handle *, struct demangle_component *, debug_type,
|
||||
bfd_boolean *);
|
||||
|
||||
static int demangle_flags = DMGL_ANSI;
|
||||
|
||||
/* Save a string in memory. */
|
||||
|
||||
static char *
|
||||
@ -4517,7 +4519,7 @@ stab_demangle_template (struct stab_demangle_info *minfo, const char **pp,
|
||||
|
||||
free (s1);
|
||||
|
||||
s3 = cplus_demangle (s2, DMGL_ANSI);
|
||||
s3 = cplus_demangle (s2, demangle_flags);
|
||||
|
||||
free (s2);
|
||||
|
||||
@ -5243,7 +5245,7 @@ stab_demangle_v3_argtypes (void *dhandle, struct stab_handle *info,
|
||||
void *mem;
|
||||
debug_type *pargs;
|
||||
|
||||
dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | DMGL_ANSI, &mem);
|
||||
dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | demangle_flags, &mem);
|
||||
if (dc == NULL)
|
||||
{
|
||||
stab_bad_demangle (physname);
|
||||
@ -5418,7 +5420,7 @@ stab_demangle_v3_arg (void *dhandle, struct stab_handle *info,
|
||||
/* We print this component to get a class name which we can
|
||||
use. FIXME: This probably won't work if the template uses
|
||||
template parameters which refer to an outer template. */
|
||||
p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
|
||||
p = cplus_demangle_print (DMGL_PARAMS | demangle_flags, dc, 20, &alc);
|
||||
if (p == NULL)
|
||||
{
|
||||
fprintf (stderr, _("Failed to print demangled template\n"));
|
||||
@ -5498,7 +5500,7 @@ stab_demangle_v3_arg (void *dhandle, struct stab_handle *info,
|
||||
/* We print this component in order to find out the type name.
|
||||
FIXME: Should we instead expose the
|
||||
demangle_builtin_type_info structure? */
|
||||
p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
|
||||
p = cplus_demangle_print (DMGL_PARAMS | demangle_flags, dc, 20, &alc);
|
||||
if (p == NULL)
|
||||
{
|
||||
fprintf (stderr, _("Couldn't get demangled builtin type\n"));
|
||||
|
44
binutils/testsuite/binutils-all/cxxfilt.exp
Normal file
44
binutils/testsuite/binutils-all/cxxfilt.exp
Normal file
@ -0,0 +1,44 @@
|
||||
# Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
|
||||
# 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, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
proc test_cxxfilt {options mangled_string demangled_string} {
|
||||
global CXXFILT
|
||||
global CXXFILTFLAGS
|
||||
|
||||
set testname "cxxfilt: demangling $mangled_string"
|
||||
set got [binutils_run $CXXFILT "$options $CXXFILTFLAGS $mangled_string"]
|
||||
|
||||
if ![regexp $demangled_string $got] then {
|
||||
fail "$testname"
|
||||
verbose 0 "expected: $demangled_string"
|
||||
return
|
||||
}
|
||||
|
||||
pass $testname
|
||||
}
|
||||
|
||||
# Mangled and demangled strings stolen from libiberty/testsuite/demangle-expected.
|
||||
test_cxxfilt {} \
|
||||
"AddAlignment__9ivTSolverUiP12ivInteractorP7ivTGlue" \
|
||||
"ivTSolver::AddAlignment(unsigned int, ivInteractor ., ivTGlue .)*"
|
||||
|
||||
test_cxxfilt {--format=lucid} \
|
||||
"__ct__12strstreambufFPFl_PvPFPv_v" \
|
||||
"strstreambuf..(strstreambuf|_ct)(void .(.)(long), void (.)(void .))*"
|
||||
|
||||
test_cxxfilt {--no-recurse-limit} \
|
||||
"Z3fooiPiPS_PS0_PS1_PS2_PS3_PS4_PS5_PS6_PS7_PS8_PS9_PSA_PSB_PSC_" \
|
||||
"foo(int, int., int.., int..., int...., int....., int......, int......., int........, int........., int.........., int..........., int............, int............., int.............., int...............)*"
|
@ -93,6 +93,12 @@ if ![info exists WINDRES] then {
|
||||
if ![info exists DLLTOOL] then {
|
||||
set DLLTOOL [findfile $base_dir/dlltool]
|
||||
}
|
||||
if ![info exists CXXFILT] then {
|
||||
set CXXFILT [findfile $base_dir/cxxfilt]
|
||||
}
|
||||
if ![info exists CXXFILTFLAGS] then {
|
||||
set CXXFILTFLAGS ""
|
||||
}
|
||||
|
||||
if ![file isdirectory tmpdir] {catch "exec mkdir tmpdir" status}
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2018-12-07 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* demangle.h (DMGL_NO_RECURSE_LIMIT): Define.
|
||||
(DEMANGLE_RECURSION_LIMIT): Define
|
||||
|
||||
2018-12-06 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* opcode/ppc.h (E_OPCODE_MASK, E_LI_MASK, E_LI_INSN): Define.
|
||||
|
@ -68,6 +68,17 @@ extern "C" {
|
||||
/* If none of these are set, use 'current_demangling_style' as the default. */
|
||||
#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST)
|
||||
|
||||
/* Disable a limit on the depth of recursion in mangled strings.
|
||||
Note if this limit is disabled then stack exhaustion is possible when
|
||||
demangling pathologically complicated strings. Bug reports about stack
|
||||
exhaustion when the option is enabled will be rejected. */
|
||||
#define DMGL_NO_RECURSE_LIMIT (1 << 18)
|
||||
|
||||
/* If DMGL_NO_RECURSE_LIMIT is not enabled, then this is the value used as
|
||||
the maximum depth of recursion allowed. It should be enough for any
|
||||
real-world mangled name. */
|
||||
#define DEMANGLE_RECURSION_LIMIT 1024
|
||||
|
||||
/* Enumeration of possible demangling styles.
|
||||
|
||||
Lucid and ARM styles are still kept logically distinct, even though
|
||||
@ -392,6 +403,9 @@ enum demangle_component_type
|
||||
template argument, and the right subtree is either NULL or
|
||||
another TEMPLATE_ARGLIST node. */
|
||||
DEMANGLE_COMPONENT_TEMPLATE_ARGLIST,
|
||||
/* A template parameter object (C++20). The left subtree is the
|
||||
corresponding template argument. */
|
||||
DEMANGLE_COMPONENT_TPARM_OBJ,
|
||||
/* An initializer list. The left subtree is either an explicit type or
|
||||
NULL, and the right subtree is a DEMANGLE_COMPONENT_ARGLIST. */
|
||||
DEMANGLE_COMPONENT_INITIALIZER_LIST,
|
||||
|
@ -1,3 +1,68 @@
|
||||
2018-12-07 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR 87681
|
||||
PR 87675
|
||||
PR 87636
|
||||
PR 87350
|
||||
PR 87335
|
||||
* cp-demangle.h (struct d_info): Add recursion_level field.
|
||||
* cp-demangle.c (d_function_type): Add recursion counter.
|
||||
If the recursion limit is reached and the check is not disabled,
|
||||
then return with a failure result.
|
||||
(cplus_demangle_init_info): Initialise the recursion_level field.
|
||||
(d_demangle_callback): If the recursion limit is enabled, check
|
||||
for a mangled string that is so long that there is not enough
|
||||
stack space for the local arrays.
|
||||
* cplus-dem.c (struct work): Add recursion_level field.
|
||||
(squangle_mop_up): Set the numb and numk fields to zero.
|
||||
(work_stuff_copy_to_from): Handle the case where a btypevec or
|
||||
ktypevec field is NULL.
|
||||
(demangle_nested_args): Add recursion counter. If
|
||||
the recursion limit is not disabled and reached, return with a
|
||||
failure result.
|
||||
|
||||
2018-10-23 Jason Merrill <jason@redhat.com>
|
||||
|
||||
Implement P0732R2, class types in non-type template parameters.
|
||||
* cp-demangle.c (d_dump, d_make_comp, d_count_templates_scopes)
|
||||
(d_print_comp_inner): Handle DEMANGLE_COMPONENT_TPARM_OBJ.
|
||||
(d_special_name): Handle TA.
|
||||
(d_expresion_1): Fix demangling of brace-enclosed initializer list.
|
||||
|
||||
2018-10-31 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
PR bootstrap/82856
|
||||
Merge from binutils-gdb:
|
||||
2018-06-19 Simon Marchi <simon.marchi@ericsson.com>
|
||||
|
||||
* configure.ac: Remove AC_PREREQ.
|
||||
* configure: Re-generate.
|
||||
* config.in: Re-generate.
|
||||
|
||||
2018-10-01 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
* configure.ac (checkfuncs): Add pipe2.
|
||||
* config.in, configure: Rebuilt.
|
||||
* pex-unix.c (pex_unix_exec_child): Comminicate errors from child
|
||||
to parent with a pipe, when possible.
|
||||
|
||||
2018-08-23 Nathan Sidwell <nathan@acm.org>
|
||||
Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR driver/87056
|
||||
* pex-unix.c (pex_unix_exec_child): Duplicate bad_fn into local
|
||||
scopes to avoid potential clobber.
|
||||
|
||||
2018-08-20 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
* pex-unix.c (pex_child_error): Delete.
|
||||
(pex_unix_exec_child): Commonize error paths to single message &
|
||||
exit.
|
||||
|
||||
2018-07-30 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* cplus-dem.c (remember_Btype): Don't call memcpy with LEN==0.
|
||||
|
||||
2018-08-01 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
Copy over from GCC
|
||||
|
@ -195,6 +195,9 @@
|
||||
/* Define to 1 if you have the `on_exit' function. */
|
||||
#undef HAVE_ON_EXIT
|
||||
|
||||
/* Define to 1 if you have the `pipe2' function. */
|
||||
#undef HAVE_PIPE2
|
||||
|
||||
/* Define to 1 if you have the <process.h> header file. */
|
||||
#undef HAVE_PROCESS_H
|
||||
|
||||
|
4
libiberty/configure
vendored
4
libiberty/configure
vendored
@ -5797,7 +5797,7 @@ funcs="$funcs setproctitle"
|
||||
vars="sys_errlist sys_nerr sys_siglist"
|
||||
|
||||
checkfuncs="__fsetlocking canonicalize_file_name dup3 getrlimit getrusage \
|
||||
getsysinfo gettimeofday on_exit psignal pstat_getdynamic pstat_getstatic \
|
||||
getsysinfo gettimeofday on_exit pipe2 psignal pstat_getdynamic pstat_getstatic \
|
||||
realpath setrlimit sbrk spawnve spawnvpe strerror strsignal sysconf sysctl \
|
||||
sysmp table times wait3 wait4"
|
||||
|
||||
@ -5813,7 +5813,7 @@ if test "x" = "y"; then
|
||||
index insque \
|
||||
memchr memcmp memcpy memmem memmove memset mkstemps \
|
||||
on_exit \
|
||||
psignal pstat_getdynamic pstat_getstatic putenv \
|
||||
pipe2 psignal pstat_getdynamic pstat_getstatic putenv \
|
||||
random realpath rename rindex \
|
||||
sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \
|
||||
stpcpy stpncpy strcasecmp strchr strdup \
|
||||
|
@ -390,7 +390,7 @@ funcs="$funcs setproctitle"
|
||||
vars="sys_errlist sys_nerr sys_siglist"
|
||||
|
||||
checkfuncs="__fsetlocking canonicalize_file_name dup3 getrlimit getrusage \
|
||||
getsysinfo gettimeofday on_exit psignal pstat_getdynamic pstat_getstatic \
|
||||
getsysinfo gettimeofday on_exit pipe2 psignal pstat_getdynamic pstat_getstatic \
|
||||
realpath setrlimit sbrk spawnve spawnvpe strerror strsignal sysconf sysctl \
|
||||
sysmp table times wait3 wait4"
|
||||
|
||||
@ -406,7 +406,7 @@ if test "x" = "y"; then
|
||||
index insque \
|
||||
memchr memcmp memcpy memmem memmove memset mkstemps \
|
||||
on_exit \
|
||||
psignal pstat_getdynamic pstat_getstatic putenv \
|
||||
pipe2 psignal pstat_getdynamic pstat_getstatic putenv \
|
||||
random realpath rename rindex \
|
||||
sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \
|
||||
stpcpy stpncpy strcasecmp strchr strdup \
|
||||
|
@ -625,6 +625,9 @@ d_dump (struct demangle_component *dc, int indent)
|
||||
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
|
||||
printf ("template parameter %ld\n", dc->u.s_number.number);
|
||||
return;
|
||||
case DEMANGLE_COMPONENT_TPARM_OBJ:
|
||||
printf ("template parameter object\n");
|
||||
break;
|
||||
case DEMANGLE_COMPONENT_FUNCTION_PARAM:
|
||||
printf ("function parameter %ld\n", dc->u.s_number.number);
|
||||
return;
|
||||
@ -1007,6 +1010,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
|
||||
case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
|
||||
case DEMANGLE_COMPONENT_NULLARY:
|
||||
case DEMANGLE_COMPONENT_TRINARY_ARG2:
|
||||
case DEMANGLE_COMPONENT_TPARM_OBJ:
|
||||
if (left == NULL)
|
||||
return NULL;
|
||||
break;
|
||||
@ -2007,6 +2011,7 @@ d_java_resource (struct d_info *di)
|
||||
::= TT <type>
|
||||
::= TI <type>
|
||||
::= TS <type>
|
||||
::= TA <template-arg>
|
||||
::= GV <(object) name>
|
||||
::= T <call-offset> <(base) encoding>
|
||||
::= Tc <call-offset> <call-offset> <(base) encoding>
|
||||
@ -2099,6 +2104,10 @@ d_special_name (struct d_info *di)
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER,
|
||||
d_name (di), NULL);
|
||||
|
||||
case 'A':
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_TPARM_OBJ,
|
||||
d_template_arg (di), NULL);
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@ -2843,21 +2852,35 @@ d_ref_qualifier (struct d_info *di, struct demangle_component *sub)
|
||||
static struct demangle_component *
|
||||
d_function_type (struct d_info *di)
|
||||
{
|
||||
struct demangle_component *ret;
|
||||
struct demangle_component *ret = NULL;
|
||||
|
||||
if (! d_check_char (di, 'F'))
|
||||
return NULL;
|
||||
if (d_peek_char (di) == 'Y')
|
||||
if ((di->options & DMGL_NO_RECURSE_LIMIT) == 0)
|
||||
{
|
||||
/* Function has C linkage. We don't print this information.
|
||||
FIXME: We should print it in verbose mode. */
|
||||
d_advance (di, 1);
|
||||
}
|
||||
ret = d_bare_function_type (di, 1);
|
||||
ret = d_ref_qualifier (di, ret);
|
||||
if (di->recursion_level > DEMANGLE_RECURSION_LIMIT)
|
||||
/* FIXME: There ought to be a way to report
|
||||
that the recursion limit has been reached. */
|
||||
return NULL;
|
||||
|
||||
if (! d_check_char (di, 'E'))
|
||||
return NULL;
|
||||
di->recursion_level ++;
|
||||
}
|
||||
|
||||
if (d_check_char (di, 'F'))
|
||||
{
|
||||
if (d_peek_char (di) == 'Y')
|
||||
{
|
||||
/* Function has C linkage. We don't print this information.
|
||||
FIXME: We should print it in verbose mode. */
|
||||
d_advance (di, 1);
|
||||
}
|
||||
ret = d_bare_function_type (di, 1);
|
||||
ret = d_ref_qualifier (di, ret);
|
||||
|
||||
if (! d_check_char (di, 'E'))
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
if ((di->options & DMGL_NO_RECURSE_LIMIT) == 0)
|
||||
di->recursion_level --;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3327,11 +3350,11 @@ d_expression_1 (struct d_info *di)
|
||||
{
|
||||
/* Brace-enclosed initializer list, untyped or typed. */
|
||||
struct demangle_component *type = NULL;
|
||||
d_advance (di, 2);
|
||||
if (peek == 't')
|
||||
type = cplus_demangle_type (di);
|
||||
if (!d_peek_next_char (di))
|
||||
return NULL;
|
||||
d_advance (di, 2);
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST,
|
||||
type, d_exprlist (di, 'E'));
|
||||
}
|
||||
@ -4101,6 +4124,7 @@ d_count_templates_scopes (int *num_templates, int *num_scopes,
|
||||
case DEMANGLE_COMPONENT_VECTOR_TYPE:
|
||||
case DEMANGLE_COMPONENT_ARGLIST:
|
||||
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
|
||||
case DEMANGLE_COMPONENT_TPARM_OBJ:
|
||||
case DEMANGLE_COMPONENT_INITIALIZER_LIST:
|
||||
case DEMANGLE_COMPONENT_CAST:
|
||||
case DEMANGLE_COMPONENT_CONVERSION:
|
||||
@ -4872,6 +4896,11 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
|
||||
}
|
||||
return;
|
||||
|
||||
case DEMANGLE_COMPONENT_TPARM_OBJ:
|
||||
d_append_string (dpi, "template parameter object for ");
|
||||
d_print_comp (dpi, options, d_left (dc));
|
||||
return;
|
||||
|
||||
case DEMANGLE_COMPONENT_CTOR:
|
||||
d_print_comp (dpi, options, dc->u.s_ctor.name);
|
||||
return;
|
||||
@ -6188,6 +6217,7 @@ cplus_demangle_init_info (const char *mangled, int options, size_t len,
|
||||
di->expansion = 0;
|
||||
di->is_expression = 0;
|
||||
di->is_conversion = 0;
|
||||
di->recursion_level = 0;
|
||||
}
|
||||
|
||||
/* Internal implementation for the demangler. If MANGLED is a g++ v3 ABI
|
||||
@ -6227,6 +6257,20 @@ d_demangle_callback (const char *mangled, int options,
|
||||
|
||||
cplus_demangle_init_info (mangled, options, strlen (mangled), &di);
|
||||
|
||||
/* PR 87675 - Check for a mangled string that is so long
|
||||
that we do not have enough stack space to demangle it. */
|
||||
if (((options & DMGL_NO_RECURSE_LIMIT) == 0)
|
||||
/* This check is a bit arbitrary, since what we really want to do is to
|
||||
compare the sizes of the di.comps and di.subs arrays against the
|
||||
amount of stack space remaining. But there is no portable way to do
|
||||
this, so instead we use the recursion limit as a guide to the maximum
|
||||
size of the arrays. */
|
||||
&& (unsigned long) di.num_comps > DEMANGLE_RECURSION_LIMIT)
|
||||
{
|
||||
/* FIXME: We need a way to indicate that a stack limit has been reached. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
#ifdef CP_DYNAMIC_ARRAYS
|
||||
__extension__ struct demangle_component comps[di.num_comps];
|
||||
|
@ -122,6 +122,9 @@ 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;
|
||||
/* If DMGL_NO_RECURSE_LIMIT is not active then this is set to
|
||||
the current recursion level. */
|
||||
unsigned int recursion_level;
|
||||
};
|
||||
|
||||
/* To avoid running past the ending '\0', don't:
|
||||
|
@ -146,6 +146,7 @@ struct work_stuff
|
||||
int *proctypevec; /* Indices of currently processed remembered typevecs. */
|
||||
int proctypevec_size;
|
||||
int nproctypes;
|
||||
unsigned int recursion_level;
|
||||
};
|
||||
|
||||
#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
|
||||
@ -1292,12 +1293,14 @@ squangle_mop_up (struct work_stuff *work)
|
||||
free ((char *) work -> btypevec);
|
||||
work->btypevec = NULL;
|
||||
work->bsize = 0;
|
||||
work->numb = 0;
|
||||
}
|
||||
if (work -> ktypevec != NULL)
|
||||
{
|
||||
free ((char *) work -> ktypevec);
|
||||
work->ktypevec = NULL;
|
||||
work->ksize = 0;
|
||||
work->numk = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1331,8 +1334,15 @@ work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
|
||||
|
||||
for (i = 0; i < from->numk; i++)
|
||||
{
|
||||
int len = strlen (from->ktypevec[i]) + 1;
|
||||
int len;
|
||||
|
||||
if (from->ktypevec[i] == NULL)
|
||||
{
|
||||
to->ktypevec[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
len = strlen (from->ktypevec[i]) + 1;
|
||||
to->ktypevec[i] = XNEWVEC (char, len);
|
||||
memcpy (to->ktypevec[i], from->ktypevec[i], len);
|
||||
}
|
||||
@ -1342,8 +1352,15 @@ work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
|
||||
|
||||
for (i = 0; i < from->numb; i++)
|
||||
{
|
||||
int len = strlen (from->btypevec[i]) + 1;
|
||||
int len;
|
||||
|
||||
if (from->btypevec[i] == NULL)
|
||||
{
|
||||
to->btypevec[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
len = strlen (from->btypevec[i]) + 1;
|
||||
to->btypevec[i] = XNEWVEC (char , len);
|
||||
memcpy (to->btypevec[i], from->btypevec[i], len);
|
||||
}
|
||||
@ -1401,6 +1418,7 @@ delete_non_B_K_work_stuff (struct work_stuff *work)
|
||||
|
||||
free ((char*) work->tmpl_argvec);
|
||||
work->tmpl_argvec = NULL;
|
||||
work->ntmpl_args = 0;
|
||||
}
|
||||
if (work->previous_argument)
|
||||
{
|
||||
@ -4471,12 +4489,14 @@ remember_Btype (struct work_stuff *work, const char *start,
|
||||
char *tem;
|
||||
|
||||
tem = XNEWVEC (char, len + 1);
|
||||
memcpy (tem, start, len);
|
||||
if (len > 0)
|
||||
memcpy (tem, start, len);
|
||||
tem[len] = '\0';
|
||||
work -> btypevec[index] = tem;
|
||||
}
|
||||
|
||||
/* Lose all the info related to B and K type codes. */
|
||||
|
||||
static void
|
||||
forget_B_and_K_types (struct work_stuff *work)
|
||||
{
|
||||
@ -4502,6 +4522,7 @@ forget_B_and_K_types (struct work_stuff *work)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Forget the remembered types, but not the type vector itself. */
|
||||
|
||||
static void
|
||||
@ -4696,6 +4717,16 @@ demangle_nested_args (struct work_stuff *work, const char **mangled,
|
||||
int result;
|
||||
int saved_nrepeats;
|
||||
|
||||
if ((work->options & DMGL_NO_RECURSE_LIMIT) == 0)
|
||||
{
|
||||
if (work->recursion_level > DEMANGLE_RECURSION_LIMIT)
|
||||
/* FIXME: There ought to be a way to report
|
||||
that the recursion limit has been reached. */
|
||||
return 0;
|
||||
|
||||
work->recursion_level ++;
|
||||
}
|
||||
|
||||
/* The G++ name-mangling algorithm does not remember types on nested
|
||||
argument lists, unless -fsquangling is used, and in that case the
|
||||
type vector updated by remember_type is not used. So, we turn
|
||||
@ -4722,6 +4753,9 @@ demangle_nested_args (struct work_stuff *work, const char **mangled,
|
||||
--work->forgetting_types;
|
||||
work->nrepeats = saved_nrepeats;
|
||||
|
||||
if ((work->options & DMGL_NO_RECURSE_LIMIT) == 0)
|
||||
--work->recursion_level;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -298,8 +298,6 @@ pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time)
|
||||
#endif /* ! defined (HAVE_WAITPID) */
|
||||
#endif /* ! defined (HAVE_WAIT4) */
|
||||
|
||||
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, int);
|
||||
static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *,
|
||||
@ -366,28 +364,6 @@ pex_unix_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
|
||||
return close (fd);
|
||||
}
|
||||
|
||||
/* Report an error from a child process. We don't use stdio routines,
|
||||
because we might be here due to a vfork call. */
|
||||
|
||||
static void
|
||||
pex_child_error (struct pex_obj *obj, const char *executable,
|
||||
const char *errmsg, int err)
|
||||
{
|
||||
int retval = 0;
|
||||
#define writeerr(s) retval |= (write (STDERR_FILE_NO, s, strlen (s)) < 0)
|
||||
writeerr (obj->pname);
|
||||
writeerr (": error trying to exec '");
|
||||
writeerr (executable);
|
||||
writeerr ("': ");
|
||||
writeerr (errmsg);
|
||||
writeerr (": ");
|
||||
writeerr (xstrerror (err));
|
||||
writeerr ("\n");
|
||||
#undef writeerr
|
||||
/* Exit with -2 if the error output failed, too. */
|
||||
_exit (retval == 0 ? -1 : -2);
|
||||
}
|
||||
|
||||
/* Execute a child. */
|
||||
|
||||
#if defined(HAVE_SPAWNVE) && defined(HAVE_SPAWNVPE)
|
||||
@ -592,21 +568,53 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
|
||||
int in, int out, int errdes,
|
||||
int toclose, const char **errmsg, int *err)
|
||||
{
|
||||
pid_t pid;
|
||||
pid_t pid = -1;
|
||||
/* Tuple to communicate error from child to parent. We can safely
|
||||
transfer string literal pointers as both run with identical
|
||||
address mappings. */
|
||||
struct fn_err
|
||||
{
|
||||
const char *fn;
|
||||
int err;
|
||||
};
|
||||
volatile int do_pipe = 0;
|
||||
volatile int pipes[2]; /* [0]:reader,[1]:writer. */
|
||||
#ifdef O_CLOEXEC
|
||||
do_pipe = 1;
|
||||
#endif
|
||||
if (do_pipe)
|
||||
{
|
||||
#ifdef HAVE_PIPE2
|
||||
if (pipe2 ((int *)pipes, O_CLOEXEC))
|
||||
do_pipe = 0;
|
||||
#else
|
||||
if (pipe ((int *)pipes))
|
||||
do_pipe = 0;
|
||||
else
|
||||
{
|
||||
if (fcntl (pipes[1], F_SETFD, FD_CLOEXEC) == -1)
|
||||
{
|
||||
close (pipes[0]);
|
||||
close (pipes[1]);
|
||||
do_pipe = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* We declare these to be volatile to avoid warnings from gcc about
|
||||
them being clobbered by vfork. */
|
||||
volatile int sleep_interval;
|
||||
volatile int sleep_interval = 1;
|
||||
volatile int retries;
|
||||
|
||||
/* We vfork and then set environ in the child before calling execvp.
|
||||
This clobbers the parent's environ so we need to restore it.
|
||||
It would be nice to use one of the exec* functions that takes an
|
||||
environment as a parameter, but that may have portability issues. */
|
||||
char **save_environ = environ;
|
||||
environment as a parameter, but that may have portability
|
||||
issues. It is marked volatile so the child doesn't consider it a
|
||||
dead variable and therefore clobber where ever it is stored. */
|
||||
char **volatile save_environ = environ;
|
||||
|
||||
sleep_interval = 1;
|
||||
pid = -1;
|
||||
for (retries = 0; retries < 4; ++retries)
|
||||
{
|
||||
pid = vfork ();
|
||||
@ -619,104 +627,138 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
|
||||
switch (pid)
|
||||
{
|
||||
case -1:
|
||||
if (do_pipe)
|
||||
{
|
||||
close (pipes[0]);
|
||||
close (pipes[1]);
|
||||
}
|
||||
*err = errno;
|
||||
*errmsg = VFORK_STRING;
|
||||
return (pid_t) -1;
|
||||
|
||||
case 0:
|
||||
/* Child process. */
|
||||
if (in != STDIN_FILE_NO)
|
||||
{
|
||||
if (dup2 (in, STDIN_FILE_NO) < 0)
|
||||
pex_child_error (obj, executable, "dup2", errno);
|
||||
if (close (in) < 0)
|
||||
pex_child_error (obj, executable, "close", errno);
|
||||
}
|
||||
if (out != STDOUT_FILE_NO)
|
||||
{
|
||||
if (dup2 (out, STDOUT_FILE_NO) < 0)
|
||||
pex_child_error (obj, executable, "dup2", errno);
|
||||
if (close (out) < 0)
|
||||
pex_child_error (obj, executable, "close", errno);
|
||||
}
|
||||
if (errdes != STDERR_FILE_NO)
|
||||
{
|
||||
if (dup2 (errdes, STDERR_FILE_NO) < 0)
|
||||
pex_child_error (obj, executable, "dup2", errno);
|
||||
if (close (errdes) < 0)
|
||||
pex_child_error (obj, executable, "close", errno);
|
||||
}
|
||||
if (toclose >= 0)
|
||||
{
|
||||
if (close (toclose) < 0)
|
||||
pex_child_error (obj, executable, "close", errno);
|
||||
}
|
||||
if ((flags & PEX_STDERR_TO_STDOUT) != 0)
|
||||
{
|
||||
if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
|
||||
pex_child_error (obj, executable, "dup2", errno);
|
||||
}
|
||||
{
|
||||
struct fn_err failed;
|
||||
failed.fn = NULL;
|
||||
|
||||
if (env)
|
||||
{
|
||||
/* NOTE: In a standard vfork implementation this clobbers the
|
||||
parent's copy of environ "too" (in reality there's only one copy).
|
||||
This is ok as we restore it below. */
|
||||
environ = (char**) env;
|
||||
}
|
||||
if (do_pipe)
|
||||
close (pipes[0]);
|
||||
if (!failed.fn && in != STDIN_FILE_NO)
|
||||
{
|
||||
if (dup2 (in, STDIN_FILE_NO) < 0)
|
||||
failed.fn = "dup2", failed.err = errno;
|
||||
else if (close (in) < 0)
|
||||
failed.fn = "close", failed.err = errno;
|
||||
}
|
||||
if (!failed.fn && out != STDOUT_FILE_NO)
|
||||
{
|
||||
if (dup2 (out, STDOUT_FILE_NO) < 0)
|
||||
failed.fn = "dup2", failed.err = errno;
|
||||
else if (close (out) < 0)
|
||||
failed.fn = "close", failed.err = errno;
|
||||
}
|
||||
if (!failed.fn && errdes != STDERR_FILE_NO)
|
||||
{
|
||||
if (dup2 (errdes, STDERR_FILE_NO) < 0)
|
||||
failed.fn = "dup2", failed.err = errno;
|
||||
else if (close (errdes) < 0)
|
||||
failed.fn = "close", failed.err = errno;
|
||||
}
|
||||
if (!failed.fn && toclose >= 0)
|
||||
{
|
||||
if (close (toclose) < 0)
|
||||
failed.fn = "close", failed.err = errno;
|
||||
}
|
||||
if (!failed.fn && (flags & PEX_STDERR_TO_STDOUT) != 0)
|
||||
{
|
||||
if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
|
||||
failed.fn = "dup2", failed.err = errno;
|
||||
}
|
||||
if (!failed.fn)
|
||||
{
|
||||
if (env)
|
||||
/* NOTE: In a standard vfork implementation this clobbers
|
||||
the parent's copy of environ "too" (in reality there's
|
||||
only one copy). This is ok as we restore it below. */
|
||||
environ = (char**) env;
|
||||
if ((flags & PEX_SEARCH) != 0)
|
||||
{
|
||||
execvp (executable, to_ptr32 (argv));
|
||||
failed.fn = "execvp", failed.err = errno;
|
||||
}
|
||||
else
|
||||
{
|
||||
execv (executable, to_ptr32 (argv));
|
||||
failed.fn = "execv", failed.err = errno;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & PEX_SEARCH) != 0)
|
||||
{
|
||||
execvp (executable, to_ptr32 (argv));
|
||||
pex_child_error (obj, executable, "execvp", errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
execv (executable, to_ptr32 (argv));
|
||||
pex_child_error (obj, executable, "execv", errno);
|
||||
}
|
||||
/* Something failed, report an error. We don't use stdio
|
||||
routines, because we might be here due to a vfork call. */
|
||||
ssize_t retval = 0;
|
||||
|
||||
if (!do_pipe
|
||||
|| write (pipes[1], &failed, sizeof (failed)) != sizeof (failed))
|
||||
{
|
||||
/* The parent will not see our scream above, so write to
|
||||
stdout. */
|
||||
#define writeerr(s) (retval |= write (STDERR_FILE_NO, s, strlen (s)))
|
||||
writeerr (obj->pname);
|
||||
writeerr (": error trying to exec '");
|
||||
writeerr (executable);
|
||||
writeerr ("': ");
|
||||
writeerr (failed.fn);
|
||||
writeerr (": ");
|
||||
writeerr (xstrerror (failed.err));
|
||||
writeerr ("\n");
|
||||
#undef writeerr
|
||||
}
|
||||
|
||||
/* Exit with -2 if the error output failed, too. */
|
||||
_exit (retval < 0 ? -2 : -1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
return (pid_t) -1;
|
||||
|
||||
default:
|
||||
/* Parent process. */
|
||||
{
|
||||
/* Restore environ. Note that the parent either doesn't run
|
||||
until the child execs/exits (standard vfork behaviour), or
|
||||
if it does run then vfork is behaving more like fork. In
|
||||
either case we needn't worry about clobbering the child's
|
||||
copy of environ. */
|
||||
environ = save_environ;
|
||||
|
||||
/* Restore environ.
|
||||
Note that the parent either doesn't run until the child execs/exits
|
||||
(standard vfork behaviour), or if it does run then vfork is behaving
|
||||
more like fork. In either case we needn't worry about clobbering
|
||||
the child's copy of environ. */
|
||||
environ = save_environ;
|
||||
struct fn_err failed;
|
||||
failed.fn = NULL;
|
||||
if (do_pipe)
|
||||
{
|
||||
close (pipes[1]);
|
||||
ssize_t len = read (pipes[0], &failed, sizeof (failed));
|
||||
if (len < 0)
|
||||
failed.fn = NULL;
|
||||
close (pipes[0]);
|
||||
}
|
||||
|
||||
if (in != STDIN_FILE_NO)
|
||||
{
|
||||
if (!failed.fn && in != STDIN_FILE_NO)
|
||||
if (close (in) < 0)
|
||||
{
|
||||
*err = errno;
|
||||
*errmsg = "close";
|
||||
return (pid_t) -1;
|
||||
}
|
||||
}
|
||||
if (out != STDOUT_FILE_NO)
|
||||
{
|
||||
failed.fn = "close", failed.err = errno;
|
||||
if (!failed.fn && out != STDOUT_FILE_NO)
|
||||
if (close (out) < 0)
|
||||
{
|
||||
*err = errno;
|
||||
*errmsg = "close";
|
||||
return (pid_t) -1;
|
||||
}
|
||||
}
|
||||
if (errdes != STDERR_FILE_NO)
|
||||
{
|
||||
failed.fn = "close", failed.err = errno;
|
||||
if (!failed.fn && errdes != STDERR_FILE_NO)
|
||||
if (close (errdes) < 0)
|
||||
{
|
||||
*err = errno;
|
||||
*errmsg = "close";
|
||||
return (pid_t) -1;
|
||||
}
|
||||
}
|
||||
failed.fn = "close", failed.err = errno;
|
||||
|
||||
if (failed.fn)
|
||||
{
|
||||
*err = failed.err;
|
||||
*errmsg = failed.fn;
|
||||
return (pid_t) -1;
|
||||
}
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user