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]

[RFA] Location list support.


Hi all,
this is a first part of my attempt to enable use of dwarf3 .debug_loc sections (as generated by GCC's rtlopt-branch) for variable tracking.
With this patch GDB at least doesn't segfault as it did when trying to debug a binary with .debug_loc section.
It can already read and parse .debug_loc and then use the appropriate first block found for a given DIE for obtaining the SYMBOL_VALUE() in newsymbol(). So now it behaves exactly like it did with GCCs that didn't emit .debug_loc.
I hope to have a full support (ie. SYMBOL_VALUE that depends on PC) available soon.
This was developped in gdb-5.3 but should be usable with mainline with no problems.

Comments? Approvals?

Michal Ludvig
--
* SuSE CR, s.r.o * mludvig@suse.cz
* (+420) 296.545.373 * http://www.suse.cz
2003-02-01  Michal Ludvig  <mludvig@suse.cz>

	* dwarf2read.c (struct loclist_block)
	(struct loclist_master): New structures.
	(loclist_base, dwarf_loc_buffer): New variables.
	(struct dwarf2_pinfo): New items dwarf_loc_buffer and 
	dwarf_loc_size.
	(DWARF_LOC_BUFFER, DWARF_LOC_SIZE): New macros.
	(dwarf2_read_loclist, dwarf2_read_loclist_blocks)
	(dwarf_alloc_loclist_block, dwarf_alloc_loclist_master)
	(dwarf2_loclist_lookup_block): New functions.
	(psymtab_to_symtab_1): Call dwarf2_read_loclist().
	(new_symbol): Handle .debug_loc references.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.66.2.2
diff -u -p -r1.66.2.2 dwarf2read.c
--- dwarf2read.c	25 Nov 2002 21:46:54 -0000	1.66.2.2
+++ dwarf2read.c	31 Jan 2003 18:10:53 -0000
@@ -312,6 +312,22 @@ struct dwarf_block
     char *data;
   };
 
+struct loclist_block
+  {
+    CORE_ADDR lowpc, highpc;	/* Range where attribute is valid.  */
+    struct dwarf_block blk;
+    struct loclist_block *next;
+  };
+
+struct loclist_master
+  {
+    unsigned int offset;	/* Offset of this block in .debug_loc.  */
+    struct loclist_block *blocks;
+    struct loclist_master *next;
+  };
+
+static struct loclist_master *loclist_base;
+
 /* We only hold one compilation unit's abbrevs in
    memory at any one time.  */
 #ifndef ABBREV_HASH_SIZE
@@ -352,6 +368,7 @@ static char *dwarf_abbrev_buffer;
 static char *dwarf_line_buffer;
 static char *dwarf_str_buffer;
 static char *dwarf_macinfo_buffer;
+static char *dwarf_loc_buffer;
 
 /* A zeroed version of a partial die for initialization purposes.  */
 static struct partial_die_info zeroed_partial_die;
@@ -454,6 +471,13 @@ struct dwarf2_pinfo
     
     unsigned int dwarf_macinfo_size;
 
+    /* Pointer to start of dwarf location list buffer for the objfile.  */
+
+    char *dwarf_loc_buffer;
+
+    /* Size of dwarf location list section for the objfile.  */
+
+    unsigned int dwarf_loc_size;
   };
 
 #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
