Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFC] Partial support for dwarf3 DW_AT_ranges
@ 2001-12-31  0:34 Richard Henderson
  2002-01-04  7:20 ` Daniel Berlin
  2002-01-04  9:47 ` Elena Zannoni
  0 siblings, 2 replies; 14+ messages in thread
From: Richard Henderson @ 2001-12-31  0:34 UTC (permalink / raw)
  To: gdb-patches; +Cc: Richard Henderson

GCC began emitting DW_AT_ranges back in September to deal with
lexical scopes made discontiguous by basic block reordering.

As of today, it may also create discontiguous lexical scopes
due to scheduling.  (Before today under the same circumstances
we'd lose track of which instructions belonged to which scope
and fail to emit any debug information whatsoever.)

However, GDB doesn't recognize DW_AT_ranges as a valid way of
marking a lexical scope, which causes it to discard the scope
entirely.  Which is probably the least useful thing that could
be done.

The following does not add proper support for discontiguous
address ranges.  I couldn't figure out how to do that in any
way that wasn't horribly invasive.  I'm willing to expend a
significant amount of effort on this if someone is willing to
provide some direction.

What this does do is find the "bounding box" of the discontiguous
range and use that.  Yes, that will do the wrong thing in some
circumstances, but the current behaviour is wrong under all
circumstances, so it may be a net improvement.

My test case for this was

	static int foo(int *);
	static void bar(int *);

	int main()
	{
	  {
	    int x = 0, r;
	    r = foo(&x);
	    if (__builtin_expect (r, 1))
	      return 0;
	    bar (&x);
	    return 1;
	  }
	}

	static int foo(int *p)
	{
	  *p = 1;
	  return 0;
	}

	static void bar(int *p)
	{
	  *p = 2;
	}

For any GCC target that can emit epilogues as rtl, we will
arrange the code here as

	x = 0
	call foo
	if r == 0 goto L1
	ret = 0
    L0:
	return ret
    L1:
	call bar
	ret = 1
	goto L0

The lexical scope created by the extra set of braces doesn't
cover the epilogue, so the scope's range is the block before
L0, plus the block after L1.


r~


	* dwarf2read.c: Remove dead comp_unit_header code.
	(dwarf_ranges_offset, dwarf_ranges_size, dwarf_ranges_buffer): New.
	(struct dwarf2_pinfo): Add dwarf_ranges_buffer, dwarf_ranges_size.
	(DWARF_RANGES_BUFFER, DWARF_RANGES_SIZE): New.
	(dwarf2_has_info): Init dwarf_ranges_offset/size.
	(dwarf2_locate_sections): Likewise.
	(dwarf2_build_psymtabs): Read .debug_ranges.
	(dwarf2_build_psymtabs_hard): Swap dwarf_ranges out.
	(psymtab_to_symtab_1): Swap dwarf_ranges in.  Set cu_header.die.
	(RANGES_SECTION): New.
	(struct comp_unit_head): Add die member.
	(dwarf2_get_pc_bounds): New cu_header argument; adjust all callers.
	Look for DW_AT_ranges and return the bounding box.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.42
diff -c -p -d -u -r1.42 dwarf2read.c
--- dwarf2read.c	2001/12/12 02:11:51	1.42
+++ dwarf2read.c	2001/12/31 04:07:13
@@ -50,23 +50,6 @@
 #define DWARF2_REG_TO_REGNUM(REG) (REG)
 #endif
 
-#if 0
-/* .debug_info header for a compilation unit
-   Because of alignment constraints, this structure has padding and cannot
-   be mapped directly onto the beginning of the .debug_info section.  */
-typedef struct comp_unit_header
-  {
-    unsigned int length;	/* length of the .debug_info
-				   contribution */
-    unsigned short version;	/* version number -- 2 for DWARF
-				   version 2 */
-    unsigned int abbrev_offset;	/* offset into .debug_abbrev section */
-    unsigned char addr_size;	/* byte size of an address -- 4 */
-  }
-_COMP_UNIT_HEADER;
-#define _ACTUAL_COMP_UNIT_HEADER_SIZE 11
-#endif
-
 /* .debug_pubnames header
    Because of alignment constraints, this structure has padding and cannot
    be mapped directly onto the beginning of the .debug_info section.  */
@@ -132,6 +115,7 @@ static file_ptr dwarf_aranges_offset;
 static file_ptr dwarf_loc_offset;
 static file_ptr dwarf_macinfo_offset;
 static file_ptr dwarf_str_offset;
+static file_ptr dwarf_ranges_offset;
 file_ptr dwarf_frame_offset;
 file_ptr dwarf_eh_frame_offset;
 
@@ -143,6 +127,7 @@ static unsigned int dwarf_aranges_size;
 static unsigned int dwarf_loc_size;
 static unsigned int dwarf_macinfo_size;
 static unsigned int dwarf_str_size;
+static unsigned int dwarf_ranges_size;
 unsigned int dwarf_frame_size;
 unsigned int dwarf_eh_frame_size;
 
@@ -156,6 +141,7 @@ unsigned int dwarf_eh_frame_size;
 #define LOC_SECTION      ".debug_loc"
 #define MACINFO_SECTION  ".debug_macinfo"
 #define STR_SECTION      ".debug_str"
+#define RANGES_SECTION   ".debug_ranges"
 #define FRAME_SECTION    ".debug_frame"
 #define EH_FRAME_SECTION ".eh_frame"
 
@@ -173,6 +159,7 @@ struct comp_unit_head
     unsigned int offset_size;	/* size of file offsets; either 4 or 8 */
     unsigned int initial_length_size; /* size of the length field; either
                                          4 or 12 */
+    struct die_info *die;
   };
 
 /* The data in the .debug_line statement prologue looks like this.  */
@@ -310,6 +297,7 @@ static char *dwarf_info_buffer;
 static char *dwarf_abbrev_buffer;
 static char *dwarf_line_buffer;
 static char *dwarf_str_buffer;
+static char *dwarf_ranges_buffer;
 
 /* A zeroed version of a partial die for initialization purposes.  */
 static struct partial_die_info zeroed_partial_die;
@@ -373,32 +361,31 @@ static CORE_ADDR baseaddr;	/* Add to eac
 struct dwarf2_pinfo
   {
     /* Pointer to start of dwarf info buffer for the objfile.  */
-
     char *dwarf_info_buffer;
 
     /* Offset in dwarf_info_buffer for this compilation unit. */
-
     unsigned long dwarf_info_offset;
 
     /* Pointer to start of dwarf abbreviation buffer for the objfile.  */
-
     char *dwarf_abbrev_buffer;
 
     /* Size of dwarf abbreviation section for the objfile.  */
-
     unsigned int dwarf_abbrev_size;
 
     /* Pointer to start of dwarf line buffer for the objfile.  */
-
     char *dwarf_line_buffer;
 
     /* Pointer to start of dwarf string buffer for the objfile.  */
-
     char *dwarf_str_buffer;
 
     /* Size of dwarf string section for the objfile.  */
-
     unsigned int dwarf_str_size;
+
+    /* Pointer to start of dwarf ranges buffer for the objfile.  */
+    char *dwarf_ranges_buffer;
+
+    /* Size of dwarf ranges buffer for the objfile.  */
+    unsigned int dwarf_ranges_size;
   };
 
 #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
@@ -409,6 +396,8 @@ struct dwarf2_pinfo
 #define DWARF_LINE_BUFFER(p) (PST_PRIVATE(p)->dwarf_line_buffer)
 #define DWARF_STR_BUFFER(p)  (PST_PRIVATE(p)->dwarf_str_buffer)
 #define DWARF_STR_SIZE(p)    (PST_PRIVATE(p)->dwarf_str_size)
+#define DWARF_RANGES_BUFFER(p) (PST_PRIVATE(p)->dwarf_ranges_buffer)
+#define DWARF_RANGES_SIZE(p) (PST_PRIVATE(p)->dwarf_ranges_size)
 
 /* Maintain an array of referenced fundamental types for the current
    compilation unit being read.  For DWARF version 1, we have to construct
@@ -692,7 +681,8 @@ static void read_lexical_block_scope (st
 				      const struct comp_unit_head *);
 
 static int dwarf2_get_pc_bounds (struct die_info *,
-				 CORE_ADDR *, CORE_ADDR *, struct objfile *);
+				 CORE_ADDR *, CORE_ADDR *, struct objfile *,
+				 const struct comp_unit_head *);
 
 static void dwarf2_add_field (struct field_info *, struct die_info *,
 			      struct objfile *, const struct comp_unit_head *);
@@ -807,9 +797,14 @@ static struct die_info *dwarf_alloc_die 
 int
 dwarf2_has_info (bfd *abfd)
 {
-  dwarf_info_offset = dwarf_abbrev_offset = dwarf_line_offset = 0;
+  dwarf_info_offset = 0;
+  dwarf_abbrev_offset = 0;
+  dwarf_line_offset = 0;
   dwarf_str_offset = 0;
-  dwarf_frame_offset = dwarf_eh_frame_offset = 0;
+  dwarf_ranges_offset = 0;
+  dwarf_frame_offset = 0;
+  dwarf_eh_frame_offset = 0;
+
   bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
   if (dwarf_info_offset && dwarf_abbrev_offset)
     {
@@ -868,6 +863,11 @@ dwarf2_locate_sections (bfd *ignore_abfd
       dwarf_str_offset = sectp->filepos;
       dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
     }
+  else if (STREQ (sectp->name, RANGES_SECTION))
+    {
+      dwarf_ranges_offset = sectp->filepos;
+      dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp);
+    }
   else if (STREQ (sectp->name, FRAME_SECTION))
     {
       dwarf_frame_offset = sectp->filepos;
@@ -905,6 +905,13 @@ dwarf2_build_psymtabs (struct objfile *o
   else
     dwarf_str_buffer = NULL;
 
+  if (dwarf_ranges_offset)
+    dwarf_ranges_buffer = dwarf2_read_section (objfile,
+					       dwarf_ranges_offset,
+					       dwarf_ranges_size);
+  else
+    dwarf_ranges_buffer = NULL;
+
   if (mainline
       || (objfile->global_psymbols.size == 0
 	  && objfile->static_psymbols.size == 0))
@@ -1112,6 +1119,8 @@ dwarf2_build_psymtabs_hard (struct objfi
       DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
       DWARF_STR_BUFFER (pst) = dwarf_str_buffer;
       DWARF_STR_SIZE (pst) = dwarf_str_size;
+      DWARF_RANGES_BUFFER (pst) = dwarf_ranges_buffer;
+      DWARF_RANGES_SIZE (pst) = dwarf_ranges_size;
       baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
       /* Store the function that reads in the rest of the symbol table */
