binutils/
Support unordered .debug_info references to .debug_ranges. * dwarf.c (struct range_entry, range_entry_compar): New. (display_debug_ranges): Remove variables last_offset, first, j, seen_first_offset, use_debug_info and next. New variables range_entries and range_entry_fill. Create the sorted copy range_entries. Remove the FIXME error on detected unordered references. * dwarf.h (debug_info <range_lists>): New comment. binutils/testsuite/ * binutils-all/objcopy.exp (testranges): New test. * binutils-all/testranges.d, binutils-all/testranges.s: New files.
This commit is contained in:
parent
140033b391
commit
01a8f077ed
7 changed files with 197 additions and 108 deletions
|
@ -1,3 +1,13 @@
|
||||||
|
2009-07-14 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
|
Support unordered .debug_info references to .debug_ranges.
|
||||||
|
* dwarf.c (struct range_entry, range_entry_compar): New.
|
||||||
|
(display_debug_ranges): Remove variables last_offset, first, j,
|
||||||
|
seen_first_offset, use_debug_info and next. New variables
|
||||||
|
range_entries and range_entry_fill. Create the sorted copy
|
||||||
|
range_entries. Remove the FIXME error on detected unordered references.
|
||||||
|
* dwarf.h (debug_info <range_lists>): New comment.
|
||||||
|
|
||||||
2009-07-14 Nick Clifton <nickc@redhat.com>
|
2009-07-14 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR 10380
|
PR 10380
|
||||||
|
|
217
binutils/dwarf.c
217
binutils/dwarf.c
|
@ -3457,6 +3457,31 @@ display_debug_aranges (struct dwarf_section *section,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Each debug_information[x].range_lists[y] gets this representation for
|
||||||
|
sorting purposes. */
|
||||||
|
|
||||||
|
struct range_entry
|
||||||
|
{
|
||||||
|
/* The debug_information[x].range_lists[y] value. */
|
||||||
|
unsigned long ranges_offset;
|
||||||
|
|
||||||
|
/* Original debug_information to find parameters of the data. */
|
||||||
|
debug_info *debug_info_p;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Sort struct range_entry in ascending order of its RANGES_OFFSET. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
range_entry_compar (const void *ap, const void *bp)
|
||||||
|
{
|
||||||
|
const struct range_entry *a_re = ap;
|
||||||
|
const struct range_entry *b_re = bp;
|
||||||
|
const unsigned long a = a_re->ranges_offset;
|
||||||
|
const unsigned long b = b_re->ranges_offset;
|
||||||
|
|
||||||
|
return (a > b) - (b > a);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
display_debug_ranges (struct dwarf_section *section,
|
display_debug_ranges (struct dwarf_section *section,
|
||||||
void *file ATTRIBUTE_UNUSED)
|
void *file ATTRIBUTE_UNUSED)
|
||||||
|
@ -3465,14 +3490,8 @@ display_debug_ranges (struct dwarf_section *section,
|
||||||
unsigned char *section_end;
|
unsigned char *section_end;
|
||||||
unsigned long bytes;
|
unsigned long bytes;
|
||||||
unsigned char *section_begin = start;
|
unsigned char *section_begin = start;
|
||||||
unsigned int num_range_list = 0;
|
unsigned int num_range_list, i;
|
||||||
unsigned long last_offset = 0;
|
struct range_entry *range_entries, *range_entry_fill;
|
||||||
unsigned int first = 0;
|
|
||||||
unsigned int i;
|
|
||||||
unsigned int j;
|
|
||||||
int seen_first_offset = 0;
|
|
||||||
int use_debug_info = 1;
|
|
||||||
unsigned char *next;
|
|
||||||
|
|
||||||
bytes = section->size;
|
bytes = section->size;
|
||||||
section_end = start + bytes;
|
section_end = start + bytes;
|
||||||
|
@ -3490,135 +3509,117 @@ display_debug_ranges (struct dwarf_section *section,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the order of range list in .debug_info section. If
|
num_range_list = 0;
|
||||||
offsets of range lists are in the ascending order, we can
|
for (i = 0; i < num_debug_info_entries; i++)
|
||||||
use `debug_information' directly. */
|
num_range_list += debug_information [i].num_range_lists;
|
||||||
|
|
||||||
|
if (num_range_list == 0)
|
||||||
|
error (_("No range lists in .debug_info section!\n"));
|
||||||
|
|
||||||
|
range_entries = xmalloc (sizeof (*range_entries) * num_range_list);
|
||||||
|
range_entry_fill = range_entries;
|
||||||
|
|
||||||
for (i = 0; i < num_debug_info_entries; i++)
|
for (i = 0; i < num_debug_info_entries; i++)
|
||||||
{
|
{
|
||||||
unsigned int num;
|
debug_info *debug_info_p = &debug_information[i];
|
||||||
|
unsigned int j;
|
||||||
|
|
||||||
num = debug_information [i].num_range_lists;
|
for (j = 0; j < debug_info_p->num_range_lists; j++)
|
||||||
num_range_list += num;
|
|
||||||
|
|
||||||
/* Check if we can use `debug_information' directly. */
|
|
||||||
if (use_debug_info && num != 0)
|
|
||||||
{
|
{
|
||||||
if (!seen_first_offset)
|
range_entry_fill->ranges_offset = debug_info_p->range_lists[j];
|
||||||
{
|
range_entry_fill->debug_info_p = debug_info_p;
|
||||||
/* This is the first range list. */
|
range_entry_fill++;
|
||||||
last_offset = debug_information [i].range_lists [0];
|
|
||||||
first = i;
|
|
||||||
seen_first_offset = 1;
|
|
||||||
j = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
j = 0;
|
|
||||||
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!use_debug_info)
|
qsort (range_entries, num_range_list, sizeof (*range_entries),
|
||||||
/* FIXME: Should we handle this case? */
|
range_entry_compar);
|
||||||
error (_("Range lists in .debug_info section aren't in ascending order!\n"));
|
|
||||||
|
|
||||||
if (!seen_first_offset)
|
|
||||||
error (_("No range lists in .debug_info section!\n"));
|
|
||||||
|
|
||||||
/* DWARF sections under Mach-O have non-zero addresses. */
|
/* DWARF sections under Mach-O have non-zero addresses. */
|
||||||
if (debug_information [first].num_range_lists > 0
|
if (range_entries[0].ranges_offset != section->address)
|
||||||
&& debug_information [first].range_lists [0] != section->address)
|
|
||||||
warn (_("Range lists in %s section start at 0x%lx\n"),
|
warn (_("Range lists in %s section start at 0x%lx\n"),
|
||||||
section->name, debug_information [first].range_lists [0]);
|
section->name, range_entries[0].ranges_offset);
|
||||||
|
|
||||||
printf (_("Contents of the %s section:\n\n"), section->name);
|
printf (_("Contents of the %s section:\n\n"), section->name);
|
||||||
printf (_(" Offset Begin End\n"));
|
printf (_(" Offset Begin End\n"));
|
||||||
|
|
||||||
seen_first_offset = 0;
|
for (i = 0; i < num_range_list; i++)
|
||||||
for (i = first; i < num_debug_info_entries; i++)
|
|
||||||
{
|
{
|
||||||
dwarf_vma begin;
|
struct range_entry *range_entry = &range_entries[i];
|
||||||
dwarf_vma end;
|
debug_info *debug_info_p = range_entry->debug_info_p;
|
||||||
unsigned long offset;
|
|
||||||
unsigned int pointer_size;
|
unsigned int pointer_size;
|
||||||
|
unsigned long offset;
|
||||||
|
unsigned char *next;
|
||||||
unsigned long base_address;
|
unsigned long base_address;
|
||||||
|
|
||||||
pointer_size = debug_information [i].pointer_size;
|
pointer_size = debug_info_p->pointer_size;
|
||||||
|
|
||||||
for (j = 0; j < debug_information [i].num_range_lists; j++)
|
/* DWARF sections under Mach-O have non-zero addresses. */
|
||||||
|
offset = range_entry->ranges_offset - section->address;
|
||||||
|
next = section_begin + offset;
|
||||||
|
base_address = debug_info_p->base_address;
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
{
|
{
|
||||||
/* DWARF sections under Mach-O have non-zero addresses. */
|
if (start < next)
|
||||||
offset = debug_information [i].range_lists [j] - section->address;
|
warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"),
|
||||||
next = section_begin + offset;
|
(unsigned long) (start - section_begin),
|
||||||
base_address = debug_information [i].base_address;
|
(unsigned long) (next - section_begin), section->name);
|
||||||
|
else if (start > next)
|
||||||
|
warn (_("There is an overlap [0x%lx - 0x%lx] in %s section.\n"),
|
||||||
|
(unsigned long) (start - section_begin),
|
||||||
|
(unsigned long) (next - section_begin), section->name);
|
||||||
|
}
|
||||||
|
start = next;
|
||||||
|
|
||||||
if (!seen_first_offset)
|
while (1)
|
||||||
seen_first_offset = 1;
|
{
|
||||||
else
|
dwarf_vma begin;
|
||||||
|
dwarf_vma end;
|
||||||
|
|
||||||
|
/* Note: we use sign extension here in order to be sure that
|
||||||
|
we can detect the -1 escape value. Sign extension into the
|
||||||
|
top 32 bits of a 32-bit address will not affect the values
|
||||||
|
that we display since we always show hex values, and always
|
||||||
|
the bottom 32-bits. */
|
||||||
|
begin = byte_get_signed (start, pointer_size);
|
||||||
|
start += pointer_size;
|
||||||
|
end = byte_get_signed (start, pointer_size);
|
||||||
|
start += pointer_size;
|
||||||
|
|
||||||
|
printf (" %8.8lx ", offset);
|
||||||
|
|
||||||
|
if (begin == 0 && end == 0)
|
||||||
{
|
{
|
||||||
if (start < next)
|
printf (_("<End of list>\n"));
|
||||||
warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"),
|
break;
|
||||||
(unsigned long) (start - section_begin),
|
|
||||||
(unsigned long) (next - section_begin), section->name);
|
|
||||||
else if (start > next)
|
|
||||||
warn (_("There is an overlap [0x%lx - 0x%lx] in %s section.\n"),
|
|
||||||
(unsigned long) (start - section_begin),
|
|
||||||
(unsigned long) (next - section_begin), section->name);
|
|
||||||
}
|
}
|
||||||
start = next;
|
|
||||||
|
|
||||||
while (1)
|
/* Check base address specifiers. */
|
||||||
|
if (begin == (dwarf_vma) -1 && end != (dwarf_vma) -1)
|
||||||
{
|
{
|
||||||
/* Note: we use sign extension here in order to be sure that
|
base_address = end;
|
||||||
we can detect the -1 escape value. Sign extension into the
|
print_dwarf_vma (begin, pointer_size);
|
||||||
top 32 bits of a 32-bit address will not affect the values
|
print_dwarf_vma (end, pointer_size);
|
||||||
that we display since we always show hex values, and always
|
printf ("(base address)\n");
|
||||||
the bottom 32-bits. */
|
continue;
|
||||||
begin = byte_get_signed (start, pointer_size);
|
|
||||||
start += pointer_size;
|
|
||||||
end = byte_get_signed (start, pointer_size);
|
|
||||||
start += pointer_size;
|
|
||||||
|
|
||||||
printf (" %8.8lx ", offset);
|
|
||||||
|
|
||||||
if (begin == 0 && end == 0)
|
|
||||||
{
|
|
||||||
printf (_("<End of list>\n"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check base address specifiers. */
|
|
||||||
if (begin == (dwarf_vma) -1 && end != (dwarf_vma) -1)
|
|
||||||
{
|
|
||||||
base_address = end;
|
|
||||||
print_dwarf_vma (begin, pointer_size);
|
|
||||||
print_dwarf_vma (end, pointer_size);
|
|
||||||
printf ("(base address)\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_dwarf_vma (begin + base_address, pointer_size);
|
|
||||||
print_dwarf_vma (end + base_address, pointer_size);
|
|
||||||
|
|
||||||
if (begin == end)
|
|
||||||
fputs (_("(start == end)"), stdout);
|
|
||||||
else if (begin > end)
|
|
||||||
fputs (_("(start > end)"), stdout);
|
|
||||||
|
|
||||||
putchar ('\n');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print_dwarf_vma (begin + base_address, pointer_size);
|
||||||
|
print_dwarf_vma (end + base_address, pointer_size);
|
||||||
|
|
||||||
|
if (begin == end)
|
||||||
|
fputs (_("(start == end)"), stdout);
|
||||||
|
else if (begin > end)
|
||||||
|
fputs (_("(start > end)"), stdout);
|
||||||
|
|
||||||
|
putchar ('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
|
|
||||||
|
free (range_entries);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ typedef struct
|
||||||
int *have_frame_base;
|
int *have_frame_base;
|
||||||
unsigned int num_loc_offsets;
|
unsigned int num_loc_offsets;
|
||||||
unsigned int max_loc_offsets;
|
unsigned int max_loc_offsets;
|
||||||
|
/* List of .debug_ranges offsets seen in this .debug_info. */
|
||||||
unsigned long *range_lists;
|
unsigned long *range_lists;
|
||||||
unsigned int num_range_lists;
|
unsigned int num_range_lists;
|
||||||
unsigned int max_range_lists;
|
unsigned int max_range_lists;
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2009-07-14 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
|
* binutils-all/objcopy.exp (testranges): New test.
|
||||||
|
* binutils-all/testranges.d, binutils-all/testranges.s: New files.
|
||||||
|
|
||||||
2009-06-25 Christopher Faylor <me+cygwin@cgf.cx>
|
2009-06-25 Christopher Faylor <me+cygwin@cgf.cx>
|
||||||
|
|
||||||
* binutils-all/objcopy.exp: Move XFAIL from objcopy_test to
|
* binutils-all/objcopy.exp: Move XFAIL from objcopy_test to
|
||||||
|
|
|
@ -874,3 +874,4 @@ if [is_elf_format] {
|
||||||
run_dump_test "localize-hidden-1"
|
run_dump_test "localize-hidden-1"
|
||||||
}
|
}
|
||||||
run_dump_test "localize-hidden-2"
|
run_dump_test "localize-hidden-2"
|
||||||
|
run_dump_test "testranges"
|
||||||
|
|
14
binutils/testsuite/binutils-all/testranges.d
Normal file
14
binutils/testsuite/binutils-all/testranges.d
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#PROG: objcopy
|
||||||
|
#source: testranges.s
|
||||||
|
#readelf: -wR --wide
|
||||||
|
#name: unordered .debug_info references to .debug_ranges
|
||||||
|
|
||||||
|
Contents of the .debug_ranges section:
|
||||||
|
|
||||||
|
Offset Begin End
|
||||||
|
00000000 00000001 00000002
|
||||||
|
00000000 <End of list>
|
||||||
|
00000010 00000000 00000002
|
||||||
|
00000010 <End of list>
|
||||||
|
|
||||||
|
#pass
|
57
binutils/testsuite/binutils-all/testranges.s
Normal file
57
binutils/testsuite/binutils-all/testranges.s
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
# Test .debug_info can reference .debug_ranges entries without ordering the
|
||||||
|
# offsets strictly as increasing.
|
||||||
|
|
||||||
|
.text
|
||||||
|
start:
|
||||||
|
.byte 1
|
||||||
|
sub:
|
||||||
|
.byte 2
|
||||||
|
end:
|
||||||
|
|
||||||
|
.section .debug_ranges,"",@progbits
|
||||||
|
range:
|
||||||
|
|
||||||
|
range_sub:
|
||||||
|
.long sub, end
|
||||||
|
.long 0, 0 # range terminator
|
||||||
|
|
||||||
|
range_cu:
|
||||||
|
.long start, end
|
||||||
|
.long 0, 0 # range terminator
|
||||||
|
|
||||||
|
.section .debug_info,"",@progbits
|
||||||
|
.long debugE - debugS # Length of Compilation Unit Info
|
||||||
|
debugS:
|
||||||
|
.value 0x2 # DWARF version number
|
||||||
|
.long abbrev0 # Offset Into Abbrev. Section
|
||||||
|
.byte 0x4 # Pointer Size (in bytes)
|
||||||
|
|
||||||
|
.uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit)
|
||||||
|
.long range_cu - range # DW_AT_ranges
|
||||||
|
|
||||||
|
.uleb128 0x2 # (DIE (0x6d) DW_TAG_subprogram)
|
||||||
|
.ascii "A\0" # DW_AT_name
|
||||||
|
.long range_sub - range # DW_AT_ranges
|
||||||
|
debugE:
|
||||||
|
|
||||||
|
.section .debug_abbrev,"",@progbits
|
||||||
|
abbrev0:
|
||||||
|
.uleb128 0x1 # (abbrev code)
|
||||||
|
.uleb128 0x11 # (TAG: DW_TAG_compile_unit)
|
||||||
|
.byte 0x0 # DW_children_no
|
||||||
|
.uleb128 0x55 # (DW_AT_ranges)
|
||||||
|
.uleb128 0x6 # (DW_FORM_data4)
|
||||||
|
.byte 0x0
|
||||||
|
.byte 0x0
|
||||||
|
|
||||||
|
.uleb128 0x2 # (abbrev code)
|
||||||
|
.uleb128 0x2e # (TAG: DW_TAG_subprogram)
|
||||||
|
.byte 0x0 # DW_children_no
|
||||||
|
.uleb128 0x3 # (DW_AT_name)
|
||||||
|
.uleb128 0x8 # (DW_FORM_string)
|
||||||
|
.uleb128 0x55 # (DW_AT_ranges)
|
||||||
|
.uleb128 0x6 # (DW_FORM_data4)
|
||||||
|
.byte 0x0
|
||||||
|
.byte 0x0
|
||||||
|
|
||||||
|
.byte 0x0 # abbrevs terminator
|
Loading…
Add table
Add a link
Reference in a new issue