Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFA] Location list support.
@ 2003-02-01  7:50 Michal Ludvig
  2003-02-01 16:57 ` Daniel Jacobowitz
  0 siblings, 1 reply; 7+ messages in thread
From: Michal Ludvig @ 2003-02-01  7:50 UTC (permalink / raw)
  To: GDB Patches

[-- Attachment #1: Type: text/plain, Size: 786 bytes --]

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

[-- Attachment #2: loclist-1.diff --]
[-- Type: text/plain, Size: 11627 bytes --]

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);
 }
 
 \f

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

* Re: [RFA] Location list support.
  2003-02-01  7:50 [RFA] Location list support Michal Ludvig
@ 2003-02-01 16:57 ` Daniel Jacobowitz
  0 siblings, 0 replies; 7+ messages in thread
From: Daniel Jacobowitz @ 2003-02-01 16:57 UTC (permalink / raw)
  To: Michal Ludvig; +Cc: GDB Patches

On Sat, Feb 01, 2003 at 08:50:13AM +0100, Michal Ludvig wrote:
> 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

Michal,

Can I ask you to sit on this patch for another two or three days?  I'll
have LOC_COMPUTED ready probably on Monday, and after that it would be
easy to take what you've done and use it for proper location lists. 
Merging this in now would make my work a lot harder.


-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


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

* Re: [RFA] Location list support
  2003-02-21 17:11 ` Daniel Jacobowitz
@ 2003-02-21 23:09   ` Michal Ludvig
  0 siblings, 0 replies; 7+ messages in thread
From: Michal Ludvig @ 2003-02-21 23:09 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: GDB Patches

Daniel Jacobowitz wrote:
> On Fri, Feb 21, 2003 at 12:05:37PM +0100, Michal Ludvig wrote:
> 
>>Hi,
>>attached is a patch that adds support for .debug_loc sections as 
>>generated by newer versions of GCC (eg. from rtlopt-branch).
> 
> Let me try saying this again... Michal, are you watching GDB HEAD
> development? 

Well, no, actually. I did this patch for gdb-5.3 since mainline for 
x86-64 is too broken to be usable (due to the merge between i386 and 
x86-64 targets). And since the patch for gdb-5.3 works pretty well I 
sent a straight mainline version port to the list.
It's nothing personal, Daniel :-)

> Have you been following my discussions with Jim about how
> DW_AT_location should be supported?  I didn't just ask you to wait for
> the LOC_COMPUTED patch out of sheer pique.  If you're not using that
> mechanism, then you're defeating the whole purpose it was implemented
> for.
> 
> For instance, a good sized chunk of code you delete in the patch below
> is no longer there.  Be careful updating, since you copied that deleted
> code to new functions; it shouldn't be there either.
> 
> Basically, location lists should be represented as LOC_COMPUTED
> symbols; the LOC_COMPUTED lookup mechanism should be updated to accept
> a PC when computing the location.

OK, so the .debug_loc parser will likely remain the same, new_symbol() 
will create variables with location lists as LOC_COMPUTED types and 
read_var_val() & Co. should compute the actual location depending on the 
current PC. Did I understand you correctly? Hm, it doesn't seem to be 
that much simpler that what I did. But I understand, that I should use 
LOC_COMPUTED once it's there.

>  The entire thing will be worlds
> simpler than all the work you did below, and a heck of a lot less
> fragile.  You just need to parse the location lists, store them in the
> location baton, and select a list to evaluate in dwarf2loc.c.  If
> there's no list entry for $pc, that's where you return optimized-out;
> it might take another little change to accept an optimized-out result
> there.  If there is a list entry you evaluate it just like presently.

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


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

* Re: [RFA] Location list support
  2003-02-21 17:47 ` Keith Walker
@ 2003-02-21 18:02   ` Daniel Jacobowitz
  0 siblings, 0 replies; 7+ messages in thread
From: Daniel Jacobowitz @ 2003-02-21 18:02 UTC (permalink / raw)
  To: Keith Walker; +Cc: Michal Ludvig, GDB Patches

On Fri, Feb 21, 2003 at 05:47:09PM +0000, Keith Walker wrote:
> Michal,
> 
> >The structure symbol itself is filled up with the first loclist entry 
> >found for this symbol (ie with the values for the lowest PC where the 
> >symbol is valid).
> 
> Just to point out that the DWARF2 specification does not require the 
> entries in the location list to be specified in any specific order .... 
> therefore you shouldn't assume that the first entry is for the lowest PC 
> where the symbol is valid.
> 
> 
> 
> Not related to your changes .... but I thought I would point out the 
> following issue once variables can be described using location lists:
> 
> A location list allows for overlapping address ranges, ie.  Where a 
> variables can be found in more that one place at a specific PC.    Now for 
> reading the variable's value this means that you can read from any of the 
> specified locations.   However if you allow writing of the variable's value 
> then the write should be performed to all the locations where the variable 
> can currently be found.

