mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-19 13:53:29 +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:
@ -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>
|
2018-12-03 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR 23941
|
PR 23941
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
-*- text -*-
|
-*- 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
|
* Objdump's --disassemble option can now take a parameter, specifying the
|
||||||
starting symbol for disassembly. Disassembly will continue from this
|
starting symbol for disassembly. Disassembly will continue from this
|
||||||
symbol up to the next symbol.
|
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 pretty_print; /* -p, print on one line. */
|
||||||
static bfd_boolean base_names; /* -s, strip directory names. */
|
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 int naddr; /* Number of addresses to process. */
|
||||||
static char **addr; /* Hex addresses to process. */
|
static char **addr; /* Hex addresses to process. */
|
||||||
|
|
||||||
@ -59,6 +62,10 @@ static struct option long_options[] =
|
|||||||
{"functions", no_argument, NULL, 'f'},
|
{"functions", no_argument, NULL, 'f'},
|
||||||
{"inlines", no_argument, NULL, 'i'},
|
{"inlines", no_argument, NULL, 'i'},
|
||||||
{"pretty-print", no_argument, NULL, 'p'},
|
{"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'},
|
{"section", required_argument, NULL, 'j'},
|
||||||
{"target", required_argument, NULL, 'b'},
|
{"target", required_argument, NULL, 'b'},
|
||||||
{"help", no_argument, NULL, 'H'},
|
{"help", no_argument, NULL, 'H'},
|
||||||
@ -91,6 +98,8 @@ usage (FILE *stream, int status)
|
|||||||
-s --basenames Strip directory names\n\
|
-s --basenames Strip directory names\n\
|
||||||
-f --functions Show function names\n\
|
-f --functions Show function names\n\
|
||||||
-C --demangle[=style] Demangle 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\
|
-h --help Display this information\n\
|
||||||
-v --version Display the program's version\n\
|
-v --version Display the program's version\n\
|
||||||
\n"));
|
\n"));
|
||||||
@ -289,7 +298,7 @@ translate_addresses (bfd *abfd, asection *section)
|
|||||||
name = "??";
|
name = "??";
|
||||||
else if (do_demangle)
|
else if (do_demangle)
|
||||||
{
|
{
|
||||||
alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
|
alloc = bfd_demangle (abfd, name, demangle_flags);
|
||||||
if (alloc != NULL)
|
if (alloc != NULL)
|
||||||
name = alloc;
|
name = alloc;
|
||||||
}
|
}
|
||||||
@ -442,7 +451,7 @@ main (int argc, char **argv)
|
|||||||
file_name = NULL;
|
file_name = NULL;
|
||||||
section_name = NULL;
|
section_name = NULL;
|
||||||
target = 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)
|
!= EOF)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
@ -469,6 +478,12 @@ main (int argc, char **argv)
|
|||||||
cplus_demangle_set_style (style);
|
cplus_demangle_set_style (style);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'r':
|
||||||
|
demangle_flags |= DMGL_NO_RECURSE_LIMIT;
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
demangle_flags &= ~ DMGL_NO_RECURSE_LIMIT;
|
||||||
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
file_name = optarg;
|
file_name = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -42,6 +42,10 @@ static const struct option long_options[] =
|
|||||||
{"no-verbose", no_argument, NULL, 'i'},
|
{"no-verbose", no_argument, NULL, 'i'},
|
||||||
{"types", no_argument, NULL, 't'},
|
{"types", no_argument, NULL, 't'},
|
||||||
{"version", no_argument, NULL, 'v'},
|
{"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}
|
{NULL, no_argument, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -102,6 +106,8 @@ Options are:\n\
|
|||||||
fprintf (stream, "\
|
fprintf (stream, "\
|
||||||
[-p|--no-params] Do not display function arguments\n\
|
[-p|--no-params] Do not display function arguments\n\
|
||||||
[-i|--no-verbose] Do not show implementation details (if any)\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\
|
[-t|--types] Also attempt to demangle type encodings\n\
|
||||||
[-s|--format ");
|
[-s|--format ");
|
||||||
print_demangler_list (stream);
|
print_demangler_list (stream);
|
||||||
@ -180,7 +186,7 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
expandargv (&argc, &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)
|
switch (c)
|
||||||
{
|
{
|
||||||
@ -195,6 +201,12 @@ main (int argc, char **argv)
|
|||||||
case 'p':
|
case 'p':
|
||||||
flags &= ~ DMGL_PARAMS;
|
flags &= ~ DMGL_PARAMS;
|
||||||
break;
|
break;
|
||||||
|
case 'r':
|
||||||
|
flags |= DMGL_NO_RECURSE_LIMIT;
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
flags &= ~ DMGL_NO_RECURSE_LIMIT;
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
flags |= DMGL_TYPES;
|
flags |= DMGL_TYPES;
|
||||||
break;
|
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{-s}|@option{--print-armap}] [@option{-t} @var{radix}|@option{--radix=}@var{radix}]
|
||||||
[@option{-u}|@option{--undefined-only}] [@option{-V}|@option{--version}]
|
[@option{-u}|@option{--undefined-only}] [@option{-V}|@option{--version}]
|
||||||
[@option{-X 32_64}] [@option{--defined-only}] [@option{--no-demangle}]
|
[@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}]
|
[@option{--synthetic}] [@option{--with-symbol-versions}] [@option{--target=}@var{bfdname}]
|
||||||
[@var{objfile}@dots{}]
|
[@var{objfile}@dots{}]
|
||||||
@c man end
|
@c man end
|
||||||
@ -939,6 +941,22 @@ for more information on demangling.
|
|||||||
@item --no-demangle
|
@item --no-demangle
|
||||||
Do not demangle low-level symbol names. This is the default.
|
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
|
@item -D
|
||||||
@itemx --dynamic
|
@itemx --dynamic
|
||||||
@cindex dynamic symbols
|
@cindex dynamic symbols
|
||||||
@ -2098,6 +2116,7 @@ objdump [@option{-a}|@option{--archive-headers}]
|
|||||||
[@option{--adjust-vma=}@var{offset}]
|
[@option{--adjust-vma=}@var{offset}]
|
||||||
[@option{--dwarf-depth=@var{n}}]
|
[@option{--dwarf-depth=@var{n}}]
|
||||||
[@option{--dwarf-start=@var{n}}]
|
[@option{--dwarf-start=@var{n}}]
|
||||||
|
[@option{--no-recurse-limit}|@option{--recurse-limit}]
|
||||||
[@option{--special-syms}]
|
[@option{--special-syms}]
|
||||||
[@option{--prefix=}@var{prefix}]
|
[@option{--prefix=}@var{prefix}]
|
||||||
[@option{--prefix-strip=}@var{level}]
|
[@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},
|
choose an appropriate demangling style for your compiler. @xref{c++filt},
|
||||||
for more information on demangling.
|
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
|
@item -g
|
||||||
@itemx --debugging
|
@itemx --debugging
|
||||||
Display debugging information. This attempts to parse STABS
|
Display debugging information. This attempts to parse STABS
|
||||||
@ -3403,6 +3438,8 @@ c++filt [@option{-_}|@option{--strip-underscore}]
|
|||||||
[@option{-p}|@option{--no-params}]
|
[@option{-p}|@option{--no-params}]
|
||||||
[@option{-t}|@option{--types}]
|
[@option{-t}|@option{--types}]
|
||||||
[@option{-i}|@option{--no-verbose}]
|
[@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{-s} @var{format}|@option{--format=}@var{format}]
|
||||||
[@option{--help}] [@option{--version}] [@var{symbol}@dots{}]
|
[@option{--help}] [@option{--version}] [@var{symbol}@dots{}]
|
||||||
@c man end
|
@c man end
|
||||||
@ -3507,6 +3544,28 @@ demangled to ``signed char''.
|
|||||||
Do not include implementation details (if any) in the demangled
|
Do not include implementation details (if any) in the demangled
|
||||||
output.
|
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}
|
@item -s @var{format}
|
||||||
@itemx --format=@var{format}
|
@itemx --format=@var{format}
|
||||||
@command{c++filt} can decode various methods of mangling, used by
|
@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}]
|
addr2line [@option{-a}|@option{--addresses}]
|
||||||
[@option{-b} @var{bfdname}|@option{--target=}@var{bfdname}]
|
[@option{-b} @var{bfdname}|@option{--target=}@var{bfdname}]
|
||||||
[@option{-C}|@option{--demangle}[=@var{style}]]
|
[@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{-e} @var{filename}|@option{--exe=}@var{filename}]
|
||||||
[@option{-f}|@option{--functions}] [@option{-s}|@option{--basename}]
|
[@option{-f}|@option{--functions}] [@option{-s}|@option{--basename}]
|
||||||
[@option{-i}|@option{--inlines}]
|
[@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.
|
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
|
If option @option{-i} is specified, lines for all enclosing scopes are
|
||||||
prefixed with @samp{(inlined by)}.
|
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
|
@end table
|
||||||
|
|
||||||
@c man end
|
@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 allow_special_symbols = 0; /* Allow special symbols. */
|
||||||
static int with_symbol_versions = 0; /* Include symbol version information in the output. */
|
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. */
|
/* 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_file = 0; /* Once per file, on its own line. */
|
||||||
static int filename_per_symbol = 0; /* Once per symbol, at start of 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_bfd;
|
||||||
static bfd *lineno_cache_rel_bfd;
|
static bfd *lineno_cache_rel_bfd;
|
||||||
|
|
||||||
#define OPTION_TARGET 200
|
enum long_option_values
|
||||||
#define OPTION_PLUGIN (OPTION_TARGET + 1)
|
{
|
||||||
#define OPTION_SIZE_SORT (OPTION_PLUGIN + 1)
|
OPTION_TARGET = 200,
|
||||||
|
OPTION_PLUGIN,
|
||||||
|
OPTION_SIZE_SORT,
|
||||||
|
OPTION_RECURSE_LIMIT,
|
||||||
|
OPTION_NO_RECURSE_LIMIT
|
||||||
|
};
|
||||||
|
|
||||||
static struct option long_options[] =
|
static struct option long_options[] =
|
||||||
{
|
{
|
||||||
@ -209,6 +216,8 @@ static struct option long_options[] =
|
|||||||
{"line-numbers", no_argument, 0, 'l'},
|
{"line-numbers", no_argument, 0, 'l'},
|
||||||
{"no-cplus", no_argument, &do_demangle, 0}, /* Linux compatibility. */
|
{"no-cplus", no_argument, &do_demangle, 0}, /* Linux compatibility. */
|
||||||
{"no-demangle", no_argument, &do_demangle, 0},
|
{"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'},
|
{"no-sort", no_argument, 0, 'p'},
|
||||||
{"numeric-sort", no_argument, 0, 'n'},
|
{"numeric-sort", no_argument, 0, 'n'},
|
||||||
{"plugin", required_argument, 0, OPTION_PLUGIN},
|
{"plugin", required_argument, 0, OPTION_PLUGIN},
|
||||||
@ -217,6 +226,8 @@ static struct option long_options[] =
|
|||||||
{"print-file-name", no_argument, 0, 'o'},
|
{"print-file-name", no_argument, 0, 'o'},
|
||||||
{"print-size", no_argument, 0, 'S'},
|
{"print-size", no_argument, 0, 'S'},
|
||||||
{"radix", required_argument, 0, 't'},
|
{"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},
|
{"reverse-sort", no_argument, &reverse_sort, 1},
|
||||||
{"size-sort", no_argument, 0, OPTION_SIZE_SORT},
|
{"size-sort", no_argument, 0, OPTION_SIZE_SORT},
|
||||||
{"special-syms", no_argument, &allow_special_symbols, 1},
|
{"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\
|
`gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
|
||||||
or `gnat'\n\
|
or `gnat'\n\
|
||||||
--no-demangle Do not demangle low-level symbol names\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\
|
-D, --dynamic Display dynamic symbols instead of normal symbols\n\
|
||||||
--defined-only Display only defined symbols\n\
|
--defined-only Display only defined symbols\n\
|
||||||
-e (ignored)\n\
|
-e (ignored)\n\
|
||||||
@ -407,7 +420,7 @@ print_symname (const char *form, const char *name, bfd *abfd)
|
|||||||
{
|
{
|
||||||
if (do_demangle && *name)
|
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)
|
if (res != NULL)
|
||||||
{
|
{
|
||||||
@ -1687,6 +1700,12 @@ main (int argc, char **argv)
|
|||||||
cplus_demangle_set_style (style);
|
cplus_demangle_set_style (style);
|
||||||
}
|
}
|
||||||
break;
|
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':
|
case 'D':
|
||||||
dynamic = 1;
|
dynamic = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -120,6 +120,8 @@ static size_t prefix_length;
|
|||||||
static bfd_boolean unwind_inlines; /* --inlines. */
|
static bfd_boolean unwind_inlines; /* --inlines. */
|
||||||
static const char * disasm_sym; /* Disassembly start symbol. */
|
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. */
|
/* A structure to record the sections mentioned in -j switches. */
|
||||||
struct only
|
struct only
|
||||||
{
|
{
|
||||||
@ -252,6 +254,8 @@ usage (FILE *stream, int status)
|
|||||||
The STYLE, if specified, can be `auto', `gnu',\n\
|
The STYLE, if specified, can be `auto', `gnu',\n\
|
||||||
`lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
|
`lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
|
||||||
or `gnat'\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\
|
-w, --wide Format output for more than 80 columns\n\
|
||||||
-z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n\
|
-z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n\
|
||||||
--start-address=ADDR Only process data whose address is >= ADDR\n\
|
--start-address=ADDR Only process data whose address is >= ADDR\n\
|
||||||
@ -302,6 +306,8 @@ enum option_values
|
|||||||
OPTION_DWARF_DEPTH,
|
OPTION_DWARF_DEPTH,
|
||||||
OPTION_DWARF_CHECK,
|
OPTION_DWARF_CHECK,
|
||||||
OPTION_DWARF_START,
|
OPTION_DWARF_START,
|
||||||
|
OPTION_RECURSE_LIMIT,
|
||||||
|
OPTION_NO_RECURSE_LIMIT,
|
||||||
OPTION_INLINES
|
OPTION_INLINES
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -333,6 +339,10 @@ static struct option long_options[]=
|
|||||||
{"line-numbers", no_argument, NULL, 'l'},
|
{"line-numbers", no_argument, NULL, 'l'},
|
||||||
{"no-show-raw-insn", no_argument, &show_raw_insn, -1},
|
{"no-show-raw-insn", no_argument, &show_raw_insn, -1},
|
||||||
{"prefix-addresses", no_argument, &prefix_addresses, 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'},
|
{"reloc", no_argument, NULL, 'r'},
|
||||||
{"section", required_argument, NULL, 'j'},
|
{"section", required_argument, NULL, 'j'},
|
||||||
{"section-headers", no_argument, NULL, 'h'},
|
{"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')
|
if (do_demangle && name[0] != '\0')
|
||||||
{
|
{
|
||||||
/* Demangle the name. */
|
/* Demangle the name. */
|
||||||
alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
|
alloc = bfd_demangle (abfd, name, demangle_flags);
|
||||||
if (alloc != NULL)
|
if (alloc != NULL)
|
||||||
name = alloc;
|
name = alloc;
|
||||||
}
|
}
|
||||||
@ -2290,7 +2300,7 @@ disassemble_section (bfd *abfd, asection *section, void *inf)
|
|||||||
if (do_demangle && name[0] != '\0')
|
if (do_demangle && name[0] != '\0')
|
||||||
{
|
{
|
||||||
/* Demangle the name. */
|
/* Demangle the name. */
|
||||||
alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
|
alloc = bfd_demangle (abfd, name, demangle_flags);
|
||||||
if (alloc != NULL)
|
if (alloc != NULL)
|
||||||
name = alloc;
|
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
|
/* If we want to demangle the name, we demangle it
|
||||||
here, and temporarily clobber it while calling
|
here, and temporarily clobber it while calling
|
||||||
bfd_print_symbol. FIXME: This is a gross hack. */
|
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)
|
if (alloc != NULL)
|
||||||
(*current)->name = alloc;
|
(*current)->name = alloc;
|
||||||
bfd_print_symbol (cur_bfd, stdout, *current,
|
bfd_print_symbol (cur_bfd, stdout, *current,
|
||||||
@ -3927,6 +3937,12 @@ main (int argc, char **argv)
|
|||||||
cplus_demangle_set_style (style);
|
cplus_demangle_set_style (style);
|
||||||
}
|
}
|
||||||
break;
|
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':
|
case 'w':
|
||||||
do_wide = wide_output = TRUE;
|
do_wide = wide_output = TRUE;
|
||||||
break;
|
break;
|
||||||
|
@ -286,6 +286,8 @@ static const struct debug_write_fns tg_fns =
|
|||||||
pr_end_function, /* Same, does nothing. */
|
pr_end_function, /* Same, does nothing. */
|
||||||
tg_lineno
|
tg_lineno
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int demangle_flags = DMGL_ANSI | DMGL_PARAMS;
|
||||||
|
|
||||||
/* Print out the generic debugging information recorded in dhandle. */
|
/* 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;
|
dname = NULL;
|
||||||
if (info->demangler)
|
if (info->demangler)
|
||||||
dname = info->demangler (info->abfd, name, DMGL_ANSI | DMGL_PARAMS);
|
dname = info->demangler (info->abfd, name, demangle_flags);
|
||||||
|
|
||||||
from_class = NULL;
|
from_class = NULL;
|
||||||
if (dname != NULL)
|
if (dname != NULL)
|
||||||
@ -2661,7 +2663,7 @@ tg_start_function (void *p, const char *name, bfd_boolean global)
|
|||||||
|
|
||||||
dname = NULL;
|
dname = NULL;
|
||||||
if (info->demangler)
|
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))
|
if (! substitute_type (info, dname ? dname : name))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -215,6 +215,8 @@ static debug_type stab_demangle_v3_arg
|
|||||||
(void *, struct stab_handle *, struct demangle_component *, debug_type,
|
(void *, struct stab_handle *, struct demangle_component *, debug_type,
|
||||||
bfd_boolean *);
|
bfd_boolean *);
|
||||||
|
|
||||||
|
static int demangle_flags = DMGL_ANSI;
|
||||||
|
|
||||||
/* Save a string in memory. */
|
/* Save a string in memory. */
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
@ -4517,7 +4519,7 @@ stab_demangle_template (struct stab_demangle_info *minfo, const char **pp,
|
|||||||
|
|
||||||
free (s1);
|
free (s1);
|
||||||
|
|
||||||
s3 = cplus_demangle (s2, DMGL_ANSI);
|
s3 = cplus_demangle (s2, demangle_flags);
|
||||||
|
|
||||||
free (s2);
|
free (s2);
|
||||||
|
|
||||||
@ -5243,7 +5245,7 @@ stab_demangle_v3_argtypes (void *dhandle, struct stab_handle *info,
|
|||||||
void *mem;
|
void *mem;
|
||||||
debug_type *pargs;
|
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)
|
if (dc == NULL)
|
||||||
{
|
{
|
||||||
stab_bad_demangle (physname);
|
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
|
/* We print this component to get a class name which we can
|
||||||
use. FIXME: This probably won't work if the template uses
|
use. FIXME: This probably won't work if the template uses
|
||||||
template parameters which refer to an outer template. */
|
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)
|
if (p == NULL)
|
||||||
{
|
{
|
||||||
fprintf (stderr, _("Failed to print demangled template\n"));
|
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.
|
/* We print this component in order to find out the type name.
|
||||||
FIXME: Should we instead expose the
|
FIXME: Should we instead expose the
|
||||||
demangle_builtin_type_info structure? */
|
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)
|
if (p == NULL)
|
||||||
{
|
{
|
||||||
fprintf (stderr, _("Couldn't get demangled builtin type\n"));
|
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 {
|
if ![info exists DLLTOOL] then {
|
||||||
set DLLTOOL [findfile $base_dir/dlltool]
|
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}
|
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>
|
2018-12-06 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* opcode/ppc.h (E_OPCODE_MASK, E_LI_MASK, E_LI_INSN): Define.
|
* 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. */
|
/* 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)
|
#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.
|
/* Enumeration of possible demangling styles.
|
||||||
|
|
||||||
Lucid and ARM styles are still kept logically distinct, even though
|
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
|
template argument, and the right subtree is either NULL or
|
||||||
another TEMPLATE_ARGLIST node. */
|
another TEMPLATE_ARGLIST node. */
|
||||||
DEMANGLE_COMPONENT_TEMPLATE_ARGLIST,
|
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
|
/* An initializer list. The left subtree is either an explicit type or
|
||||||
NULL, and the right subtree is a DEMANGLE_COMPONENT_ARGLIST. */
|
NULL, and the right subtree is a DEMANGLE_COMPONENT_ARGLIST. */
|
||||||
DEMANGLE_COMPONENT_INITIALIZER_LIST,
|
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>
|
2018-08-01 Richard Earnshaw <rearnsha@arm.com>
|
||||||
|
|
||||||
Copy over from GCC
|
Copy over from GCC
|
||||||
|
@ -195,6 +195,9 @@
|
|||||||
/* Define to 1 if you have the `on_exit' function. */
|
/* Define to 1 if you have the `on_exit' function. */
|
||||||
#undef HAVE_ON_EXIT
|
#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. */
|
/* Define to 1 if you have the <process.h> header file. */
|
||||||
#undef HAVE_PROCESS_H
|
#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"
|
vars="sys_errlist sys_nerr sys_siglist"
|
||||||
|
|
||||||
checkfuncs="__fsetlocking canonicalize_file_name dup3 getrlimit getrusage \
|
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 \
|
realpath setrlimit sbrk spawnve spawnvpe strerror strsignal sysconf sysctl \
|
||||||
sysmp table times wait3 wait4"
|
sysmp table times wait3 wait4"
|
||||||
|
|
||||||
@ -5813,7 +5813,7 @@ if test "x" = "y"; then
|
|||||||
index insque \
|
index insque \
|
||||||
memchr memcmp memcpy memmem memmove memset mkstemps \
|
memchr memcmp memcpy memmem memmove memset mkstemps \
|
||||||
on_exit \
|
on_exit \
|
||||||
psignal pstat_getdynamic pstat_getstatic putenv \
|
pipe2 psignal pstat_getdynamic pstat_getstatic putenv \
|
||||||
random realpath rename rindex \
|
random realpath rename rindex \
|
||||||
sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \
|
sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \
|
||||||
stpcpy stpncpy strcasecmp strchr strdup \
|
stpcpy stpncpy strcasecmp strchr strdup \
|
||||||
|
@ -390,7 +390,7 @@ funcs="$funcs setproctitle"
|
|||||||
vars="sys_errlist sys_nerr sys_siglist"
|
vars="sys_errlist sys_nerr sys_siglist"
|
||||||
|
|
||||||
checkfuncs="__fsetlocking canonicalize_file_name dup3 getrlimit getrusage \
|
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 \
|
realpath setrlimit sbrk spawnve spawnvpe strerror strsignal sysconf sysctl \
|
||||||
sysmp table times wait3 wait4"
|
sysmp table times wait3 wait4"
|
||||||
|
|
||||||
@ -406,7 +406,7 @@ if test "x" = "y"; then
|
|||||||
index insque \
|
index insque \
|
||||||
memchr memcmp memcpy memmem memmove memset mkstemps \
|
memchr memcmp memcpy memmem memmove memset mkstemps \
|
||||||
on_exit \
|
on_exit \
|
||||||
psignal pstat_getdynamic pstat_getstatic putenv \
|
pipe2 psignal pstat_getdynamic pstat_getstatic putenv \
|
||||||
random realpath rename rindex \
|
random realpath rename rindex \
|
||||||
sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \
|
sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \
|
||||||
stpcpy stpncpy strcasecmp strchr strdup \
|
stpcpy stpncpy strcasecmp strchr strdup \
|
||||||
|
@ -625,6 +625,9 @@ d_dump (struct demangle_component *dc, int indent)
|
|||||||
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
|
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
|
||||||
printf ("template parameter %ld\n", dc->u.s_number.number);
|
printf ("template parameter %ld\n", dc->u.s_number.number);
|
||||||
return;
|
return;
|
||||||
|
case DEMANGLE_COMPONENT_TPARM_OBJ:
|
||||||
|
printf ("template parameter object\n");
|
||||||
|
break;
|
||||||
case DEMANGLE_COMPONENT_FUNCTION_PARAM:
|
case DEMANGLE_COMPONENT_FUNCTION_PARAM:
|
||||||
printf ("function parameter %ld\n", dc->u.s_number.number);
|
printf ("function parameter %ld\n", dc->u.s_number.number);
|
||||||
return;
|
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_GLOBAL_DESTRUCTORS:
|
||||||
case DEMANGLE_COMPONENT_NULLARY:
|
case DEMANGLE_COMPONENT_NULLARY:
|
||||||
case DEMANGLE_COMPONENT_TRINARY_ARG2:
|
case DEMANGLE_COMPONENT_TRINARY_ARG2:
|
||||||
|
case DEMANGLE_COMPONENT_TPARM_OBJ:
|
||||||
if (left == NULL)
|
if (left == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
break;
|
break;
|
||||||
@ -2007,6 +2011,7 @@ d_java_resource (struct d_info *di)
|
|||||||
::= TT <type>
|
::= TT <type>
|
||||||
::= TI <type>
|
::= TI <type>
|
||||||
::= TS <type>
|
::= TS <type>
|
||||||
|
::= TA <template-arg>
|
||||||
::= GV <(object) name>
|
::= GV <(object) name>
|
||||||
::= T <call-offset> <(base) encoding>
|
::= T <call-offset> <(base) encoding>
|
||||||
::= Tc <call-offset> <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,
|
return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER,
|
||||||
d_name (di), NULL);
|
d_name (di), NULL);
|
||||||
|
|
||||||
|
case 'A':
|
||||||
|
return d_make_comp (di, DEMANGLE_COMPONENT_TPARM_OBJ,
|
||||||
|
d_template_arg (di), NULL);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -2843,10 +2852,20 @@ d_ref_qualifier (struct d_info *di, struct demangle_component *sub)
|
|||||||
static struct demangle_component *
|
static struct demangle_component *
|
||||||
d_function_type (struct d_info *di)
|
d_function_type (struct d_info *di)
|
||||||
{
|
{
|
||||||
struct demangle_component *ret;
|
struct demangle_component *ret = NULL;
|
||||||
|
|
||||||
if (! d_check_char (di, 'F'))
|
if ((di->options & DMGL_NO_RECURSE_LIMIT) == 0)
|
||||||
|
{
|
||||||
|
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;
|
return NULL;
|
||||||
|
|
||||||
|
di->recursion_level ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d_check_char (di, 'F'))
|
||||||
|
{
|
||||||
if (d_peek_char (di) == 'Y')
|
if (d_peek_char (di) == 'Y')
|
||||||
{
|
{
|
||||||
/* Function has C linkage. We don't print this information.
|
/* Function has C linkage. We don't print this information.
|
||||||
@ -2857,7 +2876,11 @@ d_function_type (struct d_info *di)
|
|||||||
ret = d_ref_qualifier (di, ret);
|
ret = d_ref_qualifier (di, ret);
|
||||||
|
|
||||||
if (! d_check_char (di, 'E'))
|
if (! d_check_char (di, 'E'))
|
||||||
return NULL;
|
ret = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((di->options & DMGL_NO_RECURSE_LIMIT) == 0)
|
||||||
|
di->recursion_level --;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3327,11 +3350,11 @@ d_expression_1 (struct d_info *di)
|
|||||||
{
|
{
|
||||||
/* Brace-enclosed initializer list, untyped or typed. */
|
/* Brace-enclosed initializer list, untyped or typed. */
|
||||||
struct demangle_component *type = NULL;
|
struct demangle_component *type = NULL;
|
||||||
|
d_advance (di, 2);
|
||||||
if (peek == 't')
|
if (peek == 't')
|
||||||
type = cplus_demangle_type (di);
|
type = cplus_demangle_type (di);
|
||||||
if (!d_peek_next_char (di))
|
if (!d_peek_next_char (di))
|
||||||
return NULL;
|
return NULL;
|
||||||
d_advance (di, 2);
|
|
||||||
return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST,
|
return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST,
|
||||||
type, d_exprlist (di, 'E'));
|
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_VECTOR_TYPE:
|
||||||
case DEMANGLE_COMPONENT_ARGLIST:
|
case DEMANGLE_COMPONENT_ARGLIST:
|
||||||
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
|
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
|
||||||
|
case DEMANGLE_COMPONENT_TPARM_OBJ:
|
||||||
case DEMANGLE_COMPONENT_INITIALIZER_LIST:
|
case DEMANGLE_COMPONENT_INITIALIZER_LIST:
|
||||||
case DEMANGLE_COMPONENT_CAST:
|
case DEMANGLE_COMPONENT_CAST:
|
||||||
case DEMANGLE_COMPONENT_CONVERSION:
|
case DEMANGLE_COMPONENT_CONVERSION:
|
||||||
@ -4872,6 +4896,11 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
|
|||||||
}
|
}
|
||||||
return;
|
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:
|
case DEMANGLE_COMPONENT_CTOR:
|
||||||
d_print_comp (dpi, options, dc->u.s_ctor.name);
|
d_print_comp (dpi, options, dc->u.s_ctor.name);
|
||||||
return;
|
return;
|
||||||
@ -6188,6 +6217,7 @@ cplus_demangle_init_info (const char *mangled, int options, size_t len,
|
|||||||
di->expansion = 0;
|
di->expansion = 0;
|
||||||
di->is_expression = 0;
|
di->is_expression = 0;
|
||||||
di->is_conversion = 0;
|
di->is_conversion = 0;
|
||||||
|
di->recursion_level = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal implementation for the demangler. If MANGLED is a g++ v3 ABI
|
/* 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);
|
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
|
#ifdef CP_DYNAMIC_ARRAYS
|
||||||
__extension__ struct demangle_component comps[di.num_comps];
|
__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
|
/* Non-zero if we are parsing the type operand of a conversion
|
||||||
operator, but not when in an expression. */
|
operator, but not when in an expression. */
|
||||||
int is_conversion;
|
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:
|
/* 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; /* Indices of currently processed remembered typevecs. */
|
||||||
int proctypevec_size;
|
int proctypevec_size;
|
||||||
int nproctypes;
|
int nproctypes;
|
||||||
|
unsigned int recursion_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
|
#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
|
||||||
@ -1292,12 +1293,14 @@ squangle_mop_up (struct work_stuff *work)
|
|||||||
free ((char *) work -> btypevec);
|
free ((char *) work -> btypevec);
|
||||||
work->btypevec = NULL;
|
work->btypevec = NULL;
|
||||||
work->bsize = 0;
|
work->bsize = 0;
|
||||||
|
work->numb = 0;
|
||||||
}
|
}
|
||||||
if (work -> ktypevec != NULL)
|
if (work -> ktypevec != NULL)
|
||||||
{
|
{
|
||||||
free ((char *) work -> ktypevec);
|
free ((char *) work -> ktypevec);
|
||||||
work->ktypevec = NULL;
|
work->ktypevec = NULL;
|
||||||
work->ksize = 0;
|
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++)
|
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);
|
to->ktypevec[i] = XNEWVEC (char, len);
|
||||||
memcpy (to->ktypevec[i], from->ktypevec[i], 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++)
|
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);
|
to->btypevec[i] = XNEWVEC (char , len);
|
||||||
memcpy (to->btypevec[i], from->btypevec[i], 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);
|
free ((char*) work->tmpl_argvec);
|
||||||
work->tmpl_argvec = NULL;
|
work->tmpl_argvec = NULL;
|
||||||
|
work->ntmpl_args = 0;
|
||||||
}
|
}
|
||||||
if (work->previous_argument)
|
if (work->previous_argument)
|
||||||
{
|
{
|
||||||
@ -4471,12 +4489,14 @@ remember_Btype (struct work_stuff *work, const char *start,
|
|||||||
char *tem;
|
char *tem;
|
||||||
|
|
||||||
tem = XNEWVEC (char, len + 1);
|
tem = XNEWVEC (char, len + 1);
|
||||||
|
if (len > 0)
|
||||||
memcpy (tem, start, len);
|
memcpy (tem, start, len);
|
||||||
tem[len] = '\0';
|
tem[len] = '\0';
|
||||||
work -> btypevec[index] = tem;
|
work -> btypevec[index] = tem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lose all the info related to B and K type codes. */
|
/* Lose all the info related to B and K type codes. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
forget_B_and_K_types (struct work_stuff *work)
|
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. */
|
/* Forget the remembered types, but not the type vector itself. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -4696,6 +4717,16 @@ demangle_nested_args (struct work_stuff *work, const char **mangled,
|
|||||||
int result;
|
int result;
|
||||||
int saved_nrepeats;
|
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
|
/* The G++ name-mangling algorithm does not remember types on nested
|
||||||
argument lists, unless -fsquangling is used, and in that case the
|
argument lists, unless -fsquangling is used, and in that case the
|
||||||
type vector updated by remember_type is not used. So, we turn
|
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->forgetting_types;
|
||||||
work->nrepeats = saved_nrepeats;
|
work->nrepeats = saved_nrepeats;
|
||||||
|
|
||||||
|
if ((work->options & DMGL_NO_RECURSE_LIMIT) == 0)
|
||||||
|
--work->recursion_level;
|
||||||
|
|
||||||
return result;
|
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_WAITPID) */
|
||||||
#endif /* ! defined (HAVE_WAIT4) */
|
#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_read (struct pex_obj *, const char *, int);
|
||||||
static int pex_unix_open_write (struct pex_obj *, const char *, int, 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 *,
|
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);
|
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. */
|
/* Execute a child. */
|
||||||
|
|
||||||
#if defined(HAVE_SPAWNVE) && defined(HAVE_SPAWNVPE)
|
#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 in, int out, int errdes,
|
||||||
int toclose, const char **errmsg, int *err)
|
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
|
/* We declare these to be volatile to avoid warnings from gcc about
|
||||||
them being clobbered by vfork. */
|
them being clobbered by vfork. */
|
||||||
volatile int sleep_interval;
|
volatile int sleep_interval = 1;
|
||||||
volatile int retries;
|
volatile int retries;
|
||||||
|
|
||||||
/* We vfork and then set environ in the child before calling execvp.
|
/* We vfork and then set environ in the child before calling execvp.
|
||||||
This clobbers the parent's environ so we need to restore it.
|
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
|
It would be nice to use one of the exec* functions that takes an
|
||||||
environment as a parameter, but that may have portability issues. */
|
environment as a parameter, but that may have portability
|
||||||
char **save_environ = environ;
|
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)
|
for (retries = 0; retries < 4; ++retries)
|
||||||
{
|
{
|
||||||
pid = vfork ();
|
pid = vfork ();
|
||||||
@ -619,104 +627,138 @@ pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
|
|||||||
switch (pid)
|
switch (pid)
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
|
if (do_pipe)
|
||||||
|
{
|
||||||
|
close (pipes[0]);
|
||||||
|
close (pipes[1]);
|
||||||
|
}
|
||||||
*err = errno;
|
*err = errno;
|
||||||
*errmsg = VFORK_STRING;
|
*errmsg = VFORK_STRING;
|
||||||
return (pid_t) -1;
|
return (pid_t) -1;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
/* Child process. */
|
/* Child process. */
|
||||||
if (in != STDIN_FILE_NO)
|
{
|
||||||
|
struct fn_err failed;
|
||||||
|
failed.fn = NULL;
|
||||||
|
|
||||||
|
if (do_pipe)
|
||||||
|
close (pipes[0]);
|
||||||
|
if (!failed.fn && in != STDIN_FILE_NO)
|
||||||
{
|
{
|
||||||
if (dup2 (in, STDIN_FILE_NO) < 0)
|
if (dup2 (in, STDIN_FILE_NO) < 0)
|
||||||
pex_child_error (obj, executable, "dup2", errno);
|
failed.fn = "dup2", failed.err = errno;
|
||||||
if (close (in) < 0)
|
else if (close (in) < 0)
|
||||||
pex_child_error (obj, executable, "close", errno);
|
failed.fn = "close", failed.err = errno;
|
||||||
}
|
}
|
||||||
if (out != STDOUT_FILE_NO)
|
if (!failed.fn && out != STDOUT_FILE_NO)
|
||||||
{
|
{
|
||||||
if (dup2 (out, STDOUT_FILE_NO) < 0)
|
if (dup2 (out, STDOUT_FILE_NO) < 0)
|
||||||
pex_child_error (obj, executable, "dup2", errno);
|
failed.fn = "dup2", failed.err = errno;
|
||||||
if (close (out) < 0)
|
else if (close (out) < 0)
|
||||||
pex_child_error (obj, executable, "close", errno);
|
failed.fn = "close", failed.err = errno;
|
||||||
}
|
}
|
||||||
if (errdes != STDERR_FILE_NO)
|
if (!failed.fn && errdes != STDERR_FILE_NO)
|
||||||
{
|
{
|
||||||
if (dup2 (errdes, STDERR_FILE_NO) < 0)
|
if (dup2 (errdes, STDERR_FILE_NO) < 0)
|
||||||
pex_child_error (obj, executable, "dup2", errno);
|
failed.fn = "dup2", failed.err = errno;
|
||||||
if (close (errdes) < 0)
|
else if (close (errdes) < 0)
|
||||||
pex_child_error (obj, executable, "close", errno);
|
failed.fn = "close", failed.err = errno;
|
||||||
}
|
}
|
||||||
if (toclose >= 0)
|
if (!failed.fn && toclose >= 0)
|
||||||
{
|
{
|
||||||
if (close (toclose) < 0)
|
if (close (toclose) < 0)
|
||||||
pex_child_error (obj, executable, "close", errno);
|
failed.fn = "close", failed.err = errno;
|
||||||
}
|
}
|
||||||
if ((flags & PEX_STDERR_TO_STDOUT) != 0)
|
if (!failed.fn && (flags & PEX_STDERR_TO_STDOUT) != 0)
|
||||||
{
|
{
|
||||||
if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
|
if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
|
||||||
pex_child_error (obj, executable, "dup2", errno);
|
failed.fn = "dup2", failed.err = errno;
|
||||||
}
|
}
|
||||||
|
if (!failed.fn)
|
||||||
if (env)
|
|
||||||
{
|
{
|
||||||
/* NOTE: In a standard vfork implementation this clobbers the
|
if (env)
|
||||||
parent's copy of environ "too" (in reality there's only one copy).
|
/* NOTE: In a standard vfork implementation this clobbers
|
||||||
This is ok as we restore it below. */
|
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;
|
environ = (char**) env;
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & PEX_SEARCH) != 0)
|
if ((flags & PEX_SEARCH) != 0)
|
||||||
{
|
{
|
||||||
execvp (executable, to_ptr32 (argv));
|
execvp (executable, to_ptr32 (argv));
|
||||||
pex_child_error (obj, executable, "execvp", errno);
|
failed.fn = "execvp", failed.err = errno;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
execv (executable, to_ptr32 (argv));
|
execv (executable, to_ptr32 (argv));
|
||||||
pex_child_error (obj, executable, "execv", errno);
|
failed.fn = "execv", failed.err = 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 */
|
/* NOTREACHED */
|
||||||
return (pid_t) -1;
|
return (pid_t) -1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Parent process. */
|
/* Parent process. */
|
||||||
|
{
|
||||||
/* Restore environ.
|
/* Restore environ. Note that the parent either doesn't run
|
||||||
Note that the parent either doesn't run until the child execs/exits
|
until the child execs/exits (standard vfork behaviour), or
|
||||||
(standard vfork behaviour), or if it does run then vfork is behaving
|
if it does run then vfork is behaving more like fork. In
|
||||||
more like fork. In either case we needn't worry about clobbering
|
either case we needn't worry about clobbering the child's
|
||||||
the child's copy of environ. */
|
copy of environ. */
|
||||||
environ = save_environ;
|
environ = save_environ;
|
||||||
|
|
||||||
if (in != STDIN_FILE_NO)
|
struct fn_err failed;
|
||||||
|
failed.fn = NULL;
|
||||||
|
if (do_pipe)
|
||||||
{
|
{
|
||||||
if (close (in) < 0)
|
close (pipes[1]);
|
||||||
{
|
ssize_t len = read (pipes[0], &failed, sizeof (failed));
|
||||||
*err = errno;
|
if (len < 0)
|
||||||
*errmsg = "close";
|
failed.fn = NULL;
|
||||||
return (pid_t) -1;
|
close (pipes[0]);
|
||||||
}
|
|
||||||
}
|
|
||||||
if (out != STDOUT_FILE_NO)
|
|
||||||
{
|
|
||||||
if (close (out) < 0)
|
|
||||||
{
|
|
||||||
*err = errno;
|
|
||||||
*errmsg = "close";
|
|
||||||
return (pid_t) -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (errdes != STDERR_FILE_NO)
|
|
||||||
{
|
|
||||||
if (close (errdes) < 0)
|
|
||||||
{
|
|
||||||
*err = errno;
|
|
||||||
*errmsg = "close";
|
|
||||||
return (pid_t) -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!failed.fn && in != STDIN_FILE_NO)
|
||||||
|
if (close (in) < 0)
|
||||||
|
failed.fn = "close", failed.err = errno;
|
||||||
|
if (!failed.fn && out != STDOUT_FILE_NO)
|
||||||
|
if (close (out) < 0)
|
||||||
|
failed.fn = "close", failed.err = errno;
|
||||||
|
if (!failed.fn && errdes != STDERR_FILE_NO)
|
||||||
|
if (close (errdes) < 0)
|
||||||
|
failed.fn = "close", failed.err = errno;
|
||||||
|
|
||||||
|
if (failed.fn)
|
||||||
|
{
|
||||||
|
*err = failed.err;
|
||||||
|
*errmsg = failed.fn;
|
||||||
|
return (pid_t) -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user