@@ -1413,6 +1422,8 @@ psymtab_to_symtab_1 (struct partial_symt
   dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
   dwarf_str_buffer = DWARF_STR_BUFFER (pst);
   dwarf_str_size = DWARF_STR_SIZE (pst);
+  dwarf_ranges_buffer = DWARF_RANGES_BUFFER (pst);
+  dwarf_ranges_size = DWARF_RANGES_SIZE (pst);
   baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
   cu_header_offset = offset;
   info_ptr = dwarf_info_buffer + offset;
@@ -1435,9 +1446,10 @@ psymtab_to_symtab_1 (struct partial_symt
   make_cleanup_free_die_list (dies);
 
   /* Do line number decoding in read_file_scope () */
+  cu_header.die = dies;
   process_die (dies, objfile, &cu_header);
 
-  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
+  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header))
     {
       /* Some compilers don't define a DW_AT_high_pc attribute for
          the compilation unit.   If the DW_AT_high_pc is missing,
@@ -1452,7 +1464,8 @@ psymtab_to_symtab_1 (struct partial_symt
 		{
 		  CORE_ADDR low, high;
 
-		  if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+		  if (dwarf2_get_pc_bounds (child_die, &low, &high,
+					    objfile, &cu_header))
 		    {
 		      highpc = max (highpc, high);
 		    }
@@ -1561,7 +1574,7 @@ read_file_scope (struct die_info *die, s
   struct die_info *child_die;
   bfd *abfd = objfile->obfd;
 
-  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
     {
       if (die->has_children)
 	{
@@ -1572,7 +1585,8 @@ read_file_scope (struct die_info *die, s
 		{
 		  CORE_ADDR low, high;
 
-		  if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+		  if (dwarf2_get_pc_bounds (child_die, &low, &high,
+					    objfile, cu_header))
 		    {
 		      lowpc = min (lowpc, low);
 		      highpc = max (highpc, high);
@@ -1675,7 +1689,8 @@ read_func_scope (struct die_info *die, s
 
   /* Ignore functions with missing or empty names and functions with
      missing or invalid low and high pc attributes.  */
-  if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+  if (name == NULL
+      || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
     return;
 
   lowpc += baseaddr;
@@ -1742,7 +1757,11 @@ read_lexical_block_scope (struct die_inf
   struct die_info *child_die;
 
   /* Ignore blocks with missing or invalid low and high pc attributes.  */
-  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+  /* ??? Perhaps consider discontiguous blocks defined by DW_AT_ranges
+     as multiple lexical blocks?  Handling children in a sane way would
+     be nasty.  Might be easier to properly extend generic blocks to 
+     describe ranges.  */
+  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
     return;
   lowpc += baseaddr;
   highpc += baseaddr;
@@ -1767,28 +1786,117 @@ read_lexical_block_scope (struct die_inf
   local_symbols = new->locals;
 }
 
-/* Get low and high pc attributes from a die.
-   Return 1 if the attributes are present and valid, otherwise, return 0.  */
+/* 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.  */
 
 static int
-dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
-		      struct objfile *objfile)
+dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
+		      CORE_ADDR *highpc, struct objfile *objfile,
+		      const struct comp_unit_head *cu_header)
 {
+  bfd *obfd = objfile->obfd;
   struct attribute *attr;
   CORE_ADDR low;
   CORE_ADDR high;
+  int ret;
 
-  attr = dwarf_attr (die, DW_AT_low_pc);
-  if (attr)
-    low = DW_ADDR (attr);
-  else
-    return 0;
   attr = dwarf_attr (die, DW_AT_high_pc);
   if (attr)
-    high = DW_ADDR (attr);
-  else
-    return 0;
+    {
+      high = DW_ADDR (attr);
+      attr = dwarf_attr (die, DW_AT_low_pc);
+      if (attr)
+	low = DW_ADDR (attr);
+      else
+	return 0;
+      ret = 1;
+    }
+  else if ((attr = dwarf_attr (die, DW_AT_ranges)) != NULL)
+    {
+      unsigned int addr_size = cu_header->addr_size;
+      CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
+      unsigned int offset = DW_UNSND (attr);
+      CORE_ADDR base;
+      int dummy;
+      unsigned int i;
+      char *buffer;
 
+      /* The applicable base address is determined by (1) the closest
+         preceding base address selection entry in the range list or
+	 (2) the DW_AT_low_pc of the compilation unit.  */
+      /* ??? We definitely need some sort of indexed data structure here.
+	 At minimum we should recognize the common case of there being
+	 no base address selection entries.  */
+
+      buffer = dwarf_ranges_buffer + offset;
+      for (i = offset; i > 2 * addr_size; )
+	{
+	  CORE_ADDR marker;
+
+	  i -= 2 * addr_size;
+	  buffer -= 2 * addr_size;
+
+	  marker = read_address (obfd, buffer, cu_header, &dummy);
+	  if ((marker & mask) == mask)
+	    {
+	      base = read_address (obfd, buffer+addr_size, cu_header, &dummy);
+	      goto found_base;
+	    }
+	}
+
+      /* ??? Was in dwarf3 draft4, and has since been removed.
+	 GCC still uses it though.  */
+      attr = dwarf_attr (cu_header->die, DW_AT_entry_pc);
+      if (attr)
+	{
+	  base = DW_ADDR (attr);
+	  goto found_base;
+	}
+
+      attr = dwarf_attr (cu_header->die, DW_AT_low_pc);
+      if (attr)
+	{
+	  base = DW_ADDR (attr);
+	  goto found_base;
+	}
+
+      /* We have no valid base address for the ranges data.  */
+      return 0;
+
+    found_base:
+      buffer = dwarf_ranges_buffer + offset;
+      low = read_address (obfd, buffer, cu_header, &dummy);
+      buffer += addr_size;
+      high = read_address (obfd, buffer, cu_header, &dummy);
+      buffer += addr_size;
+      if (low == 0 && high == 0)
+	/* If the first entry is an end-of-list marker, the range
+	   describes an empty scope, i.e. no instructions.  */
+	return 0;
+
+      while (1)
+	{
+	  CORE_ADDR b, e;
+	  offset += 2 * addr_size;
+
+	  b = read_address (obfd, buffer, cu_header, &dummy);
+	  buffer += addr_size;
+	  e = read_address (obfd, buffer, cu_header, &dummy);
+	  buffer += addr_size;
+	  if (b == 0 && e == 0)
+	    break;
+	  if (b < low)
+	    low = b;
+	  if (e > high)
+	    high = e;
+	}
+
+      low += base;
+      high += base;
+      ret = -1;
+    }
+
   if (high < low)
     return 0;
 
@@ -1800,12 +1908,12 @@ dwarf2_get_pc_bounds (struct die_info *d
      labels are not in the output, so the relocs get a value of 0.
      If this is a discarded function, mark the pc bounds as invalid,
      so that GDB will ignore it.  */
-  if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
+  if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0)
     return 0;
 
   *lowpc = low;
   *highpc = high;
-  return 1;
+  return ret;
 }
 
 /* Add an aggregate field to the field list.  */


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2001-12-31  0:34 [RFC] Partial support for dwarf3 DW_AT_ranges Richard Henderson
@ 2002-01-04  7:20 ` Daniel Berlin
  2002-01-04  9:13   ` Daniel Jacobowitz
  2002-01-04  9:47 ` Elena Zannoni
  1 sibling, 1 reply; 14+ messages in thread
From: Daniel Berlin @ 2002-01-04  7:20 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gdb-patches

On Mon, 31 Dec 2001, Richard Henderson wrote:

> GCC began emitting DW_AT_ranges back in September to deal with
> lexical scopes made discontiguous by basic block reordering.
> 
> As of today, it may also create discontiguous lexical scopes
> due to scheduling.  (Before today under the same circumstances
> we'd lose track of which instructions belonged to which scope
> and fail to emit any debug information whatsoever.)
> 
> However, GDB doesn't recognize DW_AT_ranges as a valid way of
> marking a lexical scope, which causes it to discard the scope
> entirely.  Which is probably the least useful thing that could
> be done.
> 
> The following does not add proper support for discontiguous
> address ranges.  I couldn't figure out how to do that in any
> way that wasn't horribly invasive.  
Horribly invasive to the dwarf2 reader, or to other pieces of gdb?



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2002-01-04  7:20 ` Daniel Berlin
@ 2002-01-04  9:13   ` Daniel Jacobowitz
  2002-01-04  9:48     ` Richard Henderson
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2002-01-04  9:13 UTC (permalink / raw)
  To: Daniel Berlin; +Cc: Richard Henderson, gdb-patches

On Fri, Jan 04, 2002 at 10:21:04AM -0500, Daniel Berlin wrote:
> On Mon, 31 Dec 2001, Richard Henderson wrote:
> 
> > GCC began emitting DW_AT_ranges back in September to deal with
> > lexical scopes made discontiguous by basic block reordering.
> > 
> > As of today, it may also create discontiguous lexical scopes
> > due to scheduling.  (Before today under the same circumstances
> > we'd lose track of which instructions belonged to which scope
> > and fail to emit any debug information whatsoever.)
> > 
> > However, GDB doesn't recognize DW_AT_ranges as a valid way of
> > marking a lexical scope, which causes it to discard the scope
> > entirely.  Which is probably the least useful thing that could
> > be done.
> > 
> > The following does not add proper support for discontiguous
> > address ranges.  I couldn't figure out how to do that in any
> > way that wasn't horribly invasive.  
> Horribly invasive to the dwarf2 reader, or to other pieces of gdb?

Other places in GDB; the framework isn't there to record it.

-- 
Daniel Jacobowitz                           Carnegie Mellon University
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2001-12-31  0:34 [RFC] Partial support for dwarf3 DW_AT_ranges Richard Henderson
  2002-01-04  7:20 ` Daniel Berlin
@ 2002-01-04  9:47 ` Elena Zannoni
  2003-01-29 15:53   ` Daniel Jacobowitz
  1 sibling, 1 reply; 14+ messages in thread
From: Elena Zannoni @ 2002-01-04  9:47 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gdb-patches

Richard Henderson writes:
 > GCC began emitting DW_AT_ranges back in September to deal with
 > lexical scopes made discontiguous by basic block reordering.
 > 
 > As of today, it may also create discontiguous lexical scopes
 > due to scheduling.  (Before today under the same circumstances
 > we'd lose track of which instructions belonged to which scope
 > and fail to emit any debug information whatsoever.)
 > 

Richard, there was some initial effort to deal with this problem
in gdb's symbol tables structures back in October.
See the thread at:
http://sources.redhat.com/ml/gdb-patches/2001-10/msg00304.html
However, no real changes have been made to the symbol tables yet.

 > However, GDB doesn't recognize DW_AT_ranges as a valid way of
 > marking a lexical scope, which causes it to discard the scope
 > entirely.  Which is probably the least useful thing that could
 > be done.
 > 
 > The following does not add proper support for discontiguous
 > address ranges.  I couldn't figure out how to do that in any
 > way that wasn't horribly invasive.  I'm willing to expend a
 > significant amount of effort on this if someone is willing to
 > provide some direction.
 > 

The thread mentioned above has some initial implementation of an
address set for partial symbol tables which would be used in case of
non contiguous addr ranges. You should coordinate with Jim.

 > What this does do is find the "bounding box" of the discontiguous
 > range and use that.  Yes, that will do the wrong thing in some
 > circumstances, but the current behaviour is wrong under all
 > circumstances, so it may be a net improvement.
 > 

I am OK with committing some initial support. At least now gdb can
read the info. 

I have a few comments on your changes.  Maybe I am missing it, but is
the -1 value returned by dwarf2_get_pc_bounds used anywhere yet? If
not, I would suggest we don't bother with it right now, given that the
final solution will probably have to restructure that function again.
Also, I would not want to introduce more goto's in gdb. I think that
that sequence can be rewritten w/o goto's pretty easily.  Also there
is some formatting problem (white spaces around operators, full names
for variables).  Adding some comments on how the .debug_ranges list is
organized would be helpful too.

I think JimB is the one which has the last say on this however, since
he has a patch in the works.

thanks 
Elena


 > My test case for this was
 > 
 > 	static int foo(int *);
 > 	static void bar(int *);
 > 
 > 	int main()
 > 	{
 > 	  {
 > 	    int x = 0, r;
 > 	    r = foo(&x);
 > 	    if (__builtin_expect (r, 1))
 > 	      return 0;
 > 	    bar (&x);
 > 	    return 1;
 > 	  }
 > 	}
 > 
 > 	static int foo(int *p)
 > 	{
 > 	  *p = 1;
 > 	  return 0;
 > 	}
 > 
 > 	static void bar(int *p)
 > 	{
 > 	  *p = 2;
 > 	}
 > 
 > For any GCC target that can emit epilogues as rtl, we will
 > arrange the code here as
 > 
 > 	x = 0
 > 	call foo
 > 	if r == 0 goto L1
 > 	ret = 0
 >     L0:
 > 	return ret
 >     L1:
 > 	call bar
 > 	ret = 1
 > 	goto L0
 > 
 > The lexical scope created by the extra set of braces doesn't
 > cover the epilogue, so the scope's range is the block before
 > L0, plus the block after L1.
 > 
 > 
 > r~

 > -/* Get low and high pc attributes from a die.
 > -   Return 1 if the attributes are present and valid, otherwise, return 0.  */
 > +/* 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.  */
 >  
 >  static int
 > -dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
 > -		      struct objfile *objfile)
 > +dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
 > +		      CORE_ADDR *highpc, struct objfile *objfile,
 > +		      const struct comp_unit_head *cu_header)
 >  {
 > +  bfd *obfd = objfile->obfd;
 >    struct attribute *attr;
 >    CORE_ADDR low;
 >    CORE_ADDR high;
 > +  int ret;
 >  
 > -  attr = dwarf_attr (die, DW_AT_low_pc);
 > -  if (attr)
 > -    low = DW_ADDR (attr);
 > -  else
 > -    return 0;
 >    attr = dwarf_attr (die, DW_AT_high_pc);
 >    if (attr)
 > -    high = DW_ADDR (attr);
 > -  else
 > -    return 0;
 > +    {
 > +      high = DW_ADDR (attr);
 > +      attr = dwarf_attr (die, DW_AT_low_pc);
 > +      if (attr)
 > +	low = DW_ADDR (attr);
 > +      else
 > +	return 0;
 > +      ret = 1;
 > +    }
 > +  else if ((attr = dwarf_attr (die, DW_AT_ranges)) != NULL)
 > +    {
 > +      unsigned int addr_size = cu_header->addr_size;
 > +      CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
 > +      unsigned int offset = DW_UNSND (attr);
 > +      CORE_ADDR base;
 > +      int dummy;
 > +      unsigned int i;
 > +      char *buffer;
 >  
 > +      /* The applicable base address is determined by (1) the closest
 > +         preceding base address selection entry in the range list or
 > +	 (2) the DW_AT_low_pc of the compilation unit.  */
 > +      /* ??? We definitely need some sort of indexed data structure here.
 > +	 At minimum we should recognize the common case of there being
 > +	 no base address selection entries.  */
 > +
 > +      buffer = dwarf_ranges_buffer + offset;
 > +      for (i = offset; i > 2 * addr_size; )
 > +	{
 > +	  CORE_ADDR marker;
 > +
 > +	  i -= 2 * addr_size;
 > +	  buffer -= 2 * addr_size;
 > +
 > +	  marker = read_address (obfd, buffer, cu_header, &dummy);
 > +	  if ((marker & mask) == mask)
 > +	    {
 > +	      base = read_address (obfd, buffer+addr_size, cu_header, &dummy);
 > +	      goto found_base;
 > +	    }
 > +	}
 > +
 > +      /* ??? Was in dwarf3 draft4, and has since been removed.
 > +	 GCC still uses it though.  */
 > +      attr = dwarf_attr (cu_header->die, DW_AT_entry_pc);
 > +      if (attr)
 > +	{
 > +	  base = DW_ADDR (attr);
 > +	  goto found_base;
 > +	}
 > +
 > +      attr = dwarf_attr (cu_header->die, DW_AT_low_pc);
 > +      if (attr)
 > +	{
 > +	  base = DW_ADDR (attr);
 > +	  goto found_base;
 > +	}
 > +
 > +      /* We have no valid base address for the ranges data.  */
 > +      return 0;
 > +
 > +    found_base:
 > +      buffer = dwarf_ranges_buffer + offset;
 > +      low = read_address (obfd, buffer, cu_header, &dummy);
 > +      buffer += addr_size;
 > +      high = read_address (obfd, buffer, cu_header, &dummy);
 > +      buffer += addr_size;
 > +      if (low == 0 && high == 0)
 > +	/* If the first entry is an end-of-list marker, the range
 > +	   describes an empty scope, i.e. no instructions.  */
 > +	return 0;
 > +
 > +      while (1)
 > +	{
 > +	  CORE_ADDR b, e;
 > +	  offset += 2 * addr_size;
 > +
 > +	  b = read_address (obfd, buffer, cu_header, &dummy);
 > +	  buffer += addr_size;
 > +	  e = read_address (obfd, buffer, cu_header, &dummy);
 > +	  buffer += addr_size;
 > +	  if (b == 0 && e == 0)
 > +	    break;
 > +	  if (b < low)
 > +	    low = b;
 > +	  if (e > high)
 > +	    high = e;
 > +	}
 > +
 > +      low += base;
 > +      high += base;
 > +      ret = -1;
 > +    }
 > +
 >    if (high < low)
 >      return 0;
 >  
 > @@ -1800,12 +1908,12 @@ dwarf2_get_pc_bounds (struct die_info *d
 >       labels are not in the output, so the relocs get a value of 0.
 >       If this is a discarded function, mark the pc bounds as invalid,
 >       so that GDB will ignore it.  */
 > -  if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
 > +  if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0)
 >      return 0;
 >  
 >    *lowpc = low;
 >    *highpc = high;
 > -  return 1;
 > +  return ret;
 >  }
 >  
 >  /* Add an aggregate field to the field list.  */


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2002-01-04  9:13   ` Daniel Jacobowitz
@ 2002-01-04  9:48     ` Richard Henderson
  0 siblings, 0 replies; 14+ messages in thread
From: Richard Henderson @ 2002-01-04  9:48 UTC (permalink / raw)
  To: Daniel Berlin, gdb-patches

On Fri, Jan 04, 2002 at 12:13:22PM -0500, Daniel Jacobowitz wrote:
> Other places in GDB; the framework isn't there to record it.

Indeed.


r~


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2002-01-04  9:47 ` Elena Zannoni
@ 2003-01-29 15:53   ` Daniel Jacobowitz
  2003-01-29 18:09     ` Elena Zannoni
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2003-01-29 15:53 UTC (permalink / raw)
  To: Elena Zannoni, Jim Blandy; +Cc: Richard Henderson, gdb-patches

On Fri, Jan 04, 2002 at 12:00:07PM -0500, Elena Zannoni wrote:
> Richard Henderson writes:
>  > GCC began emitting DW_AT_ranges back in September to deal with
>  > lexical scopes made discontiguous by basic block reordering.
>  > 
>  > As of today, it may also create discontiguous lexical scopes
>  > due to scheduling.  (Before today under the same circumstances
>  > we'd lose track of which instructions belonged to which scope
>  > and fail to emit any debug information whatsoever.)
>  > 
> 
> Richard, there was some initial effort to deal with this problem
> in gdb's symbol tables structures back in October.
> See the thread at:
> http://sources.redhat.com/ml/gdb-patches/2001-10/msg00304.html
> However, no real changes have been made to the symbol tables yet.
> 
>  > However, GDB doesn't recognize DW_AT_ranges as a valid way of
>  > marking a lexical scope, which causes it to discard the scope
>  > entirely.  Which is probably the least useful thing that could
>  > be done.
>  > 
>  > The following does not add proper support for discontiguous
>  > address ranges.  I couldn't figure out how to do that in any
>  > way that wasn't horribly invasive.  I'm willing to expend a
>  > significant amount of effort on this if someone is willing to
>  > provide some direction.
>  > 
> 
> The thread mentioned above has some initial implementation of an
> address set for partial symbol tables which would be used in case of
> non contiguous addr ranges. You should coordinate with Jim.
> 
>  > What this does do is find the "bounding box" of the discontiguous
>  > range and use that.  Yes, that will do the wrong thing in some
>  > circumstances, but the current behaviour is wrong under all
>  > circumstances, so it may be a net improvement.
>  > 
> 
> I am OK with committing some initial support. At least now gdb can
> read the info. 
> 
> I have a few comments on your changes.  Maybe I am missing it, but is
> the -1 value returned by dwarf2_get_pc_bounds used anywhere yet? If
> not, I would suggest we don't bother with it right now, given that the
> final solution will probably have to restructure that function again.
> Also, I would not want to introduce more goto's in gdb. I think that
> that sequence can be rewritten w/o goto's pretty easily.  Also there
> is some formatting problem (white spaces around operators, full names
> for variables).  Adding some comments on how the .debug_ranges list is
> organized would be helpful too.
> 
> I think JimB is the one which has the last say on this however, since
> he has a patch in the works.
> 

Ping out there, folks.

This lack of support for DW_AT_ranges is responsible for at least one,
probably two or more of the current PRs about "missing local
variables".  Affected GCC versions have been shipping for some time; at
least 3.2 generates DW_AT_ranges, maybe earlier.

Since nothing ever came of the grand plans to support ranges in the
symbol table directly, can we at least move forwards on this year-old
patch?  If so, I'll update it for current GDB.

> thanks 
> Elena
> 
> 
>  > My test case for this was
>  > 
>  > 	static int foo(int *);
>  > 	static void bar(int *);
>  > 
>  > 	int main()
>  > 	{
>  > 	  {
>  > 	    int x = 0, r;
>  > 	    r = foo(&x);
>  > 	    if (__builtin_expect (r, 1))
>  > 	      return 0;
>  > 	    bar (&x);
>  > 	    return 1;
>  > 	  }
>  > 	}
>  > 
>  > 	static int foo(int *p)
>  > 	{
>  > 	  *p = 1;
>  > 	  return 0;
>  > 	}
>  > 
>  > 	static void bar(int *p)
>  > 	{
>  > 	  *p = 2;
>  > 	}
>  > 
>  > For any GCC target that can emit epilogues as rtl, we will
>  > arrange the code here as
>  > 
>  > 	x = 0
>  > 	call foo
>  > 	if r == 0 goto L1
>  > 	ret = 0
>  >     L0:
>  > 	return ret
>  >     L1:
>  > 	call bar
>  > 	ret = 1
>  > 	goto L0
>  > 
>  > The lexical scope created by the extra set of braces doesn't
>  > cover the epilogue, so the scope's range is the block before
>  > L0, plus the block after L1.
>  > 
>  > 
>  > r~
> 
>  > -/* Get low and high pc attributes from a die.
>  > -   Return 1 if the attributes are present and valid, otherwise, return 0.  */
>  > +/* 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.  */
>  >  
>  >  static int
>  > -dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
>  > -		      struct objfile *objfile)
>  > +dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
>  > +		      CORE_ADDR *highpc, struct objfile *objfile,
>  > +		      const struct comp_unit_head *cu_header)
>  >  {
>  > +  bfd *obfd = objfile->obfd;
>  >    struct attribute *attr;
>  >    CORE_ADDR low;
>  >    CORE_ADDR high;
>  > +  int ret;
>  >  
>  > -  attr = dwarf_attr (die, DW_AT_low_pc);
>  > -  if (attr)
>  > -    low = DW_ADDR (attr);
>  > -  else
>  > -    return 0;
>  >    attr = dwarf_attr (die, DW_AT_high_pc);
>  >    if (attr)
>  > -    high = DW_ADDR (attr);
>  > -  else
>  > -    return 0;
>  > +    {
>  > +      high = DW_ADDR (attr);
>  > +      attr = dwarf_attr (die, DW_AT_low_pc);
>  > +      if (attr)
>  > +	low = DW_ADDR (attr);
>  > +      else
>  > +	return 0;
>  > +      ret = 1;
>  > +    }
>  > +  else if ((attr = dwarf_attr (die, DW_AT_ranges)) != NULL)
>  > +    {
>  > +      unsigned int addr_size = cu_header->addr_size;
>  > +      CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
>  > +      unsigned int offset = DW_UNSND (attr);
>  > +      CORE_ADDR base;
>  > +      int dummy;
>  > +      unsigned int i;
>  > +      char *buffer;
>  >  
>  > +      /* The applicable base address is determined by (1) the closest
>  > +         preceding base address selection entry in the range list or
>  > +	 (2) the DW_AT_low_pc of the compilation unit.  */
>  > +      /* ??? We definitely need some sort of indexed data structure here.
>  > +	 At minimum we should recognize the common case of there being
>  > +	 no base address selection entries.  */
>  > +
>  > +      buffer = dwarf_ranges_buffer + offset;
>  > +      for (i = offset; i > 2 * addr_size; )
>  > +	{
>  > +	  CORE_ADDR marker;
>  > +
>  > +	  i -= 2 * addr_size;
>  > +	  buffer -= 2 * addr_size;
>  > +
>  > +	  marker = read_address (obfd, buffer, cu_header, &dummy);
>  > +	  if ((marker & mask) == mask)
>  > +	    {
>  > +	      base = read_address (obfd, buffer+addr_size, cu_header, &dummy);
>  > +	      goto found_base;
>  > +	    }
>  > +	}
>  > +
>  > +      /* ??? Was in dwarf3 draft4, and has since been removed.
>  > +	 GCC still uses it though.  */
>  > +      attr = dwarf_attr (cu_header->die, DW_AT_entry_pc);
>  > +      if (attr)
>  > +	{
>  > +	  base = DW_ADDR (attr);
>  > +	  goto found_base;
>  > +	}
>  > +
>  > +      attr = dwarf_attr (cu_header->die, DW_AT_low_pc);
>  > +      if (attr)
>  > +	{
>  > +	  base = DW_ADDR (attr);
>  > +	  goto found_base;
>  > +	}
>  > +
>  > +      /* We have no valid base address for the ranges data.  */
>  > +      return 0;
>  > +
>  > +    found_base:
>  > +      buffer = dwarf_ranges_buffer + offset;
>  > +      low = read_address (obfd, buffer, cu_header, &dummy);
>  > +      buffer += addr_size;
>  > +      high = read_address (obfd, buffer, cu_header, &dummy);
>  > +      buffer += addr_size;
>  > +      if (low == 0 && high == 0)
>  > +	/* If the first entry is an end-of-list marker, the range
>  > +	   describes an empty scope, i.e. no instructions.  */
>  > +	return 0;
>  > +
>  > +      while (1)
>  > +	{
>  > +	  CORE_ADDR b, e;
>  > +	  offset += 2 * addr_size;
>  > +
>  > +	  b = read_address (obfd, buffer, cu_header, &dummy);
>  > +	  buffer += addr_size;
>  > +	  e = read_address (obfd, buffer, cu_header, &dummy);
>  > +	  buffer += addr_size;
>  > +	  if (b == 0 && e == 0)
>  > +	    break;
>  > +	  if (b < low)
>  > +	    low = b;
>  > +	  if (e > high)
>  > +	    high = e;
>  > +	}
>  > +
>  > +      low += base;
>  > +      high += base;
>  > +      ret = -1;
>  > +    }
>  > +
>  >    if (high < low)
>  >      return 0;
>  >  
>  > @@ -1800,12 +1908,12 @@ dwarf2_get_pc_bounds (struct die_info *d
>  >       labels are not in the output, so the relocs get a value of 0.
>  >       If this is a discarded function, mark the pc bounds as invalid,
>  >       so that GDB will ignore it.  */
>  > -  if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
>  > +  if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0)
>  >      return 0;
>  >  
>  >    *lowpc = low;
>  >    *highpc = high;
>  > -  return 1;
>  > +  return ret;
>  >  }
>  >  
>  >  /* Add an aggregate field to the field list.  */
> 

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2003-01-29 15:53   ` Daniel Jacobowitz
@ 2003-01-29 18:09     ` Elena Zannoni
  2003-01-29 21:27       ` Daniel Jacobowitz
  2003-01-30  0:51       ` Daniel Jacobowitz
  0 siblings, 2 replies; 14+ messages in thread
