From 01a8f077edb6f09060c339831a9b3c7e5f45c812 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Tue, 14 Jul 2009 16:57:18 +0000 Subject: [PATCH] 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 ): New comment. binutils/testsuite/ * binutils-all/objcopy.exp (testranges): New test. * binutils-all/testranges.d, binutils-all/testranges.s: New files. --- binutils/ChangeLog | 10 + binutils/dwarf.c | 213 ++++++++++--------- binutils/dwarf.h | 1 + binutils/testsuite/ChangeLog | 5 + binutils/testsuite/binutils-all/objcopy.exp | 1 + binutils/testsuite/binutils-all/testranges.d | 14 ++ binutils/testsuite/binutils-all/testranges.s | 57 +++++ 7 files changed, 195 insertions(+), 106 deletions(-) create mode 100644 binutils/testsuite/binutils-all/testranges.d create mode 100644 binutils/testsuite/binutils-all/testranges.s diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 91ea69cfe5..0eedd9d448 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,13 @@ +2009-07-14 Jan Kratochvil + + 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 ): New comment. + 2009-07-14 Nick Clifton PR 10380 diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 78f98840d4..5a42d798e7 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -3457,6 +3457,31 @@ display_debug_aranges (struct dwarf_section *section, 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 display_debug_ranges (struct dwarf_section *section, void *file ATTRIBUTE_UNUSED) @@ -3465,14 +3490,8 @@ display_debug_ranges (struct dwarf_section *section, 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; + unsigned int num_range_list, i; + struct range_entry *range_entries, *range_entry_fill; bytes = section->size; section_end = start + bytes; @@ -3490,135 +3509,117 @@ display_debug_ranges (struct dwarf_section *section, return 0; } - /* 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. */ + num_range_list = 0; for (i = 0; i < num_debug_info_entries; i++) - { - unsigned int num; + num_range_list += debug_information [i].num_range_lists; - num = debug_information [i].num_range_lists; - num_range_list += num; + if (num_range_list == 0) + error (_("No range lists in .debug_info section!\n")); - /* Check if we can use `debug_information' directly. */ - if (use_debug_info && num != 0) - { - 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; + range_entries = xmalloc (sizeof (*range_entries) * num_range_list); + range_entry_fill = range_entries; - 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]; - } + for (i = 0; i < num_debug_info_entries; i++) + { + debug_info *debug_info_p = &debug_information[i]; + unsigned int j; + + for (j = 0; j < debug_info_p->num_range_lists; j++) + { + range_entry_fill->ranges_offset = debug_info_p->range_lists[j]; + range_entry_fill->debug_info_p = debug_info_p; + range_entry_fill++; } } - if (!use_debug_info) - /* FIXME: Should we handle this case? */ - 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")); + qsort (range_entries, num_range_list, sizeof (*range_entries), + range_entry_compar); /* DWARF sections under Mach-O have non-zero addresses. */ - if (debug_information [first].num_range_lists > 0 - && debug_information [first].range_lists [0] != section->address) + if (range_entries[0].ranges_offset != section->address) 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 (_(" Offset Begin End\n")); - seen_first_offset = 0; - for (i = first; i < num_debug_info_entries; i++) + for (i = 0; i < num_range_list; i++) { - dwarf_vma begin; - dwarf_vma end; - unsigned long offset; + struct range_entry *range_entry = &range_entries[i]; + debug_info *debug_info_p = range_entry->debug_info_p; unsigned int pointer_size; + unsigned long offset; + unsigned char *next; unsigned long base_address; - pointer_size = debug_information [i].pointer_size; + pointer_size = debug_info_p->pointer_size; + + /* 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; - for (j = 0; j < debug_information [i].num_range_lists; j++) + if (i > 0) { - /* DWARF sections under Mach-O have non-zero addresses. */ - offset = debug_information [i].range_lists [j] - section->address; - next = section_begin + offset; - base_address = debug_information [i].base_address; + if (start < next) + warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"), + (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; - if (!seen_first_offset) - seen_first_offset = 1; - else + while (1) + { + 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) - warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"), - (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); + printf (_("\n")); + break; } - 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 - 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) - { - printf (_("\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; - } + 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); + 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); + 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; } diff --git a/binutils/dwarf.h b/binutils/dwarf.h index 6b61360d14..533400fba9 100644 --- a/binutils/dwarf.h +++ b/binutils/dwarf.h @@ -87,6 +87,7 @@ typedef struct int *have_frame_base; unsigned int num_loc_offsets; unsigned int max_loc_offsets; + /* List of .debug_ranges offsets seen in this .debug_info. */ unsigned long *range_lists; unsigned int num_range_lists; unsigned int max_range_lists; diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog index 2c5db0cdee..cf8d81f852 100644 --- a/binutils/testsuite/ChangeLog +++ b/binutils/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-07-14 Jan Kratochvil + + * binutils-all/objcopy.exp (testranges): New test. + * binutils-all/testranges.d, binutils-all/testranges.s: New files. + 2009-06-25 Christopher Faylor * binutils-all/objcopy.exp: Move XFAIL from objcopy_test to diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp index 5f63bbbf0d..aa1da7267b 100644 --- a/binutils/testsuite/binutils-all/objcopy.exp +++ b/binutils/testsuite/binutils-all/objcopy.exp @@ -874,3 +874,4 @@ if [is_elf_format] { run_dump_test "localize-hidden-1" } run_dump_test "localize-hidden-2" +run_dump_test "testranges" diff --git a/binutils/testsuite/binutils-all/testranges.d b/binutils/testsuite/binutils-all/testranges.d new file mode 100644 index 0000000000..5aa79123fe --- /dev/null +++ b/binutils/testsuite/binutils-all/testranges.d @@ -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 + 00000010 00000000 00000002 + 00000010 + +#pass diff --git a/binutils/testsuite/binutils-all/testranges.s b/binutils/testsuite/binutils-all/testranges.s new file mode 100644 index 0000000000..565e1a2e09 --- /dev/null +++ b/binutils/testsuite/binutils-all/testranges.s @@ -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 -- 2.34.1