Readelf: Add --lto-syms option to display LTO symbol tables.
* readelf.c (do_lto_syms): New local. (long_option_values): Add OPTION_LTO_SYMS. (options): Add --lto-syms. (usage): Mention the new option. (parse_args): Parse the new option. (get_lto_kind): New function. (get_lto_visibility): New function. (get_lto_sym_type): New function. (display_lto_symtab): New function - displays the contents of an LTo symbol table section. (process_lto_symbol_tables): New functions. Calls dipslay_lto_symtab on any LTO symbol table section. (process_object_file): Call process_lto_symbol_tables. * doc/binutils.texi: Document the new option. * NEWS: Mention the new feature.
This commit is contained in:
parent
740341b9be
commit
0f03783c8e
@ -1,3 +1,21 @@
|
||||
2020-10-19 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* readelf.c (do_lto_syms): New local.
|
||||
(long_option_values): Add OPTION_LTO_SYMS.
|
||||
(options): Add --lto-syms.
|
||||
(usage): Mention the new option.
|
||||
(parse_args): Parse the new option.
|
||||
(get_lto_kind): New function.
|
||||
(get_lto_visibility): New function.
|
||||
(get_lto_sym_type): New function.
|
||||
(display_lto_symtab): New function - displays the contents of an
|
||||
LTo symbol table section.
|
||||
(process_lto_symbol_tables): New functions. Calls
|
||||
dipslay_lto_symtab on any LTO symbol table section.
|
||||
(process_object_file): Call process_lto_symbol_tables.
|
||||
* doc/binutils.texi: Document the new option.
|
||||
* NEWS: Mention the new feature.
|
||||
|
||||
2020-10-09 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR gas/26703
|
||||
|
@ -1,5 +1,8 @@
|
||||
-*- text -*-
|
||||
|
||||
* Readelf can now display the contents of LTO symbol table sections when asked
|
||||
to do so via the --lto-syms command line option.
|
||||
|
||||
* 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.
|
||||
|
@ -4707,7 +4707,7 @@ readelf [@option{-a}|@option{--all}]
|
||||
[@option{-t}|@option{--section-details}]
|
||||
[@option{-e}|@option{--headers}]
|
||||
[@option{-s}|@option{--syms}|@option{--symbols}]
|
||||
[@option{--dyn-syms}]
|
||||
[@option{--dyn-syms}|@option{--lto-syms}]
|
||||
[@option{--demangle@var{=style}}|@option{--no-demangle}]
|
||||
[@option{--recurse-limit}|@option{--no-recurse-limit}]
|
||||
[@option{-n}|@option{--notes}]
|
||||
@ -4825,6 +4825,10 @@ 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 --lto-syms
|
||||
@cindex LTO symbol table
|
||||
Displays the contents of any LTO symbol tables in the file.
|
||||
|
||||
@item -C
|
||||
@itemx --demangle[=@var{style}]
|
||||
@cindex demangling in nm
|
||||
|
@ -216,6 +216,7 @@ static bfd_boolean show_name = FALSE;
|
||||
static bfd_boolean do_dynamic = FALSE;
|
||||
static bfd_boolean do_syms = FALSE;
|
||||
static bfd_boolean do_dyn_syms = FALSE;
|
||||
static bfd_boolean do_lto_syms = FALSE;
|
||||
static bfd_boolean do_reloc = FALSE;
|
||||
static bfd_boolean do_sections = FALSE;
|
||||
static bfd_boolean do_section_groups = FALSE;
|
||||
@ -4483,6 +4484,7 @@ enum long_option_values
|
||||
{
|
||||
OPTION_DEBUG_DUMP = 512,
|
||||
OPTION_DYN_SYMS,
|
||||
OPTION_LTO_SYMS,
|
||||
OPTION_DWARF_DEPTH,
|
||||
OPTION_DWARF_START,
|
||||
OPTION_DWARF_CHECK,
|
||||
@ -4538,6 +4540,7 @@ static struct option options[] =
|
||||
{"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},
|
||||
{"lto-syms", no_argument, 0, OPTION_LTO_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},
|
||||
@ -4570,6 +4573,7 @@ usage (FILE * stream)
|
||||
-s --syms Display the symbol table\n\
|
||||
--symbols An alias for --syms\n\
|
||||
--dyn-syms Display the dynamic symbol table\n\
|
||||
--lto-syms Display LTO symbol tables\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\
|
||||
@ -4809,7 +4813,7 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
|
||||
break;
|
||||
case 'w':
|
||||
do_dump = TRUE;
|
||||
if (optarg == 0)
|
||||
if (optarg == NULL)
|
||||
{
|
||||
do_debugging = TRUE;
|
||||
dwarf_select_sections_all ();
|
||||
@ -4822,7 +4826,7 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
|
||||
break;
|
||||
case OPTION_DEBUG_DUMP:
|
||||
do_dump = TRUE;
|
||||
if (optarg == 0)
|
||||
if (optarg == NULL)
|
||||
do_debugging = TRUE;
|
||||
else
|
||||
{
|
||||
@ -4866,6 +4870,9 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
|
||||
case OPTION_DYN_SYMS:
|
||||
do_dyn_syms = TRUE;
|
||||
break;
|
||||
case OPTION_LTO_SYMS:
|
||||
do_lto_syms = TRUE;
|
||||
break;
|
||||
#ifdef SUPPORT_DISASSEMBLY
|
||||
case 'i':
|
||||
request_dump (dumpdata, DISASS_DUMP);
|
||||
@ -4922,7 +4929,7 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
|
||||
&& !do_segments && !do_header && !do_dump && !do_version
|
||||
&& !do_histogram && !do_debugging && !do_arch && !do_notes
|
||||
&& !do_section_groups && !do_archive_index
|
||||
&& !do_dyn_syms)
|
||||
&& !do_dyn_syms && !do_lto_syms)
|
||||
{
|
||||
if (do_checks)
|
||||
{
|
||||
@ -4931,6 +4938,7 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
|
||||
do_segments = do_header = do_dump = do_version = TRUE;
|
||||
do_histogram = do_debugging = do_arch = do_notes = TRUE;
|
||||
do_section_groups = do_archive_index = do_dyn_syms = TRUE;
|
||||
do_lto_syms = TRUE;
|
||||
}
|
||||
else
|
||||
usage (stderr);
|
||||
@ -12179,7 +12187,256 @@ print_dynamic_symbol (Filedata *filedata, unsigned long si,
|
||||
si, printable_section_name (filedata, section), section->sh_info);
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_lto_kind (unsigned int kind)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case 0: return "DEF";
|
||||
case 1: return "WEAKDEF";
|
||||
case 2: return "UNDEF";
|
||||
case 3: return "WEAKUNDEF";
|
||||
case 4: return "COMMON";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
static char buffer[30];
|
||||
error (_("Unknown LTO symbol definition encountered: %u\n"), kind);
|
||||
sprintf (buffer, "<unknown: %u>", kind);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_lto_visibility (unsigned int visibility)
|
||||
{
|
||||
switch (visibility)
|
||||
{
|
||||
case 0: return "DEFAULT";
|
||||
case 1: return "PROTECTED";
|
||||
case 2: return "INTERNAL";
|
||||
case 3: return "HIDDEN";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
static char buffer[30];
|
||||
error (_("Unknown LTO symbol visibility encountered: %u\n"), visibility);
|
||||
sprintf (buffer, "<unknown: %u>", visibility);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_lto_sym_type (unsigned int sym_type)
|
||||
{
|
||||
switch (sym_type)
|
||||
{
|
||||
case 0: return "UNKNOWN";
|
||||
case 1: return "FUNCTION";
|
||||
case 2: return "VARIABLE";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
static char buffer[30];
|
||||
error (_("Unknown LTO symbol type encountered: %u\n"), sym_type);
|
||||
sprintf (buffer, "<unknown: %u>", sym_type);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Display an LTO format symbol table.
|
||||
FIXME: The format of LTO symbol tables is not formalized.
|
||||
So this code could need changing in the future. */
|
||||
|
||||
static bfd_boolean
|
||||
display_lto_symtab (Filedata * filedata,
|
||||
Elf_Internal_Shdr * section)
|
||||
{
|
||||
if (section->sh_size == 0)
|
||||
{
|
||||
printf (_("\nLTO Symbol table '%s' is empty!\n"),
|
||||
printable_section_name (filedata, section));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (section->sh_size > filedata->file_size)
|
||||
{
|
||||
error (_("Section %s has an invalid sh_size of 0x%lx\n"),
|
||||
printable_section_name (filedata, section),
|
||||
(unsigned long) section->sh_size);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void * alloced_data = get_data (NULL, filedata, section->sh_offset,
|
||||
section->sh_size, 1, _("LTO symbols"));
|
||||
if (alloced_data == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Look for extended data for the symbol table. */
|
||||
Elf_Internal_Shdr * ext;
|
||||
void * ext_data_orig = NULL;
|
||||
char * ext_data = NULL;
|
||||
char * ext_data_end = NULL;
|
||||
char * ext_name = NULL;
|
||||
|
||||
if (asprintf (& ext_name, ".gnu.lto_.ext_symtab.%s",
|
||||
SECTION_NAME (section) + strlen (".gnu.lto_.symtab.")) > 0
|
||||
&& ext_name != NULL /* Paranoia. */
|
||||
&& (ext = find_section (filedata, ext_name)) != NULL)
|
||||
{
|
||||
if (ext->sh_size < 3)
|
||||
error (_("LTO Symbol extension table '%s' is empty!\n"),
|
||||
printable_section_name (filedata, ext));
|
||||
else
|
||||
{
|
||||
ext_data_orig = ext_data = get_data (NULL, filedata, ext->sh_offset,
|
||||
ext->sh_size, 1,
|
||||
_("LTO ext symbol data"));
|
||||
if (ext_data != NULL)
|
||||
{
|
||||
ext_data_end = ext_data + ext->sh_size;
|
||||
if (* ext_data++ != 1)
|
||||
error (_("Unexpected version number in symbol extension table\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned char * data = (const unsigned char *) alloced_data;
|
||||
const unsigned char * end = data + section->sh_size;
|
||||
|
||||
if (ext_data_orig != NULL)
|
||||
{
|
||||
if (do_wide)
|
||||
printf (_("\nLTO Symbol table '%s' and extension table '%s' contain:\n"),
|
||||
printable_section_name (filedata, section),
|
||||
printable_section_name (filedata, ext));
|
||||
else
|
||||
{
|
||||
printf (_("\nLTO Symbol table '%s'\n"),
|
||||
printable_section_name (filedata, section));
|
||||
printf (_(" and extension table '%s' contain:\n"),
|
||||
printable_section_name (filedata, ext));
|
||||
}
|
||||
}
|
||||
else
|
||||
printf (_("\nLTO Symbol table '%s' contains:\n"),
|
||||
printable_section_name (filedata, section));
|
||||
|
||||
|
||||
/* FIXME: Add a wide version. */
|
||||
if (ext_data_orig != NULL)
|
||||
printf (_(" Comdat_Key Kind Visibility Size Slot Type Section Name\n"));
|
||||
else
|
||||
printf (_(" Comdat_Key Kind Visibility Size Slot Name\n"));
|
||||
|
||||
/* FIXME: We do not handle style prefixes. */
|
||||
|
||||
while (data < end)
|
||||
{
|
||||
const unsigned char * sym_name = data;
|
||||
data += strnlen ((const char *) sym_name, end - data) + 1;
|
||||
if (data >= end)
|
||||
goto fail;
|
||||
|
||||
const unsigned char * comdat_key = data;
|
||||
data += strnlen ((const char *) comdat_key, end - data) + 1;
|
||||
if (data >= end)
|
||||
goto fail;
|
||||
|
||||
if (data + 2 + 8 + 4 > end)
|
||||
goto fail;
|
||||
|
||||
unsigned int kind = *data++;
|
||||
unsigned int visibility = *data++;
|
||||
|
||||
elf_vma size = byte_get (data, 8);
|
||||
data += 8;
|
||||
|
||||
elf_vma slot = byte_get (data, 4);
|
||||
data += 4;
|
||||
|
||||
if (ext_data != NULL)
|
||||
{
|
||||
if (ext_data < (ext_data_end - 1))
|
||||
{
|
||||
unsigned int sym_type = * ext_data ++;
|
||||
unsigned int sec_kind = * ext_data ++;
|
||||
|
||||
printf (" %10s %10s %11s %08lx %08lx %9s %08lx _",
|
||||
* comdat_key == 0 ? "-" : (char *) comdat_key,
|
||||
get_lto_kind (kind),
|
||||
get_lto_visibility (visibility),
|
||||
(long) size,
|
||||
(long) slot,
|
||||
get_lto_sym_type (sym_type),
|
||||
(long) sec_kind);
|
||||
print_symbol (6, (const char *) sym_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
error (_("Ran out of LTO symbol extension data\n"));
|
||||
ext_data = NULL;
|
||||
/* FIXME: return FAIL result ? */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf (" %10s %10s %11s %08lx %08lx _",
|
||||
* comdat_key == 0 ? "-" : (char *) comdat_key,
|
||||
get_lto_kind (kind),
|
||||
get_lto_visibility (visibility),
|
||||
(long) size,
|
||||
(long) slot);
|
||||
print_symbol (21, (const char *) sym_name);
|
||||
}
|
||||
putchar ('\n');
|
||||
}
|
||||
|
||||
if (ext_data != NULL && ext_data < ext_data_end)
|
||||
{
|
||||
error (_("Data remains in the LTO symbol extension table\n"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
free (alloced_data);
|
||||
free (ext_data_orig);
|
||||
free (ext_name);
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
error (_("Buffer overrun encountered whilst decoding LTO symbol table\n"));
|
||||
free (alloced_data);
|
||||
free (ext_data_orig);
|
||||
free (ext_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Display LTO symbol tables. */
|
||||
|
||||
static bfd_boolean
|
||||
process_lto_symbol_tables (Filedata * filedata)
|
||||
{
|
||||
Elf_Internal_Shdr * section;
|
||||
unsigned int i;
|
||||
bfd_boolean res = TRUE;
|
||||
|
||||
if (!do_lto_syms)
|
||||
return TRUE;
|
||||
|
||||
if (filedata->section_headers == NULL)
|
||||
return TRUE;
|
||||
|
||||
for (i = 0, section = filedata->section_headers;
|
||||
i < filedata->file_header.e_shnum;
|
||||
i++, section++)
|
||||
if (CONST_STRNEQ (SECTION_NAME (section), ".gnu.lto_.symtab"))
|
||||
res &= display_lto_symtab (filedata, section);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Dump the symbol table. */
|
||||
|
||||
static bfd_boolean
|
||||
process_symbol_table (Filedata * filedata)
|
||||
{
|
||||
@ -20604,6 +20861,9 @@ process_object (Filedata * filedata)
|
||||
if (! process_symbol_table (filedata))
|
||||
res = FALSE;
|
||||
|
||||
if (! process_lto_symbol_tables (filedata))
|
||||
res = FALSE;
|
||||
|
||||
if (! process_syminfo (filedata))
|
||||
res = FALSE;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user