From: Elena Zannoni @ 2003-01-29 18:09 UTC (permalink / raw)
  To: Daniel Jacobowitz
  Cc: Elena Zannoni, Jim Blandy, Richard Henderson, gdb-patches

Daniel Jacobowitz writes:
 > On Fri, Jan 04, 2002 at 12:00:07PM -0500, Elena Zannoni wrote:
 > > Richard Henderson writes:
 > >  > GCC began emitting DW_AT_ranges back in September to deal with
 > >  > lexical scopes made discontiguous by basic block reordering.
 > >  > 
 > >  > As of today, it may also create discontiguous lexical scopes
 > >  > due to scheduling.  (Before today under the same circumstances
 > >  > we'd lose track of which instructions belonged to which scope
 > >  > and fail to emit any debug information whatsoever.)
 > >  > 
 > > 
 > > Richard, there was some initial effort to deal with this problem
 > > in gdb's symbol tables structures back in October.
 > > See the thread at:
 > > http://sources.redhat.com/ml/gdb-patches/2001-10/msg00304.html
 > > However, no real changes have been made to the symbol tables yet.
 > > 
 > >  > However, GDB doesn't recognize DW_AT_ranges as a valid way of
 > >  > marking a lexical scope, which causes it to discard the scope
 > >  > entirely.  Which is probably the least useful thing that could
 > >  > be done.
 > >  > 
 > >  > The following does not add proper support for discontiguous
 > >  > address ranges.  I couldn't figure out how to do that in any
 > >  > way that wasn't horribly invasive.  I'm willing to expend a
 > >  > significant amount of effort on this if someone is willing to
 > >  > provide some direction.
 > >  > 
 > > 
 > > The thread mentioned above has some initial implementation of an
 > > address set for partial symbol tables which would be used in case of
 > > non contiguous addr ranges. You should coordinate with Jim.
 > > 
 > >  > What this does do is find the "bounding box" of the discontiguous
 > >  > range and use that.  Yes, that will do the wrong thing in some
 > >  > circumstances, but the current behaviour is wrong under all
 > >  > circumstances, so it may be a net improvement.
 > >  > 
 > > 
 > > I am OK with committing some initial support. At least now gdb can
 > > read the info. 
 > > 
 > > I have a few comments on your changes.  Maybe I am missing it, but is
 > > the -1 value returned by dwarf2_get_pc_bounds used anywhere yet? If
 > > not, I would suggest we don't bother with it right now, given that the
 > > final solution will probably have to restructure that function again.
 > > Also, I would not want to introduce more goto's in gdb. I think that
 > > that sequence can be rewritten w/o goto's pretty easily.  Also there
 > > is some formatting problem (white spaces around operators, full names
 > > for variables).  Adding some comments on how the .debug_ranges list is
 > > organized would be helpful too.
 > > 
 > > I think JimB is the one which has the last say on this however, since
 > > he has a patch in the works.
 > > 
 > 
 > Ping out there, folks.
 > 
 > This lack of support for DW_AT_ranges is responsible for at least one,
 > probably two or more of the current PRs about "missing local
 > variables".  Affected GCC versions have been shipping for some time; at
 > least 3.2 generates DW_AT_ranges, maybe earlier.

