|
|
|
|
diff -rup binutils.orig.1/binutils/NEWS binutils-2.30/binutils/NEWS
|
|
|
|
|
--- binutils.orig.1/binutils/NEWS 2024-10-29 14:04:54.266101412 +0000
|
|
|
|
|
+++ binutils-2.30/binutils/NEWS 2024-10-29 14:15:21.886239329 +0000
|
|
|
|
|
@@ -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.
|
|
|
|
|
+
|
|
|
|
|
* Tools which display names or strings (readelf, strings, nm, objdump)
|
|
|
|
|
have a new command line option which controls how unicode characters are
|
|
|
|
|
handled. By default they are treated as normal for the tool. Using
|
|
|
|
|
diff -rup binutils.orig.1/binutils/addr2line.c binutils-2.30/binutils/addr2line.c
|
|
|
|
|
--- binutils.orig.1/binutils/addr2line.c 2024-10-29 14:04:54.258101392 +0000
|
|
|
|
|
+++ binutils-2.30/binutils/addr2line.c 2024-10-29 14:14:33.062109460 +0000
|
|
|
|
|
@@ -45,6 +45,9 @@ static bfd_boolean do_demangle; /* -C,
|
|
|
|
|
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
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
@@ -441,7 +450,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)
|
|
|
|
|
@@ -468,6 +477,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;
|
|
|
|
|
diff -rup binutils.orig.1/binutils/cxxfilt.c binutils-2.30/binutils/cxxfilt.c
|
|
|
|
|
--- binutils.orig.1/binutils/cxxfilt.c 2024-10-29 14:04:54.258101392 +0000
|
|
|
|
|
+++ binutils-2.30/binutils/cxxfilt.c 2024-10-29 14:14:33.062109460 +0000
|
|
|
|
|
@@ -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;
|
|
|
|
|
diff -rup binutils.orig.1/binutils/doc/binutils.texi binutils-2.30/binutils/doc/binutils.texi
|
|
|
|
|
--- binutils.orig.1/binutils/doc/binutils.texi 2024-10-29 14:04:54.257101390 +0000
|
|
|
|
|
+++ binutils-2.30/binutils/doc/binutils.texi 2024-10-29 14:14:33.062109460 +0000
|
|
|
|
|
@@ -769,7 +769,9 @@ nm [@option{-A}|@option{-o}|@option{--pr
|
|
|
|
|
[@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
|
|
|
|
|
@@ -936,6 +938,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
|
|
|
|
|
@@ -2105,6 +2123,7 @@ objdump [@option{-a}|@option{--archive-h
|
|
|
|
|
[@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}]
|
|
|
|
|
@@ -2182,6 +2201,22 @@ mangling styles. The optional demangling
|
|
|
|
|
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 and IEEE
|
|
|
|
|
@@ -3440,6 +3475,8 @@ c++filt [@option{-_}|@option{--strip-und
|
|
|
|
|
[@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
|
|
|
|
|
@@ -3544,6 +3581,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
|
|
|
|
|
@@ -3617,6 +3676,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}]
|
|
|
|
|
@@ -3742,6 +3803,32 @@ Read offsets relative to the specified s
|
|
|
|
|
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
|
|
|
|
|
diff -rup binutils.orig.1/binutils/nm.c binutils-2.30/binutils/nm.c
|
|
|
|
|
--- binutils.orig.1/binutils/nm.c 2024-10-29 14:04:54.266101412 +0000
|
|
|
|
|
+++ binutils-2.30/binutils/nm.c 2024-10-29 14:14:33.063109462 +0000
|
|
|
|
|
@@ -167,6 +167,8 @@ static int line_numbers = 0; /* Print li
|
|
|
|
|
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. */
|
|
|
|
|
@@ -211,9 +213,14 @@ typedef enum unicode_display_type
|
|
|
|
|
|
|
|
|
|
static unicode_display_type unicode_display = unicode_default;
|
|
|
|
|
|
|
|
|
|
-#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[] =
|
|
|
|
|
{
|
|
|
|
|
@@ -226,6 +233,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},
|
|
|
|
|
@@ -234,6 +243,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},
|
|
|
|
|
@@ -263,6 +274,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\
|
|
|
|
|
@@ -610,7 +623,7 @@ print_symname (const char *form, const c
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
@@ -1892,6 +1905,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;
|
|
|
|
|
diff -rup binutils.orig.1/binutils/objdump.c binutils-2.30/binutils/objdump.c
|
|
|
|
|
--- binutils.orig.1/binutils/objdump.c 2024-10-29 14:04:54.266101412 +0000
|
|
|
|
|
+++ binutils-2.30/binutils/objdump.c 2024-10-29 14:14:33.063109462 +0000
|
|
|
|
|
@@ -119,6 +119,8 @@ static int prefix_strip; /* --prefix-st
|
|
|
|
|
static size_t prefix_length;
|
|
|
|
|
static bfd_boolean unwind_inlines; /* --inlines. */
|
|
|
|
|
|
|
|
|
|
+static int demangle_flags = DMGL_ANSI | DMGL_PARAMS;
|
|
|
|
|
+
|
|
|
|
|
/* A structure to record the sections mentioned in -j switches. */
|
|
|
|
|
struct only
|
|
|
|
|
{
|
|
|
|
|
@@ -264,6 +266,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\
|
|
|
|
|
@@ -314,6 +318,8 @@ enum option_values
|
|
|
|
|
OPTION_DWARF_DEPTH,
|
|
|
|
|
OPTION_DWARF_CHECK,
|
|
|
|
|
OPTION_DWARF_START,
|
|
|
|
|
+ OPTION_RECURSE_LIMIT,
|
|
|
|
|
+ OPTION_NO_RECURSE_LIMIT,
|
|
|
|
|
OPTION_INLINES
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -345,6 +351,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'},
|
|
|
|
|
@@ -1082,7 +1092,7 @@ objdump_print_symname (bfd *abfd, struct
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
@@ -3436,7 +3446,7 @@ dump_symbols (bfd *abfd ATTRIBUTE_UNUSED
|
|
|
|
|
/* 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,
|
|
|
|
|
@@ -4107,6 +4117,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;
|
|
|
|
|
diff -rup binutils.orig.1/binutils/prdbg.c binutils-2.30/binutils/prdbg.c
|
|
|
|
|
--- binutils.orig.1/binutils/prdbg.c 2024-10-29 14:04:54.258101392 +0000
|
|
|
|
|
+++ binutils-2.30/binutils/prdbg.c 2024-10-29 14:14:33.063109462 +0000
|
|
|
|
|
@@ -286,6 +286,8 @@ static const struct debug_write_fns tg_f
|
|
|
|
|
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,
|
|
|
|
|
|
|
|
|
|
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 *
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
diff -rup binutils.orig.1/binutils/stabs.c binutils-2.30/binutils/stabs.c
|
|
|
|
|
--- binutils.orig.1/binutils/stabs.c 2024-10-29 14:04:54.267101415 +0000
|
|
|
|
|
+++ binutils-2.30/binutils/stabs.c 2024-10-29 14:14:33.063109462 +0000
|
|
|
|
|
@@ -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 *
|
|
|
|
|
@@ -4551,7 +4553,7 @@ stab_demangle_template (struct stab_dema
|
|
|
|
|
|
|
|
|
|
free (s1);
|
|
|
|
|
|
|
|
|
|
- s3 = cplus_demangle (s2, DMGL_ANSI);
|
|
|
|
|
+ s3 = cplus_demangle (s2, demangle_flags);
|
|
|
|
|
|
|
|
|
|
free (s2);
|
|
|
|
|
|
|
|
|
|
@@ -5277,7 +5279,7 @@ stab_demangle_v3_argtypes (void *dhandle
|
|
|
|
|
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);
|
|
|
|
|
@@ -5452,7 +5454,7 @@ stab_demangle_v3_arg (void *dhandle, str
|
|
|
|
|
/* 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"));
|
|
|
|
|
@@ -5534,7 +5536,7 @@ stab_demangle_v3_arg (void *dhandle, str
|
|
|
|
|
/* 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"));
|
|
|
|
|
diff -rup binutils.orig.1/binutils/testsuite/config/default.exp binutils-2.30/binutils/testsuite/config/default.exp
|
|
|
|
|
--- binutils.orig.1/binutils/testsuite/config/default.exp 2024-10-29 14:04:54.266101412 +0000
|
|
|
|
|
+++ binutils-2.30/binutils/testsuite/config/default.exp 2024-10-29 14:14:33.064109465 +0000
|
|
|
|
|
@@ -72,6 +72,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}
|
|
|
|
|
|
|
|
|
|
diff -rup binutils.orig.1/include/demangle.h binutils-2.30/include/demangle.h
|
|
|
|
|
--- binutils.orig.1/include/demangle.h 2024-10-29 14:04:54.545102141 +0000
|
|
|
|
|
+++ binutils-2.30/include/demangle.h 2024-10-29 14:14:33.064109465 +0000
|
|
|
|
|
@@ -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,
|
|
|
|
|
diff -rup binutils.orig.1/libiberty/config.in binutils-2.30/libiberty/config.in
|
|
|
|
|
--- binutils.orig.1/libiberty/config.in 2024-10-29 14:04:54.532102107 +0000
|
|
|
|
|
+++ binutils-2.30/libiberty/config.in 2024-10-29 14:14:33.064109465 +0000
|
|
|
|
|
@@ -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
|
|
|
|
|
|
|
|
|
|
diff -rup binutils.orig.1/libiberty/configure binutils-2.30/libiberty/configure
|
|
|
|
|
--- binutils.orig.1/libiberty/configure 2024-10-29 14:04:54.532102107 +0000
|
|
|
|
|
+++ binutils-2.30/libiberty/configure 2024-10-29 14:14:33.065109468 +0000
|
|
|
|
|
@@ -5727,7 +5727,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"
|
|
|
|
|
|
|
|
|
|
@@ -5743,7 +5743,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 \
|
|
|
|
|
diff -rup binutils.orig.1/libiberty/configure.ac binutils-2.30/libiberty/configure.ac
|
|
|
|
|
--- binutils.orig.1/libiberty/configure.ac 2024-10-29 14:04:54.532102107 +0000
|
|
|
|
|
+++ binutils-2.30/libiberty/configure.ac 2024-10-29 14:14:33.065109468 +0000
|
|
|
|
|
@@ -391,7 +391,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"
|
|
|
|
|
|
|
|
|
|
@@ -407,7 +407,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 \
|
|
|
|
|
diff -rup binutils.orig.1/libiberty/cp-demangle.c binutils-2.30/libiberty/cp-demangle.c
|
|
|
|
|
--- binutils.orig.1/libiberty/cp-demangle.c 2024-10-29 14:04:54.532102107 +0000
|
|
|
|
|
+++ binutils-2.30/libiberty/cp-demangle.c 2024-10-29 14:14:33.065109468 +0000
|
|
|
|
|
@@ -625,6 +625,9 @@ d_dump (struct demangle_component *dc, i
|
|
|
|
|
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 dem
|
|
|
|
|
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, stru
|
|
|
|
|
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);
|
|
|
|
|
+ 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;
|
|
|
|
|
+
|
|
|
|
|
+ di->recursion_level ++;
|
|
|
|
|
}
|
|
|
|
|
- ret = d_bare_function_type (di, 1);
|
|
|
|
|
- ret = d_ref_qualifier (di, ret);
|
|
|
|
|
|
|
|
|
|
- if (! d_check_char (di, 'E'))
|
|
|
|
|
- return NULL;
|
|
|
|
|
+ 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_templ
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
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 *ma
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
diff -rup binutils.orig.1/libiberty/cp-demangle.h binutils-2.30/libiberty/cp-demangle.h
|
|
|
|
|
--- binutils.orig.1/libiberty/cp-demangle.h 2024-10-29 14:04:54.532102107 +0000
|
|
|
|
|
+++ binutils-2.30/libiberty/cp-demangle.h 2024-10-29 14:14:33.065109468 +0000
|
|
|
|
|
@@ -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:
|
|
|
|
|
diff -rup binutils.orig.1/libiberty/cplus-dem.c binutils-2.30/libiberty/cplus-dem.c
|
|
|
|
|
--- binutils.orig.1/libiberty/cplus-dem.c 2024-10-29 14:04:54.530102102 +0000
|
|
|
|
|
+++ binutils-2.30/libiberty/cplus-dem.c 2024-10-29 14:14:33.065109468 +0000
|
|
|
|
|
@@ -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_stu
|
|
|
|
|
|
|
|
|
|
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_stu
|
|
|
|
|
|
|
|
|
|
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_s
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
+
|
|
|
|
|
/* Forget the remembered types, but not the type vector itself. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
@@ -4696,6 +4717,16 @@ demangle_nested_args (struct work_stuff
|
|
|
|
|
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->forgetting_types;
|
|
|
|
|
work->nrepeats = saved_nrepeats;
|
|
|
|
|
|
|
|
|
|
+ if ((work->options & DMGL_NO_RECURSE_LIMIT) == 0)
|
|
|
|
|
+ --work->recursion_level;
|
|
|
|
|
+
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
diff -rup binutils.orig.1/libiberty/pex-unix.c binutils-2.30/libiberty/pex-unix.c
|
|
|
|
|
--- binutils.orig.1/libiberty/pex-unix.c 2024-10-29 14:04:54.531102105 +0000
|
|
|
|
|
+++ binutils-2.30/libiberty/pex-unix.c 2024-10-29 14:14:33.065109468 +0000
|
|
|
|
|
@@ -298,8 +298,6 @@ pex_wait (struct pex_obj *obj, pid_t pid
|
|
|
|
|
#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 ATTR
|
|
|
|
|
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 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
|
|
|
|
|
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);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- 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));
|
|
|
|
|
- pex_child_error (obj, executable, "execvp", errno);
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- execv (executable, to_ptr32 (argv));
|
|
|
|
|
- pex_child_error (obj, executable, "execv", errno);
|
|
|
|
|
- }
|
|
|
|
|
+ {
|
|
|
|
|
+ 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)
|
|
|
|
|
+ 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;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* 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;
|
|
|
|
|
+
|
|
|
|
|
+ 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]);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
- /* 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;
|
|
|
|
|
-
|
|
|
|
|
- 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;
|
|
|
|
|
}
|
|
|
|
|
}
|