Thanks.  This'll probably be a FIXME for now... we're not quite set up
for multiple locations.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


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

* Re: [RFA] Location list support
  2003-02-21 11:06 Michal Ludvig
  2003-02-21 17:11 ` Daniel Jacobowitz
@ 2003-02-21 17:47 ` Keith Walker
  2003-02-21 18:02   ` Daniel Jacobowitz
  1 sibling, 1 reply; 7+ messages in thread
From: Keith Walker @ 2003-02-21 17:47 UTC (permalink / raw)
  To: Michal Ludvig, GDB Patches

Michal,

>The structure symbol itself is filled up with the first loclist entry 
>found for this symbol (ie with the values for the lowest PC where the 
>symbol is valid).

Just to point out that the DWARF2 specification does not require the 
entries in the location list to be specified in any specific order .... 
therefore you shouldn't assume that the first entry is for the lowest PC 
where the symbol is valid.



Not related to your changes .... but I thought I would point out the 
following issue once variables can be described using location lists:

A location list allows for overlapping address ranges, ie.  Where a 
variables can be found in more that one place at a specific PC.    Now for 
reading the variable's value this means that you can read from any of the 
specified locations.   However if you allow writing of the variable's value 
then the write should be performed to all the locations where the variable 
can currently be found.

Keith


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

* Re: [RFA] Location list support
  2003-02-21 11:06 Michal Ludvig
@ 2003-02-21 17:11 ` Daniel Jacobowitz
  2003-02-21 23:09   ` Michal Ludvig
  2003-02-21 17:47 ` Keith Walker
  1 sibling, 1 reply; 7+ messages in thread
From: Daniel Jacobowitz @ 2003-02-21 17:11 UTC (permalink / raw)
  To: Michal Ludvig; +Cc: GDB Patches

On Fri, Feb 21, 2003 at 12:05:37PM +0100, Michal Ludvig wrote:
> Hi,
> attached is a patch that adds support for .debug_loc sections as 
> generated by newer versions of GCC (eg. from rtlopt-branch).
> 
> It works in this way:
> - Parse .debug_loc into a list of new internal structures (struct 
> loclist_master, struct loclist_block). Each loclist_master belongs to 
> one variable and contains a pointer to a chain of loclist_blocks that 
> represent different locations where the given variable can be found 
> during it's life.
> - Next the .debug_info is parsed and when a new symbol is being added, 
> the function new_symbol() first checks, if it's location is described by 
> a location list or not. If not, then the old method is used. If there is 
> a location list (in loclist_master) found for this variable, each one of 
> its loclist_blocks is parsed and added to symbol.loclist chain. The 
> structure symbol itself is filled up with the first loclist entry found 
> for this symbol (ie with the values for the lowest PC where the symbol 
> is valid).
> - When the variable's value is to be read (in read_var_value()), it's 
> first checked if there is a non-null loclist pointer in variable's 
> 'symbol' structure. If not, everything continued like it did until now. 
> If there is a loclist it's searched for a block valid for the actual PC 
> and if found, the variable is updated with description found there. If a 
> valid block is not found, it's assumed that a variable was already 
> optimized out on this PC and again the symbol structure is updated in an 
> appropriate way.
> 
> Comments? Approvals?

Let me try saying this again... Michal, are you watching GDB HEAD
development?  Have you been following my discussions with Jim about how
DW_AT_location should be supported?  I didn't just ask you to wait for
the LOC_COMPUTED patch out of sheer pique.  If you're not using that
mechanism, then you're defeating the whole purpose it was implemented
for.

For instance, a good sized chunk of code you delete in the patch below
is no longer there.  Be careful updating, since you copied that deleted
code to new functions; it shouldn't be there either.

Basically, location lists should be represented as LOC_COMPUTED
symbols; the LOC_COMPUTED lookup mechanism should be updated to accept
a PC when computing the location.  The entire thing will be worlds
simpler than all the work you did below, and a heck of a lot less
fragile.  You just need to parse the location lists, store them in the
location baton, and select a list to evaluate in dwarf2loc.c.  If
there's no list entry for $pc, that's where you return optimized-out;
it might take another little change to accept an optimized-out result
there.  If there is a list entry you evaluate it just like presently.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


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

* [RFA] Location list support
@ 2003-02-21 11:06 Michal Ludvig
  2003-02-21 17:11 ` Daniel Jacobowitz
  2003-02-21 17:47 ` Keith Walker
  0 siblings, 2 replies; 7+ messages in thread
From: Michal Ludvig @ 2003-02-21 11:06 UTC (permalink / raw)
  To: GDB Patches