Yes, I am looking at this patch at the moment, too. The lack of this
feature is creating lots of troubles. 

 > 
 > Since nothing ever came of the grand plans to support ranges in the
 > symbol table directly, can we at least move forwards on this year-old
 > patch?  If so, I'll update it for current GDB.
 > 

If you have time, I'd appreciate it. I have adapted the patch to the
current sources, but even with it, I wasn't able to make Jakub's
example work.  The example is in PR 833.
I can send you the diffs I have, if it helps.


Elena


 > > thanks 
 > > Elena
 > > 
 > > 
 > >  > My test case for this was
 > >  > 
 > >  > 	static int foo(int *);
 > >  > 	static void bar(int *);
 > >  > 
 > >  > 	int main()
 > >  > 	{
 > >  > 	  {
 > >  > 	    int x = 0, r;
 > >  > 	    r = foo(&x);
 > >  > 	    if (__builtin_expect (r, 1))
 > >  > 	      return 0;
 > >  > 	    bar (&x);
 > >  > 	    return 1;
 > >  > 	  }
 > >  > 	}
 > >  > 
 > >  > 	static int foo(int *p)
 > >  > 	{
 > >  > 	  *p = 1;
 > >  > 	  return 0;
 > >  > 	}
 > >  > 
 > >  > 	static void bar(int *p)
 > >  > 	{
 > >  > 	  *p = 2;
 > >  > 	}
 > >  > 
 > >  > For any GCC target that can emit epilogues as rtl, we will
 > >  > arrange the code here as
 > >  > 
 > >  > 	x = 0
 > >  > 	call foo
 > >  > 	if r == 0 goto L1
 > >  > 	ret = 0
 > >  >     L0:
 > >  > 	return ret
 > >  >     L1:
 > >  > 	call bar
 > >  > 	ret = 1
 > >  > 	goto L0
 > >  > 
 > >  > The lexical scope created by the extra set of braces doesn't
 > >  > cover the epilogue, so the scope's range is the block before
 > >  > L0, plus the block after L1.
 > >  > 
 > >  > 
 > >  > r~
 > > 
 > >  > -/* Get low and high pc attributes from a die.
 > >  > -   Return 1 if the attributes are present and valid, otherwise, return 0.  */
 > >  > +/* 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.  */
 > >  >  
 > >  >  static int
 > >  > -dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
 > >  > -		      struct objfile *objfile)
 > >  > +dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
 > >  > +		      CORE_ADDR *highpc, struct objfile *objfile,
 > >  > +		      const struct comp_unit_head *cu_header)
 > >  >  {
 > >  > +  bfd *obfd = objfile->obfd;
 > >  >    struct attribute *attr;
 > >  >    CORE_ADDR low;
 > >  >    CORE_ADDR high;
 > >  > +  int ret;
 > >  >  
 > >  > -  attr = dwarf_attr (die, DW_AT_low_pc);
 > >  > -  if (attr)
 > >  > -    low = DW_ADDR (attr);
 > >  > -  else
 > >  > -    return 0;
 > >  >    attr = dwarf_attr (die, DW_AT_high_pc);
 > >  >    if (attr)
 > >  > -    high = DW_ADDR (attr);
 > >  > -  else
 > >  > -    return 0;
 > >  > +    {
 > >  > +      high = DW_ADDR (attr);
 > >  > +      attr = dwarf_attr (die, DW_AT_low_pc);
 > >  > +      if (attr)
 > >  > +	low = DW_ADDR (attr);
 > >  > +      else
 > >  > +	return 0;
 > >  > +      ret = 1;
 > >  > +    }
 > >  > +  else if ((attr = dwarf_attr (die, DW_AT_ranges)) != NULL)
 > >  > +    {
 > >  > +      unsigned int addr_size = cu_header->addr_size;
 > >  > +      CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
 > >  > +      unsigned int offset = DW_UNSND (attr);
 > >  > +      CORE_ADDR base;
 > >  > +      int dummy;
 > >  > +      unsigned int i;
 > >  > +      char *buffer;
 > >  >  
 > >  > +      /* The applicable base address is determined by (1) the closest
 > >  > +         preceding base address selection entry in the range list or
 > >  > +	 (2) the DW_AT_low_pc of the compilation unit.  */
 > >  > +      /* ??? We definitely need some sort of indexed data structure here.
 > >  > +	 At minimum we should recognize the common case of there being
 > >  > +	 no base address selection entries.  */
 > >  > +
 > >  > +      buffer = dwarf_ranges_buffer + offset;
 > >  > +      for (i = offset; i > 2 * addr_size; )
 > >  > +	{
 > >  > +	  CORE_ADDR marker;
 > >  > +
 > >  > +	  i -= 2 * addr_size;
 > >  > +	  buffer -= 2 * addr_size;
 > >  > +
 > >  > +	  marker = read_address (obfd, buffer, cu_header, &dummy);
 > >  > +	  if ((marker & mask) == mask)
 > >  > +	    {
 > >  > +	      base = read_address (obfd, buffer+addr_size, cu_header, &dummy);
 > >  > +	      goto found_base;
 > >  > +	    }
 > >  > +	}
 > >  > +
 > >  > +      /* ??? Was in dwarf3 draft4, and has since been removed.
 > >  > +	 GCC still uses it though.  */
 > >  > +      attr = dwarf_attr (cu_header->die, DW_AT_entry_pc);
 > >  > +      if (attr)
 > >  > +	{
 > >  > +	  base = DW_ADDR (attr);
 > >  > +	  goto found_base;
 > >  > +	}
 > >  > +
 > >  > +      attr = dwarf_attr (cu_header->die, DW_AT_low_pc);
 > >  > +      if (attr)
 > >  > +	{
 > >  > +	  base = DW_ADDR (attr);
 > >  > +	  goto found_base;
 > >  > +	}
 > >  > +
 > >  > +      /* We have no valid base address for the ranges data.  */
 > >  > +      return 0;
 > >  > +
 > >  > +    found_base:
 > >  > +      buffer = dwarf_ranges_buffer + offset;
 > >  > +      low = read_address (obfd, buffer, cu_header, &dummy);
 > >  > +      buffer += addr_size;
 > >  > +      high = read_address (obfd, buffer, cu_header, &dummy);
 > >  > +      buffer += addr_size;
 > >  > +      if (low == 0 && high == 0)
 > >  > +	/* If the first entry is an end-of-list marker, the range
 > >  > +	   describes an empty scope, i.e. no instructions.  */
 > >  > +	return 0;
 > >  > +
 > >  > +      while (1)
 > >  > +	{
 > >  > +	  CORE_ADDR b, e;
 > >  > +	  offset += 2 * addr_size;
 > >  > +
 > >  > +	  b = read_address (obfd, buffer, cu_header, &dummy);
 > >  > +	  buffer += addr_size;
 > >  > +	  e = read_address (obfd, buffer, cu_header, &dummy);
 > >  > +	  buffer += addr_size;
 > >  > +	  if (b == 0 && e == 0)
 > >  > +	    break;
 > >  > +	  if (b < low)
 > >  > +	    low = b;
 > >  > +	  if (e > high)
 > >  > +	    high = e;
 > >  > +	}
 > >  > +
 > >  > +      low += base;
 > >  > +      high += base;
 > >  > +      ret = -1;
 > >  > +    }
 > >  > +
 > >  >    if (high < low)
 > >  >      return 0;
 > >  >  
 > >  > @@ -1800,12 +1908,12 @@ dwarf2_get_pc_bounds (struct die_info *d
 > >  >       labels are not in the output, so the relocs get a value of 0.
 > >  >       If this is a discarded function, mark the pc bounds as invalid,
 > >  >       so that GDB will ignore it.  */
 > >  > -  if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
 > >  > +  if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0)
 > >  >      return 0;
 > >  >  
 > >  >    *lowpc = low;
 > >  >    *highpc = high;
 > >  > -  return 1;
 > >  > +  return ret;
 > >  >  }
 > >  >  
 > >  >  /* Add an aggregate field to the field list.  */
 > > 
 > 
 > -- 
 > Daniel Jacobowitz
 > MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2003-01-29 18:09     ` Elena Zannoni
@ 2003-01-29 21:27       ` Daniel Jacobowitz
  2003-01-29 22:44         ` Daniel Jacobowitz
  2003-01-30  0:51       ` Daniel Jacobowitz
  1 sibling, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2003-01-29 21:27 UTC (permalink / raw)
  To: Elena Zannoni; +Cc: Jim Blandy, Richard Henderson, gdb-patches

