diff options
author | Nick Clifton <nickc@redhat.com> | 2020-08-12 13:31:59 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2020-08-12 13:31:59 +0100 |
commit | 79bc120c7be00596098c09cecd25383ae6ddce34 (patch) | |
tree | 52603d55375f972945e4e25f611f7bd89f637a1e /binutils | |
parent | 79ddc88496c3c18eac94b7776dc75b05c33abf25 (diff) | |
download | gdb-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/ChangeLog | 17 | ||||
-rw-r--r-- | binutils/NEWS | 4 | ||||
-rw-r--r-- | binutils/doc/binutils.texi | 30 | ||||
-rw-r--r-- | binutils/readelf.c | 132 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/mangled.s | 6 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/readelf.demangled | 5 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/readelf.exp | 16 |
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)" |