This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] Partial support for dwarf3 DW_AT_ranges


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.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]