On Wed, Jan 29, 2003 at 01:13:36PM -0500, Elena Zannoni wrote:
> Daniel Jacobowitz writes:
>  > On Fri, Jan 04, 2002 at 12:00:07PM -0500, Elena Zannoni wrote:
>  > > Richard Henderson writes:
>  > >  > GCC began emitting DW_AT_ranges back in September to deal with
>  > >  > lexical scopes made discontiguous by basic block reordering.
>  > >  > 
>  > >  > As of today, it may also create discontiguous lexical scopes
>  > >  > due to scheduling.  (Before today under the same circumstances
>  > >  > we'd lose track of which instructions belonged to which scope
>  > >  > and fail to emit any debug information whatsoever.)
>  > >  > 
>  > > 
>  > > Richard, there was some initial effort to deal with this problem
>  > > in gdb's symbol tables structures back in October.
>  > > See the thread at:
>  > > http://sources.redhat.com/ml/gdb-patches/2001-10/msg00304.html
>  > > However, no real changes have been made to the symbol tables yet.
>  > > 
>  > >  > However, GDB doesn't recognize DW_AT_ranges as a valid way of
>  > >  > marking a lexical scope, which causes it to discard the scope
>  > >  > entirely.  Which is probably the least useful thing that could
>  > >  > be done.
>  > >  > 
>  > >  > The following does not add proper support for discontiguous
>  > >  > address ranges.  I couldn't figure out how to do that in any
>  > >  > way that wasn't horribly invasive.  I'm willing to expend a
>  > >  > significant amount of effort on this if someone is willing to
>  > >  > provide some direction.
>  > >  > 
>  > > 
>  > > The thread mentioned above has some initial implementation of an
>  > > address set for partial symbol tables which would be used in case of
>  > > non contiguous addr ranges. You should coordinate with Jim.
>  > > 
>  > >  > What this does do is find the "bounding box" of the discontiguous
>  > >  > range and use that.  Yes, that will do the wrong thing in some
>  > >  > circumstances, but the current behaviour is wrong under all
>  > >  > circumstances, so it may be a net improvement.
>  > >  > 
>  > > 
>  > > I am OK with committing some initial support. At least now gdb can
>  > > read the info. 
>  > > 
>  > > I have a few comments on your changes.  Maybe I am missing it, but is
>  > > the -1 value returned by dwarf2_get_pc_bounds used anywhere yet? If
>  > > not, I would suggest we don't bother with it right now, given that the
>  > > final solution will probably have to restructure that function again.
>  > > Also, I would not want to introduce more goto's in gdb. I think that
>  > > that sequence can be rewritten w/o goto's pretty easily.  Also there
>  > > is some formatting problem (white spaces around operators, full names
>  > > for variables).  Adding some comments on how the .debug_ranges list is
>  > > organized would be helpful too.
>  > > 
>  > > I think JimB is the one which has the last say on this however, since
>  > > he has a patch in the works.
>  > > 
>  > 
>  > Ping out there, folks.
>  > 
>  > This lack of support for DW_AT_ranges is responsible for at least one,
>  > probably two or more of the current PRs about "missing local
>  > variables".  Affected GCC versions have been shipping for some time; at
>  > least 3.2 generates DW_AT_ranges, maybe earlier.
> 
> Yes, I am looking at this patch at the moment, too. The lack of this
> feature is creating lots of troubles. 
> 
>  > 
>  > Since nothing ever came of the grand plans to support ranges in the
>  > symbol table directly, can we at least move forwards on this year-old
>  > patch?  If so, I'll update it for current GDB.
>  > 
> 
> If you have time, I'd appreciate it. I have adapted the patch to the
> current sources, but even with it, I wasn't able to make Jakub's
> example work.  The example is in PR 833.
> I can send you the diffs I have, if it helps.

I'm going to go look at the GCC code that generates these, and the
current standard...  It looks like the meaning has changed since GCC
started using them.  Or else GCC broke at some point.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2003-01-29 21:27       ` Daniel Jacobowitz
@ 2003-01-29 22:44         ` Daniel Jacobowitz
  2003-02-04 14:59           ` Elena Zannoni
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2003-01-29 22:44 UTC (permalink / raw)
  To: Elena Zannoni, Jim Blandy, Richard Henderson, gdb-patches

On Wed, Jan 29, 2003 at 04:27:57PM -0500, Daniel Jacobowitz wrote:
> On Wed, Jan 29, 2003 at 01:13:36PM -0500, Elena Zannoni wrote:
> > Daniel Jacobowitz writes:
> >  > On Fri, Jan 04, 2002 at 12:00:07PM -0500, Elena Zannoni wrote:
> >  > > Richard Henderson writes:
> >  > >  > GCC began emitting DW_AT_ranges back in September to deal with
> >  > >  > lexical scopes made discontiguous by basic block reordering.
> >  > >  > 
> >  > >  > As of today, it may also create discontiguous lexical scopes
> >  > >  > due to scheduling.  (Before today under the same circumstances
> >  > >  > we'd lose track of which instructions belonged to which scope
> >  > >  > and fail to emit any debug information whatsoever.)
> >  > >  > 
> >  > > 
> >  > > Richard, there was some initial effort to deal with this problem
> >  > > in gdb's symbol tables structures back in October.
> >  > > See the thread at:
> >  > > http://sources.redhat.com/ml/gdb-patches/2001-10/msg00304.html
> >  > > However, no real changes have been made to the symbol tables yet.
> >  > > 
> >  > >  > However, GDB doesn't recognize DW_AT_ranges as a valid way of
> >  > >  > marking a lexical scope, which causes it to discard the scope
> >  > >  > entirely.  Which is probably the least useful thing that could
> >  > >  > be done.
> >  > >  > 
> >  > >  > The following does not add proper support for discontiguous
> >  > >  > address ranges.  I couldn't figure out how to do that in any
> >  > >  > way that wasn't horribly invasive.  I'm willing to expend a
> >  > >  > significant amount of effort on this if someone is willing to
> >  > >  > provide some direction.
> >  > >  > 
> >  > > 
> >  > > The thread mentioned above has some initial implementation of an
> >  > > address set for partial symbol tables which would be used in case of
> >  > > non contiguous addr ranges. You should coordinate with Jim.
> >  > > 
> >  > >  > What this does do is find the "bounding box" of the discontiguous
> >  > >  > range and use that.  Yes, that will do the wrong thing in some
> >  > >  > circumstances, but the current behaviour is wrong under all
> >  > >  > circumstances, so it may be a net improvement.
> >  > >  > 
> >  > > 
> >  > > I am OK with committing some initial support. At least now gdb can
> >  > > read the info. 
> >  > > 
> >  > > I have a few comments on your changes.  Maybe I am missing it, but is
> >  > > the -1 value returned by dwarf2_get_pc_bounds used anywhere yet? If
> >  > > not, I would suggest we don't bother with it right now, given that the
> >  > > final solution will probably have to restructure that function again.
> >  > > Also, I would not want to introduce more goto's in gdb. I think that
> >  > > that sequence can be rewritten w/o goto's pretty easily.  Also there
> >  > > is some formatting problem (white spaces around operators, full names
> >  > > for variables).  Adding some comments on how the .debug_ranges list is
> >  > > organized would be helpful too.
> >  > > 
> >  > > I think JimB is the one which has the last say on this however, since
> >  > > he has a patch in the works.
> >  > > 
> >  > 
> >  > Ping out there, folks.
> >  > 
> >  > This lack of support for DW_AT_ranges is responsible for at least one,
> >  > probably two or more of the current PRs about "missing local
> >  > variables".  Affected GCC versions have been shipping for some time; at
> >  > least 3.2 generates DW_AT_ranges, maybe earlier.
> > 
> > Yes, I am looking at this patch at the moment, too. The lack of this
> > feature is creating lots of troubles. 
> > 
> >  > 
> >  > Since nothing ever came of the grand plans to support ranges in the
> >  > symbol table directly, can we at least move forwards on this year-old
> >  > patch?  If so, I'll update it for current GDB.
> >  > 
> > 
> > If you have time, I'd appreciate it. I have adapted the patch to the
> > current sources, but even with it, I wasn't able to make Jakub's
> > example work.  The example is in PR 833.
> > I can send you the diffs I have, if it helps.
> 
> I'm going to go look at the GCC code that generates these, and the
> current standard...  It looks like the meaning has changed since GCC
> started using them.  Or else GCC broke at some point.

My conclusions from today are:
  - Richard's patch works.  The ugliest bit of it (the linear search
for a base address) is not necessary according to the DWARF-3 standard
(draft 8).  I'll redo the patch without that and post it this evening.
I think that with that revision, the patch should be included.

  - Jakub's testcase reveals some other problems.  Two, in particular:

    - GDB actually needs to be aware of the address ranges to get it
      right; there are interleaved blocks and we're getting the wrong
      one.  We already knew this would happen.  That's one reason the
      test fails.

    - GCC's debug info is wrong.  It outputs a lexical block for the
      large for loop, a nested lexical block for one inner block, and
      a sibling lexical block for another inner block - that is, the
      block is actually inside the for loop, and the debug info claims
      it is lexically outside the loop.  Presumably an optimizer
      somewhere is eating it.  This happens to be the block GDB decides
      we're in, which is why we lose.  That's the other reason.


-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2003-01-29 18:09     ` Elena Zannoni
  2003-01-29 21:27       ` Daniel Jacobowitz
@ 2003-01-30  0:51       ` Daniel Jacobowitz
  2003-01-30  1:02         ` Elena Zannoni
  1 sibling, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2003-01-30  0:51 UTC (permalink / raw)
  To: Elena Zannoni; +Cc: Jim Blandy, Richard Henderson, gdb-patches

On Wed, Jan 29, 2003 at 01:13:36PM -0500, Elena Zannoni wrote:
> If you have time, I'd appreciate it. I have adapted the patch to the
> current sources, but even with it, I wasn't able to make Jakub's
> example work.  The example is in PR 833.
> I can send you the diffs I have, if it helps.

This is pretty similar to what you sent me, cleaned up a little to
match my reading of the standard.  It works to fix my testcase for PR
gdb/961, which is a simpler case of disappearing local variables. 
I'll submit that for the testsuite separately but I don't know quite
how to do it yet; the problem is not going to show up if you don't have
optimization.

This doesn't solve PR gdb/833, for the reasons outlined in my previous
message.

How does this patch look?

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2003-01-29  Richard Henderson  <rth@redhat.com>
	    Elena Zannoni  <ezannoni@redhat.com>
	    Daniel Jacobowitz  <drow@mvista.com>

	Fix PR gdb/961.
	* dwarf2read.c 	(dwarf_ranges_offset, dwarf_ranges_size): New
	variables.
	(RANGES_SECTION): New.
	(dwarf_ranges_buffer): New variable.
	(struct comp_unit_head): Add member "die".
	(struct dwarf2_pinfo): Add dwarf_ranges_buffer, dwarf_ranges_size.
	(DWARF_RANGES_BUFFER, DWARF_RANGES_SIZE): New.
	(dwarf2_has_info): Init dwarf_ranges_offset and dwarf_ranges_size.
	(dwarf2_locate_sections): Likewise.
	(dwarf2_build_psymtabs): Read .debug_ranges.
	(dwarf2_build_psymtabs_hard): Swap dwarf_ranges out.
	(psymtab_to_symtab_1): Swap dwarf_ranges in.  Set cu_header.die.
	(RANGES_SECTION): New.
	(dwarf2_get_pc_bounds): New cu_header argument; adjust all callers.
	Look for DW_AT_ranges and return the bounding box.

Index: dwarf2read.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2read.c,v
retrieving revision 1.79
diff -u -p -r1.79 dwarf2read.c
--- dwarf2read.c	18 Jan 2003 15:55:51 -0000	1.79
+++ dwarf2read.c	30 Jan 2003 00:41:19 -0000
@@ -133,6 +133,7 @@ static file_ptr dwarf_aranges_offset;
 static file_ptr dwarf_loc_offset;
 static file_ptr dwarf_macinfo_offset;
 static file_ptr dwarf_str_offset;
+static file_ptr dwarf_ranges_offset;
 file_ptr dwarf_frame_offset;
 file_ptr dwarf_eh_frame_offset;
 
@@ -144,6 +145,7 @@ static unsigned int dwarf_aranges_size;
 static unsigned int dwarf_loc_size;
 static unsigned int dwarf_macinfo_size;
 static unsigned int dwarf_str_size;
+static unsigned int dwarf_ranges_size;
 unsigned int dwarf_frame_size;
 unsigned int dwarf_eh_frame_size;
 
@@ -157,6 +159,7 @@ unsigned int dwarf_eh_frame_size;
 #define LOC_SECTION      ".debug_loc"
 #define MACINFO_SECTION  ".debug_macinfo"
 #define STR_SECTION      ".debug_str"
+#define RANGES_SECTION   ".debug_ranges"
 #define FRAME_SECTION    ".debug_frame"
 #define EH_FRAME_SECTION ".eh_frame"
 
@@ -202,6 +205,10 @@ struct comp_unit_head
     /* DWARF abbreviation table associated with this compilation unit */
 
     struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
+
+    /* Pointer to the DIE associated with the compilation unit.  */
+
+    struct die_info *die;
   };
 
 /* The line number information for a compilation unit (found in the
@@ -373,6 +380,7 @@ static char *dwarf_abbrev_buffer;
 static char *dwarf_line_buffer;
 static char *dwarf_str_buffer;
 static char *dwarf_macinfo_buffer;
+static char *dwarf_ranges_buffer;
 
 /* A zeroed version of a partial die for initialization purposes.  */
 static struct partial_die_info zeroed_partial_die;
@@ -481,6 +489,14 @@ struct dwarf2_pinfo
     
     unsigned int dwarf_macinfo_size;
 
+    /* Pointer to start of dwarf ranges buffer for the objfile.  */
+
+    char *dwarf_ranges_buffer;
+
+    /* Size of dwarf ranges buffer for the objfile.  */
+
+    unsigned int dwarf_ranges_size;
+
   };
 
 #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
@@ -494,6 +510,8 @@ struct dwarf2_pinfo
 #define DWARF_STR_SIZE(p)    (PST_PRIVATE(p)->dwarf_str_size)
 #define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer)
 #define DWARF_MACINFO_SIZE(p)   (PST_PRIVATE(p)->dwarf_macinfo_size)
+#define DWARF_RANGES_BUFFER(p)  (PST_PRIVATE(p)->dwarf_ranges_buffer)
+#define DWARF_RANGES_SIZE(p)    (PST_PRIVATE(p)->dwarf_ranges_size)
 
 /* Maintain an array of referenced fundamental types for the current
    compilation unit being read.  For DWARF version 1, we have to construct
@@ -751,7 +769,8 @@ static void read_lexical_block_scope (st
 				      const struct comp_unit_head *);
 
 static int dwarf2_get_pc_bounds (struct die_info *,
-				 CORE_ADDR *, CORE_ADDR *, struct objfile *);
+				 CORE_ADDR *, CORE_ADDR *, struct objfile *,
+				 const struct comp_unit_head *);
 
 static void dwarf2_add_field (struct field_info *, struct die_info *,
 			      struct objfile *, const struct comp_unit_head *);
@@ -886,6 +905,8 @@ dwarf2_has_info (bfd *abfd)
   dwarf_macinfo_offset = 0;
   dwarf_frame_offset = 0;
   dwarf_eh_frame_offset = 0;
+  dwarf_ranges_offset = 0;
+  
   bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
   if (dwarf_info_offset && dwarf_abbrev_offset)
     {
@@ -954,6 +975,11 @@ dwarf2_locate_sections (bfd *ignore_abfd
       dwarf_eh_frame_offset = sectp->filepos;
       dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
     }
+  else if (STREQ (sectp->name, RANGES_SECTION))
+    {
+      dwarf_ranges_offset = sectp->filepos;
+      dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp);
+    }
 }
 
 /* Build a partial symbol table.  */
@@ -992,6 +1018,13 @@ dwarf2_build_psymtabs (struct objfile *o
   else
     dwarf_macinfo_buffer = NULL;
 
+  if (dwarf_ranges_offset)
+    dwarf_ranges_buffer = dwarf2_read_section (objfile,
+					       dwarf_ranges_offset,
+					       dwarf_ranges_size);
+  else
+    dwarf_ranges_buffer = NULL;
+
   if (mainline
       || (objfile->global_psymbols.size == 0
 	  && objfile->static_psymbols.size == 0))
@@ -1207,6 +1240,8 @@ dwarf2_build_psymtabs_hard (struct objfi
       DWARF_STR_SIZE (pst) = dwarf_str_size;
       DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer;
       DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size;
+      DWARF_RANGES_BUFFER (pst) = dwarf_ranges_buffer;
+      DWARF_RANGES_SIZE (pst) = dwarf_ranges_size;
       baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
       /* Store the function that reads in the rest of the symbol table */
@@ -1543,6 +1578,8 @@ psymtab_to_symtab_1 (struct partial_symt
   dwarf_str_size = DWARF_STR_SIZE (pst);
   dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst);
   dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst);
+  dwarf_ranges_buffer = DWARF_RANGES_BUFFER (pst);
+  dwarf_ranges_size = DWARF_RANGES_SIZE (pst);
   baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
   cu_header_offset = offset;
   info_ptr = dwarf_info_buffer + offset;
@@ -1565,9 +1602,10 @@ psymtab_to_symtab_1 (struct partial_symt
   make_cleanup_free_die_list (dies);
 
   /* Do line number decoding in read_file_scope () */
+  cu_header.die = dies;
   process_die (dies, objfile, &cu_header);
 
-  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
+  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header))
     {
       /* Some compilers don't define a DW_AT_high_pc attribute for
          the compilation unit.   If the DW_AT_high_pc is missing,
@@ -1582,7 +1620,8 @@ psymtab_to_symtab_1 (struct partial_symt
 		{
 		  CORE_ADDR low, high;
 
-		  if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+		  if (dwarf2_get_pc_bounds (child_die, &low, &high,
+					    objfile, &cu_header))
 		    {
 		      highpc = max (highpc, high);
 		    }
@@ -1711,7 +1750,7 @@ read_file_scope (struct die_info *die, s
   bfd *abfd = objfile->obfd;
   struct line_header *line_header = 0;
 
-  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
     {
       if (die->has_children)
 	{
@@ -1722,7 +1761,8 @@ read_file_scope (struct die_info *die, s
 		{
 		  CORE_ADDR low, high;
 
-		  if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+		  if (dwarf2_get_pc_bounds (child_die, &low, &high,
+					    objfile, cu_header))
 		    {
 		      lowpc = min (lowpc, low);
 		      highpc = max (highpc, high);
@@ -1868,7 +1908,7 @@ read_func_scope (struct die_info *die, s
 
   /* Ignore functions with missing or empty names and functions with
      missing or invalid low and high pc attributes.  */
-  if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+  if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
     return;
 
   lowpc += baseaddr;
@@ -1966,7 +2006,11 @@ read_lexical_block_scope (struct die_inf
   struct die_info *child_die;
 
   /* Ignore blocks with missing or invalid low and high pc attributes.  */
-  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+  /* ??? Perhaps consider discontiguous blocks defined by DW_AT_ranges
+     as multiple lexical blocks?  Handling children in a sane way would
+     be nasty.  Might be easier to properly extend generic blocks to 
+     describe ranges.  */
+  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
     return;
   lowpc += baseaddr;
   highpc += baseaddr;
@@ -1991,27 +2035,159 @@ read_lexical_block_scope (struct die_inf
   local_symbols = new->locals;
 }
 
-/* Get low and high pc attributes from a die.
-   Return 1 if the attributes are present and valid, otherwise, return 0.  */
-
+/* 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.  */
 static int
-dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
-		      struct objfile *objfile)
+dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
+		      CORE_ADDR *highpc, struct objfile *objfile,
+		      const struct comp_unit_head *cu_header)
 {
   struct attribute *attr;
-  CORE_ADDR low;
-  CORE_ADDR high;
+  bfd *obfd = objfile->obfd;
+  CORE_ADDR low = 0;
+  CORE_ADDR high = 0;
+  int ret = 0;
 
-  attr = dwarf_attr (die, DW_AT_low_pc);
-  if (attr)
-    low = DW_ADDR (attr);
-  else
-    return 0;
   attr = dwarf_attr (die, DW_AT_high_pc);
   if (attr)
-    high = DW_ADDR (attr);
+    {
+      high = DW_ADDR (attr);
+      attr = dwarf_attr (die, DW_AT_low_pc);
+      if (attr)
+	low = DW_ADDR (attr);
+      else
+	/* Found high w/o low attribute.  */
+	return 0;
+
+      /* Found consecutive range of addresses.  */
+      ret = 1;
+    }
   else
-    return 0;
+    {
+      attr = dwarf_attr (die, DW_AT_ranges);
+      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_renges section.  */
+	  unsigned int offset = DW_UNSND (attr);
+	  /* Base address selection entry.  */
+	  CORE_ADDR base = 0;
+	  int found_base = 0;
+	  int dummy;
+	  unsigned int i;
+	  char *buffer;
+	  CORE_ADDR marker;
+	  int low_set;
+ 
+	  /* The applicable base address is determined by (1) the closest
+	     preceding base address selection entry in the range list or
+	     (2) the DW_AT_low_pc of the compilation unit.  */
+
+	  /* ??? Was in dwarf3 draft4, and has since been removed.
+	     GCC still uses it though.  */
+	  attr = dwarf_attr (cu_header->die, DW_AT_entry_pc);
+	  if (attr)
+	    {
+	      base = DW_ADDR (attr);
+	      found_base = 1;
+	    }
+
+	  if (!found_base)
+	    {
+	      attr = dwarf_attr (cu_header->die, DW_AT_low_pc);
+	      if (attr)
+		{
+		  base = DW_ADDR (attr);
+		  found_base = 1;
+		}
+	    }
+
+	  buffer = dwarf_ranges_buffer + offset;
+
+
+	  /* Read in the largest possible address.  */
+	  marker = read_address (obfd, buffer, cu_header, &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_header, &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_header, &dummy);
+	      buffer += addr_size;
+	      range_end = read_address (obfd, buffer, cu_header, &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_header, &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;
+		}
+
+	      /* 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;
+
+	  ret = -1;
+	}
+    }
 
   if (high < low)
     return 0;
@@ -2024,12 +2200,12 @@ dwarf2_get_pc_bounds (struct die_info *d
      labels are not in the output, so the relocs get a value of 0.
      If this is a discarded function, mark the pc bounds as invalid,
      so that GDB will ignore it.  */
-  if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
+  if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0)
     return 0;
 
   *lowpc = low;
   *highpc = high;
-  return 1;
+  return ret;
 }
 
 /* Add an aggregate field to the field list.  */


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2003-01-30  0:51       ` Daniel Jacobowitz
@ 2003-01-30  1:02         ` Elena Zannoni
  2003-01-30  1:52           ` Daniel Jacobowitz
  0 siblings, 1 reply; 14+ messages in thread