[-- Attachment #1: Type: text/plain, Size: 1609 bytes --]

Hi,
attached is a patch that adds support for .debug_loc sections as 
generated by newer versions of GCC (eg. from rtlopt-branch).

It works in this way:
- Parse .debug_loc into a list of new internal structures (struct 
loclist_master, struct loclist_block). Each loclist_master belongs to 
one variable and contains a pointer to a chain of loclist_blocks that 
represent different locations where the given variable can be found 
during it's life.
- Next the .debug_info is parsed and when a new symbol is being added, 
the function new_symbol() first checks, if it's location is described by 
a location list or not. If not, then the old method is used. If there is 
a location list (in loclist_master) found for this variable, each one of 
its loclist_blocks is parsed and added to symbol.loclist chain. The 
structure symbol itself is filled up with the first loclist entry found 
for this symbol (ie with the values for the lowest PC where the symbol 
is valid).
- When the variable's value is to be read (in read_var_value()), it's 
first checked if there is a non-null loclist pointer in variable's 
'symbol' structure. If not, everything continued like it did until now. 
If there is a loclist it's searched for a block valid for the actual PC 
and if found, the variable is updated with description found there. If a 
valid block is not found, it's assumed that a variable was already 
optimized out on this PC and again the symbol structure is updated in an 
appropriate way.

Comments? Approvals?

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

[-- Attachment #2: loclist-final-head-1.diff --]
[-- Type: text/plain, Size: 28577 bytes --]

2003-02-21  Michal Ludvig  <mludvig@suse.cz>

	* dwarf2read.c (struct comp_unit_head): Added lowpc, highpc.
	(struct loclist_block, struct loclist_master)
	(loclist_base, dwarf_loc_buffer): New variables.
	(struct dwarf2_pinfo): Added dwarf_loc_buffer, dwarf_loc_size.
	(DWARF_LOC_BUFFER, DWARF_LOC_SIZE): New macros.
	(dwarf2_read_loclist, dwarf_alloc_loclist_block)
	(dwarf_alloc_loclist_master): New functions.
	(dwarf2_build_psymtabs): Init dwarf_loc_buffer.
	(dwarf2_build_psymtabs_hard): Use dwarf_loc_{buffer,size}.
	(psymtab_to_symtab_1): Use dwarf_loc_{buffer,size}.
	Parse .debug_loc, fill lowpc/highpc.
	(dwarf2_update_symbol_from_loclist): New function.
	(update_symbol_class_function): New function type.
	(update_external_symbol_class, update_variable_symbol_class)
	(update_parameter_symbol_class, update_symbol_loclist_class):
	New functions with code moved from new_symbol().
	(create_location_list): New function.
	(new_symbol): Add support for location lists, moved some 
	parts to separate functions.
	(dwarf_alloc_loclist_block, dwarf_alloc_loclist_master):
	New helper functions.
	* findvar.c (read_var_value): Added searching in variable's
	location list.
	* symfile.h (dwarf2_update_symbol_from_loclist): New prototype.
	* symtab.h (union symbol_info_value, union symbol_aux_value): 
	New unions cutted off struct general_symbol_info/struct symbol.
	(struct symbol_loclist): New.
	(struct symbol): New item loclist.
	(SYMBOL_LOCLIST): New macro.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.86
diff -u -p -r1.86 dwarf2read.c
--- dwarf2read.c	14 Feb 2003 19:05:52 -0000	1.86
+++ dwarf2read.c	21 Feb 2003 09:53:13 -0000
@@ -221,6 +221,10 @@ struct comp_unit_head
   /* Pointer to the DIE associated with the compilation unit.  */
 
   struct die_info *die;
+
+  /* PC bounds of this CU */
+
+  CORE_ADDR lowpc, highpc;
 };
 
 /* The line number information for a compilation unit (found in the
@@ -360,6 +364,24 @@ 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 *parent;
+};
+
+struct loclist_master
+{
+  unsigned int offset;		/* Offset of this block in .debug_loc.  */
+  CORE_ADDR baseaddr;
+  struct loclist_block *blocks;
+  struct loclist_master *next;
+};
+
+static struct loclist_master *loclist_base;
+
 #ifndef ATTR_ALLOC_CHUNK
 #define ATTR_ALLOC_CHUNK 4
 #endif
@@ -394,6 +416,7 @@ static char *dwarf_line_buffer;
 static char *dwarf_str_buffer;
 static char *dwarf_macinfo_buffer;
 static char *dwarf_ranges_buffer;
+static char *dwarf_loc_buffer;
 
 /* A zeroed version of a partial die for initialization purposes.  */
 static struct partial_die_info zeroed_partial_die;
@@ -510,6 +533,13 @@ struct dwarf2_pinfo
 
   unsigned int dwarf_ranges_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)
