keiths / rpms / gdb

Forked from rpms/gdb 13 days ago
Clone
7969725
2007-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
7969725
7969725
	* dwarf2read.c (dwarf2_get_pc_bounds): Moved the `DW_AT_ranges' parsing
7969725
	code with its variables OBJFILE, CU_HEADER and OBFD into ...
7969725
	(dwarf2_ranges_read): ... a new function.
7969725
	(read_partial_die): Implemented the parsing of `DW_AT_ranges'.
7969725
7969725
2007-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
7969725
7969725
	* gdb.dwarf2/dw2-ranges.S, gdb.dwarf2/dw2-ranges.exp,
7969725
	gdb.dwarf2/dw2-ranges.lds: New files.
7969725
7969725
--- ./gdb/dwarf2read.c	26 Sep 2007 13:59:54 -0000	1.232
7969725
+++ ./gdb/dwarf2read.c	9 Oct 2007 15:03:09 -0000
7969725
@@ -3075,6 +3075,124 @@ read_lexical_block_scope (struct die_inf
7969725
   local_symbols = new->locals;
7969725
 }
7969725
 
7969725
+/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
7969725
+   Return 1 if the attributes are present and valid, otherwise, return 0.  */
7969725
+
7969725
+static int
7969725
+dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
7969725
+		    CORE_ADDR *high_return, struct dwarf2_cu *cu)
7969725
+{
7969725
+  struct objfile *objfile = cu->objfile;
7969725
+  struct comp_unit_head *cu_header = &cu->header;
7969725
+  bfd *obfd = objfile->obfd;
7969725
+  unsigned int addr_size = cu_header->addr_size;
7969725
+  CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
7969725
+  /* Base address selection entry.  */
7969725
+  CORE_ADDR base;
7969725
+  int found_base;
7969725
+  unsigned int dummy;
7969725
+  gdb_byte *buffer;
7969725
+  CORE_ADDR marker;
7969725
+  int low_set;
7969725
+  CORE_ADDR low = 0;
7969725
+  CORE_ADDR high = 0;
7969725
+
7969725
+  found_base = cu_header->base_known;
7969725
+  base = cu_header->base_address;
7969725
+
7969725
+  if (offset >= dwarf2_per_objfile->ranges_size)
7969725
+    {
7969725
+      complaint (&symfile_complaints,
7969725
+		 _("Offset %d out of bounds for DW_AT_ranges attribute"),
7969725
+		 offset);
7969725
+      return 0;
7969725
+    }
7969725
+  buffer = dwarf2_per_objfile->ranges_buffer + offset;
7969725
+
7969725
+  /* Read in the largest possible address.  */
7969725
+  marker = read_address (obfd, buffer, cu, &dummy);
7969725
+  if ((marker & mask) == mask)
7969725
+    {
7969725
+      /* If we found the largest possible address, then
7969725
+	 read the base address.  */
7969725
+      base = read_address (obfd, buffer + addr_size, cu, &dummy);
7969725
+      buffer += 2 * addr_size;
7969725
+      offset += 2 * addr_size;
7969725
+      found_base = 1;
7969725
+    }
7969725
+
7969725
+  low_set = 0;
7969725
+
7969725
+  while (1)
7969725
+    {
7969725
+      CORE_ADDR range_beginning, range_end;
7969725
+
7969725
+      range_beginning = read_address (obfd, buffer, cu, &dummy);
7969725
+      buffer += addr_size;
7969725
+      range_end = read_address (obfd, buffer, cu, &dummy);
7969725
+      buffer += addr_size;
7969725
+      offset += 2 * addr_size;
7969725
+
7969725
+      /* An end of list marker is a pair of zero addresses.  */
7969725
+      if (range_beginning == 0 && range_end == 0)
7969725
+	/* Found the end of list entry.  */
7969725
+	break;
7969725
+
7969725
+      /* Each base address selection entry is a pair of 2 values.
7969725
+	 The first is the largest possible address, the second is
7969725
+	 the base address.  Check for a base address here.  */
7969725
+      if ((range_beginning & mask) == mask)
7969725
+	{
7969725
+	  /* If we found the largest possible address, then
7969725
+	     read the base address.  */
7969725
+	  base = read_address (obfd, buffer + addr_size, cu, &dummy);
7969725
+	  found_base = 1;
7969725
+	  continue;
7969725
+	}
7969725
+
7969725
+      if (!found_base)
7969725
+	{
7969725
+	  /* We have no valid base address for the ranges
7969725
+	     data.  */
7969725
+	  complaint (&symfile_complaints,
7969725
+		     _("Invalid .debug_ranges data (no base address)"));
7969725
+	  return 0;
7969725
+	}
7969725
+
7969725
+      range_beginning += base;
7969725
+      range_end += base;
7969725
+
7969725
+      /* FIXME: This is recording everything as a low-high
7969725
+	 segment of consecutive addresses.  We should have a
7969725
+	 data structure for discontiguous block ranges
7969725
+	 instead.  */
7969725
+      if (! low_set)
7969725
+	{
7969725
+	  low = range_beginning;
7969725
+	  high = range_end;
7969725
+	  low_set = 1;
7969725
+	}
7969725
+      else
7969725
+	{
7969725
+	  if (range_beginning < low)
7969725
+	    low = range_beginning;
7969725
+	  if (range_end > high)
7969725
+	    high = range_end;
7969725
+	}
7969725
+    }
7969725
+
7969725
+  if (! low_set)
7969725
+    /* If the first entry is an end-of-list marker, the range
7969725
+       describes an empty scope, i.e. no instructions.  */
7969725
+    return 0;
7969725
+
7969725
+  if (low_return)
7969725
+    *low_return = low;
7969725
+  if (high_return)
7969725
+    *high_return = high;
7969725
+  return 1;
7969725
+}
7969725
+
7969725
 /* Get low and high pc attributes from a die.  Return 1 if the attributes
7969725
    are present and valid, otherwise, return 0.  Return -1 if the range is
7969725
    discontinuous, i.e. derived from DW_AT_ranges information.  */