From: Elena Zannoni @ 2003-01-30  1:02 UTC (permalink / raw)
  To: Daniel Jacobowitz
  Cc: Elena Zannoni, Jim Blandy, Richard Henderson, gdb-patches

Daniel Jacobowitz writes:
 > On Wed, Jan 29, 2003 at 01:13:36PM -0500, Elena Zannoni wrote:
 > > If you have time, I'd appreciate it. I have adapted the patch to the
 > > current sources, but even with it, I wasn't able to make Jakub's
 > > example work.  The example is in PR 833.
 > > I can send you the diffs I have, if it helps.
 > 
 > This is pretty similar to what you sent me, cleaned up a little to
 > match my reading of the standard.  It works to fix my testcase for PR
 > gdb/961, which is a simpler case of disappearing local variables. 
 > I'll submit that for the testsuite separately but I don't know quite
 > how to do it yet; the problem is not going to show up if you don't have
 > optimization.
 > 

cool! i think there is a testcase in gdb.base somewhere that turns
optimization up to -O2, so you could copy that (mips-pro.exp and
break.exp), if this is what you are asking.

 > This doesn't solve PR gdb/833, for the reasons outlined in my previous
 > message.
 > 
 > How does this patch look?
 > 

ok with me.

thanks!!

elena


 > -- 
 > Daniel Jacobowitz
 > MontaVista Software                         Debian GNU/Linux Developer
 > 
 > 2003-01-29  Richard Henderson  <rth@redhat.com>
 > 	    Elena Zannoni  <ezannoni@redhat.com>
 > 	    Daniel Jacobowitz  <drow@mvista.com>
 > 
 > 	Fix PR gdb/961.
 > 	* dwarf2read.c 	(dwarf_ranges_offset, dwarf_ranges_size): New
 > 	variables.
 > 	(RANGES_SECTION): New.
 > 	(dwarf_ranges_buffer): New variable.
 > 	(struct comp_unit_head): Add member "die".
 > 	(struct dwarf2_pinfo): Add dwarf_ranges_buffer, dwarf_ranges_size.
 > 	(DWARF_RANGES_BUFFER, DWARF_RANGES_SIZE): New.
 > 	(dwarf2_has_info): Init dwarf_ranges_offset and dwarf_ranges_size.
 > 	(dwarf2_locate_sections): Likewise.
 > 	(dwarf2_build_psymtabs): Read .debug_ranges.
 > 	(dwarf2_build_psymtabs_hard): Swap dwarf_ranges out.
 > 	(psymtab_to_symtab_1): Swap dwarf_ranges in.  Set cu_header.die.
 > 	(RANGES_SECTION): New.

