aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2020-08-12 13:31:59 +0100
committerNick Clifton <nickc@redhat.com>2020-08-12 13:31:59 +0100
commit79bc120c7be00596098c09cecd25383ae6ddce34 (patch)
tree52603d55375f972945e4e25f611f7bd89f637a1e /binutils
parent79ddc88496c3c18eac94b7776dc75b05c33abf25 (diff)
downloadgdb-79bc120c7be00596098c09cecd25383ae6ddce34.zip
gdb-79bc120c7be00596098c09cecd25383ae6ddce34.tar.gz
gdb-79bc120c7be00596098c09cecd25383ae6ddce34.tar.bz2
Add demangling support to readelf.
PR binutils/26331 * readelf.c (do_demangle): New option flag. (print_symbol): If do_demangle is enabled, demangle the symbol. (enum long_option_values): New enum to hold long option values. (options): Add demangle, no-demangle, recursion-limit and no-recursion-limit options. Alpha sort the table. (usage): Describe the new options. (parse_args): Handle the new options. * NEWS: Mention the new feature. * doc/binutils.texi: Document the new feature. * testsuite/binutils-all/readelf.exp: Test the new feature. * testsuite/binutils-all/mangled.s: New file - assembler source. * testsuite/binutils-all/readelf.demangled: New file - expected output from readelf.
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog17
-rw-r--r--binutils/NEWS4
-rw-r--r--binutils/doc/binutils.texi30
-rw-r--r--binutils/readelf.c132
-rw-r--r--binutils/testsuite/binutils-all/mangled.s6
-rw-r--r--binutils/testsuite/binutils-all/readelf.demangled5
-rw-r--r--binutils/testsuite/binutils-all/readelf.exp16
7 files changed, 172 insertions, 38 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 4d2ac2b..162159f 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,5 +1,22 @@
2020-08-12 Nick Clifton <nickc@redhat.com>
+ PR binutils/26331
+ * readelf.c (do_demangle): New option flag.
+ (print_symbol): If do_demangle is enabled, demangle the symbol.
+ (enum long_option_values): New enum to hold long option values.
+ (options): Add demangle, no-demangle, recursion-limit and
+ no-recursion-limit options. Alpha sort the table.
+ (usage): Describe the new options.
+ (parse_args): Handle the new options.
+ * NEWS: Mention the new feature.
+ * doc/binutils.texi: Document the new feature.
+ * testsuite/binutils-all/readelf.exp: Test the new feature.
+ * testsuite/binutils-all/mangled.s: New file - assembler source.
+ * testsuite/binutils-all/readelf.demangled: New file - expected
+ output from readelf.
+
+2020-08-12 Nick Clifton <nickc@redhat.com>
+
* po/sr.po: Updated Serbian translation.
2020-08-10 H.J. Lu <hongjiu.lu@intel.com>
diff --git a/binutils/NEWS b/binutils/NEWS
index e776f5a..c0dc73d 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,5 +1,9 @@
-*- text -*-
+* Readelf now accepts the -C command line option to enable the demangling of
+ symbol names. In addition the --demangle=<style>, --no-demangle,
+ --recurse-limit and --no-recurse-limit options are also now availale.
+
Changes in 2.35:
* Changed readelf's display of symbol names when wide mode is not enabled.
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 0822b5c..968da2c 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -4694,6 +4694,8 @@ readelf [@option{-a}|@option{--all}]
[@option{-e}|@option{--headers}]
[@option{-s}|@option{--syms}|@option{--symbols}]
[@option{--dyn-syms}]
+ [@option{--demangle@var{=style}}|@option{--no-demangle}]
+ [@option{--recurse-limit}|@option{--no-recurse-limit}]
[@option{-n}|@option{--notes}]
[@option{-r}|@option{--relocs}]
[@option{-u}|@option{--unwind}]
@@ -4809,6 +4811,34 @@ Displays the entries in dynamic symbol table section of the file, if it
has one. The output format is the same as the format used by the
@option{--syms} option.
+@item -C
+@itemx --demangle[=@var{style}]
+@cindex demangling in nm
+Decode (@dfn{demangle}) low-level symbol names into user-level names.
+This makes C++ function names readable. Different compilers have
+different mangling styles. The optional demangling style argument can
+be used to choose an appropriate demangling style for your
+compiler. @xref{c++filt}, for more information on demangling.
+
+@item --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 2048 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 -e
@itemx --headers
Display all the headers in the file. Equivalent to @option{-h -l -S}.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 421992d..17868e2 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -61,6 +61,7 @@
#include "elfcomm.h"
#include "dwarf.h"
#include "ctf-api.h"
+#include "demangle.h"
#include "elf/common.h"
#include "elf/external.h"
@@ -235,6 +236,8 @@ static bfd_boolean check_all = FALSE;
static bfd_boolean is_32bit_elf = FALSE;
static bfd_boolean decompress_dumps = FALSE;
static bfd_boolean do_not_show_symbol_truncation = FALSE;
+static bfd_boolean do_demangle = FALSE; /* Pretty print C++ symbol names. */
+static int demangle_flags = DMGL_ANSI | DMGL_PARAMS;
static char *dump_ctf_parent_name;
static char *dump_ctf_symtab_name;
@@ -552,6 +555,7 @@ print_symbol (signed int width, const char * symbol)
mbstate_t state;
#endif
unsigned int width_remaining;
+ const void * alloced_symbol = NULL;
if (width < 0)
{
@@ -584,6 +588,14 @@ print_symbol (signed int width, const char * symbol)
memset (& state, 0, sizeof (state));
#endif
+ if (do_demangle && *symbol)
+ {
+ const char * res = cplus_demangle (symbol, demangle_flags);
+
+ if (res != NULL)
+ alloced_symbol = symbol = res;
+ }
+
while (width_remaining)
{
size_t n;
@@ -643,6 +655,7 @@ print_symbol (signed int width, const char * symbol)
num_printed = width;
}
+ free ((void *) alloced_symbol);
return num_printed;
}
@@ -4471,67 +4484,76 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type)
}
}
-#define OPTION_DEBUG_DUMP 512
-#define OPTION_DYN_SYMS 513
-#define OPTION_DWARF_DEPTH 514
-#define OPTION_DWARF_START 515
-#define OPTION_DWARF_CHECK 516
-#define OPTION_CTF_DUMP 517
-#define OPTION_CTF_PARENT 518
-#define OPTION_CTF_SYMBOLS 519
-#define OPTION_CTF_STRINGS 520
+enum long_option_values
+{
+ OPTION_DEBUG_DUMP = 512,
+ OPTION_DYN_SYMS,
+ OPTION_DWARF_DEPTH,
+ OPTION_DWARF_START,
+ OPTION_DWARF_CHECK,
+ OPTION_CTF_DUMP,
+ OPTION_CTF_PARENT,
+ OPTION_CTF_SYMBOLS,
+ OPTION_CTF_STRINGS,
+ OPTION_WITH_SYMBOL_VERSIONS,
+ OPTION_RECURSE_LIMIT,
+ OPTION_NO_RECURSE_LIMIT,
+ OPTION_NO_DEMANGLING
+};
static struct option options[] =
{
+ /* Note - This table is alpha-sorted on the 'val'
+ field in order to make adding new options easier. */
+ {"arch-specific", no_argument, 0, 'A'},
{"all", no_argument, 0, 'a'},
- {"file-header", no_argument, 0, 'h'},
- {"program-headers", no_argument, 0, 'l'},
+ {"demangle", optional_argument, 0, 'C'},
+ {"archive-index", no_argument, 0, 'c'},
+ {"use-dynamic", no_argument, 0, 'D'},
+ {"dynamic", no_argument, 0, 'd'},
{"headers", no_argument, 0, 'e'},
+ {"section-groups", no_argument, 0, 'g'},
+ {"help", no_argument, 0, 'H'},
+ {"file-header", no_argument, 0, 'h'},
{"histogram", no_argument, 0, 'I'},
+ {"lint", no_argument, 0, 'L'},
+ {"enable-checks", no_argument, 0, 'L'},
+ {"program-headers", no_argument, 0, 'l'},
{"segments", no_argument, 0, 'l'},
- {"sections", no_argument, 0, 'S'},
- {"section-headers", no_argument, 0, 'S'},
- {"section-groups", no_argument, 0, 'g'},
- {"section-details", no_argument, 0, 't'},
{"full-section-name",no_argument, 0, 'N'},
+ {"notes", no_argument, 0, 'n'},
+ {"string-dump", required_argument, 0, 'p'},
+ {"relocated-dump", required_argument, 0, 'R'},
+ {"relocs", no_argument, 0, 'r'},
+ {"section-headers", no_argument, 0, 'S'},
+ {"sections", no_argument, 0, 'S'},
{"symbols", no_argument, 0, 's'},
{"syms", no_argument, 0, 's'},
- {"dyn-syms", no_argument, 0, OPTION_DYN_SYMS},
- {"relocs", no_argument, 0, 'r'},
- {"notes", no_argument, 0, 'n'},
- {"dynamic", no_argument, 0, 'd'},
- {"lint", no_argument, 0, 'L'},
- {"enable-checks", no_argument, 0, 'L'},
- {"arch-specific", no_argument, 0, 'A'},
- {"version-info", no_argument, 0, 'V'},
- {"use-dynamic", no_argument, 0, 'D'},
+ {"silent-truncation",no_argument, 0, 'T'},
+ {"section-details", no_argument, 0, 't'},
{"unwind", no_argument, 0, 'u'},
- {"archive-index", no_argument, 0, 'c'},
+ {"version-info", no_argument, 0, 'V'},
+ {"version", no_argument, 0, 'v'},
+ {"wide", no_argument, 0, 'W'},
{"hex-dump", required_argument, 0, 'x'},
- {"relocated-dump", required_argument, 0, 'R'},
- {"string-dump", required_argument, 0, 'p'},
{"decompress", no_argument, 0, 'z'},
-#ifdef SUPPORT_DISASSEMBLY
- {"instruction-dump", required_argument, 0, 'i'},
-#endif
- {"debug-dump", optional_argument, 0, OPTION_DEBUG_DUMP},
+ {"no-demangle", no_argument, 0, OPTION_NO_DEMANGLING},
+ {"recurse-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},
+ {"dyn-syms", no_argument, 0, OPTION_DYN_SYMS},
+ {"debug-dump", optional_argument, 0, OPTION_DEBUG_DUMP},
{"dwarf-depth", required_argument, 0, OPTION_DWARF_DEPTH},
{"dwarf-start", required_argument, 0, OPTION_DWARF_START},
{"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK},
-
#ifdef ENABLE_LIBCTF
{"ctf", required_argument, 0, OPTION_CTF_DUMP},
-
{"ctf-symbols", required_argument, 0, OPTION_CTF_SYMBOLS},
{"ctf-strings", required_argument, 0, OPTION_CTF_STRINGS},
{"ctf-parent", required_argument, 0, OPTION_CTF_PARENT},
#endif
- {"version", no_argument, 0, 'v'},
- {"wide", no_argument, 0, 'W'},
- {"silent-truncation",no_argument, 0, 'T'},
- {"help", no_argument, 0, 'H'},
{0, no_argument, 0, 0}
};
@@ -4553,6 +4575,13 @@ usage (FILE * stream)
-s --syms Display the symbol table\n\
--symbols An alias for --syms\n\
--dyn-syms Display the dynamic symbol table\n\
+ -C --demangle[=STYLE] Decode low-level symbol names into user-level names\n\
+ The STYLE, if specified, can be `auto' (the default),\n\
+ `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
+ or `gnat'\n\
+ --no-demangle Do not demangle low-level symbol names. (This is the default)\n\
+ --recurse-limit Enable a demangling recursion limit. (This is the default)\n\
+ --no-recurse-limit Disable a demangling recursion limit\n\
-n --notes Display the core notes (if present)\n\
-r --relocs Display the relocations (if present)\n\
-u --unwind Display the unwind info (if present)\n\
@@ -4693,7 +4722,7 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
usage (stderr);
while ((c = getopt_long
- (argc, argv, "ADHILNR:STVWacdeghi:lnp:rstuvw::x:z", options, NULL)) != EOF)
+ (argc, argv, "ACDHILNR:STVWacdeghi:lnp:rstuvw::x:z", options, NULL)) != EOF)
{
switch (c)
{
@@ -4718,6 +4747,7 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
do_arch = TRUE;
do_notes = TRUE;
break;
+
case 'g':
do_section_groups = TRUE;
break;
@@ -4858,6 +4888,32 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
case 'T':
do_not_show_symbol_truncation = TRUE;
break;
+ case 'C':
+ do_demangle = TRUE;
+ if (optarg != NULL)
+ {
+ enum demangling_styles style;
+
+ style = cplus_demangle_name_to_style (optarg);
+ if (style == unknown_demangling)
+ error (_("unknown demangling style `%s'"), optarg);
+
+ cplus_demangle_set_style (style);
+ }
+ break;
+ case OPTION_NO_DEMANGLING:
+ do_demangle = FALSE;
+ 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 OPTION_WITH_SYMBOL_VERSIONS:
+ /* Ignored for backward compatibility. */
+ break;
+
default:
/* xgettext:c-format */
error (_("Invalid option '-%c'\n"), c);
diff --git a/binutils/testsuite/binutils-all/mangled.s b/binutils/testsuite/binutils-all/mangled.s
new file mode 100644
index 0000000..0a28d6d
--- /dev/null
+++ b/binutils/testsuite/binutils-all/mangled.s
@@ -0,0 +1,6 @@
+ .text
+
+ .global _ZN4gold12Output_relocILi9ELb1ELi64ELb0EEC2EPNS_12Sized_relobjILi64ELb0EEEjjPNS_11Output_dataEmbbbb
+_ZN4gold12Output_relocILi9ELb1ELi64ELb0EEC2EPNS_12Sized_relobjILi64ELb0EEEjjPNS_11Output_dataEmbbbb:
+ .dc.d 0
+
diff --git a/binutils/testsuite/binutils-all/readelf.demangled b/binutils/testsuite/binutils-all/readelf.demangled
new file mode 100644
index 0000000..a137ced
--- /dev/null
+++ b/binutils/testsuite/binutils-all/readelf.demangled
@@ -0,0 +1,5 @@
+
+Symbol table '.symtab' contains .* entries:
+#...
+.*gold::Output_reloc<9, true, 64, false>::Output_reloc\(gold::Sized_relobj<64, false>\*, unsigned int, unsigned int, gold::Output_data\*, unsigned long, bool, bool, bool, bool\)
+#pass
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index 0ca2748..d7f47da 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -345,12 +345,28 @@ if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
readelf_test -r $tempfile readelf.r {}
}
+# Test demangling symbol names.
+if {![binutils_assemble $srcdir/$subdir/mangled.s tmpdir/mangled.o]} then {
+ unresolved "readelf -s -C bintest (failed to assemble)"
+} else {
+
+ if ![is_remote host] {
+ set tempfile tmpdir/mangled.o
+ } else {
+ set tempfile [remote_download host tmpdir/mangled.o]
+ }
+
+ # Run the test.
+ readelf_test {--syms --demangle --wide} $tempfile readelf.demangled {}
+}
+
readelf_wi_test
readelf_compressed_wa_test
readelf_dump_test
run_dump_test "pr25543"
+
# PR 13482 - Check for off-by-one errors when dumping .note sections.
if {![binutils_assemble $srcdir/$subdir/version.s tmpdir/version.o]} then {
unresolved "readelf -n version (failed to assemble)"