7969725
@@ -3082,10 +3200,7 @@ static int
7969725
 dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
7969725
 		      CORE_ADDR *highpc, struct dwarf2_cu *cu)
7969725
 {
7969725
-  struct objfile *objfile = cu->objfile;
7969725
-  struct comp_unit_head *cu_header = &cu->header;
7969725
   struct attribute *attr;
7969725
-  bfd *obfd = objfile->obfd;
7969725
   CORE_ADDR low = 0;
7969725
   CORE_ADDR high = 0;
7969725
   int ret = 0;
7969725
@@ -3109,108 +3224,11 @@ dwarf2_get_pc_bounds (struct die_info *d
7969725
       attr = dwarf2_attr (die, DW_AT_ranges, cu);
7969725
       if (attr != NULL)
7969725
 	{
7969725
-	  unsigned int addr_size = cu_header->addr_size;
7969725
-	  CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
7969725
 	  /* Value of the DW_AT_ranges attribute is the offset in the
7969725
 	     .debug_ranges section.  */
7969725
-	  unsigned int offset = DW_UNSND (attr);
7969725
-	  /* Base address selection entry.  */
7969725
-	  CORE_ADDR base;
7969725
-	  int found_base;
7969725
-	  unsigned int dummy;
7969725
-	  gdb_byte *buffer;
7969725
-	  CORE_ADDR marker;
7969725
-	  int low_set;
7969725
- 
7969725
-	  found_base = cu_header->base_known;
7969725
-	  base = cu_header->base_address;
7969725
-
7969725
-	  if (offset >= dwarf2_per_objfile->ranges_size)
7969725
-	    {
7969725
-	      complaint (&symfile_complaints,
7969725
-	                 _("Offset %d out of bounds for DW_AT_ranges attribute"),
7969725
-			 offset);
7969725
-	      return 0;
7969725
-	    }
7969725
-	  buffer = dwarf2_per_objfile->ranges_buffer + offset;
7969725
-
7969725
-	  /* Read in the largest possible address.  */
7969725
-	  marker = read_address (obfd, buffer, cu, &dummy);
7969725
-	  if ((marker & mask) == mask)
7969725
-	    {
7969725
-	      /* If we found the largest possible address, then
7969725
-		 read the base address.  */
7969725
-	      base = read_address (obfd, buffer + addr_size, cu, &dummy);
7969725
-	      buffer += 2 * addr_size;
7969725
-	      offset += 2 * addr_size;
7969725
-	      found_base = 1;
7969725
-	    }
7969725
-
7969725
-	  low_set = 0;
7969725
-
7969725
-	  while (1)
7969725
-	    {
7969725
-	      CORE_ADDR range_beginning, range_end;
7969725
-
7969725
-	      range_beginning = read_address (obfd, buffer, cu, &dummy);
7969725
-	      buffer += addr_size;
7969725
-	      range_end = read_address (obfd, buffer, cu, &dummy);
7969725
-	      buffer += addr_size;
7969725
-	      offset += 2 * addr_size;
7969725
-
7969725
-	      /* An end of list marker is a pair of zero addresses.  */
7969725
-	      if (range_beginning == 0 && range_end == 0)
7969725
-		/* Found the end of list entry.  */
7969725
-		break;
7969725
-
7969725
-	      /* Each base address selection entry is a pair of 2 values.
7969725
-		 The first is the largest possible address, the second is
7969725
-		 the base address.  Check for a base address here.  */
7969725
-	      if ((range_beginning & mask) == mask)
7969725
-		{
7969725
-		  /* If we found the largest possible address, then
7969725
-		     read the base address.  */
7969725
-		  base = read_address (obfd, buffer + addr_size, cu, &dummy);
7969725
-		  found_base = 1;
7969725
-		  continue;
7969725
-		}
7969725
-
7969725
-	      if (!found_base)
7969725
-		{
7969725
-		  /* We have no valid base address for the ranges
7969725
-		     data.  */
7969725
-		  complaint (&symfile_complaints,
7969725
-			     _("Invalid .debug_ranges data (no base address)"));
7969725
-		  return 0;
7969725
-		}
7969725
-
7969725
-	      range_beginning += base;
7969725
-	      range_end += base;
7969725
-
7969725
-	      /* FIXME: This is recording everything as a low-high
7969725
-		 segment of consecutive addresses.  We should have a
7969725
-		 data structure for discontiguous block ranges
7969725
-		 instead.  */
7969725
-	      if (! low_set)
7969725
-		{
7969725
-		  low = range_beginning;
7969725
-		  high = range_end;
7969725
-		  low_set = 1;
7969725
-		}
7969725
-	      else
7969725
-		{
7969725
-		  if (range_beginning < low)
7969725
-		    low = range_beginning;
7969725
-		  if (range_end > high)
7969725
-		    high = range_end;
7969725
-		}
7969725
-	    }
7969725
-
7969725
-	  if (! low_set)
7969725
-	    /* If the first entry is an end-of-list marker, the range
7969725
-	       describes an empty scope, i.e. no instructions.  */
7969725
+	  if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu))
7969725
 	    return 0;
7969725
-
7969725
+	  /* Found discontinuous range of addresses.  */
7969725
 	  ret = -1;
7969725
 	}
