aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2023-09-05 11:08:23 +0100
committerNick Clifton <nickc@redhat.com>2023-09-05 11:08:23 +0100
commitb6ac461ace19ba19aaf135a028df4e67e47e21d7 (patch)
treee23c55a5f0b131654b4cf76813732e160572f474 /binutils
parentd4868004365e6bc4232a1b8ebd4b328fc5bec8b1 (diff)
downloadgdb-b6ac461ace19ba19aaf135a028df4e67e47e21d7.zip
gdb-b6ac461ace19ba19aaf135a028df4e67e47e21d7.tar.gz
gdb-b6ac461ace19ba19aaf135a028df4e67e47e21d7.tar.bz2
readelf: Add option to display the names of sections referenced by symbols.
PR 30684 * readelf.c (extra_sym_info): New variable. (section_name_valid): Also check for filedata being NULL. (section_name_print): Delete. (section_index_real): New function. Returns true if the given section index references a real section. (print_symbol): Rename to print_sumbol_name. (printable_section_name): Use a rotating array of static buffers for the return string. (printable_section_name_from_index): Merge code from dump_relocations and get_symbol_index_type into here. (long_option_values): Add OPTION_NO_EXTRA_SYM_INFO. (options): Add "extra-sym-info" and "no-extra-sym-info". (usage): Mention new options. (parse_args): Parse new options. (get_symbol_index_type): Delete. (print_dynamic_symbol_size): Rename to print_symbol_size. (print_dynamic_symbol): Rename to print_symbol. (print_symbol_table_heading): New function. (process_symbol_table): Use new function. * doc/binutils.texi: Document the new option. * NEWS: Mention the new feature.
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog25
-rw-r--r--binutils/NEWS6
-rw-r--r--binutils/doc/binutils.texi15
-rw-r--r--binutils/readelf.c515
4 files changed, 366 insertions, 195 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index eab6f5d..ac14aff 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,28 @@
+2023-09-05 Nick Clifton <nickc@redhat.com>
+
+ PR 30684
+ * readelf.c (extra_sym_info): New variable.
+ (section_name_valid): Also check for filedata being NULL.
+ (section_name_print): Delete.
+ (section_index_real): New function. Returns true if the given
+ section index references a real section.
+ (print_symbol): Rename to print_sumbol_name.
+ (printable_section_name): Use a rotating array of static buffers
+ for the return string.
+ (printable_section_name_from_index): Merge code from
+ dump_relocations and get_symbol_index_type into here.
+ (long_option_values): Add OPTION_NO_EXTRA_SYM_INFO.
+ (options): Add "extra-sym-info" and "no-extra-sym-info".
+ (usage): Mention new options.
+ (parse_args): Parse new options.
+ (get_symbol_index_type): Delete.
+ (print_dynamic_symbol_size): Rename to print_symbol_size.
+ (print_dynamic_symbol): Rename to print_symbol.
+ (print_symbol_table_heading): New function.
+ (process_symbol_table): Use new function.
+ * doc/binutils.texi: Document the new option.
+ * NEWS: Mention the new feature.
+
2023-08-23 Nick Clifton <nickc@redhat.com>
PR 30781
diff --git a/binutils/NEWS b/binutils/NEWS
index d64cae0..1aae340 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,5 +1,11 @@
-*- text -*-
+* The readelf program has a new command line option --extra-sym-info which
+ extends the information displayed by the --symbols option. When enabled
+ the display will include the name of the section referenced by a symbol's
+ index field (st_shndx). In the future more information may also be displayed
+ when this option is enabled.
+
* objcopy --set-section-flags now supports "large" to set SHF_X86_64_LARGE
for ELF x86-64 objects.
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 9f80f39..56394b2 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -4961,6 +4961,7 @@ readelf [@option{-a}|@option{--all}]
[@option{--quiet}]
[@option{--recurse-limit}|@option{--no-recurse-limit}]
[@option{-U} @var{method}|@option{--unicode=}@var{method}]
+ [@option{-X}|@option{--extra-sym-info}|@option{--no-extra-sym-info}]
[@option{-n}|@option{--notes}]
[@option{-r}|@option{--relocs}]
[@option{-u}|@option{--unwind}]
@@ -5152,6 +5153,20 @@ assuming that colouring is supported by the output device. The
colouring is intended to draw attention to the presence of unicode
sequences when they might not be expected.
+@item -X
+@itemx --extra-sym-info
+When displaying details of symbols, include extra information not
+normally presented. Currently this just adds the name of the section
+referenced by the symbol's index field, if there is one. In the
+future more information may be displayed when this option is enabled.
+
+Enabling this option effectively enables the @option{--wide} option as
+well, at least when displaying symbol information.
+
+@item --no-extra-sym-info
+Disables the effect of the @option{--extra-sym-info} option. This
+is the default.
+
@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 c0015ca..5c69efc 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -248,6 +248,7 @@ static bool do_not_show_symbol_truncation = false;
static bool do_demangle = false; /* Pretty print C++ symbol names. */
static bool process_links = false;
static bool dump_any_debugging = false;
+static bool extra_sym_info = false;
static int demangle_flags = DMGL_ANSI | DMGL_PARAMS;
static int sym_base = 0;
@@ -412,23 +413,25 @@ section_name (const Filedata *filedata, const Elf_Internal_Shdr *hdr)
static inline bool
section_name_valid (const Filedata *filedata, const Elf_Internal_Shdr *hdr)
{
- return (hdr != NULL
+ return (filedata != NULL
+ && hdr != NULL
&& filedata->string_table != NULL
&& hdr->sh_name < filedata->string_table_length);
}
-static inline const char *
-section_name_print (const Filedata *filedata, const Elf_Internal_Shdr *hdr)
+/* Returns true if the given index is real/valid. Note: "real" here
+ means "references a real section in the section header" and not
+ "is a valid section index as per the ELF standard". */
+
+static inline bool
+section_index_real (const Filedata *filedata, unsigned int ndx)
{
- if (hdr == NULL)
- return _("<none>");
- if (filedata->string_table == NULL)
- return _("<no-strings>");
- if (hdr->sh_name >= filedata->string_table_length)
- return _("<corrupt>");
- return section_name (filedata, hdr);
+ return (filedata != NULL
+ && filedata->section_headers != NULL
+ && ndx < filedata->file_header.e_shnum
+ && ndx > 0);
}
-
+
#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
static inline bool
@@ -612,7 +615,8 @@ print_vma (uint64_t vma, print_mode mode)
/* Display a symbol on stdout. Handles the display of control characters and
multibye characters (assuming the host environment supports them).
- Display at most abs(WIDTH) characters, truncating as necessary, unless do_wide is true.
+ Display at most abs(WIDTH) characters, truncating as necessary,
+ unless do_wide or extra_sym_info is true.
If truncation will happen and do_not_show_symbol_truncation is FALSE then display
abs(WIDTH) - 5 characters followed by "[...]".
@@ -623,7 +627,7 @@ print_vma (uint64_t vma, print_mode mode)
Returns the number of emitted characters. */
static unsigned int
-print_symbol (signed int width, const char * symbol)
+print_symbol_name (signed int width, const char * symbol)
{
bool extra_padding = false;
bool do_dots = false;
@@ -643,13 +647,14 @@ print_symbol (signed int width, const char * symbol)
else if (width == 0)
return 0;
- if (do_wide)
+ if (do_wide || extra_sym_info)
/* Set the remaining width to a very large value.
This simplifies the code below. */
width_remaining = INT_MAX;
else
{
width_remaining = width;
+
if (! do_not_show_symbol_truncation
&& (int) strlen (symbol) > width)
{
@@ -876,13 +881,37 @@ print_symbol (signed int width, const char * symbol)
static const char *
printable_section_name (Filedata * filedata, const Elf_Internal_Shdr * sec)
{
-#define MAX_PRINT_SEC_NAME_LEN 256
- static char sec_name_buf [MAX_PRINT_SEC_NAME_LEN + 1];
- const char * name = section_name_print (filedata, sec);
- char * buf = sec_name_buf;
+#define NUM_SEC_NAME_BUFS 5
+#define MAX_PRINT_SEC_NAME_LEN 256
+
+ static int sec_name_buf_index = 0;
+ /* We use a rotating array of static buffers, so that multiple successive calls
+ to printable_section_name() will still work. eg when used in a printf. */
+ static char sec_name_buf [NUM_SEC_NAME_BUFS][MAX_PRINT_SEC_NAME_LEN + 1];
+
+ const char * name;
+ char * buf;
+ char * buf_start;
char c;
unsigned int remaining = MAX_PRINT_SEC_NAME_LEN;
+ /* Validate the input parameters. */
+ if (filedata == NULL)
+ return _("<internal error>");
+ if (sec == NULL)
+ return _("<none>");
+ if (filedata->string_table == NULL)
+ return _("<no-strings>");
+ if (sec->sh_name >= filedata->string_table_length)
+ return _("<corrupt>");
+
+ /* Select a buffer to use. */
+ buf_start = buf = sec_name_buf[sec_name_buf_index];
+ if (++sec_name_buf_index >= NUM_SEC_NAME_BUFS)
+ sec_name_buf_index = 0;
+
+ name = section_name (filedata, sec);
+
while ((c = * name ++) != 0)
{
if (ISCNTRL (c))
@@ -917,16 +946,101 @@ printable_section_name (Filedata * filedata, const Elf_Internal_Shdr * sec)
}
* buf = 0;
- return sec_name_buf;
+ return buf_start;
+}
+
+/* Return TRUE if the current file is for IA-64 machine and OpenVMS ABI.
+ This OS has so many departures from the ELF standard that we test it at
+ many places. */
+
+static inline bool
+is_ia64_vms (Filedata * filedata)
+{
+ return filedata->file_header.e_machine == EM_IA_64
+ && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_OPENVMS;
}
static const char *
-printable_section_name_from_index (Filedata *filedata, size_t ndx)
+printable_section_name_from_index (Filedata * filedata,
+ size_t ndx,
+ bool * is_special)
{
- if (ndx >= filedata->file_header.e_shnum)
- return _("<corrupt>");
+ if (is_special != NULL)
+ * is_special = true;
+
+ switch (ndx)
+ {
+ case SHN_UNDEF: return "UND";
+ case SHN_ABS: return "ABS";
+ case SHN_COMMON: return "COM";
+ break;
+ }
- return printable_section_name (filedata, filedata->section_headers + ndx);
+ if (filedata != NULL)
+ {
+ switch (filedata->file_header.e_machine)
+ {
+ case EM_MIPS:
+ if (ndx == SHN_MIPS_SCOMMON)
+ return "SCOMMON";
+ if (ndx == SHN_MIPS_SUNDEFINED)
+ return "SUNDEF";
+ break;
+
+ case EM_TI_C6000:
+ if (ndx == SHN_TIC6X_SCOMMON)
+ return "SCOM";
+ break;
+
+ case EM_X86_64:
+ case EM_L1OM:
+ case EM_K1OM:
+ if (ndx == SHN_X86_64_LCOMMON)
+ return "LARGE_COM";
+ break;
+
+ case EM_IA_64:
+ if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_HPUX
+ && ndx == SHN_IA_64_ANSI_COMMON)
+ return "ANSI_COM";
+
+ if (is_ia64_vms (filedata) && ndx == SHN_IA_64_VMS_SYMVEC)
+ return "VMS_SYMVEC";
+ break;
+
+ default:
+ break;
+ }
+
+ if (filedata->section_headers != NULL
+ && ndx < filedata->file_header.e_shnum)
+ {
+ const char * res;
+
+ res = printable_section_name (filedata, filedata->section_headers + ndx);
+ if (is_special != NULL)
+ * is_special = (res[0] == '<');
+
+ return res;
+ }
+ }
+
+ static char name_buf[40];
+ unsigned int short_ndx = (unsigned int) (ndx & 0xffff);
+
+ if (ndx >= SHN_LOPROC && ndx <= SHN_HIPROC)
+ sprintf (name_buf, "PRC[0x%04x]", short_ndx);
+ else if (ndx >= SHN_LOOS && ndx <= SHN_HIOS)
+ sprintf (name_buf, "OS [0x%04x]", short_ndx);
+ else if (ndx >= SHN_LORESERVE)
+ sprintf (name_buf, "RSV[0x%04x]", short_ndx);
+ else if (filedata->file_header.e_shnum != 0
+ && ndx >= filedata->file_header.e_shnum)
+ sprintf (name_buf, _("BAD[0x%lx]"), (long) ndx);
+ else
+ sprintf (name_buf, "<section 0x%lx>", (long) ndx);
+
+ return name_buf;
}
/* Return a pointer to section NAME, or NULL if no such section exists. */
@@ -1018,17 +1132,6 @@ find_section_in_set (Filedata * filedata, const char * name, unsigned int * set)
return find_section (filedata, name);
}
-/* Return TRUE if the current file is for IA-64 machine and OpenVMS ABI.
- This OS has so many departures from the ELF standard that we test it at
- many places. */
-
-static inline bool
-is_ia64_vms (Filedata * filedata)
-{
- return filedata->file_header.e_machine == EM_IA_64
- && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_OPENVMS;
-}
-
/* Guess the relocation size commonly used by the specific machines. */
static bool
@@ -2011,7 +2114,7 @@ dump_relocations (Filedata *filedata,
else
name = strtab + psym->st_name;
- len = print_symbol (width, name);
+ len = print_symbol_name (width, name);
if (version_string)
printf (sym_info == symbol_public ? "@@%s" : "@%s",
version_string);
@@ -2027,47 +2130,12 @@ dump_relocations (Filedata *filedata,
if (psym->st_name == 0)
{
const char * sec_name = "<null>";
- char name_buf[40];
if (ELF_ST_TYPE (psym->st_info) == STT_SECTION)
- {
- if (psym->st_shndx < filedata->file_header.e_shnum
- && filedata->section_headers != NULL)
- sec_name = section_name_print (filedata,
- filedata->section_headers
- + psym->st_shndx);
- else if (psym->st_shndx == SHN_ABS)
- sec_name = "ABS";
- else if (psym->st_shndx == SHN_COMMON)
- sec_name = "COMMON";
- else if ((filedata->file_header.e_machine == EM_MIPS
- && psym->st_shndx == SHN_MIPS_SCOMMON)
- || (filedata->file_header.e_machine == EM_TI_C6000
- && psym->st_shndx == SHN_TIC6X_SCOMMON))
- sec_name = "SCOMMON";
- else if (filedata->file_header.e_machine == EM_MIPS
- && psym->st_shndx == SHN_MIPS_SUNDEFINED)
- sec_name = "SUNDEF";
- else if ((filedata->file_header.e_machine == EM_X86_64
- || filedata->file_header.e_machine == EM_L1OM
- || filedata->file_header.e_machine == EM_K1OM)
- && psym->st_shndx == SHN_X86_64_LCOMMON)
- sec_name = "LARGE_COMMON";
- else if (filedata->file_header.e_machine == EM_IA_64
- && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_HPUX
- && psym->st_shndx == SHN_IA_64_ANSI_COMMON)
- sec_name = "ANSI_COM";
- else if (is_ia64_vms (filedata)
- && psym->st_shndx == SHN_IA_64_VMS_SYMVEC)
- sec_name = "VMS_SYMVEC";
- else
- {
- sprintf (name_buf, "<section 0x%x>",
- (unsigned int) psym->st_shndx);
- sec_name = name_buf;
- }
- }
- print_symbol (22, sec_name);
+ sec_name = printable_section_name_from_index
+ (filedata, psym->st_shndx, NULL);
+
+ print_symbol_name (22, sec_name);
}
else if (strtab == NULL)
printf (_("<string table index: %3ld>"), psym->st_name);
@@ -2079,7 +2147,7 @@ dump_relocations (Filedata *filedata,
}
else
{
- print_symbol (22, strtab + psym->st_name);
+ print_symbol_name (22, strtab + psym->st_name);
if (version_string)
printf (sym_info == symbol_public ? "@@%s" : "@%s",
version_string);
@@ -5484,6 +5552,7 @@ enum long_option_values
OPTION_RECURSE_LIMIT,
OPTION_NO_RECURSE_LIMIT,
OPTION_NO_DEMANGLING,
+ OPTION_NO_EXTRA_SYM_INFO,
OPTION_SYM_BASE
};
@@ -5523,10 +5592,12 @@ static struct option options[] =
{"version-info", no_argument, 0, 'V'},
{"version", no_argument, 0, 'v'},
{"wide", no_argument, 0, 'W'},
+ {"extra-sym-info", no_argument, 0, 'X'},
{"hex-dump", required_argument, 0, 'x'},
{"decompress", no_argument, 0, 'z'},
{"no-demangle", no_argument, 0, OPTION_NO_DEMANGLING},
+ {"no-extra-sym-info",no_argument, 0, OPTION_NO_EXTRA_SYM_INFO},
{"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},
@@ -5601,7 +5672,11 @@ usage (FILE * stream)
escape sequences, or treat them as invalid and display as\n\
\"{hex sequences}\"\n"));
fprintf (stream, _("\
- -n --notes Display the core notes (if present)\n"));
+ -X --extra-sym-info Display extra information when showing symbols\n"));
+ fprintf (stream, _("\
+ --no-extra-sym-info Do not display extra information when showing symbols (default)\n"));
+ fprintf (stream, _("\
+ -n --notes Display the contents of note sections (if present)\n"));
fprintf (stream, _("\
-r --relocs Display the relocations (if present)\n"));
fprintf (stream, _("\
@@ -5794,7 +5869,7 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
usage (stderr);
while ((c = getopt_long
- (argc, argv, "ACDHILNPR:STU:VWacdeghi:lnp:rstuvw::x:z", options, NULL)) != EOF)
+ (argc, argv, "ACDHILNPR:STU:VWXacdeghi:lnp:rstuvw::x:z", options, NULL)) != EOF)
{
switch (c)
{
@@ -5977,6 +6052,13 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
case OPTION_LTO_SYMS:
do_lto_syms = true;
break;
+ case 'X':
+ extra_sym_info = true;
+ break;
+ case OPTION_NO_EXTRA_SYM_INFO:
+ extra_sym_info = false;
+ break;
+
#ifdef SUPPORT_DISASSEMBLY
case 'i':
request_dump (dumpdata, DISASS_DUMP);
@@ -7652,7 +7734,7 @@ process_section_headers (Filedata * filedata)
i < filedata->file_header.e_shnum;
i++, section++)
{
- const char *name = section_name_print (filedata, section);
+ const char *name = printable_section_name (filedata, section);
/* Run some sanity checks on the headers and
possibly fill in some file data as well. */
@@ -7999,7 +8081,7 @@ process_section_headers (Filedata * filedata)
if (do_section_details)
printf ("%s\n ", printable_section_name (filedata, section));
else
- print_symbol (-17, section_name_print (filedata, section));
+ print_symbol_name (-17, printable_section_name (filedata, section));
printf (do_wide ? " %-15s " : " %-15.15s ",
get_section_type_name (filedata, section->sh_type));
@@ -8424,9 +8506,9 @@ process_section_groups (Filedata * filedata)
continue;
}
- group_name = section_name_print (filedata,
- filedata->section_headers
- + sym->st_shndx);
+ group_name = printable_section_name (filedata,
+ filedata->section_headers
+ + sym->st_shndx);
strtab_sec = NULL;
free (strtab);
strtab = NULL;
@@ -12530,7 +12612,7 @@ process_version_sections (Filedata * filedata)
printf (_(" Addr: 0x%016" PRIx64), section->sh_addr);
printf (_(" Offset: 0x%08" PRIx64 " Link: %u (%s)\n"),
section->sh_offset, section->sh_link,
- printable_section_name_from_index (filedata, section->sh_link));
+ printable_section_name_from_index (filedata, section->sh_link, NULL));
edefs = (Elf_External_Verdef *)
get_data (NULL, filedata, section->sh_offset, 1,section->sh_size,
@@ -12676,7 +12758,7 @@ process_version_sections (Filedata * filedata)
printf (_(" Addr: 0x%016" PRIx64), section->sh_addr);
printf (_(" Offset: 0x%08" PRIx64 " Link: %u (%s)\n"),
section->sh_offset, section->sh_link,
- printable_section_name_from_index (filedata, section->sh_link));
+ printable_section_name_from_index (filedata, section->sh_link, NULL));
eneed = (Elf_External_Verneed *) get_data (NULL, filedata,
section->sh_offset, 1,
@@ -13349,51 +13431,6 @@ get_symbol_other (Filedata * filedata, unsigned int other)
}
static const char *
-get_symbol_index_type (Filedata * filedata, unsigned int type)
-{
- static char buff[32];
-
- switch (type)
- {
- case SHN_UNDEF: return "UND";
- case SHN_ABS: return "ABS";
- case SHN_COMMON: return "COM";
- default:
- if (type == SHN_IA_64_ANSI_COMMON
- && filedata->file_header.e_machine == EM_IA_64
- && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
- return "ANSI_COM";
- else if ((filedata->file_header.e_machine == EM_X86_64
- || filedata->file_header.e_machine == EM_L1OM
- || filedata->file_header.e_machine == EM_K1OM)
- && type == SHN_X86_64_LCOMMON)
- return "LARGE_COM";
- else if ((type == SHN_MIPS_SCOMMON
- && filedata->file_header.e_machine == EM_MIPS)
- || (type == SHN_TIC6X_SCOMMON
- && filedata->file_header.e_machine == EM_TI_C6000))
- return "SCOM";
- else if (type == SHN_MIPS_SUNDEFINED
- && filedata->file_header.e_machine == EM_MIPS)
- return "SUND";
- else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
- sprintf (buff, "PRC[0x%04x]", type & 0xffff);
- else if (type >= SHN_LOOS && type <= SHN_HIOS)
- sprintf (buff, "OS [0x%04x]", type & 0xffff);
- else if (type >= SHN_LORESERVE)
- sprintf (buff, "RSV[0x%04x]", type & 0xffff);
- else if (filedata->file_header.e_shnum != 0
- && type >= filedata->file_header.e_shnum)
- sprintf (buff, _("bad section index[%3d]"), type);
- else
- sprintf (buff, "%3d", type);
- break;
- }
-
- return buff;
-}
-
-static const char *
get_symbol_version_string (Filedata *filedata,
bool is_dynsym,
const char *strtab,
@@ -13570,7 +13607,7 @@ get_symbol_version_string (Filedata *filedata,
/* Display a symbol size on stdout. Format is based on --sym-base setting. */
static unsigned int
-print_dynamic_symbol_size (uint64_t vma, int base)
+print_symbol_size (uint64_t vma, int base)
{
switch (base)
{
@@ -13589,23 +13626,28 @@ print_dynamic_symbol_size (uint64_t vma, int base)
}
}
+/* Print information on a single symbol. */
+
static void
-print_dynamic_symbol (Filedata *filedata, uint64_t si,
- Elf_Internal_Sym *symtab,
- Elf_Internal_Shdr *section,
- char *strtab, size_t strtab_size)
+print_symbol (Filedata * filedata,
+ uint64_t symbol_index,
+ Elf_Internal_Sym * symtab,
+ Elf_Internal_Shdr * section,
+ char * strtab,
+ size_t strtab_size)
{
const char *version_string;
enum versioned_symbol_info sym_info;
unsigned short vna_other;
- bool is_valid;
const char * sstr;
- Elf_Internal_Sym *psym = symtab + si;
+ Elf_Internal_Sym *psym = symtab + symbol_index;
- printf ("%6" PRId64 ": ", si);
+ /* FIXME: We should have a table of field widths,
+ rather than using hard coded constants. */
+ printf ("%6" PRId64 ": ", symbol_index);
print_vma (psym->st_value, LONG_HEX);
putchar (' ');
- print_dynamic_symbol_size (psym->st_size, sym_base);
+ print_symbol_size (psym->st_size, sym_base);
printf (" %-7s", get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)));
printf (" %-6s", get_symbol_binding (filedata, ELF_ST_BIND (psym->st_info)));
if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
@@ -13615,29 +13657,61 @@ print_dynamic_symbol (Filedata *filedata, uint64_t si,
unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
printf (" %-7s", get_symbol_visibility (vis));
+
/* Check to see if any other bits in the st_other field are set.
- Note - displaying this information disrupts the layout of the
- table being generated, but for the moment this case is very rare. */
+ FIXME: Displaying this information here disrupts the layout
+ of the table being generated. */
if (psym->st_other ^ vis)
printf (" [%s] ", get_symbol_other (filedata, psym->st_other ^ vis));
}
- printf (" %4s ", get_symbol_index_type (filedata, psym->st_shndx));
+ bool is_special;
+
+ sstr = printable_section_name_from_index (filedata, psym->st_shndx, & is_special);
+
+ /* Print the symbol's section index. If the index is special
+ then print the index's name rather than its number. */
+ if (is_special)
+ {
+ int printed;
+
+ /* Special case: If there are no section headers, and the printable
+ name is "<section 0x...." then just display the section number
+ as a decimal. This happens when objcopy --strip -section-headers
+ is used. */
+ if (filedata->file_header.e_shnum == 0 && startswith (sstr, "<section"))
+ printed = printf (" %4d ", psym->st_shndx);
+ else
+ printed = printf (" %4s ", sstr);
+
+ if (extra_sym_info && printed < 16)
+ printf ("%*s", 16 - printed, "");
+ }
+ else
+ {
+ printf (" %4u ", psym->st_shndx);
+
+ if (extra_sym_info)
+ {
+ /* Display the section name referenced by the section index. */
+ int printed = printf ("(%s) ", sstr);
+ if (printed < 10)
+ printf ("%*s", 10 - printed, "");
+ }
+ }
+
+ /* Get the symbol's name. For section symbols without a
+ specific name use the (already computed) section name. */
if (ELF_ST_TYPE (psym->st_info) == STT_SECTION
- && psym->st_shndx < filedata->file_header.e_shnum
- && filedata->section_headers != NULL
+ && section_index_real (filedata, psym->st_shndx)
&& psym->st_name == 0)
{
- is_valid
- = section_name_valid (filedata,
- filedata->section_headers + psym->st_shndx);
- sstr = is_valid ?
- section_name_print (filedata,
- filedata->section_headers + psym->st_shndx)
- : _("<corrupt>");
+ ;
}
else
{
+ bool is_valid;
+
is_valid = valid_symbol_name (strtab, strtab_size, psym->st_name);
sstr = is_valid ? strtab + psym->st_name : _("<corrupt>");
}
@@ -13646,7 +13720,7 @@ print_dynamic_symbol (Filedata *filedata, uint64_t si,
= get_symbol_version_string (filedata,
(section == NULL
|| section->sh_type == SHT_DYNSYM),
- strtab, strtab_size, si,
+ strtab, strtab_size, symbol_index,
psym, &sym_info, &vna_other);
int len_avail = 21;
@@ -13662,7 +13736,7 @@ print_dynamic_symbol (Filedata *filedata, uint64_t si,
len_avail -= 1;
}
- print_symbol (len_avail, sstr);
+ print_symbol_name (len_avail, sstr);
if (version_string)
{
@@ -13677,14 +13751,14 @@ print_dynamic_symbol (Filedata *filedata, uint64_t si,
if (ELF_ST_BIND (psym->st_info) == STB_LOCAL
&& section != NULL
- && si >= section->sh_info
+ && symbol_index >= section->sh_info
/* Irix 5 and 6 MIPS binaries are known to ignore this requirement. */
&& filedata->file_header.e_machine != EM_MIPS
/* Solaris binaries have been found to violate this requirement as
well. Not sure if this is a bug or an ABI requirement. */
&& filedata->file_header.e_ident[EI_OSABI] != ELFOSABI_SOLARIS)
warn (_("local symbol %" PRIu64 " found at index >= %s's sh_info value of %u\n"),
- si, printable_section_name (filedata, section), section->sh_info);
+ symbol_index, printable_section_name (filedata, section), section->sh_info);
}
static const char *
@@ -13881,7 +13955,7 @@ display_lto_symtab (Filedata * filedata,
slot,
get_lto_sym_type (sym_type),
sec_kind);
- print_symbol (6, (const char *) sym_name);
+ print_symbol_name (6, (const char *) sym_name);
}
else
{
@@ -13898,7 +13972,7 @@ display_lto_symtab (Filedata * filedata,
get_lto_visibility (visibility),
size,
slot);
- print_symbol (21, (const char *) sym_name);
+ print_symbol_name (21, (const char *) sym_name);
}
putchar ('\n');
}
@@ -13947,6 +14021,57 @@ process_lto_symbol_tables (Filedata * filedata)
return res;
}
+static void
+print_symbol_table_heading (void)
+{
+ /* FIXME: We should store the size of each field in the display in a table and
+ then use the values inside print_symbol(), instead of that function using
+ hard coded constants. */
+ if (is_32bit_elf)
+ {
+ if (extra_sym_info)
+ {
+ printf (_(" Num: Value Size Type Bind Vis+Other Ndx(SecName) Name [+ Version Info]\n"));
+ /* |--6-|: |--8---| |-5-| |--7--| |-6--| |--7--| |---8--| |----13.....| |........... */
+ /* eg: 5: 00000000 14 FUNC LOCAL DEFAULT 1 (.text) get_sections */
+ }
+ else if (do_wide)
+ {
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
+ /* |--6-|: |--8---| |-5-| |--7--| |-6--| |--7--| |-4| |........... */
+ /* eg: 5: 00000000 14 FUNC LOCAL DEFAULT 1 get_sections */
+ }
+ else
+ {
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
+ /* |--6-|: |--8---| |-5-| |--7--| |-6--| |--7--| |-4| |------------29-------------| */
+ /* eg: 5: 00000000 14 FUNC LOCAL DEFAULT 1 get_sections */
+ }
+ }
+ else
+ {
+ if (extra_sym_info)
+ {
+ printf (_(" Num: Value Size Type Bind Vis+Other Ndx(SecName) Name [+ Version Info]\n"));
+ /* |--6-|: |------16------| |-5-| |--7--| |-6--| |--7--| |-------14---| |..... */
+ /* eg: 2: 0000000000000000 0 FUNC LOCAL DEFAULT 1 (.text) .very_long_function_name */
+
+ }
+ else if (do_wide)
+ {
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
+ /* |--6-|: |------16------| |-5-| |--7--| |-6--| |--7--| |-4| |........... */
+ /* eg: 5: 0000000000000000 14 FUNC LOCAL DEFAULT 1 very_long_function_name */
+ }
+ else
+ {
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
+ /* |--6-|: |------16------| |-5-| |--7--| |-6--| |--7--| |-4| |--------21---------| */
+ /* eg: 5: 0000000000000000 14 FUNC LOCAL DEFAULT 1 very_long_functi[...] */
+ }
+ }
+}
+
/* Dump the symbol table. */
static bool
@@ -13984,15 +14109,13 @@ process_symbol_table (Filedata * filedata)
filedata->num_dynamic_syms),
filedata->num_dynamic_syms);
}
- if (is_32bit_elf)
- printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
- else
- printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
+
+ print_symbol_table_heading ();
for (si = 0; si < filedata->num_dynamic_syms; si++)
- print_dynamic_symbol (filedata, si, filedata->dynamic_symbols, NULL,
- filedata->dynamic_strings,
- filedata->dynamic_strings_length);
+ print_symbol (filedata, si, filedata->dynamic_symbols, NULL,
+ filedata->dynamic_strings,
+ filedata->dynamic_strings_length);
}
else if ((do_dyn_syms || (do_syms && !do_using_dynamic))
&& filedata->section_headers != NULL)
@@ -14041,10 +14164,7 @@ process_symbol_table (Filedata * filedata)
printable_section_name (filedata, section),
num_syms);
- if (is_32bit_elf)
- printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
- else
- printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
+ print_symbol_table_heading ();
symtab = get_elf_symbols (filedata, section, & num_syms);
if (symtab == NULL)
@@ -14068,8 +14188,8 @@ process_symbol_table (Filedata * filedata)
}
for (si = 0; si < num_syms; si++)
- print_dynamic_symbol (filedata, si, symtab, section,
- strtab, strtab_size);
+ print_symbol (filedata, si, symtab, section,
+ strtab, strtab_size);
free (symtab);
if (strtab != filedata->string_table)
@@ -14297,7 +14417,7 @@ process_syminfo (Filedata * filedata)
if (i >= filedata->num_dynamic_syms)
printf (_("<corrupt index>"));
else if (valid_dynamic_name (filedata, filedata->dynamic_symbols[i].st_name))
- print_symbol (30, get_dynamic_name (filedata,
+ print_symbol_name (30, get_dynamic_name (filedata,
filedata->dynamic_symbols[i].st_name));
else
printf (_("<corrupt: %19ld>"), filedata->dynamic_symbols[i].st_name);
@@ -14317,7 +14437,7 @@ process_syminfo (Filedata * filedata)
&& valid_dynamic_name (filedata,
filedata->dynamic_section[filedata->dynamic_syminfo[i].si_boundto].d_un.d_val))
{
- print_symbol (10, get_dynamic_name (filedata,
+ print_symbol_name (10, get_dynamic_name (filedata,
filedata->dynamic_section[filedata->dynamic_syminfo[i].si_boundto].d_un.d_val));
putchar (' ' );
}
@@ -16215,7 +16335,7 @@ dump_section_as_bytes (Elf_Internal_Shdr *section,
static ctf_sect_t *
shdr_to_ctf_sect (ctf_sect_t *buf, Elf_Internal_Shdr *shdr, Filedata *filedata)
{
- buf->cts_name = section_name_print (filedata, shdr);
+ buf->cts_name = printable_section_name (filedata, shdr);
buf->cts_size = shdr->sh_size;
buf->cts_entsize = shdr->sh_entsize;
@@ -17046,7 +17166,7 @@ display_tag_value (signed int tag,
putchar ('"');
if (maxlen > 0)
{
- print_symbol ((int) maxlen, (const char *) p);
+ print_symbol_name ((int) maxlen, (const char *) p);
p += strnlen ((char *) p, maxlen) + 1;
}
else
@@ -17471,7 +17591,7 @@ display_arm_attribute (unsigned char * p,
{
size_t maxlen = (end - p) - 1;
- print_symbol ((int) maxlen, (const char *) p);
+ print_symbol_name ((int) maxlen, (const char *) p);
p += strnlen ((char *) p, maxlen) + 1;
}
else
@@ -17560,7 +17680,7 @@ display_gnu_attribute (unsigned char * p,
{
size_t maxlen = (end - p) - 1;
- print_symbol ((int) maxlen, (const char *) p);
+ print_symbol_name ((int) maxlen, (const char *) p);
p += strnlen ((char *) p, maxlen) + 1;
}
else
@@ -18153,7 +18273,7 @@ display_tic6x_attribute (unsigned char * p,
{
size_t maxlen = (end - p) - 1;
- print_symbol ((int) maxlen, (const char *) p);
+ print_symbol_name ((int) maxlen, (const char *) p);
p += strnlen ((char *) p, maxlen) + 1;
}
else
@@ -18172,7 +18292,7 @@ display_tic6x_attribute (unsigned char * p,
{
size_t maxlen = (end - p) - 1;
- print_symbol ((int) maxlen, (const char *) p);
+ print_symbol_name ((int) maxlen, (const char *) p);
p += strnlen ((char *) p, maxlen) + 1;
}
else
@@ -18291,7 +18411,7 @@ display_msp430_attribute (unsigned char * p,
{
size_t maxlen = (end - p) - 1;
- print_symbol ((int) maxlen, (const char *) p);
+ print_symbol_name ((int) maxlen, (const char *) p);
p += strnlen ((char *) p, maxlen) + 1;
}
else
@@ -18613,7 +18733,7 @@ process_attributes (Filedata * filedata,
}
printf (_("Attribute Section: "));
- print_symbol (INT_MAX, (const char *) p);
+ print_symbol_name (INT_MAX, (const char *) p);
putchar ('\n');
if (public_name && streq ((char *) p, public_name))
@@ -19180,7 +19300,7 @@ process_mips_specific (Filedata * filedata)
printf ("%3zu: ", cnt);
if (valid_dynamic_name (filedata, liblist.l_name))
- print_symbol (20, get_dynamic_name (filedata, liblist.l_name));
+ print_symbol_name (20, get_dynamic_name (filedata, liblist.l_name));
else
printf (_("<corrupt: %9ld>"), liblist.l_name);
printf (" %s %#10lx %-7ld", timebuf, liblist.l_checksum,
@@ -19559,7 +19679,7 @@ process_mips_specific (Filedata * filedata)
print_vma (psym->st_value, FULL_HEX);
putchar (' ');
if (valid_dynamic_name (filedata, psym->st_name))
- print_symbol (25, get_dynamic_name (filedata, psym->st_name));
+ print_symbol_name (25, get_dynamic_name (filedata, psym->st_name));
else
printf (_("<corrupt: %14ld>"), psym->st_name);
}
@@ -19680,12 +19800,17 @@ process_mips_specific (Filedata * filedata)
Elf_Internal_Sym * psym = filedata->dynamic_symbols + i;
print_vma (psym->st_value, LONG_HEX);
- printf (" %-7s %3s ",
- get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)),
- get_symbol_index_type (filedata, psym->st_shndx));
+ printf (" %-7s ", get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)));
+
+ bool is_special;
+ const char * s = printable_section_name_from_index (filedata, psym->st_shndx, & is_special);
+ if (is_special)
+ printf ("%3s ", s);
+ else
+ printf ("%3u ", psym->st_shndx);
if (valid_dynamic_name (filedata, psym->st_name))
- print_symbol (sym_width,
+ print_symbol_name (sym_width,
get_dynamic_name (filedata, psym->st_name));
else
printf (_("<corrupt: %14ld>"), psym->st_name);
@@ -19771,9 +19896,9 @@ process_mips_specific (Filedata * filedata)
print_vma (psym->st_value, LONG_HEX);
printf (" %-7s %3s ",
get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)),
- get_symbol_index_type (filedata, psym->st_shndx));
+ printable_section_name_from_index (filedata, psym->st_shndx, NULL));
if (valid_dynamic_name (filedata, psym->st_name))
- print_symbol (sym_width,
+ print_symbol_name (sym_width,
get_dynamic_name (filedata, psym->st_name));
else
printf (_("<corrupt: %14ld>"), psym->st_name);
@@ -21774,7 +21899,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
if (name == NULL || pnote->namesz < 2)
{
error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz);
- print_symbol (-20, _(" <corrupt name>"));
+ print_symbol_name (-20, _(" <corrupt name>"));
return false;
}
@@ -21789,7 +21914,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
if (pnote->namesz < 4)
{
error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz);
- print_symbol (-20, _(" <corrupt name>"));
+ print_symbol_name (-20, _(" <corrupt name>"));
return false;
}
@@ -21809,7 +21934,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
break;
default:
error (_("unrecognised attribute type in name field: %d\n"), name_type);
- print_symbol (-20, _("<unknown name type>"));
+ print_symbol_name (-20, _("<unknown name type>"));
return false;
}
@@ -21963,7 +22088,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
if (decoded != NULL)
{
- print_symbol (-left, decoded);
+ print_symbol_name (-left, decoded);
left = 0;
}
else if (val == 0)
@@ -21981,13 +22106,13 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
}
break;
case GNU_BUILD_ATTRIBUTE_TYPE_STRING:
- left -= print_symbol (- left, name);
+ left -= print_symbol_name (- left, name);
break;
case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE:
- left -= print_symbol (- left, "true");
+ left -= print_symbol_name (- left, "true");
break;
case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE:
- left -= print_symbol (- left, "false");
+ left -= print_symbol_name (- left, "false");
break;
}
@@ -22275,7 +22400,7 @@ process_note (Elf_Internal_Note * pnote,
|| pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC))
print_gnu_build_attribute_name (pnote);
else
- print_symbol (-20, name);
+ print_symbol_name (-20, name);
if (do_wide)
printf (" 0x%08lx\t%s\t", pnote->descsz, nt);