@@ -525,6 +555,8 @@ struct dwarf2_pinfo
 #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)
+#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
@@ -676,6 +708,8 @@ char *dwarf2_read_section (struct objfil
 
 static void dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header);
 
+static void dwarf2_read_loclist (bfd *abfd, struct comp_unit_head *cu_header);
+
 static void dwarf2_empty_abbrev_table (void *);
 
 static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
@@ -901,6 +935,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);
@@ -922,6 +959,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;
   dwarf_ranges_offset = 0;
@@ -1061,6 +1099,14 @@ dwarf2_build_psymtabs (struct objfile *o
   else
     dwarf_ranges_buffer = NULL;
 
+  if (dwarf_loc_offset)
+    dwarf_loc_buffer = dwarf2_read_section (objfile,
+					    dwarf_loc_offset,
+					    dwarf_loc_size,
+					    dwarf_loc_section);
+  else
+    dwarf_loc_buffer = NULL;
+
   if (mainline
       || (objfile->global_psymbols.size == 0
 	  && objfile->static_psymbols.size == 0))
@@ -1287,6 +1333,8 @@ dwarf2_build_psymtabs_hard (struct objfi
       DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size;
       DWARF_RANGES_BUFFER (pst) = dwarf_ranges_buffer;
       DWARF_RANGES_SIZE (pst) = dwarf_ranges_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 */
@@ -1614,6 +1662,8 @@ psymtab_to_symtab_1 (struct partial_symt
   struct symtab *symtab;
   struct cleanup *back_to;
 
+  memset (&cu_header, 0, sizeof (cu_header));
+
   /* Set local variables from the partial symbol table info.  */
   offset = DWARF_INFO_OFFSET (pst);
   dwarf_info_buffer = DWARF_INFO_BUFFER (pst);
@@ -1627,6 +1677,8 @@ psymtab_to_symtab_1 (struct partial_symt
   dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst);
   dwarf_ranges_buffer = DWARF_RANGES_BUFFER (pst);
   dwarf_ranges_size = DWARF_RANGES_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;
@@ -1644,13 +1696,13 @@ psymtab_to_symtab_1 (struct partial_symt
   dwarf2_read_abbrevs (abfd, &cu_header);
   make_cleanup (dwarf2_empty_abbrev_table, cu_header.dwarf2_abbrevs);
 
+  dwarf2_read_loclist (abfd, &cu_header);
+
   dies = read_comp_unit (info_ptr, abfd, &cu_header);
 
   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, &cu_header))
     {
@@ -1677,6 +1729,13 @@ psymtab_to_symtab_1 (struct partial_symt
 	    }
 	}
     }
+
+  cu_header.lowpc = lowpc;
+  cu_header.highpc = highpc;
+
+  /* Do line number decoding in read_file_scope () */
+  process_die (dies, objfile, &cu_header);
+
   symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
 
   /* Set symtab language to language from DW_AT_language.
@@ -3663,6 +3722,124 @@ dwarf2_read_section (struct objfile *obj
   return buf;
 }
 
+/* The following functions parse .debug_loc section and
+   store the contents to a list of lists. These lists are
+   then used when creating the actual "symbol" structures. */
+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,
+			    struct loclist_master *ll_master)
+{
+  char *ptr;
+  CORE_ADDR lowpc, highpc;
+  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)
+	{
+	  lowpc = read_4_bytes (abfd, ptr);
+	  ptr += 4;
+	  highpc = read_4_bytes (abfd, ptr);
+	  ptr += 4;
+	}
+      else if (addr_size == 8)
+	{
+	  lowpc = read_8_bytes (abfd, ptr);
+	  ptr += 8;
+	  highpc = read_8_bytes (abfd, ptr);
+	  ptr += 8;
+	}
+      else
+	error ("Address size == %d ... unsupported!", addr_size);
+
+      if (lowpc == 0 && highpc == 0)
+	break;
+
+      if (lowpc == (CORE_ADDR) -1L)
+	{
+	  ll_master->baseaddr = highpc;
+	  continue;
+	}
+
+      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->parent = ll_master;
+      llb_last->lowpc = lowpc;
+      llb_last->highpc = highpc;
+
+      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, ll_master);
+    }
+}
+
 /* 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
@@ -4952,6 +5129,173 @@ dwarf2_start_subfile (char *filename, ch
   start_subfile (filename, dirname);
 }
 
+void
+dwarf2_update_symbol_from_loclist (struct symbol *sym,
+				   struct symbol_loclist *symll)
+{
+  SYMBOL_CLASS (sym) = SYMBOL_CLASS (symll);
+  memcpy ((void *) &sym->ginfo.value, (void *) &symll->ginfo.value,
+	  sizeof (sym->ginfo.value));
+  memcpy ((void *) &sym->aux_value, (void *) &symll->aux_value,
+	  sizeof (union symbol_aux_value));
+}
+
+typedef void (update_symbol_class_function) (struct symbol * sym,
+					     struct objfile * objfile);
+
+static void
+update_external_symbol_class (struct symbol *sym, struct objfile *objfile)
+{
+  if (is_thread_local)
+    {
+      /* SYMBOL_VALUE_ADDRESS contains at this point the
+         offset of the variable within the thread local
+         storage.  */
+      SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
+      SYMBOL_OBJFILE (sym) = objfile;
+    }
+  /* In shared libraries the address of the variable
+     in the location descriptor might still be relocatable,
+     so its value could be zero.
+     Enter the symbol as a LOC_UNRESOLVED symbol, if its
+     value is zero, the address of the variable will then
+     be determined from the minimal symbol table whenever
+     the variable is referenced.  */
+  if (SYMBOL_VALUE_ADDRESS (sym))
+    {
+      fixup_symbol_section (sym, objfile);
+      SYMBOL_VALUE_ADDRESS (sym) +=
+	ANOFFSET (objfile->section_offsets, SYMBOL_SECTION (sym));
+      SYMBOL_CLASS (sym) = LOC_STATIC;
+    }
+  else
+    SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
+}
+
+static void
+update_variable_symbol_class (struct symbol *sym, struct objfile *objfile)
+{
+  if (optimized_out)
+    SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+  else if (isreg)
+    {
+      SYMBOL_CLASS (sym) = LOC_REGISTER;
+      SYMBOL_VALUE (sym) = DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
+    }
+  else if (offreg)
+    {
+      SYMBOL_CLASS (sym) = LOC_BASEREG;
+      SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
+    }
+  else if (islocal)
+    SYMBOL_CLASS (sym) = LOC_LOCAL;
+  else if (is_thread_local)
+    {
+      SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
+      SYMBOL_OBJFILE (sym) = objfile;
+    }
+  else
+    {
+      fixup_symbol_section (sym, objfile);
+      SYMBOL_VALUE_ADDRESS (sym) +=
+	ANOFFSET (objfile->section_offsets, SYMBOL_SECTION (sym));
+      SYMBOL_CLASS (sym) = LOC_STATIC;
+    }
+}
+
+static void
+update_parameter_symbol_class (struct symbol *sym, struct objfile *objfile)
+{
+  if (isreg)
+    {
+      SYMBOL_CLASS (sym) = LOC_REGPARM;
+      SYMBOL_VALUE (sym) = DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
+    }
+  else if (offreg)
+    {
+      if (isderef)
+	{
+	  if (basereg != frame_base_reg)
+	    dwarf2_complex_location_expr_complaint ();
+	  SYMBOL_CLASS (sym) = LOC_REF_ARG;
+	}
+      else
+	{
+	  SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+	  SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
+	}
+    }
+  else
+    SYMBOL_CLASS (sym) = LOC_ARG;
+}
+
+static void
+update_symbol_loclist_class (struct symbol_loclist *symll,
+			     struct objfile *objfile,
+			     update_symbol_class_function * update_function)
+{
+  struct symbol *sym = alloca (sizeof (struct symbol));
+
+  SYMBOL_VALUE (sym) = SYMBOL_VALUE (symll);
+  SYMBOL_BASEREG (sym) = SYMBOL_BASEREG (symll);
+
+  (*update_function) (sym, objfile);
+
+  SYMBOL_VALUE (symll) = SYMBOL_VALUE (sym);
+  SYMBOL_BASEREG (symll) = SYMBOL_BASEREG (sym);
+  SYMBOL_CLASS (symll) = SYMBOL_CLASS (sym);
+}
+
+static void
+create_location_list (struct symbol *sym, struct objfile *objfile,
+		      struct attribute *attr,
+		      const struct comp_unit_head *cu_header,
+		      update_symbol_class_function * update_function)
+{
+  struct dwarf_block *blkp = NULL;
+  struct loclist_block *llbp;
+  struct symbol_loclist *last_loclist_ptr = NULL;
+  CORE_ADDR baseaddr;
+
+  llbp = dwarf2_loclist_lookup_block ((unsigned int) DW_ADDR (attr));
+  gdb_assert (llbp != NULL);
+  blkp = &llbp->blk;
+  gdb_assert (blkp != NULL);
+
+  SYMBOL_VALUE_ADDRESS (sym) = decode_locdesc (blkp, objfile, cu_header);
+
+  (*update_function) (sym, objfile);
+
+  baseaddr = llbp->parent->baseaddr ?
+    llbp->parent->baseaddr : cu_header->lowpc;
+  baseaddr += ANOFFSET (objfile->section_offsets, objfile->sect_index_text);
+
+  /* Create location list. */
+  while (llbp)
+    {
+      struct symbol_loclist *symll;
+
+      blkp = &llbp->blk;
+      gdb_assert (blkp != NULL);
+
+      symll = xmalloc (sizeof (struct symbol_loclist));
+      symll->ginfo.value.address = decode_locdesc (blkp, objfile, cu_header);
+
+      symll->lowpc = llbp->lowpc + baseaddr;
+      symll->highpc = llbp->highpc + baseaddr;
+
+      if (last_loclist_ptr == NULL)
+	SYMBOL_LOCLIST (sym) = symll;
+      else
+	last_loclist_ptr->next = symll;
+      last_loclist_ptr = symll;
+
+      update_symbol_loclist_class (symll, objfile, update_function);
+
+      llbp = llbp->next;
+    }
+}
+
 /* Given a pointer to a DWARF information entry, figure out if we need
    to make a symbol table entry for it, and if so, create a new entry
    and return a pointer to it.
@@ -5048,11 +5392,13 @@ new_symbol (struct die_info *die, struct
 		    {
 		      SYMBOL_VALUE_ADDRESS (sym) =
 			decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+		      update_external_symbol_class (sym, objfile);
 		    }
 		  else if (attr->form == DW_FORM_data4
 			   || attr->form == DW_FORM_data8)
 		    {
-		      dwarf2_complex_location_expr_complaint ();
+		      create_location_list (sym, objfile, attr, cu_header,
+					    update_external_symbol_class);
 		    }
 		  else
 		    {
@@ -5060,32 +5406,6 @@ new_symbol (struct die_info *die, struct
 							     "external variable");
 		    }
 		  add_symbol_to_list (sym, &global_symbols);
-		  if (is_thread_local)
-		    {
-		      /* SYMBOL_VALUE_ADDRESS contains at this point the
-		         offset of the variable within the thread local
-		         storage.  */
-		      SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
-		      SYMBOL_OBJFILE (sym) = objfile;
-		    }
-
-		  /* In shared libraries the address of the variable
-		     in the location descriptor might still be relocatable,
-		     so its value could be zero.
-		     Enter the symbol as a LOC_UNRESOLVED symbol, if its
-		     value is zero, the address of the variable will then
-		     be determined from the minimal symbol table whenever
-		     the variable is referenced.  */
-		  else if (SYMBOL_VALUE_ADDRESS (sym))
-		    {
-		      fixup_symbol_section (sym, objfile);
-		      SYMBOL_VALUE_ADDRESS (sym) +=
-			ANOFFSET (objfile->section_offsets,
-				  SYMBOL_SECTION (sym));
-		      SYMBOL_CLASS (sym) = LOC_STATIC;
-		    }
-		  else
-		    SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
 		}
 	      else
 		{
@@ -5094,11 +5414,13 @@ new_symbol (struct die_info *die, struct
 		    {
 		      SYMBOL_VALUE (sym) = addr =
 			decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+		      update_variable_symbol_class (sym, objfile);
 		    }
 		  else if (attr->form == DW_FORM_data4
 			   || attr->form == DW_FORM_data8)
 		    {
-		      dwarf2_complex_location_expr_complaint ();
+		      create_location_list (sym, objfile, attr, cu_header,
+					    update_variable_symbol_class);
 		    }
 		  else
 		    {
@@ -5107,38 +5429,6 @@ new_symbol (struct die_info *die, struct
 		      addr = 0;
 		    }
 		  add_symbol_to_list (sym, list_in_scope);
-		  if (optimized_out)
-		    {
-		      SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
-		    }
-		  else if (isreg)
-		    {
-		      SYMBOL_CLASS (sym) = LOC_REGISTER;
-		      SYMBOL_VALUE (sym) =
-			DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
-		    }
-		  else if (offreg)
-		    {
-		      SYMBOL_CLASS (sym) = LOC_BASEREG;
-		      SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
-		    }
-		  else if (islocal)
-		    {
-		      SYMBOL_CLASS (sym) = LOC_LOCAL;
-		    }
-		  else if (is_thread_local)
-		    {
-		      SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
-		      SYMBOL_OBJFILE (sym) = objfile;
-		    }
-		  else
-		    {
-		      fixup_symbol_section (sym, objfile);
-		      SYMBOL_VALUE_ADDRESS (sym) =
-			addr + ANOFFSET (objfile->section_offsets,
-					 SYMBOL_SECTION (sym));
-		      SYMBOL_CLASS (sym) = LOC_STATIC;
-		    }
 		}
 	    }
 	  else
@@ -5162,31 +5452,21 @@ 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 (isreg)
+	      if (attr_form_is_block (attr))
 		{
-		  SYMBOL_CLASS (sym) = LOC_REGPARM;
 		  SYMBOL_VALUE (sym) =
-		    DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
+		    decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+		  update_parameter_symbol_class (sym, objfile);
 		}
-	      else if (offreg)
+	      else if (attr->form == DW_FORM_data4
+		       || attr->form == DW_FORM_data8)
 		{
-		  if (isderef)
-		    {
-		      if (basereg != frame_base_reg)
-			dwarf2_complex_location_expr_complaint ();
-		      SYMBOL_CLASS (sym) = LOC_REF_ARG;
-		    }
-		  else
-		    {
-		      SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
-		      SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
-		    }
+		  create_location_list (sym, objfile, attr, cu_header,
+					update_parameter_symbol_class);
 		}
 	      else
 		{
-		  SYMBOL_CLASS (sym) = LOC_ARG;
+		  dwarf2_complex_location_expr_complaint ();
 		}
 	    }
 	  attr = dwarf_attr (die, DW_AT_const_value);
