gdb/
authorJan Kratochvil <jan.kratochvil@redhat.com>
Sun, 25 Nov 2007 21:40:39 +0000 (21:40 +0000)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Sun, 25 Nov 2007 21:40:39 +0000 (21:40 +0000)
* dwarf2read.c (dwarf2_get_pc_bounds): Moved the `DW_AT_ranges' parsing
code with its variables OBJFILE, CU_HEADER and OBFD into ...
(dwarf2_ranges_read): ... a new function.
(read_partial_die): Implemented the parsing of `DW_AT_ranges'.

gdb/testsuite/
* gdb.dwarf2/dw2-ranges.S, gdb.dwarf2/dw2-ranges.exp: New files.

gdb/ChangeLog
gdb/dwarf2read.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.dwarf2/dw2-ranges.S [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/dw2-ranges.exp [new file with mode: 0644]

index 2e3fc01..3cb6fb6 100644 (file)
@@ -1,3 +1,10 @@
+2007-11-25  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       * dwarf2read.c (dwarf2_get_pc_bounds): Moved the `DW_AT_ranges' parsing
+       code with its variables OBJFILE, CU_HEADER and OBFD into ...
+       (dwarf2_ranges_read): ... a new function.
+       (read_partial_die): Implemented the parsing of `DW_AT_ranges'.
+
 2007-11-24  Pedro Alves  <pedro_alves@portugalmail.pt>
 
        * win32-nat.c (DR6_CLEAR_VALUE): New define.
index 1498d1f..d6178a7 100644 (file)
@@ -3077,6 +3077,124 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
   local_symbols = new->locals;
 }
 
+/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
+   Return 1 if the attributes are present and valid, otherwise, return 0.  */
+
+static int
+dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
+                   CORE_ADDR *high_return, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  struct comp_unit_head *cu_header = &cu->header;
+  bfd *obfd = objfile->obfd;
+  unsigned int addr_size = cu_header->addr_size;
+  CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
+  /* Base address selection entry.  */
+  CORE_ADDR base;
+  int found_base;
+  unsigned int dummy;
+  gdb_byte *buffer;
+  CORE_ADDR marker;
+  int low_set;
+  CORE_ADDR low = 0;
+  CORE_ADDR high = 0;
+
+  found_base = cu_header->base_known;
+  base = cu_header->base_address;
+
+  if (offset >= dwarf2_per_objfile->ranges_size)
+    {
+      complaint (&symfile_complaints,
+                _("Offset %d out of bounds for DW_AT_ranges attribute"),
+                offset);
+      return 0;
+    }
+  buffer = dwarf2_per_objfile->ranges_buffer + offset;
+
+  /* Read in the largest possible address.  */
+  marker = read_address (obfd, buffer, cu, &dummy);
+  if ((marker & mask) == mask)
+    {
+      /* If we found the largest possible address, then
+        read the base address.  */
+      base = read_address (obfd, buffer + addr_size, cu, &dummy);
+      buffer += 2 * addr_size;
+      offset += 2 * addr_size;
+      found_base = 1;
+    }
+
+  low_set = 0;
+
+  while (1)
+    {
+      CORE_ADDR range_beginning, range_end;
+
+      range_beginning = read_address (obfd, buffer, cu, &dummy);
+      buffer += addr_size;
+      range_end = read_address (obfd, buffer, cu, &dummy);
+      buffer += addr_size;
+      offset += 2 * addr_size;
+
+      /* An end of list marker is a pair of zero addresses.  */
+      if (range_beginning == 0 && range_end == 0)
+       /* Found the end of list entry.  */
+       break;
+
+      /* Each base address selection entry is a pair of 2 values.
+        The first is the largest possible address, the second is
+        the base address.  Check for a base address here.  */
+      if ((range_beginning & mask) == mask)
+       {
+         /* If we found the largest possible address, then
+            read the base address.  */
+         base = read_address (obfd, buffer + addr_size, cu, &dummy);
+         found_base = 1;
+         continue;
+       }
+
+      if (!found_base)
+       {
+         /* We have no valid base address for the ranges
+            data.  */
+         complaint (&symfile_complaints,
+                    _("Invalid .debug_ranges data (no base address)"));
+         return 0;
+       }
+
+      range_beginning += base;
+      range_end += base;
+
+      /* FIXME: This is recording everything as a low-high
+        segment of consecutive addresses.  We should have a
+        data structure for discontiguous block ranges
+        instead.  */
+      if (! low_set)
+       {
+         low = range_beginning;
+         high = range_end;
+         low_set = 1;
+       }
+      else
+       {
+         if (range_beginning < low)
+           low = range_beginning;
+         if (range_end > high)
+           high = range_end;
+       }
+    }
+
+  if (! low_set)
+    /* If the first entry is an end-of-list marker, the range
+       describes an empty scope, i.e. no instructions.  */
+    return 0;
+
+  if (low_return)
+    *low_return = low;
+  if (high_return)
+    *high_return = high;
+  return 1;
+}
+
 /* Get low and high pc attributes from a die.  Return 1 if the attributes
    are present and valid, otherwise, return 0.  Return -1 if the range is
    discontinuous, i.e. derived from DW_AT_ranges information.  */