7969725
     }
7969725
@@ -5571,6 +5589,11 @@ read_partial_die (struct partial_die_inf
7969725
 	  has_high_pc_attr = 1;
7969725
 	  part_die->highpc = DW_ADDR (&attr);
7969725
 	  break;
7969725
+	case DW_AT_ranges:
7969725
+	  if (dwarf2_ranges_read (DW_UNSND (&attr), &part_die->lowpc,
7969725
+				  &part_die->highpc, cu))
7969725
+	    has_low_pc_attr = has_high_pc_attr = 1;
7969725
+	  break;
7969725
 	case DW_AT_location:
7969725
           /* Support the .debug_loc offsets */
7969725
           if (attr_form_is_block (&attr))
7969725
--- /dev/null	1 Jan 1970 00:00:00 -0000
7969725
+++ ./gdb/testsuite/gdb.dwarf2/dw2-ranges.S	9 Oct 2007 15:03:10 -0000
7969725
@@ -0,0 +1,33 @@
7969725
+/*
7969725
+   Copyright 2007 Free Software Foundation, Inc.
7969725
+   
7969725
+   This program is free software; you can redistribute it and/or modify
7969725
+   it under the terms of the GNU General Public License as published by
7969725
+   the Free Software Foundation; either version 3 of the License, or
7969725
+   (at your option) any later version.
7969725
+   
7969725
+   This program is distributed in the hope that it will be useful,
7969725
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
7969725
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7969725
+   GNU General Public License for more details.
7969725
+   
7969725
+   You should have received a copy of the GNU General Public License
7969725
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
7969725
+ */
7969725
+
7969725
+	.text
7969725
+
7969725
+	.section	.text._start, "ax", @progbits
7969725
+	.globl	_start
7969725
+	.func	_start
7969725
+_start:	call	func
7969725
+	.endfunc
7969725
+	.size	_start, . - _start
7969725
+
7969725
+	.section	.text.func, "ax", @progbits
7969725
+	.globl	func
7969725
+	.func	func
7969725
+func:	int3
7969725
+	nop
7969725
+	.endfunc
7969725
+	.size	func, . - func
7969725
--- /dev/null	1 Jan 1970 00:00:00 -0000
7969725
+++ ./gdb/testsuite/gdb.dwarf2/dw2-ranges.exp	9 Oct 2007 15:03:10 -0000
7969725
@@ -0,0 +1,82 @@
7969725
+# Copyright 2007 Free Software Foundation, Inc.
7969725
+
7969725
+# This program is free software; you can redistribute it and/or modify
7969725
+# it under the terms of the GNU General Public License as published by
7969725
+# the Free Software Foundation; either version 3 of the License, or
7969725
+# (at your option) any later version.
7969725
+#
7969725
+# This program is distributed in the hope that it will be useful,
7969725
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
7969725
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7969725
+# GNU General Public License for more details.
7969725
+#
7969725
+# You should have received a copy of the GNU General Public License
7969725
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
7969725
+
7969725
+# Test DW_TAG_compile_unit with no children and with neither DW_AT_low_pc nor
7969725
+# DW_AT_high_pc but with DW_AT_ranges instead.  We created the hole there for
7969725
+# DW_AT_ranges by the linker script.
7969725
+
7969725
+# This test can only be run on targets which support DWARF-2 and use gas.
7969725
+# For now pick a sampling of likely targets.
7969725
+if {![istarget *-*-linux*]
7969725
+    && ![istarget *-*-gnu*]
7969725
+    && ![istarget *-*-elf*]
7969725
+    && ![istarget *-*-openbsd*]
7969725
+    && ![istarget arm-*-eabi*]
7969725
+    && ![istarget powerpc-*-eabi*]} {
7969725
+    verbose "Skipping i386/amd64 DW_AT_ranges test."
7969725
+    return 0  
7969725
+}
7969725
+if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } then {
7969725
+    verbose "Skipping i386/amd64 DW_AT_ranges test."
7969725
+    return 0
7969725
+}
7969725
+
7969725
+set testfile "dw2-ranges"
7969725
+set srcfile ${testfile}.S
7969725
+set ldsfile ${testfile}.lds
7969725
+set binfile ${objdir}/${subdir}/${testfile}
7969725
+
7969725
+# Avoid `-lm' from `lib/ada.exp' as it would fail with out `-nostdlib'.
7969725
+# Provide BOARD for SET_BOARD_INFO.
7969725
+set board [target_info name]
7969725
+set_board_info mathlib ""
7969725
+
7969725
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "additional_flags=-Wl,--script=${srcdir}/${subdir}/${ldsfile} -nostdlib"]] != "" } {
7969725
+    return -1
7969725
+}
7969725
+
7969725
+gdb_exit
7969725
+gdb_start
7969725
+gdb_reinitialize_dir $srcdir/$subdir
7969725
+gdb_load ${binfile}
7969725
+
7969725
+# Former wrong output:
7969725
+# 	Program received signal SIGTRAP, Trace/breakpoint trap.
7969725
+# 	0x000000000000002b in func ()
7969725
+# 	(gdb) bt
7969725
+# 	#0  0x000000000000002b in func ()
7969725
+# 	#1  0x0000000000000029 in _start ()
7969725
+# 	(gdb) _
7969725
+# Correct output:
7969725
+# 	Program received signal SIGTRAP, Trace/breakpoint trap.
7969725
+# 	func () at dw2-ranges.S:14
7969725
+# 	14              nop
7969725
+# 	Current language:  auto; currently asm
7969725
+# 	(gdb) bt
7969725
+# 	#0  func () at dw2-ranges.S:14
7969725
+# 	#1  0x0000000000000029 in _start () at dw2-ranges.S:6
7969725
+# 	(gdb) _
7969725
+# The entry #1 is missing on i386.
7969725
+# 	"#0 +func \\(\\) at .*dw2-ranges.S:\[0-9\]+\r\n#1 .*in _start \\(\\) at .*dw2-ranges.S:\[0-9\]+"
7969725
+
7969725
+gdb_run_cmd
7969725
+set test "run"
7969725
+gdb_test_multiple "" "$test" {
7969725
+    -re "Program received signal SIGTRAP,.*$gdb_prompt $" {
7969725
+	pass $test
7969725
+    }
7969725
+}
7969725
+
7969725
+gdb_test "backtrace" "#0 +func \\(\\) at .*dw2-ranges.S:\[0-9\]+"
7969725
--- /dev/null	1 Jan 1970 00:00:00 -0000
7969725
+++ ./gdb/testsuite/gdb.dwarf2/dw2-ranges.lds	9 Oct 2007 15:03:10 -0000
7969725
@@ -0,0 +1,25 @@
7969725
+/*
7969725
+   Copyright 2007 Free Software Foundation, Inc.
7969725
+   
7969725
+   This program is free software; you can redistribute it and/or modify
7969725
+   it under the terms of the GNU General Public License as published by
7969725
+   the Free Software Foundation; either version 3 of the License, or
7969725
+   (at your option) any later version.
7969725
+   
7969725
+   This program is distributed in the hope that it will be useful,
7969725
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
7969725
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7969725
+   GNU General Public License for more details.
7969725
+   
7969725
+   You should have received a copy of the GNU General Public License
7969725
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
7969725
+ */
7969725
+
7969725
+SECTIONS
7969725
+{
7969725
+	.text._start : { *(.text._start) }
7969725
+	/* Create the hole.  */
7969725
+	. = . + 1;
7969725
+	.text.func : { *(.text.func) }
7969725
+}
7969725
+ENTRY(_start)