binutils/
authorJan Kratochvil <jan.kratochvil@redhat.com>
Tue, 14 Jul 2009 16:57:18 +0000 (16:57 +0000)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Tue, 14 Jul 2009 16:57:18 +0000 (16:57 +0000)
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.

binutils/ChangeLog
binutils/dwarf.c
binutils/dwarf.h
binutils/testsuite/ChangeLog
binutils/testsuite/binutils-all/objcopy.exp
binutils/testsuite/binutils-all/testranges.d [new file with mode: 0644]
binutils/testsuite/binutils-all/testranges.s [new file with mode: 0644]

index 91ea69cfe5f5636889bc8502ee6baf928587ed7b..0eedd9d448637305ac39ef531e4883be387927d0 100644 (file)
@@ -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>
 
        PR 10380
index 78f98840d4df3a7f8d501f040307dc5b5e97e975..5a42d798e777b332fa04c193d42c37fc59f85fca 100644 (file)
@@ -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 (_("<End of list>\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 (_("<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;
-               }
+             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;
 }
 
index 6b61360d149c5d361ad1969a6d0d45cdb925abd7..533400fba9f619a00c828f43ee056bd4a668e602 100644 (file)
@@ -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;
index 2c5db0cdeebe1a9f9744869b6dbba10b66202a25..cf8d81f8524cf86dc7abcfed7b7f3f2ba8ab711d 100644 (file)
@@ -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>
 
        * binutils-all/objcopy.exp: Move XFAIL from objcopy_test to
index 5f63bbbf0dba4511c704917f09a308d7590509ca..aa1da7267b23b6b1214623f369af8dec01d1a09b 100644 (file)
@@ -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 (file)
index 0000000..5aa7912
--- /dev/null
@@ -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
diff --git a/binutils/testsuite/binutils-all/testranges.s b/binutils/testsuite/binutils-all/testranges.s
new file mode 100644 (file)
index 0000000..565e1a2
--- /dev/null
@@ -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