@@ -467,6 +491,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_LOC_BUFFER(p) (PST_PRIVATE(p)->dwarf_loc_buffer)
+#define DWARF_LOC_SIZE(p)   (PST_PRIVATE(p)->dwarf_loc_size)
 
 /* Maintain an array of referenced fundamental types for the current
    compilation unit being read.  For DWARF version 1, we have to construct
@@ -688,6 +714,8 @@ char *dwarf2_read_section (struct objfil
 
 static void dwarf2_read_abbrevs (bfd *, unsigned int);
 
+static void dwarf2_read_loclist (bfd *abfd, struct comp_unit_head *cu_header);
+
 static void dwarf2_empty_abbrev_table (PTR);
 
 static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int);
@@ -874,12 +902,6 @@ static char *dwarf_bool_name (unsigned i
 
 static char *dwarf_type_encoding_name (unsigned int);
 
-#if 0
-static char *dwarf_cfi_name (unsigned int);
-
-struct die_info *copy_die (struct die_info *);
-#endif
-
 static struct die_info *sibling_die (struct die_info *);
 
 static void dump_die (struct die_info *);
@@ -906,6 +928,9 @@ static struct abbrev_info *dwarf_alloc_a
 
 static struct die_info *dwarf_alloc_die (void);
 
+static struct loclist_block *dwarf_alloc_loclist_block (void);
+static struct loclist_master *dwarf_alloc_loclist_master (void);
+
 static void initialize_cu_func_list (void);
 
 static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR);
@@ -927,6 +952,7 @@ dwarf2_has_info (bfd *abfd)
   dwarf_line_offset = 0;
   dwarf_str_offset = 0;
   dwarf_macinfo_offset = 0;
+  dwarf_loc_offset = 0;
   dwarf_frame_offset = 0;
   dwarf_eh_frame_offset = 0;
   bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
@@ -1035,6 +1061,13 @@ dwarf2_build_psymtabs (struct objfile *o
   else
     dwarf_macinfo_buffer = NULL;
 
+  if (dwarf_loc_offset)
+    dwarf_loc_buffer = dwarf2_read_section (objfile,
+		    			    dwarf_loc_offset,
+					    dwarf_loc_size);
+  else
+    dwarf_loc_buffer = NULL;
+  
   if (mainline
       || (objfile->global_psymbols.size == 0
 	  && objfile->static_psymbols.size == 0))
@@ -1245,6 +1280,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_LOC_BUFFER (pst) = dwarf_loc_buffer;
+      DWARF_LOC_SIZE (pst) = dwarf_loc_size;
       baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
       /* Store the function that reads in the rest of the symbol table */
@@ -1581,6 +1618,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_loc_buffer = DWARF_LOC_BUFFER (pst);
+  dwarf_loc_size = DWARF_LOC_SIZE (pst);
   baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
   cu_header_offset = offset;
   info_ptr = dwarf_info_buffer + offset;