@@ -3084,10 +3202,7 @@ static int
 dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
                      CORE_ADDR *highpc, struct dwarf2_cu *cu)
 {
-  struct objfile *objfile = cu->objfile;
-  struct comp_unit_head *cu_header = &cu->header;
   struct attribute *attr;
-  bfd *obfd = objfile->obfd;
   CORE_ADDR low = 0;
   CORE_ADDR high = 0;
   int ret = 0;
@@ -3111,108 +3226,11 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
       attr = dwarf2_attr (die, DW_AT_ranges, cu);
       if (attr != NULL)
        {
-         unsigned int addr_size = cu_header->addr_size;
-         CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
          /* Value of the DW_AT_ranges attribute is the offset in the
             .debug_ranges section.  */
-         unsigned int offset = DW_UNSND (attr);
-         /* Base address selection entry.  */
-         CORE_ADDR base;
-         int found_base;
-         unsigned int dummy;
-         gdb_byte *buffer;
-         CORE_ADDR marker;
-         int low_set;
-         found_base = cu_header->base_known;
-         base = cu_header->base_address;
-
-         if (offset >= dwarf2_per_objfile->ranges_size)
-           {
-             complaint (&symfile_complaints,
-                        _("Offset %d out of bounds for DW_AT_ranges attribute"),
-                        offset);
-             return 0;
-           }
-         buffer = dwarf2_per_objfile->ranges_buffer + offset;
-
-         /* Read in the largest possible address.  */
-         marker = read_address (obfd, buffer, cu, &dummy);
-         if ((marker & mask) == mask)
-           {
-             /* If we found the largest possible address, then
-                read the base address.  */
-             base = read_address (obfd, buffer + addr_size, cu, &dummy);
-             buffer += 2 * addr_size;
-             offset += 2 * addr_size;
-             found_base = 1;
-           }
-
-         low_set = 0;
-
-         while (1)
-           {
-             CORE_ADDR range_beginning, range_end;
-
-             range_beginning = read_address (obfd, buffer, cu, &dummy);
-             buffer += addr_size;
-             range_end = read_address (obfd, buffer, cu, &dummy);
-             buffer += addr_size;
-             offset += 2 * addr_size;
-
-             /* An end of list marker is a pair of zero addresses.  */
-             if (range_beginning == 0 && range_end == 0)
-               /* Found the end of list entry.  */
-               break;
-
-             /* Each base address selection entry is a pair of 2 values.
-                The first is the largest possible address, the second is
-                the base address.  Check for a base address here.  */
-             if ((range_beginning & mask) == mask)
-               {
-                 /* If we found the largest possible address, then
-                    read the base address.  */
-                 base = read_address (obfd, buffer + addr_size, cu, &dummy);
-                 found_base = 1;
-                 continue;
-               }
-
-             if (!found_base)
-               {
-                 /* We have no valid base address for the ranges
-                    data.  */
-                 complaint (&symfile_complaints,
-                            _("Invalid .debug_ranges data (no base address)"));
-                 return 0;
-               }
-
-             range_beginning += base;
-             range_end += base;
-
-             /* FIXME: This is recording everything as a low-high
-                segment of consecutive addresses.  We should have a
-                data structure for discontiguous block ranges
-                instead.  */
-             if (! low_set)
-               {
-                 low = range_beginning;
-                 high = range_end;
-                 low_set = 1;
-               }
-             else
-               {
-                 if (range_beginning < low)
-                   low = range_beginning;
-                 if (range_end > high)
-                   high = range_end;
-               }
-           }
-
-         if (! low_set)
-           /* If the first entry is an end-of-list marker, the range
-              describes an empty scope, i.e. no instructions.  */
+         if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu))
            return 0;