twice mentioned

 > 	(dwarf2_get_pc_bounds): New cu_header argument; adjust all callers.
 > 	Look for DW_AT_ranges and return the bounding box.
 > 
 > Index: dwarf2read.c
 > ===================================================================
 > RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2read.c,v
 > retrieving revision 1.79
 > diff -u -p -r1.79 dwarf2read.c
 > --- dwarf2read.c	18 Jan 2003 15:55:51 -0000	1.79
 > +++ dwarf2read.c	30 Jan 2003 00:41:19 -0000
 > @@ -133,6 +133,7 @@ static file_ptr dwarf_aranges_offset;
 >  static file_ptr dwarf_loc_offset;
 >  static file_ptr dwarf_macinfo_offset;
 >  static file_ptr dwarf_str_offset;
 > +static file_ptr dwarf_ranges_offset;
 >  file_ptr dwarf_frame_offset;
 >  file_ptr dwarf_eh_frame_offset;
 >  
 > @@ -144,6 +145,7 @@ static unsigned int dwarf_aranges_size;
 >  static unsigned int dwarf_loc_size;
 >  static unsigned int dwarf_macinfo_size;
 >  static unsigned int dwarf_str_size;
 > +static unsigned int dwarf_ranges_size;
 >  unsigned int dwarf_frame_size;
 >  unsigned int dwarf_eh_frame_size;
 >  
 > @@ -157,6 +159,7 @@ unsigned int dwarf_eh_frame_size;
 >  #define LOC_SECTION      ".debug_loc"
 >  #define MACINFO_SECTION  ".debug_macinfo"
 >  #define STR_SECTION      ".debug_str"
 > +#define RANGES_SECTION   ".debug_ranges"
 >  #define FRAME_SECTION    ".debug_frame"
 >  #define EH_FRAME_SECTION ".eh_frame"
 >  
 > @@ -202,6 +205,10 @@ struct comp_unit_head
 >      /* DWARF abbreviation table associated with this compilation unit */
 >  
 >      struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
 > +
 > +    /* Pointer to the DIE associated with the compilation unit.  */
 > +
 > +    struct die_info *die;
 >    };
 >  
 >  /* The line number information for a compilation unit (found in the
 > @@ -373,6 +380,7 @@ static char *dwarf_abbrev_buffer;
 >  static char *dwarf_line_buffer;
 >  static char *dwarf_str_buffer;
 >  static char *dwarf_macinfo_buffer;
 > +static char *dwarf_ranges_buffer;
 >  
 >  /* A zeroed version of a partial die for initialization purposes.  */
 >  static struct partial_die_info zeroed_partial_die;
 > @@ -481,6 +489,14 @@ struct dwarf2_pinfo
 >      
 >      unsigned int dwarf_macinfo_size;
 >  
 > +    /* Pointer to start of dwarf ranges buffer for the objfile.  */
 > +
 > +    char *dwarf_ranges_buffer;
 > +
 > +    /* Size of dwarf ranges buffer for the objfile.  */
 > +
 > +    unsigned int dwarf_ranges_size;
 > +
 >    };
 >  
 >  #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
 > @@ -494,6 +510,8 @@ struct dwarf2_pinfo
 >  #define DWARF_STR_SIZE(p)    (PST_PRIVATE(p)->dwarf_str_size)
 >  #define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer)
 >  #define DWARF_MACINFO_SIZE(p)   (PST_PRIVATE(p)->dwarf_macinfo_size)
 > +#define DWARF_RANGES_BUFFER(p)  (PST_PRIVATE(p)->dwarf_ranges_buffer)
 > +#define DWARF_RANGES_SIZE(p)    (PST_PRIVATE(p)->dwarf_ranges_size)
 >  
 >  /* Maintain an array of referenced fundamental types for the current
 >     compilation unit being read.  For DWARF version 1, we have to construct
 > @@ -751,7 +769,8 @@ static void read_lexical_block_scope (st
 >  				      const struct comp_unit_head *);
 >  
 >  static int dwarf2_get_pc_bounds (struct die_info *,
 > -				 CORE_ADDR *, CORE_ADDR *, struct objfile *);
 > +				 CORE_ADDR *, CORE_ADDR *, struct objfile *,
 > +				 const struct comp_unit_head *);
 >  
 >  static void dwarf2_add_field (struct field_info *, struct die_info *,
 >  			      struct objfile *, const struct comp_unit_head *);
 > @@ -886,6 +905,8 @@ dwarf2_has_info (bfd *abfd)
 >    dwarf_macinfo_offset = 0;
 >    dwarf_frame_offset = 0;
 >    dwarf_eh_frame_offset = 0;
 > +  dwarf_ranges_offset = 0;
 > +  
 >    bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
 >    if (dwarf_info_offset && dwarf_abbrev_offset)
 >      {
 > @@ -954,6 +975,11 @@ dwarf2_locate_sections (bfd *ignore_abfd
 >        dwarf_eh_frame_offset = sectp->filepos;
 >        dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
 >      }
 > +  else if (STREQ (sectp->name, RANGES_SECTION))
 > +    {
 > +      dwarf_ranges_offset = sectp->filepos;
 > +      dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp);
 > +    }
 >  }
 >  
 >  /* Build a partial symbol table.  */
 > @@ -992,6 +1018,13 @@ dwarf2_build_psymtabs (struct objfile *o
 >    else
 >      dwarf_macinfo_buffer = NULL;
 >  
 > +  if (dwarf_ranges_offset)
 > +    dwarf_ranges_buffer = dwarf2_read_section (objfile,
 > +					       dwarf_ranges_offset,
 > +					       dwarf_ranges_size);
 > +  else
 > +    dwarf_ranges_buffer = NULL;
 > +
 >    if (mainline
 >        || (objfile->global_psymbols.size == 0
 >  	  && objfile->static_psymbols.size == 0))
 > @@ -1207,6 +1240,8 @@ dwarf2_build_psymtabs_hard (struct objfi
 >        DWARF_STR_SIZE (pst) = dwarf_str_size;
 >        DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer;
 >        DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size;
 > +      DWARF_RANGES_BUFFER (pst) = dwarf_ranges_buffer;
 > +      DWARF_RANGES_SIZE (pst) = dwarf_ranges_size;
 >        baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 >  
 >        /* Store the function that reads in the rest of the symbol table */
 > @@ -1543,6 +1578,8 @@ psymtab_to_symtab_1 (struct partial_symt
 >    dwarf_str_size = DWARF_STR_SIZE (pst);
 >    dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst);
 >    dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst);
 > +  dwarf_ranges_buffer = DWARF_RANGES_BUFFER (pst);
 > +  dwarf_ranges_size = DWARF_RANGES_SIZE (pst);
 >    baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
 >    cu_header_offset = offset;
 >    info_ptr = dwarf_info_buffer + offset;
 > @@ -1565,9 +1602,10 @@ psymtab_to_symtab_1 (struct partial_symt
 >    make_cleanup_free_die_list (dies);
 >  
 >    /* Do line number decoding in read_file_scope () */
 > +  cu_header.die = dies;
 >    process_die (dies, objfile, &cu_header);
 >  
 > -  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
 > +  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header))
 >      {
 >        /* Some compilers don't define a DW_AT_high_pc attribute for
 >           the compilation unit.   If the DW_AT_high_pc is missing,
 > @@ -1582,7 +1620,8 @@ psymtab_to_symtab_1 (struct partial_symt
 >  		{
 >  		  CORE_ADDR low, high;
 >  
 > -		  if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
 > +		  if (dwarf2_get_pc_bounds (child_die, &low, &high,
 > +					    objfile, &cu_header))
 >  		    {
 >  		      highpc = max (highpc, high);
 >  		    }
 > @@ -1711,7 +1750,7 @@ read_file_scope (struct die_info *die, s
 >    bfd *abfd = objfile->obfd;
 >    struct line_header *line_header = 0;
 >  
 > -  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
 > +  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
 >      {
 >        if (die->has_children)
 >  	{
 > @@ -1722,7 +1761,8 @@ read_file_scope (struct die_info *die, s
 >  		{
 >  		  CORE_ADDR low, high;
 >  
 > -		  if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
 > +		  if (dwarf2_get_pc_bounds (child_die, &low, &high,
 > +					    objfile, cu_header))
 >  		    {
 >  		      lowpc = min (lowpc, low);
 >  		      highpc = max (highpc, high);
 > @@ -1868,7 +1908,7 @@ read_func_scope (struct die_info *die, s
 >  
 >    /* Ignore functions with missing or empty names and functions with
 >       missing or invalid low and high pc attributes.  */
 > -  if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
 > +  if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
 >      return;
 >  
 >    lowpc += baseaddr;
 > @@ -1966,7 +2006,11 @@ read_lexical_block_scope (struct die_inf
 >    struct die_info *child_die;
 >  
 >    /* Ignore blocks with missing or invalid low and high pc attributes.  */
 > -  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
 > +  /* ??? Perhaps consider discontiguous blocks defined by DW_AT_ranges
 > +     as multiple lexical blocks?  Handling children in a sane way would
 > +     be nasty.  Might be easier to properly extend generic blocks to 
 > +     describe ranges.  */
 > +  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
 >      return;
 >    lowpc += baseaddr;
 >    highpc += baseaddr;
 > @@ -1991,27 +2035,159 @@ read_lexical_block_scope (struct die_inf
 >    local_symbols = new->locals;
 >  }
 >  
 > -/* Get low and high pc attributes from a die.
 > -   Return 1 if the attributes are present and valid, otherwise, return 0.  */
 > -
 > +/* 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.  */
 >  static int
 > -dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
 > -		      struct objfile *objfile)
 > +dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
 > +		      CORE_ADDR *highpc, struct objfile *objfile,
 > +		      const struct comp_unit_head *cu_header)
 >  {
 >    struct attribute *attr;
 > -  CORE_ADDR low;
 > -  CORE_ADDR high;
 > +  bfd *obfd = objfile->obfd;
 > +  CORE_ADDR low = 0;
 > +  CORE_ADDR high = 0;
 > +  int ret = 0;
 >  
 > -  attr = dwarf_attr (die, DW_AT_low_pc);
 > -  if (attr)
 > -    low = DW_ADDR (attr);
 > -  else
 > -    return 0;
 >    attr = dwarf_attr (die, DW_AT_high_pc);
 >    if (attr)
 > -    high = DW_ADDR (attr);
 > +    {
 > +      high = DW_ADDR (attr);
 > +      attr = dwarf_attr (die, DW_AT_low_pc);
 > +      if (attr)
 > +	low = DW_ADDR (attr);
 > +      else
 > +	/* Found high w/o low attribute.  */
 > +	return 0;
 > +
 > +      /* Found consecutive range of addresses.  */
 > +      ret = 1;
 > +    }
 >    else
 > -    return 0;
 > +    {
 > +      attr = dwarf_attr (die, DW_AT_ranges);
 > +      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_renges section.  */
 > +	  unsigned int offset = DW_UNSND (attr);
 > +	  /* Base address selection entry.  */
 > +	  CORE_ADDR base = 0;
 > +	  int found_base = 0;
 > +	  int dummy;
 > +	  unsigned int i;
 > +	  char *buffer;
 > +	  CORE_ADDR marker;
 > +	  int low_set;
 > + 
 > +	  /* The applicable base address is determined by (1) the closest
 > +	     preceding base address selection entry in the range list or
 > +	     (2) the DW_AT_low_pc of the compilation unit.  */
 > +
 > +	  /* ??? Was in dwarf3 draft4, and has since been removed.
 > +	     GCC still uses it though.  */
 > +	  attr = dwarf_attr (cu_header->die, DW_AT_entry_pc);
 > +	  if (attr)
 > +	    {
 > +	      base = DW_ADDR (attr);
 > +	      found_base = 1;
 > +	    }
 > +
 > +	  if (!found_base)
 > +	    {
 > +	      attr = dwarf_attr (cu_header->die, DW_AT_low_pc);
 > +	      if (attr)
 > +		{
 > +		  base = DW_ADDR (attr);
 > +		  found_base = 1;
 > +		}
 > +	    }
 > +
 > +	  buffer = dwarf_ranges_buffer + offset;
 > +
 > +
 > +	  /* Read in the largest possible address.  */
 > +	  marker = read_address (obfd, buffer, cu_header, &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_header, &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_header, &dummy);
 > +	      buffer += addr_size;
 > +	      range_end = read_address (obfd, buffer, cu_header, &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_header, &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;
 > +		}
 > +
 > +	      /* 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;
 > +
 > +	  ret = -1;
 > +	}
 > +    }
 >  
 >    if (high < low)
 >      return 0;
 > @@ -2024,12 +2200,12 @@ dwarf2_get_pc_bounds (struct die_info *d
 >       labels are not in the output, so the relocs get a value of 0.
 >       If this is a discarded function, mark the pc bounds as invalid,
 >       so that GDB will ignore it.  */
 > -  if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
 > +  if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0)
 >      return 0;
 >  
 >    *lowpc = low;
 >    *highpc = high;
 > -  return 1;
 > +  return ret;
 >  }
 >  
 >  /* Add an aggregate field to the field list.  */


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2003-01-30  1:02         ` Elena Zannoni
@ 2003-01-30  1:52           ` Daniel Jacobowitz
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Jacobowitz @ 2003-01-30  1:52 UTC (permalink / raw)
  To: gdb-patches

On Wed, Jan 29, 2003 at 08:06:45PM -0500, Elena Zannoni wrote:
> Daniel Jacobowitz writes:
>  > On Wed, Jan 29, 2003 at 01:13:36PM -0500, Elena Zannoni wrote:
>  > > If you have time, I'd appreciate it. I have adapted the patch to the
>  > > current sources, but even with it, I wasn't able to make Jakub's
>  > > example work.  The example is in PR 833.
>  > > I can send you the diffs I have, if it helps.
>  > 
>  > This is pretty similar to what you sent me, cleaned up a little to
>  > match my reading of the standard.  It works to fix my testcase for PR
>  > gdb/961, which is a simpler case of disappearing local variables. 
>  > I'll submit that for the testsuite separately but I don't know quite
>  > how to do it yet; the problem is not going to show up if you don't have
>  > optimization.
>  > 
> 
> cool! i think there is a testcase in gdb.base somewhere that turns
> optimization up to -O2, so you could copy that (mips-pro.exp and
> break.exp), if this is what you are asking.
> 
>  > This doesn't solve PR gdb/833, for the reasons outlined in my previous
>  > message.
>  > 
>  > How does this patch look?
>  > 
> 
> ok with me.
> 
> thanks!!