@@ -1598,6 +1637,7 @@ psymtab_to_symtab_1 (struct partial_symt
   dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
   make_cleanup (dwarf2_empty_abbrev_table, NULL);
 
+  dwarf2_read_loclist (abfd, &cu_header);
   dies = read_comp_unit (info_ptr, abfd, &cu_header);
 
   make_cleanup_free_die_list (dies);
@@ -3408,6 +3448,115 @@ dwarf2_read_section (struct objfile *obj
   return buf;
 }
 
+static struct loclist_block *
+dwarf2_loclist_lookup_block (unsigned int offset)
+{
+  /* .debug_loc goes here ... mludvig */
+  struct dwarf_block *blkp;
+  struct loclist_master *ll_ptr;
+
+  ll_ptr = loclist_base;
+  
+  while (ll_ptr && ll_ptr->offset != offset)
+    ll_ptr = ll_ptr->next;
+
+  if(!ll_ptr)
+  {
+    warning ("Couldn't find appropriate location list for offset %u\n",
+		offset);
+    return NULL;
+  }
+  
+  if (ll_ptr && !ll_ptr->blocks)
+  {
+    warning ("Loclist for off=%u doesn't have any blocks?\n", offset);
+    return NULL;
+  }
+  
+  return ll_ptr->blocks;
+}
+
+static struct loclist_block *
+dwarf2_read_loclist_blocks (bfd *abfd, char **base, char *end, 
+		unsigned int addr_size)
+{
+	char *ptr;
+	CORE_ADDR lopc, hipc;
+	unsigned int data_size;
+	char *data_ptr;
+	struct loclist_block *llb_first = NULL, *llb_last = NULL;
+	
+	ptr = *base;
+
+	while (ptr < end) {
+		if (addr_size == 4) {
+			lopc = read_4_bytes (abfd, ptr);
+			ptr += 4;
+			hipc = read_4_bytes (abfd, ptr);
+			ptr += 4;
+		}
+		else if (addr_size == 8) {
+			lopc = read_8_bytes (abfd, ptr);
+			ptr += 8;
+			hipc = read_8_bytes (abfd, ptr);
+			ptr += 8;
+		}
+		else
+			error ("Address size == %d ... unsupported!", addr_size);
+
+		if (lopc == 0 && hipc == 0)
+			break;
+
+		if (lopc == 0 && llb_last != NULL)
+		{
+			ptr -= 8;
+			break;
+		}
+
+		if (llb_last == NULL) {
+			llb_last = dwarf_alloc_loclist_block ();
+			llb_first = llb_last;
+		}
+		else {
+			llb_last->next = dwarf_alloc_loclist_block ();
+			llb_last = llb_last->next;
+		}
+
+		llb_last->lowpc = lopc;
+		llb_last->highpc = hipc;
+
+		llb_last->blk.size = read_2_bytes (abfd, ptr);
+		ptr += 2;
+		llb_last->blk.data = ptr;
+		ptr += llb_last->blk.size;
+	}
+	
+	*base = ptr;
+	return llb_first;
+}
+
+static void 
+dwarf2_read_loclist (bfd *abfd, struct comp_unit_head *cu_header)
+{
+	char *loclist_ptr, *loclist_end;
+	struct loclist_master *ll_master;
+	
+	loclist_ptr = dwarf_loc_buffer;
+	loclist_end = dwarf_loc_buffer + dwarf_loc_size;
+
+	while (loclist_ptr < loclist_end)
+	{
+		ll_master = dwarf_alloc_loclist_master();
+		ll_master->next = loclist_base;
+		loclist_base = ll_master;
+
+		ll_master->offset = loclist_ptr - dwarf_loc_buffer;
+		ll_master->blocks = dwarf2_read_loclist_blocks 
+					(abfd, &loclist_ptr, loclist_end,
+					 cu_header->addr_size);
+	}
+}
+
 /* In DWARF version 2, the description of the debugging information is
    stored in a separate .debug_abbrev section.  Before we read any
    dies from a section we read in all abbreviations and install them
@@ -4785,7 +4942,16 @@ new_symbol (struct die_info *die, struct
                   else if (attr->form == DW_FORM_data4
                            || attr->form == DW_FORM_data8)
                     {
-                      complain (&dwarf2_complex_location_expr);
+		      struct dwarf_block *blkp = NULL;
+		      struct loclist_block *llbp;
+
+		      llbp = dwarf2_loclist_lookup_block (
+				      (unsigned int)DW_ADDR (attr));
+		      if (llbp)
+			blkp = &llbp->blk;
+		      if (blkp)
+		        SYMBOL_VALUE_ADDRESS (sym) =
+		          decode_locdesc (blkp, objfile, cu_header);
                     }
                   else
                     {
@@ -4823,7 +4989,16 @@ new_symbol (struct die_info *die, struct
                   else if (attr->form == DW_FORM_data4
                            || attr->form == DW_FORM_data8)
                     {
-                      complain (&dwarf2_complex_location_expr);
+		      struct dwarf_block *blkp = NULL;
+		      struct loclist_block *llbp;
+
+		      llbp = dwarf2_loclist_lookup_block (
+				      (unsigned int)DW_ADDR (attr));
+		      if (llbp)
+			blkp = &llbp->blk;
+		      if (blkp)
+		        SYMBOL_VALUE_ADDRESS (sym) = addr =
+		          decode_locdesc (blkp, objfile, cu_header);
                     }
                   else
                     {
@@ -4882,8 +5057,31 @@ new_symbol (struct die_info *die, struct
 	  attr = dwarf_attr (die, DW_AT_location);
 	  if (attr)
 	    {
-	      SYMBOL_VALUE (sym) =
-		decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+	      if (attr_form_is_block (attr))
+	      {
+	        SYMBOL_VALUE (sym) =
+		  decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+	      }
+	      else if (attr->form == DW_FORM_data4
+		       || attr->form == DW_FORM_data8)
+	      {
+		 struct dwarf_block *blkp = NULL;
+		 struct loclist_block *llbp;
+
+		 llbp = dwarf2_loclist_lookup_block (
+		   	      (unsigned int)DW_ADDR (attr));
+		 if (llbp)
+		   blkp = &llbp->blk;
+		 if (blkp)
+		   SYMBOL_VALUE_ADDRESS (sym) =
+		     decode_locdesc (blkp, objfile, cu_header);
+	      }
+              else
+                {
+                  complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
+                            "external variable");
+                  addr = 0;
+                }
 	      if (isreg)
 		{
 		  SYMBOL_CLASS (sym) = LOC_REGPARM;
@@ -6660,6 +6863,26 @@ dwarf_alloc_die (void)
   die = (struct die_info *) xmalloc (sizeof (struct die_info));
   memset (die, 0, sizeof (struct die_info));
   return (die);
+}
+
+static struct loclist_block *
+dwarf_alloc_loclist_block (void)
+{
+  struct loclist_block *llb;
+
+  llb = (struct loclist_block *) xmalloc (sizeof (struct loclist_block));
+  memset (llb, 0, sizeof (struct loclist_block));
+  return (llb);
+}
+
+static struct loclist_master *
+dwarf_alloc_loclist_master (void)
+{
+  struct loclist_master *llm;
+
+  llm = (struct loclist_master *) xmalloc (sizeof (struct loclist_master));
+  memset (llm, 0, sizeof (struct loclist_master));
+  return (llm);
 }
 
 

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