Add -ws switch to display contents of .debug_str sections
This commit is contained in:
parent
b8908f93e2
commit
261a45adff
3 changed files with 174 additions and 54 deletions
|
@ -1,3 +1,24 @@
|
|||
2001-11-19 Nick Clifton <nickc@cambridge.redhat.com>
|
||||
|
||||
* readelf.c (do_debug_str): New variable.
|
||||
(display_debug_str): New function: Display the contents of a
|
||||
.debug_str section.
|
||||
(load_debug_str): New function: Load in the contents of a
|
||||
.debug_str section.
|
||||
(free_debug_str): New function: Free the memory used by
|
||||
load_debug_str().
|
||||
(fetch_indirect_string): Retrieve a string from the .debug_str
|
||||
section.
|
||||
(usage): Add -ws.
|
||||
(parse_args): Accept -ws.
|
||||
(process_section_headers): Allow the display of the .debug_str
|
||||
section.
|
||||
(read_and_display_attr_value): Use fetch_indirect_string. Show
|
||||
offset into .debug_str section.
|
||||
(display_debug_info): Use load_debug_str and free_debug_str.
|
||||
(debug_displays): Add .debug_str.
|
||||
* doc/binutils.texi: Document -ws.
|
||||
|
||||
2001-11-19 Andreas Jaeger <aj@suse.de>
|
||||
|
||||
* testsuite/binutils-all/objdump.exp: Add x86-64.
|
||||
|
|
|
@ -2851,7 +2851,7 @@ readelf [@option{-a}|@option{--all}]
|
|||
[@option{-V}|@option{--version-info}]
|
||||
[@option{-D}|@option{--use-dynamic}]
|
||||
[@option{-x} <number>|@option{--hex-dump=}<number>]
|
||||
[@option{-w[liaprmf]}|@option{--debug-dump}[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames]]
|
||||
[@option{-w[liaprmfs]}|@option{--debug-dump}[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str]]
|
||||
[@option{-histogram}]
|
||||
[@option{-v}|@option{--version}]
|
||||
[@option{-W}|@option{--wide}]
|
||||
|
@ -2953,8 +2953,8 @@ symbols section.
|
|||
@itemx --hex-dump=<number>
|
||||
Displays the contents of the indicated section as a hexadecimal dump.
|
||||
|
||||
@item -w[liaprmf]
|
||||
@itemx --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames]
|
||||
@item -w[liaprmfs]
|
||||
@itemx --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str]
|
||||
Displays the contents of the debug sections in the file, if any are
|
||||
present. If one of the optional letters or words follows the switch
|
||||
then only data found in those specific sections will be dumped.
|
||||
|
|
|
@ -123,6 +123,7 @@ int do_debug_aranges;
|
|||
int do_debug_frames;
|
||||
int do_debug_frames_interp;
|
||||
int do_debug_macinfo;
|
||||
int do_debug_str;
|
||||
int do_arch;
|
||||
int do_notes;
|
||||
int is_32bit_elf;
|
||||
|
@ -220,7 +221,11 @@ static int display_debug_abbrev PARAMS ((Elf32_Internal_Sh
|
|||
static int display_debug_aranges PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
|
||||
static int display_debug_frames PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
|
||||
static int display_debug_macinfo PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
|
||||
static int display_debug_str PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
|
||||
static unsigned char * process_abbrev_section PARAMS ((unsigned char *, unsigned char *));
|
||||
static void load_debug_str PARAMS ((FILE *));
|
||||
static void free_debug_str PARAMS ((void));
|
||||
static const char * fetch_indirect_string PARAMS ((unsigned long));
|
||||
static unsigned long read_leb128 PARAMS ((unsigned char *, int *, int));
|
||||
static int process_extended_line_op PARAMS ((unsigned char *, int, int));
|
||||
static void reset_state_machine PARAMS ((int));
|
||||
|
@ -276,7 +281,7 @@ typedef int Elf32_Word;
|
|||
#define BYTE_GET8(field) byte_get (field, 8)
|
||||
#endif
|
||||
|
||||
#define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0]))
|
||||
#define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0]))
|
||||
|
||||
#define GET_ELF_SYMBOLS(file, offset, size) \
|
||||
(is_32bit_elf ? get_32bit_elf_symbols (file, offset, size) \
|
||||
|
@ -2072,7 +2077,7 @@ usage ()
|
|||
fprintf (stdout, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n"));
|
||||
fprintf (stdout, _(" -x <number> or --hex-dump=<number>\n"));
|
||||
fprintf (stdout, _(" Dump the contents of section <number>\n"));
|
||||
fprintf (stdout, _(" -w[liaprmf] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames]\n"));
|
||||
fprintf (stdout, _(" -w[liaprmfs] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str]\n"));
|
||||
fprintf (stdout, _(" Display the contents of DWARF2 debug sections\n"));
|
||||
#ifdef SUPPORT_DISASSEMBLY
|
||||
fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n"));
|
||||
|
@ -2252,6 +2257,11 @@ parse_args (argc, argv)
|
|||
do_debug_macinfo = 1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
case 'S':
|
||||
do_debug_str = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
warn (_("Unrecognised debug option '%s'\n"), optarg);
|
||||
break;
|
||||
|
@ -3046,7 +3056,7 @@ process_section_headers (file)
|
|||
}
|
||||
else if ((do_debugging || do_debug_info || do_debug_abbrevs
|
||||
|| do_debug_lines || do_debug_pubnames || do_debug_aranges
|
||||
|| do_debug_frames || do_debug_macinfo)
|
||||
|| do_debug_frames || do_debug_macinfo || do_debug_str)
|
||||
&& strncmp (name, ".debug_", 7) == 0)
|
||||
{
|
||||
name += 7;
|
||||
|
@ -3059,6 +3069,7 @@ process_section_headers (file)
|
|||
|| (do_debug_aranges && (strcmp (name, "aranges") == 0))
|
||||
|| (do_debug_frames && (strcmp (name, "frame") == 0))
|
||||
|| (do_debug_macinfo && (strcmp (name, "macinfo") == 0))
|
||||
|| (do_debug_str && (strcmp (name, "str") == 0))
|
||||
)
|
||||
request_dump (i, DEBUG_DUMP);
|
||||
}
|
||||
|
@ -4091,7 +4102,6 @@ process_dynamic_segment (file)
|
|||
|
||||
dynamic_strings = (char *) get_data (NULL, file, offset, str_tab_len,
|
||||
_("dynamic string table"));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4740,12 +4750,12 @@ process_version_sections (file)
|
|||
case SHT_GNU_versym:
|
||||
{
|
||||
Elf32_Internal_Shdr * link_section;
|
||||
int total;
|
||||
int cnt;
|
||||
unsigned char * edata;
|
||||
unsigned short * data;
|
||||
char * strtab;
|
||||
Elf_Internal_Sym * symbols;
|
||||
int total;
|
||||
int cnt;
|
||||
unsigned char * edata;
|
||||
unsigned short * data;
|
||||
char * strtab;
|
||||
Elf_Internal_Sym * symbols;
|
||||
Elf32_Internal_Shdr * string_sec;
|
||||
|
||||
link_section = section_headers + section->sh_link;
|
||||
|
@ -6307,9 +6317,6 @@ get_FORM_name (form)
|
|||
}
|
||||
}
|
||||
|
||||
static const char *debug_str;
|
||||
static bfd_vma debug_str_size;
|
||||
|
||||
/* FIXME: There are better and more effiecint ways to handle
|
||||
these structures. For now though, I just want something that
|
||||
is simple to implement. */
|
||||
|
@ -6933,6 +6940,123 @@ decode_location_expression (data, pointer_size, length)
|
|||
}
|
||||
|
||||
|
||||
static const char * debug_str_contents;
|
||||
static bfd_vma debug_str_size;
|
||||
|
||||
static void
|
||||
load_debug_str (file)
|
||||
FILE * file;
|
||||
{
|
||||
Elf32_Internal_Shdr * sec;
|
||||
int i;
|
||||
|
||||
/* If it is already loaded, do nothing. */
|
||||
if (debug_str_contents != NULL)
|
||||
return;
|
||||
|
||||
/* Locate the .debug_str section. */
|
||||
for (i = 0, sec = section_headers;
|
||||
i < elf_header.e_shnum;
|
||||
i ++, sec ++)
|
||||
if (strcmp (SECTION_NAME (sec), ".debug_str") == 0)
|
||||
break;
|
||||
|
||||
if (i == elf_header.e_shnum || sec->sh_size == 0)
|
||||
return;
|
||||
|
||||
debug_str_size = sec->sh_size;
|
||||
|
||||
debug_str_contents = ((char *)
|
||||
get_data (NULL, file, sec->sh_offset, sec->sh_size,
|
||||
_("debug_str section data")));
|
||||
}
|
||||
|
||||
static void
|
||||
free_debug_str ()
|
||||
{
|
||||
if (debug_str_contents == NULL)
|
||||
return;
|
||||
|
||||
free ((char *) debug_str_contents);
|
||||
debug_str_contents = NULL;
|
||||
debug_str_size = 0;
|
||||
}
|
||||
|
||||
static const char *
|
||||
fetch_indirect_string (offset)
|
||||
unsigned long offset;
|
||||
{
|
||||
if (debug_str_contents == NULL)
|
||||
return _("<no .debug_str section>");
|
||||
|
||||
if (offset > debug_str_size)
|
||||
return _("<offset is too big>");
|
||||
|
||||
return debug_str_contents + offset;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
display_debug_str (section, start, file)
|
||||
Elf32_Internal_Shdr * section;
|
||||
unsigned char * start;
|
||||
FILE * file ATTRIBUTE_UNUSED;
|
||||
{
|
||||
unsigned long bytes;
|
||||
bfd_vma addr;
|
||||
|
||||
addr = section->sh_addr;
|
||||
bytes = section->sh_size;
|
||||
|
||||
if (bytes == 0)
|
||||
{
|
||||
printf (_("\nThe .debug_str section is empty.\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf (_("Contents of the .debug_str section:\n\n"));
|
||||
|
||||
while (bytes)
|
||||
{
|
||||
int j;
|
||||
int k;
|
||||
int lbytes;
|
||||
|
||||
lbytes = (bytes > 16 ? 16 : bytes);
|
||||
|
||||
printf (" 0x%8.8lx ", (unsigned long) addr);
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
{
|
||||
if (j < lbytes)
|
||||
printf ("%2.2x", start [j]);
|
||||
else
|
||||
printf (" ");
|
||||
|
||||
if ((j & 3) == 3)
|
||||
printf (" ");
|
||||
}
|
||||
|
||||
for (j = 0; j < lbytes; j++)
|
||||
{
|
||||
k = start [j];
|
||||
if (k >= ' ' && k < 0x80)
|
||||
printf ("%c", k);
|
||||
else
|
||||
printf (".");
|
||||
}
|
||||
|
||||
putchar ('\n');
|
||||
|
||||
start += lbytes;
|
||||
addr += lbytes;
|
||||
bytes -= lbytes;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static unsigned char *
|
||||
read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
|
||||
unsigned long attribute;
|
||||
|
@ -7061,13 +7185,8 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
|
|||
break;
|
||||
|
||||
case DW_FORM_strp:
|
||||
if (debug_str == NULL)
|
||||
warn (_("DW_FORM_strp used but no .debug_str section\n"));
|
||||
else if (uvalue >= debug_str_size)
|
||||
warn (_("DW_FORM_strp %lx points outside of .debug_str section\n"),
|
||||
uvalue);
|
||||
else
|
||||
printf (" %s", debug_str + uvalue);
|
||||
printf (_(" (indirect string, offset: 0x%lx): "), uvalue);
|
||||
printf (fetch_indirect_string (uvalue));
|
||||
break;
|
||||
|
||||
case DW_FORM_indirect:
|
||||
|
@ -7259,23 +7378,7 @@ display_debug_info (section, start, file)
|
|||
|
||||
printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
|
||||
|
||||
{
|
||||
Elf32_Internal_Shdr * sec;
|
||||
int i;
|
||||
|
||||
/* Locate the .debug_str section and read it. */
|
||||
for (i = 0, sec = section_headers;
|
||||
i < elf_header.e_shnum;
|
||||
i ++, sec ++)
|
||||
if (strcmp (SECTION_NAME (sec), ".debug_str") == 0 && sec->sh_size != 0)
|
||||
{
|
||||
debug_str = (const char *)
|
||||
get_data (NULL, file, sec->sh_offset, sec->sh_size,
|
||||
_("debug_str section data"));
|
||||
debug_str_size = sec->sh_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
load_debug_str (file);
|
||||
|
||||
while (start < end)
|
||||
{
|
||||
|
@ -7378,8 +7481,7 @@ display_debug_info (section, start, file)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (first_abbrev != NULL)
|
||||
free_abbrevs ();
|
||||
free_abbrevs ();
|
||||
|
||||
/* Read in the abbrevs used by this compilation unit. */
|
||||
|
||||
|
@ -7461,11 +7563,7 @@ display_debug_info (section, start, file)
|
|||
}
|
||||
}
|
||||
|
||||
if (debug_str != NULL)
|
||||
{
|
||||
free ((char *) debug_str);
|
||||
debug_str = NULL;
|
||||
}
|
||||
free_debug_str ();
|
||||
|
||||
printf ("\n");
|
||||
|
||||
|
@ -8262,22 +8360,24 @@ prescan_debug_info (section, start, file)
|
|||
sections. */
|
||||
struct
|
||||
{
|
||||
char * name;
|
||||
const char * const name;
|
||||
int (* display) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
|
||||
int (* prescan) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
|
||||
}
|
||||
debug_displays[] =
|
||||
{
|
||||
{ ".debug_info", display_debug_info, prescan_debug_info },
|
||||
{ ".debug_abbrev", display_debug_abbrev, NULL },
|
||||
{ ".debug_line", display_debug_lines, NULL },
|
||||
{ ".debug_aranges", display_debug_aranges, NULL },
|
||||
{ ".debug_pubnames", display_debug_pubnames, NULL },
|
||||
{ ".debug_frame", display_debug_frames, NULL },
|
||||
{ ".debug_info", display_debug_info, prescan_debug_info },
|
||||
{ ".debug_line", display_debug_lines, NULL },
|
||||
{ ".debug_pubnames", display_debug_pubnames, NULL },
|
||||
{ ".eh_frame", display_debug_frames, NULL },
|
||||
{ ".debug_macinfo", display_debug_macinfo, NULL },
|
||||
{ ".debug_str", display_debug_str, NULL },
|
||||
|
||||
{ ".debug_pubtypes", display_debug_not_supported, NULL },
|
||||
{ ".debug_str", display_debug_not_supported, NULL },
|
||||
{ ".debug_ranges", display_debug_not_supported, NULL },
|
||||
{ ".debug_static_func", display_debug_not_supported, NULL },
|
||||
{ ".debug_static_vars", display_debug_not_supported, NULL },
|
||||
{ ".debug_types", display_debug_not_supported, NULL },
|
||||
|
@ -8324,8 +8424,7 @@ display_debug_section (section, file)
|
|||
|
||||
/* If we loaded in the abbrev section at some point,
|
||||
we must release it here. */
|
||||
if (first_abbrev != NULL)
|
||||
free_abbrevs ();
|
||||
free_abbrevs ();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue