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.
This commit is contained in:
Nick Clifton
2020-08-12 13:31:59 +01:00
parent 79ddc88496
commit 79bc120c7b
7 changed files with 176 additions and 42 deletions

View File

@ -1,3 +1,20 @@
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> 2020-08-12 Nick Clifton <nickc@redhat.com>
* po/sr.po: Updated Serbian translation. * po/sr.po: Updated Serbian translation.

View File

@ -1,5 +1,9 @@
-*- text -*- -*- 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: Changes in 2.35:
* Changed readelf's display of symbol names when wide mode is not enabled. * Changed readelf's display of symbol names when wide mode is not enabled.

View File

@ -4694,6 +4694,8 @@ readelf [@option{-a}|@option{--all}]
[@option{-e}|@option{--headers}] [@option{-e}|@option{--headers}]
[@option{-s}|@option{--syms}|@option{--symbols}] [@option{-s}|@option{--syms}|@option{--symbols}]
[@option{--dyn-syms}] [@option{--dyn-syms}]
[@option{--demangle@var{=style}}|@option{--no-demangle}]
[@option{--recurse-limit}|@option{--no-recurse-limit}]
[@option{-n}|@option{--notes}] [@option{-n}|@option{--notes}]
[@option{-r}|@option{--relocs}] [@option{-r}|@option{--relocs}]
[@option{-u}|@option{--unwind}] [@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 has one. The output format is the same as the format used by the
@option{--syms} option. @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 @item -e
@itemx --headers @itemx --headers
Display all the headers in the file. Equivalent to @option{-h -l -S}. Display all the headers in the file. Equivalent to @option{-h -l -S}.

View File

@ -61,6 +61,7 @@
#include "elfcomm.h" #include "elfcomm.h"
#include "dwarf.h" #include "dwarf.h"
#include "ctf-api.h" #include "ctf-api.h"
#include "demangle.h"
#include "elf/common.h" #include "elf/common.h"
#include "elf/external.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 is_32bit_elf = FALSE;
static bfd_boolean decompress_dumps = FALSE; static bfd_boolean decompress_dumps = FALSE;
static bfd_boolean do_not_show_symbol_truncation = 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_parent_name;
static char *dump_ctf_symtab_name; static char *dump_ctf_symtab_name;
@ -552,6 +555,7 @@ print_symbol (signed int width, const char * symbol)
mbstate_t state; mbstate_t state;
#endif #endif
unsigned int width_remaining; unsigned int width_remaining;
const void * alloced_symbol = NULL;
if (width < 0) if (width < 0)
{ {
@ -584,6 +588,14 @@ print_symbol (signed int width, const char * symbol)
memset (& state, 0, sizeof (state)); memset (& state, 0, sizeof (state));
#endif #endif
if (do_demangle && *symbol)
{
const char * res = cplus_demangle (symbol, demangle_flags);
if (res != NULL)
alloced_symbol = symbol = res;
}
while (width_remaining) while (width_remaining)
{ {
size_t n; size_t n;
@ -643,6 +655,7 @@ print_symbol (signed int width, const char * symbol)
num_printed = width; num_printed = width;
} }
free ((void *) alloced_symbol);
return num_printed; return num_printed;
} }
@ -4471,67 +4484,76 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type)
} }
} }
#define OPTION_DEBUG_DUMP 512 enum long_option_values
#define OPTION_DYN_SYMS 513 {
#define OPTION_DWARF_DEPTH 514 OPTION_DEBUG_DUMP = 512,
#define OPTION_DWARF_START 515 OPTION_DYN_SYMS,
#define OPTION_DWARF_CHECK 516 OPTION_DWARF_DEPTH,
#define OPTION_CTF_DUMP 517 OPTION_DWARF_START,
#define OPTION_CTF_PARENT 518 OPTION_DWARF_CHECK,
#define OPTION_CTF_SYMBOLS 519 OPTION_CTF_DUMP,
#define OPTION_CTF_STRINGS 520 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[] = 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'}, {"all", no_argument, 0, 'a'},
{"file-header", no_argument, 0, 'h'}, {"demangle", optional_argument, 0, 'C'},
{"program-headers", no_argument, 0, 'l'}, {"archive-index", no_argument, 0, 'c'},
{"headers", no_argument, 0, 'e'}, {"use-dynamic", no_argument, 0, 'D'},
{"histogram", no_argument, 0, 'I'},
{"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'},
{"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'}, {"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'}, {"lint", no_argument, 0, 'L'},
{"enable-checks", no_argument, 0, 'L'}, {"enable-checks", no_argument, 0, 'L'},
{"arch-specific", no_argument, 0, 'A'}, {"program-headers", no_argument, 0, 'l'},
{"version-info", no_argument, 0, 'V'}, {"segments", no_argument, 0, 'l'},
{"use-dynamic", no_argument, 0, 'D'}, {"full-section-name",no_argument, 0, 'N'},
{"unwind", no_argument, 0, 'u'}, {"notes", no_argument, 0, 'n'},
{"archive-index", no_argument, 0, 'c'},
{"hex-dump", required_argument, 0, 'x'},
{"relocated-dump", required_argument, 0, 'R'},
{"string-dump", required_argument, 0, 'p'}, {"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'},
{"silent-truncation",no_argument, 0, 'T'},
{"section-details", no_argument, 0, 't'},
{"unwind", no_argument, 0, 'u'},
{"version-info", no_argument, 0, 'V'},
{"version", no_argument, 0, 'v'},
{"wide", no_argument, 0, 'W'},
{"hex-dump", required_argument, 0, 'x'},
{"decompress", no_argument, 0, 'z'}, {"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-depth", required_argument, 0, OPTION_DWARF_DEPTH},
{"dwarf-start", required_argument, 0, OPTION_DWARF_START}, {"dwarf-start", required_argument, 0, OPTION_DWARF_START},
{"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK}, {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK},
#ifdef ENABLE_LIBCTF #ifdef ENABLE_LIBCTF
{"ctf", required_argument, 0, OPTION_CTF_DUMP}, {"ctf", required_argument, 0, OPTION_CTF_DUMP},
{"ctf-symbols", required_argument, 0, OPTION_CTF_SYMBOLS}, {"ctf-symbols", required_argument, 0, OPTION_CTF_SYMBOLS},
{"ctf-strings", required_argument, 0, OPTION_CTF_STRINGS}, {"ctf-strings", required_argument, 0, OPTION_CTF_STRINGS},
{"ctf-parent", required_argument, 0, OPTION_CTF_PARENT}, {"ctf-parent", required_argument, 0, OPTION_CTF_PARENT},
#endif #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} {0, no_argument, 0, 0}
}; };
@ -4553,6 +4575,13 @@ usage (FILE * stream)
-s --syms Display the symbol table\n\ -s --syms Display the symbol table\n\
--symbols An alias for --syms\n\ --symbols An alias for --syms\n\
--dyn-syms Display the dynamic symbol table\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\ -n --notes Display the core notes (if present)\n\
-r --relocs Display the relocations (if present)\n\ -r --relocs Display the relocations (if present)\n\
-u --unwind Display the unwind info (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); usage (stderr);
while ((c = getopt_long 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) switch (c)
{ {
@ -4718,6 +4747,7 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
do_arch = TRUE; do_arch = TRUE;
do_notes = TRUE; do_notes = TRUE;
break; break;
case 'g': case 'g':
do_section_groups = TRUE; do_section_groups = TRUE;
break; break;
@ -4858,6 +4888,32 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
case 'T': case 'T':
do_not_show_symbol_truncation = TRUE; do_not_show_symbol_truncation = TRUE;
break; 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: default:
/* xgettext:c-format */ /* xgettext:c-format */
error (_("Invalid option '-%c'\n"), c); error (_("Invalid option '-%c'\n"), c);

View File

@ -0,0 +1,6 @@
.text
.global _ZN4gold12Output_relocILi9ELb1ELi64ELb0EEC2EPNS_12Sized_relobjILi64ELb0EEEjjPNS_11Output_dataEmbbbb
_ZN4gold12Output_relocILi9ELb1ELi64ELb0EEC2EPNS_12Sized_relobjILi64ELb0EEEjjPNS_11Output_dataEmbbbb:
.dc.d 0

View File

@ -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

View File

@ -345,12 +345,28 @@ if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
readelf_test -r $tempfile readelf.r {} 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_wi_test
readelf_compressed_wa_test readelf_compressed_wa_test
readelf_dump_test readelf_dump_test
run_dump_test "pr25543" run_dump_test "pr25543"
# PR 13482 - Check for off-by-one errors when dumping .note sections. # PR 13482 - Check for off-by-one errors when dumping .note sections.
if {![binutils_assemble $srcdir/$subdir/version.s tmpdir/version.o]} then { if {![binutils_assemble $srcdir/$subdir/version.s tmpdir/version.o]} then {
unresolved "readelf -n version (failed to assemble)" unresolved "readelf -n version (failed to assemble)"