int is_32bit_elf;
int have_frame_base;
int need_base_address;
-unsigned long saved_base_address;
struct group_list
{
return need_frame_base;
}
-/* Decode a DW_AT_ranges attribute for 64bit DWARF3 . */
-
-static void
-decode_64bit_range (unsigned long offset, bfd_vma base_address)
-{
- const char * start = debug_range_contents + offset;
- const char * end = debug_range_contents + debug_range_size;
-
- do
- {
- bfd_vma a;
- bfd_vma b;
-
- a = byte_get ((unsigned char *) start, 8);
- b = byte_get ((unsigned char *) start + 8, 8);
-
- if (a == 0xffffffff)
- {
- base_address = b;
- }
- else if (a == 0 && b == 0)
- break;
- else if (a > b)
- printf (_(" [corrupt: start > end]"));
- else
- {
- printf (" ");
- print_vma (base_address + a, PREFIX_HEX);
- printf (" - ");
- print_vma (base_address + b, PREFIX_HEX);
- printf (", ");
- }
-
- start += 16;
- }
- while (start < end);
-}
-
-/* Decode a DW_AT_ranges attribute. */
-
-static void
-decode_range (unsigned long offset, bfd_vma base_address)
-{
- const char * start;
- const char * end;
-
- if (offset >= (debug_range_size - 8))
- {
- printf (_("[corrupt: offset is outside the .debug_ranges section]"));
- return;
- }
-
- /* Since all entries in the .debug_ranges section are pairs of either
- 4-byte integers (32-bit DWARF3) or 8-byte integers (64-bit DWARF3)
- the offset should always be a multiple of 8 bytes. */
- if (offset % 8)
- {
- printf (_("[corrupt: offset is not a multiple of 8]"));
- return;
- }
-
- start = debug_range_contents + offset;
-
- if (offset > 0
- /* Be paranoid - check to see if the previous
- two words were and end-of-range marker. */
- && (byte_get ((unsigned char *) start - 4, 4) != 0
- || byte_get ((unsigned char *) start - 8, 4) != 0))
- {
- printf (_("[corrupt: offset is not at the start of a range]"));
- return;
- }
-
- end = debug_range_contents + debug_range_size;
-
- printf ("(");
- do
- {
- unsigned long a;
- unsigned long b;
-
- a = byte_get ((unsigned char *) start, 4);
- b = byte_get ((unsigned char *) start + 4, 4);
-
- if (a == 0xffffffff)
- {
- if (b == 0xffffffff)
- {
- decode_64bit_range (offset, base_address);
- return;
- }
-
- base_address = b;
- }
- else if (a == 0 && b == 0)
- break;
- else if (a > b)
- printf (_("[corrupt: start > end]"));
- else
- {
- if (start > debug_range_contents + offset)
- printf (", ");
-
- printf (_("0x%lx - 0x%lx"),
- (unsigned long) base_address + a,
- (unsigned long) base_address + b);
- }
-
- start += 8;
- }
- while (start < end);
- printf (")");
-}
-
/* This structure records the information that
we extract from the.debug_info section. */
typedef struct
int *have_frame_base;
unsigned int num_loc_offsets;
unsigned int max_loc_offsets;
+ unsigned long *range_lists;
+ unsigned int num_range_lists;
+ unsigned int max_range_lists;
}
debug_info;
printf (" %lx", uvalue);
printf (" %lx", (unsigned long) byte_get (data + 4, 4));
}
- if ((do_loc || do_debug_loc)
+ if ((do_loc || do_debug_loc || do_debug_ranges)
&& num_debug_info_entries == 0)
{
if (sizeof (uvalue) == 8)
}
/* For some attributes we can display further information. */
- if ((do_loc || do_debug_loc)
+ if ((do_loc || do_debug_loc || do_debug_ranges)
&& num_debug_info_entries == 0)
{
switch (attribute)
debug_info_p->base_address = uvalue;
break;
+ case DW_AT_ranges:
+ if (form == DW_FORM_data4 || form == DW_FORM_data8)
+ {
+ /* Process range list. */
+ unsigned int max = debug_info_p->max_range_lists;
+ unsigned int num = debug_info_p->num_range_lists;
+
+ if (max == 0 || num >= max)
+ {
+ max += 1024;
+ debug_info_p->range_lists
+ = xrealloc (debug_info_p->range_lists,
+ max * sizeof (*debug_info_p->range_lists));
+ debug_info_p->max_range_lists = max;
+ }
+ debug_info_p->range_lists [num] = uvalue;
+ debug_info_p->num_range_lists++;
+ }
+ break;
+
default:
break;
}
break;
- case DW_AT_low_pc:
- if (need_base_address)
- saved_base_address = uvalue;
- break;
-
- case DW_AT_ranges:
- decode_range (uvalue, saved_base_address);
- break;
-
default:
break;
}
unsigned int unit;
unsigned int num_units = 0;
- if ((do_loc || do_debug_loc)
+ if ((do_loc || do_debug_loc || do_debug_ranges)
&& num_debug_info_entries == 0)
{
unsigned long length;
compunit.cu_pointer_size = byte_get (hdrptr, 1);
hdrptr += 1;
- if ((do_loc || do_debug_loc)
+ if ((do_loc || do_debug_loc || do_debug_ranges)
&& num_debug_info_entries == 0)
{
debug_information [unit].cu_offset = cu_offset;
debug_information [unit].have_frame_base = NULL;
debug_information [unit].max_loc_offsets = 0;
debug_information [unit].num_loc_offsets = 0;
+ debug_information [unit].range_lists = NULL;
+ debug_information [unit].max_range_lists= 0;
+ debug_information [unit].num_range_lists = 0;
}
tags = hdrptr;
break;
case DW_TAG_compile_unit:
need_base_address = 1;
- saved_base_address = 0;
break;
case DW_TAG_entry_point:
case DW_TAG_inlined_subroutine:
}
}
- /* Set num_debug_info_entries here so that it can be used
- to check if we need to proecess .debug_loc section. */
- if ((do_loc || do_debug_loc)
+ /* Set num_debug_info_entries here so that it can be used to check if
+ we need to proecess .debug_loc and .debug_ranges sections. */
+ if ((do_loc || do_debug_loc || do_debug_ranges)
&& num_debug_info_entries == 0)
num_debug_info_entries = num_units;
}
static int
-display_64bit_debug_ranges (unsigned char * start, unsigned char * end)
+display_debug_ranges (Elf_Internal_Shdr *section,
+ unsigned char *start,
+ FILE *file ATTRIBUTE_UNUSED)
{
- bfd_vma base_address = 0;
+ unsigned char *section_end;
+ unsigned long bytes;
+ unsigned char *section_begin = start;
+ unsigned int num_range_list = 0;
+ unsigned long last_offset = 0;
+ unsigned int first = 0;
+ unsigned int i;
+ unsigned int j;
+ int seen_first_offset = 0;
+ int use_debug_info = 1;
+ unsigned char *next;
- while (start < end)
+ bytes = section->sh_size;
+ section_end = start + bytes;
+
+ if (bytes == 0)
{
- bfd_vma a, b;
+ printf (_("\nThe .debug_ranges section is empty.\n"));
+ return 0;
+ }
- a = byte_get (start, 8);
- b = byte_get (start + 8, 8);
+ get_debug_info (file);
- if (a == 0xffffffffffffffffLL)
- {
- printf (_(" set base address to "));
- print_vma (b, PREFIX_HEX);
- base_address = b;
- }
- else if (a == 0 && b == 0)
- printf ( _("end of range"));
- else if (a > b)
- printf (_(" <corrupt range entry, start is greater than end>"));
- else if (base_address == 0)
- {
- printf ("range from base address + ");
- print_vma (a, PREFIX_HEX);
- printf (" to base address + ");
- print_vma (b, PREFIX_HEX);
- }
- else
+ /* Check the order of range list in .debug_info section. If
+ offsets of range lists are in the ascending order, we can
+ use `debug_information' directly. */
+ for (i = 0; i < num_debug_info_entries; i++)
+ {
+ unsigned int num;
+
+ num = debug_information [i].num_range_lists;
+ num_range_list += num;
+
+ /* Check if we can use `debug_information' directly. */
+ if (use_debug_info && num != 0)
{
- printf ("range from ");
- print_vma (base_address + a, PREFIX_HEX);
- printf (" to ");
- print_vma (base_address + b, PREFIX_HEX);
- }
+ if (!seen_first_offset)
+ {
+ /* This is the first range list. */
+ last_offset = debug_information [i].range_lists [0];
+ first = i;
+ seen_first_offset = 1;
+ j = 1;
+ }
+ else
+ j = 0;
- start += 16;
- printf ("\n");
+ for (; j < num; j++)
+ {
+ if (last_offset >
+ debug_information [i].range_lists [j])
+ {
+ use_debug_info = 0;
+ break;
+ }
+ last_offset = debug_information [i].range_lists [j];
+ }
+ }
}
- return 1;
-}
+ if (!use_debug_info)
+ /* FIXME: Should we handle this case? */
+ error (_("Range lists in .debug_info section aren't in ascending order!\n"));
-static int
-display_debug_ranges (Elf_Internal_Shdr *section,
- unsigned char *start,
- FILE *file ATTRIBUTE_UNUSED)
-{
- unsigned long base_address = 0;
- unsigned char *end = start + section->sh_size;
+ if (!seen_first_offset)
+ error (_("No range lists in .debug_info section!\n"));
- printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
+ if (debug_information [first].range_lists [0] != 0)
+ warn (_("Range lists in .debug_ranges section start at 0x%lx\n"),
+ debug_information [first].range_lists [0]);
- while (start < end)
+ printf (_("Contents of the .debug_ranges section:\n\n"));
+ printf (_(" Offset Begin End\n"));
+
+ seen_first_offset = 0;
+ for (i = first; i < num_debug_info_entries; i++)
{
- unsigned long a;
- unsigned long b;
+ unsigned long begin;
+ unsigned long end;
+ unsigned long offset;
+ unsigned int pointer_size;
+ unsigned long base_address;
- a = byte_get (start, 4);
- b = byte_get (start + 4, 4);
+ pointer_size = debug_information [i].pointer_size;
- if (a == 0xffffffff)
+ for (j = 0; j < debug_information [i].num_range_lists; j++)
{
- /* Attempt to handle 64-bit DWARF3 format. This assumes
- that in a 32-bit DWARF3 file the base address will
- never be 0xffffffff, and that the .debug_ranges section
- will never contain a mixture of 32-bit and 64-bit entries. */
- if (b == 0xffffffff)
- return display_64bit_debug_ranges (start, end);
-
- printf (_(" set base address to 0x%lx\n"), b);
- base_address = b;
- }
- else if (a == 0 && b == 0)
- printf (_(" end of range\n"));
- else if (a > b)
- printf (_(" <corrupt range entry, start is greater than end>\n"));
- else if (base_address == 0)
- printf (_(" range from base address + 0x%lx to base address + 0x%lx\n"), a, b);
- else
- printf (_(" range from 0x%lx to 0x%lx\n"), base_address + a, base_address + b);
+ offset = debug_information [i].range_lists [j];
+ next = section_begin + offset;
+ base_address = debug_information [i].base_address;
- start += 8;
- }
+ if (!seen_first_offset)
+ seen_first_offset = 1;
+ else
+ {
+ if (start < next)
+ warn (_("There is a hole [0x%lx - 0x%lx] in .debug_ranges section.\n"),
+ start - section_begin, next - section_begin);
+ else if (start > next)
+ warn (_("There is an overlap [0x%lx - 0x%lx] in .debug_ranges section.\n"),
+ start - section_begin, next - section_begin);
+ }
+ start = next;
+
+ while (1)
+ {
+ begin = byte_get (start, pointer_size);
+ start += pointer_size;
+ end = byte_get (start, pointer_size);
+ start += pointer_size;
+
+ if (begin == 0 && end == 0)
+ break;
+
+ /* Check base address specifiers. */
+ if (begin == -1UL && end != -1UL)
+ {
+ base_address = end;
+ printf (" %8.8lx %8.8lx %8.8lx (base address)\n",
+ offset, begin, end);
+ continue;
+ }
+
+ printf (" %8.8lx %8.8lx %8.8lx",
+ offset, begin + base_address, end + base_address);
+
+ if (begin == end)
+ fputs (_(" (start == end)"), stdout);
+ else if (begin > end)
+ fputs (_(" (start > end)"), stdout);
+ putchar ('\n');
+ }
+ fputs (_(" <End of list>\n"), stdout);
+ }
+ }
+ putchar ('\n');
return 1;
}
if (debug_information)
{
for (i = 0; i < num_debug_info_entries; i++)
- if (!debug_information [i].max_loc_offsets)
- {
- free (debug_information [i].loc_offsets);
- free (debug_information [i].have_frame_base);
- }
+ {
+ if (!debug_information [i].max_loc_offsets)
+ {
+ free (debug_information [i].loc_offsets);
+ free (debug_information [i].have_frame_base);
+ }
+ if (!debug_information [i].max_range_lists)
+ free (debug_information [i].range_lists);
+ }
free (debug_information);
debug_information = NULL;
num_debug_info_entries = 0;