-
+         /* Found discontinuous range of addresses.  */
          ret = -1;
        }
     }
@@ -5569,6 +5587,11 @@ read_partial_die (struct partial_die_info *part_die,
          has_high_pc_attr = 1;
          part_die->highpc = DW_ADDR (&attr);
          break;
+       case DW_AT_ranges:
+         if (dwarf2_ranges_read (DW_UNSND (&attr), &part_die->lowpc,
+                                 &part_die->highpc, cu))
+           has_low_pc_attr = has_high_pc_attr = 1;
+         break;
        case DW_AT_location:
           /* Support the .debug_loc offsets */
           if (attr_form_is_block (&attr))
index e58ac5c..6385c74 100644 (file)
@@ -1,3 +1,7 @@
+2007-11-25  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       * gdb.dwarf2/dw2-ranges.S, gdb.dwarf2/dw2-ranges.exp: New files.
+
 2007-11-22  Maciej W. Rozycki  <macro@mips.com>
 
        * gdb.trace/backtrace.exp: Fix a typo.
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-ranges.S b/gdb/testsuite/gdb.dwarf2/dw2-ranges.S
new file mode 100644 (file)
index 0000000..87dc019
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+   Copyright 2007 Free Software Foundation, Inc.
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Despite the sections below will be adjacent the assembler has to produce
+   DW_AT_ranges as the linker could place both sections at arbitrary locations.
+   */
+
+       /* Without this directive GAS will not emit DWARF2 unless we provide an
+          instruction to assemble.  We want to avoid any instructions to
+          remain architecture independent.  */
+       .loc_mark_labels        1
+
+       .text
+
+       .globl  main
+       .func   main
+main:  .int    0
+       .endfunc
+       .size   main, . - main
+
+       .section        .text.func, "ax", @progbits
+       .globl  func
+       .func   func
+func:  .int    0
+       .endfunc
+       .size   func, . - func
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-ranges.exp b/gdb/testsuite/gdb.dwarf2/dw2-ranges.exp
new file mode 100644 (file)
index 0000000..4921551
--- /dev/null
@@ -0,0 +1,49 @@
+# Copyright 2007 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test DW_TAG_compile_unit with no children and with neither DW_AT_low_pc nor
+# DW_AT_high_pc but with DW_AT_ranges instead.
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    verbose "Skipping DW_AT_ranges test."
+    return 0  
+}
+
+set testfile "dw2-ranges"
+set srcfile ${testfile}.S
+set binfile ${objdir}/${subdir}/${testfile}.o
+
+if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" object debug] != "" } {
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Correct output:
+#      Line 39 of "../.././gdb/testsuite/gdb.dwarf2/dw2-ranges.S" starts at address 0x4 and ends at 0x8.
+# Wrong output:
+#      No line number information available for address 0x4
+
+gdb_test "info line func" "Line \[0-9\]* of .* starts at address .* and ends at .*"