@@ -6992,6 +7272,26 @@ dwarf_alloc_die (void)
   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);
+}
 \f
 
 /* Macro support.  */
Index: findvar.c
===================================================================
RCS file: /cvs/src/src/gdb/findvar.c,v
retrieving revision 1.47
diff -u -p -r1.47 findvar.c
--- findvar.c	20 Feb 2003 17:17:23 -0000	1.47
+++ findvar.c	21 Feb 2003 09:53:13 -0000
@@ -415,12 +415,15 @@ symbol_read_needs_frame (struct symbol *
    If FRAME is NULL, use the deprecated_selected_frame.  */
 
 struct value *
-read_var_value (register struct symbol *var, struct frame_info *frame)
+read_var_value (register struct symbol *varorig, struct frame_info *frame)
 {
   register struct value *v;
-  struct type *type = SYMBOL_TYPE (var);
+  struct type *type = SYMBOL_TYPE (varorig);
   CORE_ADDR addr;
   register int len;
+  struct symbol *var = alloca (sizeof (struct symbol));
+
+  memcpy (var, varorig, sizeof (struct symbol));
 
   v = allocate_value (type);
   VALUE_LVAL (v) = lval_memory;	/* The most likely possibility.  */
@@ -431,6 +434,37 @@ read_var_value (register struct symbol *
   if (frame == NULL)
     frame = deprecated_selected_frame;
 
+  if (var->loclist)
+    {
+      struct symbol_loclist *llp = var->loclist;
+      int i = 0;
+
+      if (info_verbose)
+	printf (" (%s(%p) ", SYMBOL_NAME (var), (void *) frame->pc);
+      while (llp)
+	{
+	  if (llp->lowpc <= frame->pc && llp->highpc > frame->pc)
+	    break;
+	  llp = llp->next;
+	}
+
+      if (llp)
+	{
+	  dwarf2_update_symbol_from_loclist (var, llp);
+	  if (info_verbose)
+	    printf (" %p/%p ) ", (void *) llp->lowpc, (void *) llp->highpc);
+	}
+      else
+	{
+	  SYMBOL_CLASS (var) = LOC_OPTIMIZED_OUT;
+	  if (info_verbose)
+	    printf_filtered
+	      ("Variable '%s' has a location list but I couldn't\n"
+	       "find an entry for pc=%p\n", SYMBOL_NAME (var),
+	       (void *) frame->pc);
+	}
+    }
+
   switch (SYMBOL_CLASS (var))
     {
     case LOC_CONST:
Index: symfile.h
===================================================================
RCS file: /cvs/src/src/gdb/symfile.h,v
retrieving revision 1.19
diff -u -p -r1.19 symfile.h
--- symfile.h	20 Feb 2003 00:01:06 -0000	1.19
+++ symfile.h	21 Feb 2003 09:53:14 -0000
@@ -317,6 +317,9 @@ extern int dwarf2_has_info (bfd * abfd);
 extern void dwarf2_build_psymtabs (struct objfile *, int);
 extern void dwarf2_build_frame_info (struct objfile *);
 
+extern void dwarf2_update_symbol_from_loclist (struct symbol *sym,
+		struct symbol_loclist *symll);
+
 /* From mdebugread.c */
 
 /* Hack to force structures to exist before use in parameter list.  */
Index: symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.60
diff -u -p -r1.60 symtab.h
--- symtab.h	20 Feb 2003 17:17:25 -0000	1.60
+++ symtab.h	21 Feb 2003 09:53:14 -0000
@@ -42,29 +42,13 @@ struct blockvector;
 #define	BYTE_BITFIELD		/*nothing */
 #endif
 
-/* Define a structure for the information that is common to all symbol types,
-   including minimal symbols, partial symbols, and full symbols.  In a
-   multilanguage environment, some language specific information may need to
-   be recorded along with each symbol.
-
-   These fields are ordered to encourage good packing, since we frequently
-   have tens or hundreds of thousands of these.  */
+/* Value of the symbol.  Which member of this union to use, and what
+   it means, depends on what kind of symbol this is and its
+   SYMBOL_CLASS.  See comments there for more details.  All of these
+   are in host byte order (though what they point to might be in
+   target byte order, e.g. LOC_CONST_BYTES).  */
 
-struct general_symbol_info
-{
-  /* Name of the symbol.  This is a required field.  Storage for the name is
-     allocated on the psymbol_obstack or symbol_obstack for the associated
-     objfile. */
-
-  char *name;
-
-  /* Value of the symbol.  Which member of this union to use, and what
-     it means, depends on what kind of symbol this is and its
-     SYMBOL_CLASS.  See comments there for more details.  All of these
-     are in host byte order (though what they point to might be in
-     target byte order, e.g. LOC_CONST_BYTES).  */
-
-  union
+union symbol_info_value
   {
     /* The fact that this is a long not a LONGEST mainly limits the
        range of a LOC_CONST.  Since LOC_CONST_BYTES exists, I'm not
@@ -80,8 +64,25 @@ struct general_symbol_info
     /* for opaque typedef struct chain */
 
     struct symbol *chain;
-  }
-  value;
+  };
+
+/* Define a structure for the information that is common to all symbol types,
+   including minimal symbols, partial symbols, and full symbols.  In a
+   multilanguage environment, some language specific information may need to
+   be recorded along with each symbol.
+
+   These fields are ordered to encourage good packing, since we frequently
+   have tens or hundreds of thousands of these.  */
+
+struct general_symbol_info
+{
+  /* Name of the symbol.  This is a required field.  Storage for the name is
+     allocated on the psymbol_obstack or symbol_obstack for the associated
+     objfile. */
+
+  char *name;
+
+  union symbol_info_value value;
 
   /* Since one and only one language can apply, wrap the language specific
      information inside a union. */
@@ -501,6 +502,27 @@ struct alias_list
   struct alias_list *next;
 };
 
+union symbol_aux_value
+{
+  /* Used by LOC_BASEREG and LOC_BASEREG_ARG.  */
+  short basereg;
+
+  /* Used by LOC_THREAD_LOCAL_STATIC.  The objfile in which this
+     symbol is defined.  To find a thread-local variable (e.g., a
+     variable declared with the `__thread' storage class), we may
+     need to know which object file it's in.  */
+  struct objfile *objfile;
+};
+
+struct symbol_loclist
+  {
+    CORE_ADDR lowpc, highpc;
+    enum address_class aclass BYTE_BITFIELD;
+    struct general_symbol_info ginfo;
+    union symbol_aux_value aux_value;
+    struct symbol_loclist *next;
+  }; 
+    
 struct symbol
 {
 
@@ -534,19 +556,7 @@ struct symbol
   /* Some symbols require an additional value to be recorded on a per-
      symbol basis.  Stash those values here. */
 
-  union
-  {
-    /* Used by LOC_BASEREG and LOC_BASEREG_ARG.  */
-    short basereg;
-
-    /* Used by LOC_THREAD_LOCAL_STATIC.  The objfile in which this
-       symbol is defined.  To find a thread-local variable (e.g., a
-       variable declared with the `__thread' storage class), we may
-       need to know which object file it's in.  */
-    struct objfile *objfile;
-  }
-  aux_value;
-
+  union symbol_aux_value aux_value;
 
   /* Link to a list of aliases for this symbol.
      Only a "primary/main symbol may have aliases.  */
@@ -557,6 +567,8 @@ struct symbol
   struct range_list *ranges;
 
   struct symbol *hash_next;
+  
+  struct symbol_loclist *loclist;
 };
 
 
@@ -568,6 +580,7 @@ struct symbol
 #define SYMBOL_OBJFILE(symbol)          (symbol)->aux_value.objfile
 #define SYMBOL_ALIASES(symbol)		(symbol)->aliases
 #define SYMBOL_RANGES(symbol)		(symbol)->ranges
+#define SYMBOL_LOCLIST(symbol)		(symbol)->loclist
 \f
 /* A partial_symbol records the name, namespace, and address class of
    symbols whose types we have not parsed yet.  For functions, it also

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

end of thread, other threads:[~2003-02-21 23:09 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-02-01  7:50 [RFA] Location list support Michal Ludvig
2003-02-01 16:57 ` Daniel Jacobowitz
2003-02-21 11:06 Michal Ludvig
2003-02-21 17:11 ` Daniel Jacobowitz
2003-02-21 23:09   ` Michal Ludvig
2003-02-21 17:47 ` Keith Walker
2003-02-21 18:02   ` Daniel Jacobowitz

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