It's checked in.  Onwards - I may try to dig up my notes from the last
discussion about discontiguous address ranges, if I have time.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2003-01-29 22:44         ` Daniel Jacobowitz
@ 2003-02-04 14:59           ` Elena Zannoni
  2003-02-04 15:05             ` Daniel Jacobowitz
  0 siblings, 1 reply; 14+ messages in thread
From: Elena Zannoni @ 2003-02-04 14:59 UTC (permalink / raw)
  To: Daniel Jacobowitz
  Cc: Elena Zannoni, Jim Blandy, Richard Henderson, gdb-patches


Daniel, did you file a gcc bug report for this?

elena


Daniel Jacobowitz writes:
 > On Wed, Jan 29, 2003 at 04:27:57PM -0500, Daniel Jacobowitz wrote:
 > > On Wed, Jan 29, 2003 at 01:13:36PM -0500, Elena Zannoni wrote:
 > > > Daniel Jacobowitz writes:
 > > >  > On Fri, Jan 04, 2002 at 12:00:07PM -0500, Elena Zannoni wrote:
 > > >  > > Richard Henderson writes:
 > > >  > >  > GCC began emitting DW_AT_ranges back in September to deal with
 > > >  > >  > lexical scopes made discontiguous by basic block reordering.
 > > >  > >  > 
 > > >  > >  > As of today, it may also create discontiguous lexical scopes
 > > >  > >  > due to scheduling.  (Before today under the same circumstances
 > > >  > >  > we'd lose track of which instructions belonged to which scope
 > > >  > >  > and fail to emit any debug information whatsoever.)
 > > >  > >  > 
 > > >  > > 
 > > >  > > Richard, there was some initial effort to deal with this problem
 > > >  > > in gdb's symbol tables structures back in October.
 > > >  > > See the thread at:
 > > >  > > http://sources.redhat.com/ml/gdb-patches/2001-10/msg00304.html
 > > >  > > However, no real changes have been made to the symbol tables yet.
 > > >  > > 
 > > >  > >  > However, GDB doesn't recognize DW_AT_ranges as a valid way of
 > > >  > >  > marking a lexical scope, which causes it to discard the scope
 > > >  > >  > entirely.  Which is probably the least useful thing that could
 > > >  > >  > be done.
 > > >  > >  > 
 > > >  > >  > The following does not add proper support for discontiguous
 > > >  > >  > address ranges.  I couldn't figure out how to do that in any
 > > >  > >  > way that wasn't horribly invasive.  I'm willing to expend a
 > > >  > >  > significant amount of effort on this if someone is willing to
 > > >  > >  > provide some direction.
 > > >  > >  > 
 > > >  > > 
 > > >  > > The thread mentioned above has some initial implementation of an
 > > >  > > address set for partial symbol tables which would be used in case of
 > > >  > > non contiguous addr ranges. You should coordinate with Jim.
 > > >  > > 
 > > >  > >  > What this does do is find the "bounding box" of the discontiguous
 > > >  > >  > range and use that.  Yes, that will do the wrong thing in some
 > > >  > >  > circumstances, but the current behaviour is wrong under all
 > > >  > >  > circumstances, so it may be a net improvement.
 > > >  > >  > 
 > > >  > > 
 > > >  > > I am OK with committing some initial support. At least now gdb can
 > > >  > > read the info. 
 > > >  > > 
 > > >  > > I have a few comments on your changes.  Maybe I am missing it, but is
 > > >  > > the -1 value returned by dwarf2_get_pc_bounds used anywhere yet? If
 > > >  > > not, I would suggest we don't bother with it right now, given that the
 > > >  > > final solution will probably have to restructure that function again.
 > > >  > > Also, I would not want to introduce more goto's in gdb. I think that
 > > >  > > that sequence can be rewritten w/o goto's pretty easily.  Also there
 > > >  > > is some formatting problem (white spaces around operators, full names
 > > >  > > for variables).  Adding some comments on how the .debug_ranges list is
 > > >  > > organized would be helpful too.
 > > >  > > 
 > > >  > > I think JimB is the one which has the last say on this however, since
 > > >  > > he has a patch in the works.
 > > >  > > 
 > > >  > 
 > > >  > Ping out there, folks.
 > > >  > 
 > > >  > This lack of support for DW_AT_ranges is responsible for at least one,
 > > >  > probably two or more of the current PRs about "missing local
 > > >  > variables".  Affected GCC versions have been shipping for some time; at
 > > >  > least 3.2 generates DW_AT_ranges, maybe earlier.
 > > > 
 > > > Yes, I am looking at this patch at the moment, too. The lack of this
 > > > feature is creating lots of troubles. 
 > > > 
 > > >  > 
 > > >  > Since nothing ever came of the grand plans to support ranges in the
 > > >  > symbol table directly, can we at least move forwards on this year-old
 > > >  > patch?  If so, I'll update it for current GDB.
 > > >  > 
 > > > 
 > > > If you have time, I'd appreciate it. I have adapted the patch to the
 > > > current sources, but even with it, I wasn't able to make Jakub's
 > > > example work.  The example is in PR 833.
 > > > I can send you the diffs I have, if it helps.
 > > 
 > > I'm going to go look at the GCC code that generates these, and the
 > > current standard...  It looks like the meaning has changed since GCC
 > > started using them.  Or else GCC broke at some point.
 > 
 > My conclusions from today are:
 >   - Richard's patch works.  The ugliest bit of it (the linear search
 > for a base address) is not necessary according to the DWARF-3 standard
 > (draft 8).  I'll redo the patch without that and post it this evening.
 > I think that with that revision, the patch should be included.
 > 
 >   - Jakub's testcase reveals some other problems.  Two, in particular:
 > 
 >     - GDB actually needs to be aware of the address ranges to get it
 >       right; there are interleaved blocks and we're getting the wrong
 >       one.  We already knew this would happen.  That's one reason the
 >       test fails.
 > 
 >     - GCC's debug info is wrong.  It outputs a lexical block for the
 >       large for loop, a nested lexical block for one inner block, and
 >       a sibling lexical block for another inner block - that is, the
 >       block is actually inside the for loop, and the debug info claims
 >       it is lexically outside the loop.  Presumably an optimizer
 >       somewhere is eating it.  This happens to be the block GDB decides
 >       we're in, which is why we lose.  That's the other reason.
 > 
 > 
 > -- 
 > Daniel Jacobowitz
 > MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC] Partial support for dwarf3 DW_AT_ranges
  2003-02-04 14:59           ` Elena Zannoni
@ 2003-02-04 15:05             ` Daniel Jacobowitz
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Jacobowitz @ 2003-02-04 15:05 UTC (permalink / raw)
  To: Elena Zannoni; +Cc: Jim Blandy, Richard Henderson, gdb-patches

On Tue, Feb 04, 2003 at 10:03:53AM -0500, Elena Zannoni wrote:
> 
> Daniel, did you file a gcc bug report for this?

Nope.  I don't know what compiler Jakub was using to build the test he
gave us, other than the fact that it emits DW_AT_ranges.  So I don't
have enough information to know whether there's still a problem.

> 
> elena
> 
> 
> Daniel Jacobowitz writes:
>  > On Wed, Jan 29, 2003 at 04:27:57PM -0500, Daniel Jacobowitz wrote:
>  > > On Wed, Jan 29, 2003 at 01:13:36PM -0500, Elena Zannoni wrote:
>  > > > Daniel Jacobowitz writes:
>  > > >  > On Fri, Jan 04, 2002 at 12:00:07PM -0500, Elena Zannoni wrote:
>  > > >  > > Richard Henderson writes:
>  > > >  > >  > GCC began emitting DW_AT_ranges back in September to deal with
>  > > >  > >  > lexical scopes made discontiguous by basic block reordering.
>  > > >  > >  > 
>  > > >  > >  > As of today, it may also create discontiguous lexical scopes
>  > > >  > >  > due to scheduling.  (Before today under the same circumstances
>  > > >  > >  > we'd lose track of which instructions belonged to which scope
>  > > >  > >  > and fail to emit any debug information whatsoever.)
>  > > >  > >  > 
>  > > >  > > 
>  > > >  > > Richard, there was some initial effort to deal with this problem
>  > > >  > > in gdb's symbol tables structures back in October.
>  > > >  > > See the thread at:
>  > > >  > > http://sources.redhat.com/ml/gdb-patches/2001-10/msg00304.html
>  > > >  > > However, no real changes have been made to the symbol tables yet.
>  > > >  > > 
>  > > >  > >  > However, GDB doesn't recognize DW_AT_ranges as a valid way of
>  > > >  > >  > marking a lexical scope, which causes it to discard the scope
>  > > >  > >  > entirely.  Which is probably the least useful thing that could
>  > > >  > >  > be done.
>  > > >  > >  > 
>  > > >  > >  > The following does not add proper support for discontiguous
>  > > >  > >  > address ranges.  I couldn't figure out how to do that in any
>  > > >  > >  > way that wasn't horribly invasive.  I'm willing to expend a
>  > > >  > >  > significant amount of effort on this if someone is willing to
>  > > >  > >  > provide some direction.
>  > > >  > >  > 
>  > > >  > > 
>  > > >  > > The thread mentioned above has some initial implementation of an
>  > > >  > > address set for partial symbol tables which would be used in case of
>  > > >  > > non contiguous addr ranges. You should coordinate with Jim.
>  > > >  > > 
>  > > >  > >  > What this does do is find the "bounding box" of the discontiguous
>  > > >  > >  > range and use that.  Yes, that will do the wrong thing in some
>  > > >  > >  > circumstances, but the current behaviour is wrong under all
>  > > >  > >  > circumstances, so it may be a net improvement.
>  > > >  > >  > 
>  > > >  > > 
>  > > >  > > I am OK with committing some initial support. At least now gdb can
>  > > >  > > read the info. 
>  > > >  > > 
>  > > >  > > I have a few comments on your changes.  Maybe I am missing it, but is
>  > > >  > > the -1 value returned by dwarf2_get_pc_bounds used anywhere yet? If
>  > > >  > > not, I would suggest we don't bother with it right now, given that the
>  > > >  > > final solution will probably have to restructure that function again.
>  > > >  > > Also, I would not want to introduce more goto's in gdb. I think that
>  > > >  > > that sequence can be rewritten w/o goto's pretty easily.  Also there
>  > > >  > > is some formatting problem (white spaces around operators, full names
>  > > >  > > for variables).  Adding some comments on how the .debug_ranges list is
>  > > >  > > organized would be helpful too.
>  > > >  > > 
>  > > >  > > I think JimB is the one which has the last say on this however, since
>  > > >  > > he has a patch in the works.
>  > > >  > > 
>  > > >  > 
>  > > >  > Ping out there, folks.
>  > > >  > 
>  > > >  > This lack of support for DW_AT_ranges is responsible for at least one,
>  > > >  > probably two or more of the current PRs about "missing local
>  > > >  > variables".  Affected GCC versions have been shipping for some time; at
>  > > >  > least 3.2 generates DW_AT_ranges, maybe earlier.
>  > > > 
>  > > > Yes, I am looking at this patch at the moment, too. The lack of this
>  > > > feature is creating lots of troubles. 
>  > > > 
>  > > >  > 
>  > > >  > Since nothing ever came of the grand plans to support ranges in the
>  > > >  > symbol table directly, can we at least move forwards on this year-old
>  > > >  > patch?  If so, I'll update it for current GDB.
>  > > >  > 
>  > > > 
>  > > > If you have time, I'd appreciate it. I have adapted the patch to the
>  > > > current sources, but even with it, I wasn't able to make Jakub's
>  > > > example work.  The example is in PR 833.
>  > > > I can send you the diffs I have, if it helps.
>  > > 
>  > > I'm going to go look at the GCC code that generates these, and the
>  > > current standard...  It looks like the meaning has changed since GCC
>  > > started using them.  Or else GCC broke at some point.
>  > 
>  > My conclusions from today are:
>  >   - Richard's patch works.  The ugliest bit of it (the linear search
>  > for a base address) is not necessary according to the DWARF-3 standard
>  > (draft 8).  I'll redo the patch without that and post it this evening.
>  > I think that with that revision, the patch should be included.
>  > 
>  >   - Jakub's testcase reveals some other problems.  Two, in particular:
>  > 
>  >     - GDB actually needs to be aware of the address ranges to get it
>  >       right; there are interleaved blocks and we're getting the wrong
>  >       one.  We already knew this would happen.  That's one reason the
>  >       test fails.
>  > 
>  >     - GCC's debug info is wrong.  It outputs a lexical block for the
>  >       large for loop, a nested lexical block for one inner block, and
>  >       a sibling lexical block for another inner block - that is, the
>  >       block is actually inside the for loop, and the debug info claims
>  >       it is lexically outside the loop.  Presumably an optimizer
>  >       somewhere is eating it.  This happens to be the block GDB decides
>  >       we're in, which is why we lose.  That's the other reason.
>  > 
>  > 
>  > -- 
>  > Daniel Jacobowitz
>  > MontaVista Software                         Debian GNU/Linux Developer
> 

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2003-02-04 15:05 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-12-31  0:34 [RFC] Partial support for dwarf3 DW_AT_ranges Richard Henderson
2002-01-04  7:20 ` Daniel Berlin
2002-01-04  9:13   ` Daniel Jacobowitz
2002-01-04  9:48     ` Richard Henderson
2002-01-04  9:47 ` Elena Zannoni
2003-01-29 15:53   ` Daniel Jacobowitz
2003-01-29 18:09     ` Elena Zannoni
2003-01-29 21:27       ` Daniel Jacobowitz
2003-01-29 22:44         ` Daniel Jacobowitz
2003-02-04 14:59           ` Elena Zannoni
2003-02-04 15:05             ` Daniel Jacobowitz
2003-01-30  0:51       ` Daniel Jacobowitz
2003-01-30  1:02         ` Elena Zannoni
2003-01-30  1:52           ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox