2002-03-20 Daniel Berlin <dan@dberlin.org>

* readelf.c: Add support for displaying dwarf2 location lists.
	(do_debug_loc, debug_loc_section, debug_loc_size): New.
	(parse_args): Use 'O' as shorthand for displaying location list
	section.
	(process_section_headers): Handle debug_loc as well.
	(load_debug_loc): New.
	(free_debug_loc): New.
	(fetch_location_list): New.
	(display_debug_loc): New.
	(display_debug_info): Call load_debug_loc and free_debug_loc.
	(debug_displays): We can display .debug_loc now, too.
	(usage): Update usage string.
	(read_and_display_attr_value): Note location lists, but don't
	display them inline.
This commit is contained in:
Daniel Berlin 2002-03-21 05:00:58 +00:00
parent bdbe574731
commit a2f14207f3
2 changed files with 157 additions and 3 deletions

View File

@ -1,3 +1,20 @@
2002-03-20 Daniel Berlin <dan@dberlin.org>
* readelf.c: Add support for displaying dwarf2 location lists.
(do_debug_loc, debug_loc_section, debug_loc_size): New.
(parse_args): Use 'O' as shorthand for displaying location list
section.
(process_section_headers): Handle debug_loc as well.
(load_debug_loc): New.
(free_debug_loc): New.
(fetch_location_list): New.
(display_debug_loc): New.
(display_debug_info): Call load_debug_loc and free_debug_loc.
(debug_displays): We can display .debug_loc now, too.
(usage): Update usage string.
(read_and_display_attr_value): Note location lists, but don't
display them inline.
2002-03-18 Tom Rix <trix@redhat.com>
* Makefile.am: Add binutils emulation support.

View File

@ -127,6 +127,7 @@ int do_debug_frames;
int do_debug_frames_interp;
int do_debug_macinfo;
int do_debug_str;
int do_debug_loc;
int do_arch;
int do_notes;
int is_32bit_elf;
@ -227,10 +228,14 @@ static int display_debug_aranges PARAMS ((Elf32_Internal_Sh
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 int display_debug_loc 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 void load_debug_loc PARAMS ((FILE *));
static void free_debug_loc PARAMS ((void));
static const char * fetch_location_list 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));
@ -2248,7 +2253,7 @@ usage ()
-A --arch-specific Display architecture specific information (if any).\n\
-D --use-dynamic Use the dynamic section info when displaying symbols\n\
-x --hex-dump=<number> Dump the contents of section <number>\n\
-w --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str]\n\
-w --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str,=loc]\n\
Display the contents of DWARF2 debug sections\n"));
#ifdef SUPPORT_DISASSEMBLY
fprintf (stdout, _("\
@ -2435,6 +2440,11 @@ parse_args (argc, argv)
do_debug_str = 1;
break;
case 'o':
case 'O':
do_debug_loc = 1;
break;
default:
warn (_("Unrecognized debug option '%s'\n"), optarg);
break;
@ -3301,7 +3311,8 @@ 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_str)
|| do_debug_frames || do_debug_macinfo || do_debug_str
|| do_debug_loc)
&& strncmp (name, ".debug_", 7) == 0)
{
name += 7;
@ -3315,6 +3326,7 @@ process_section_headers (file)
|| (do_debug_frames && (strcmp (name, "frame") == 0))
|| (do_debug_macinfo && (strcmp (name, "macinfo") == 0))
|| (do_debug_str && (strcmp (name, "str") == 0))
|| (do_debug_loc && (strcmp (name, "loc") == 0))
)
request_dump (i, DEBUG_DUMP);
}
@ -7187,6 +7199,123 @@ decode_location_expression (data, pointer_size, length)
}
}
static const char * debug_loc_contents;
static bfd_vma debug_loc_size;
static void
load_debug_loc (file)
FILE * file;
{
Elf32_Internal_Shdr * sec;
unsigned int i;
/* If it is already loaded, do nothing. */
if (debug_loc_contents != NULL)
return;
/* Locate the .debug_loc section. */
for (i = 0, sec = section_headers;
i < elf_header.e_shnum;
i ++, sec ++)
if (strcmp (SECTION_NAME (sec), ".debug_loc") == 0)
break;
if (i == elf_header.e_shnum || sec->sh_size == 0)
return;
debug_loc_size = sec->sh_size;
debug_loc_contents = ((char *)
get_data (NULL, file, sec->sh_offset, sec->sh_size,
_("debug_loc section data")));
}
static void
free_debug_loc ()
{
if (debug_loc_contents == NULL)
return;
free ((char *) debug_loc_contents);
debug_loc_contents = NULL;
debug_loc_size = 0;
}
static const char *
fetch_location_list (offset)
unsigned long offset;
{
if (debug_loc_contents == NULL)
return _("<no .debug_loc section>");
if (offset > debug_loc_size)
return _("<offset is too big>");
return debug_loc_contents + offset;
}
static int
display_debug_loc (section, start, file)
Elf32_Internal_Shdr * section;
unsigned char * start;
FILE * file ATTRIBUTE_UNUSED;
{
unsigned char *section_end;
unsigned long bytes;
unsigned char *section_begin = start;
bfd_vma addr;
addr = section->sh_addr;
bytes = section->sh_size;
section_end = start + bytes;
if (bytes == 0)
{
printf (_("\nThe .debug_loc section is empty.\n"));
return 0;
}
printf (_("Contents of the .debug_loc section:\n\n"));
printf (_("\n Offset Begin End Expression\n"));
while (start < section_end)
{
unsigned long begin;
unsigned long end;
unsigned short length;
unsigned long offset;
offset = start - section_begin;
while (1)
{
/* Normally, the lists in the debug_loc section are related to a
given compilation unit, and thus, we would use the
pointer size of that compilation unit. However, since we are
displaying it seperately here, we either have to store
pointer sizes of all compilation units, or assume they don't
change. We assume, like the debug_line display, that
it doesn't change. */
begin = byte_get (start, debug_line_pointer_size);
start += debug_line_pointer_size;
end = byte_get (start, debug_line_pointer_size);
start += debug_line_pointer_size;
if (begin == 0 && end == 0)
break;
begin += addr;
end += addr;
length = byte_get (start, 2);
start += 2;
printf (" %8.8lx %8.8lx %8.8lx (", offset, begin, end);
decode_location_expression (start, debug_line_pointer_size, length);
printf (")\n");
start += length;
}
printf ("\n");
}
return 1;
}
static const char * debug_str_contents;
static bfd_vma debug_str_size;
@ -7591,6 +7720,12 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
decode_location_expression (block_start, pointer_size, uvalue);
printf (")");
}
else if (form == DW_FORM_data4)
{
printf ("(");
printf ("location list");
printf (")");
}
break;
default:
@ -7627,6 +7762,7 @@ display_debug_info (section, start, file)
printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
load_debug_str (file);
load_debug_loc (file);
while (start < end)
{
@ -7811,6 +7947,7 @@ display_debug_info (section, start, file)
}
free_debug_str ();
free_debug_loc ();
printf ("\n");
@ -8622,7 +8759,7 @@ debug_displays[] =
{ ".eh_frame", display_debug_frames, NULL },
{ ".debug_macinfo", display_debug_macinfo, NULL },
{ ".debug_str", display_debug_str, NULL },
{ ".debug_loc", display_debug_loc, NULL },
{ ".debug_pubtypes", display_debug_not_supported, NULL },
{ ".debug_ranges", display_debug_not_supported, NULL },
{ ".debug_static_func", display_debug_not_supported, NULL },