This is the mail archive of the gdb-patches@sourceware.org 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]

[PATCH] Dwarf location expressions, tracing and printing


This patch solves a number of problems related to variables with Dwarf2 location expressions - which these days, means just about every local in optimized code. :-) Perhaps the most interesting part is that I finally got tired of working blind and filled out description location functions, so now both "info scope" and "info address" have quite a lot of say about variables. Try things like "info scope handle_inferior_event" to get some truly awesome verbiage. :-)

Since there's a lot of new code here, I'll leave it up for a couple days before committing.

Stan

2010-04-15  Stan Shebs  <stan@codesourcery.com>
       Nathan Sidwell  <nathan@codesourcery.com>

   * dwarf2loc.c (struct axs_var_loc): New struct.
   (dwarf2_tracepoint_var_loc): New function.
   (dwarf2_tracepoint_var_access): New function.
   (dwarf2_tracepoint_var_ref): Use dwarf2_tracepoint_var_loc, deal
   with DW_OP_piece.
   (locexpr_describe_location_piece): New function.
   (locexpr_describe_location_1): New function.
   (locexpr_describe_location): Call it, update signature.
   (loclist_describe_location): Rewrite to loop over locations,
   update signature.
   * symtab.h (struct symbol_computed_ops): Add address to
   describe_location arguments, return void.
   * printcmd.c (address_info): Get context PC, pass to computed
   location description.
   * tracepoint.c (scope_info): Ditto.
   * ax-gdb.c (trace_kludge): Export.


Index: ax-gdb.c
===================================================================
RCS file: /cvs/src/src/gdb/ax-gdb.c,v
retrieving revision 1.72
diff -p -r1.72 ax-gdb.c
*** ax-gdb.c	19 Mar 2010 22:00:17 -0000	1.72
--- ax-gdb.c	16 Apr 2010 00:14:41 -0000
*************** maybe_const_expr (union exp_element **pc
*** 329,335 ****
  
     Setting the flag trace_kludge to non-zero enables the code that
     emits the trace bytecodes at the appropriate points.  */
! static int trace_kludge;
  
  /* Scan for all static fields in the given class, including any base
     classes, and generate tracing bytecodes for each.  */
--- 329,335 ----
  
     Setting the flag trace_kludge to non-zero enables the code that
     emits the trace bytecodes at the appropriate points.  */
! int trace_kludge;
  
  /* Scan for all static fields in the given class, including any base
     classes, and generate tracing bytecodes for each.  */
Index: dwarf2loc.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2loc.c,v
retrieving revision 1.74
diff -p -r1.74 dwarf2loc.c
*** dwarf2loc.c	17 Mar 2010 22:04:43 -0000	1.74
--- dwarf2loc.c	16 Apr 2010 00:14:41 -0000
*************** dwarf2_loc_desc_needs_frame (gdb_byte *d
*** 614,641 ****
    return baton.needs_frame || in_reg;
  }
  
! static void
! dwarf2_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
! 			   struct agent_expr *ax, struct axs_value *value,
! 			   gdb_byte *data, int size)
  {
!   if (!data || size == 0)
!     {
!       value->optimized_out = 1;
!     }
!   else if (size == 1
!       && data[0] >= DW_OP_reg0
!       && data[0] <= DW_OP_reg31)
      {
!       value->kind = axs_lvalue_register;
!       value->u.reg = data[0] - DW_OP_reg0;
      }
    else if (data[0] == DW_OP_regx)
      {
        ULONGEST reg;
!       read_uleb128 (data + 1, data + size, &reg);
!       value->kind = axs_lvalue_register;
!       value->u.reg = reg;
      }
    else if (data[0] == DW_OP_fbreg)
      {
--- 614,660 ----
    return baton.needs_frame || in_reg;
  }
  
! /* This struct keeps track of the pieces that make up a multi-location
!    object, for use in agent expression generation.  It is
!    superficially similar to struct dwarf_expr_piece, but
!    dwarf_expr_piece is designed for use in immediate evaluation, and
!    does not, for example, have a way to record both base register and
!    offset.  */
! 
! struct axs_var_loc
  {
!   /* Memory vs register, etc */
!   enum axs_lvalue_kind kind;
! 
!   /* If non-zero, number of bytes in this fragment */
!   unsigned bytes;
! 
!   /* (GDB-numbered) reg, or base reg if >= 0 */
!   int reg;
! 
!   /* offset from reg */
!   LONGEST offset;
! };
! 
! static gdb_byte *
! dwarf2_tracepoint_var_loc (struct symbol *symbol,
! 			   struct agent_expr *ax,
! 			   struct axs_var_loc *loc,
! 			   struct gdbarch *gdbarch,
! 			   gdb_byte *data, gdb_byte *end)
! {
!   if (data[0] >= DW_OP_reg0 && data[0] <= DW_OP_reg31)
      {
!       loc->kind = axs_lvalue_register;
!       loc->reg = gdbarch_dwarf2_reg_to_regnum (gdbarch, data[0] - DW_OP_reg0);
!       data += 1;
      }
    else if (data[0] == DW_OP_regx)
      {
        ULONGEST reg;
!       data = read_uleb128 (data + 1, end, &reg);
!       loc->kind = axs_lvalue_register;
!       loc->reg = gdbarch_dwarf2_reg_to_regnum (gdbarch, reg);
      }
    else if (data[0] == DW_OP_fbreg)
      {
*************** dwarf2_tracepoint_var_ref (struct symbol
*** 643,649 ****
        struct symbol *framefunc;
        int frame_reg = 0;
        LONGEST frame_offset;
-       gdb_byte *buf_end;
        gdb_byte *base_data;
        size_t base_size;
        LONGEST base_offset = 0;
--- 662,667 ----
*************** dwarf2_tracepoint_var_ref (struct symbol
*** 661,717 ****
        dwarf_expr_frame_base_1 (framefunc, ax->scope,
  			       &base_data, &base_size);
  
!       if (base_data[0] >= DW_OP_breg0
! 	   && base_data[0] <= DW_OP_breg31)
  	{
  	  frame_reg = base_data[0] - DW_OP_breg0;
! 	  buf_end = read_sleb128 (base_data + 1, base_data + base_size, &base_offset);
  	  if (buf_end != base_data + base_size)
  	    error (_("Unexpected opcode after DW_OP_breg%u for symbol \"%s\"."),
  		   frame_reg, SYMBOL_PRINT_NAME (symbol));
  	}
        else
  	{
  	  /* We don't know what to do with the frame base expression,
  	     so we can't trace this variable; give up.  */
! 	  error (_("Cannot generate expression to collect symbol \"%s\"; DWARF 2 encoding not handled"),
! 		 SYMBOL_PRINT_NAME (symbol));
  	}
  
!       buf_end = read_sleb128 (data + 1, data + size, &frame_offset);
!       if (buf_end != data + size)
! 	error (_("Unexpected opcode after DW_OP_fbreg for symbol \"%s\"."),
! 	       SYMBOL_PRINT_NAME (symbol));
  
!       ax_reg (ax, frame_reg);
!       ax_const_l (ax, base_offset + frame_offset);
!       ax_simple (ax, aop_add);
! 
!       value->kind = axs_lvalue_memory;
      }
!   else if (data[0] >= DW_OP_breg0
! 	   && data[0] <= DW_OP_breg31)
      {
        unsigned int reg;
        LONGEST offset;
-       gdb_byte *buf_end;
  
        reg = data[0] - DW_OP_breg0;
!       buf_end = read_sleb128 (data + 1, data + size, &offset);
!       if (buf_end != data + size)
! 	error (_("Unexpected opcode after DW_OP_breg%u for symbol \"%s\"."),
! 	       reg, SYMBOL_PRINT_NAME (symbol));
! 
!       ax_reg (ax, reg);
!       ax_const_l (ax, offset);
!       ax_simple (ax, aop_add);
  
!       value->kind = axs_lvalue_memory;
      }
    else
      error (_("Unsupported DWARF opcode 0x%x in the location of \"%s\"."),
  	   data[0], SYMBOL_PRINT_NAME (symbol));
  }
  
  /* Return the value of SYMBOL in FRAME using the DWARF-2 expression
     evaluator to calculate the location.  */
--- 679,880 ----
        dwarf_expr_frame_base_1 (framefunc, ax->scope,
  			       &base_data, &base_size);
  
!       if (base_data[0] >= DW_OP_breg0 && base_data[0] <= DW_OP_breg31)
  	{
+ 	  gdb_byte *buf_end;
+ 	  
  	  frame_reg = base_data[0] - DW_OP_breg0;
! 	  buf_end = read_sleb128 (base_data + 1,
! 				  base_data + base_size, &base_offset);
  	  if (buf_end != base_data + base_size)
  	    error (_("Unexpected opcode after DW_OP_breg%u for symbol \"%s\"."),
  		   frame_reg, SYMBOL_PRINT_NAME (symbol));
  	}
+       else if (base_data[0] >= DW_OP_reg0 && base_data[0] <= DW_OP_reg31)
+ 	{
+ 	  /* The frame base is just the register, with no offset.  */
+ 	  frame_reg = base_data[0] - DW_OP_reg0;
+ 	  base_offset = 0;
+ 	}
        else
  	{
  	  /* We don't know what to do with the frame base expression,
  	     so we can't trace this variable; give up.  */
! 	  error (_("Cannot generate expression to collect symbol \"%s\"; DWARF 2 encoding not handled, first opcode in base data is 0x%x."),
! 		 SYMBOL_PRINT_NAME (symbol), base_data[0]);
  	}
  
!       data = read_sleb128 (data + 1, end, &frame_offset);
  
!       loc->kind = axs_lvalue_memory;
!       loc->reg = gdbarch_dwarf2_reg_to_regnum (gdbarch, frame_reg);
!       loc->offset = base_offset + frame_offset;
      }
!   else if (data[0] >= DW_OP_breg0 && data[0] <= DW_OP_breg31)
      {
        unsigned int reg;
        LONGEST offset;
  
        reg = data[0] - DW_OP_breg0;
!       data = read_sleb128 (data + 1, end, &offset);
  
!       loc->kind = axs_lvalue_memory;
!       loc->reg = gdbarch_dwarf2_reg_to_regnum (gdbarch, reg);
!       loc->offset = offset;
      }
    else
      error (_("Unsupported DWARF opcode 0x%x in the location of \"%s\"."),
  	   data[0], SYMBOL_PRINT_NAME (symbol));
+   
+   return data;
  }
+ 
+ /* Given the location of a piece, issue bytecodes that will access it.  */
+ 
+ static void
+ dwarf2_tracepoint_var_access (struct agent_expr *ax,
+ 			      struct axs_value *value,
+ 			      struct axs_var_loc *loc)
+ {
+   value->kind = loc->kind;
+   
+   switch (loc->kind)
+     {
+     case axs_lvalue_register:
+       value->u.reg = loc->reg;
+       break;
+       
+     case axs_lvalue_memory:
+       ax_reg (ax, loc->reg);
+       if (loc->offset)
+ 	{
+ 	  ax_const_l (ax, loc->offset);
+ 	  ax_simple (ax, aop_add);
+ 	}
+       break;
+       
+     default:
+       internal_error (__FILE__, __LINE__, _("Unhandled value kind in dwarf2_tracepoint_var_access"));
+     }
+ }
+ 
+ static void
+ dwarf2_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
+ 			   struct agent_expr *ax, struct axs_value *value,
+ 			   gdb_byte *data, int size)
+ {
+   gdb_byte *end = data + size;
+   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+   /* In practice, a variable is not going to be spread across
+      dozens of registers or memory locations.  If someone comes up
+      with a real-world example, revisit this.  */
+ #define MAX_FRAGS 16
+   struct axs_var_loc fragments[MAX_FRAGS];
+   int nfrags = 0, frag;
+   int length = 0;
+   int piece_ok = 0;
+   int bad = 0;
+   int first = 1;
+       
+   if (!data || size == 0)
+     {
+       value->optimized_out = 1;
+       return;
+     }
+ 
+   while (data < end)
+     {
+       if (!piece_ok)
+ 	{
+ 	  if (nfrags == MAX_FRAGS)
+ 	    error (_("Too many pieces in location for \"%s\"."),
+ 		   SYMBOL_PRINT_NAME (symbol));
+ 
+ 	  fragments[nfrags].bytes = 0;
+ 	  data = dwarf2_tracepoint_var_loc (symbol, ax, &fragments[nfrags],
+ 					    gdbarch, data, end);
+ 	  nfrags++;
+ 	  piece_ok = 1;
+ 	}
+       else if (data[0] == DW_OP_piece)
+ 	{
+ 	  ULONGEST bytes;
+ 	      
+ 	  data = read_uleb128 (data + 1, end, &bytes);
+ 	  /* Only deal with 4 byte fragments for now.  */
+ 	  if (bytes != 4)
+ 	    error (_("DW_OP_piece %s not supported in location for \"%s\"."),
+ 		   pulongest (bytes), SYMBOL_PRINT_NAME (symbol));
+ 	  fragments[nfrags - 1].bytes = bytes;
+ 	  length += bytes;
+ 	  piece_ok = 0;
+ 	}
+       else
+ 	{
+ 	  bad = 1;
+ 	  break;
+ 	}
+     }
+ 
+   if (bad || data > end)
+     error (_("Corrupted DWARF expression for \"%s\"."),
+ 	   SYMBOL_PRINT_NAME (symbol));
+ 
+   /* If single expression, no pieces, convert to external format.  */
+   if (length == 0)
+     {
+       dwarf2_tracepoint_var_access (ax, value, &fragments[0]);
+       return;
+     }
+ 
+   if (length != TYPE_LENGTH (value->type))
+     error (_("Inconsistent piece information for \"%s\"."),
+ 	   SYMBOL_PRINT_NAME (symbol));
+ 
+   /* Emit bytecodes to assemble the pieces into a single stack entry.  */
+ 
+   for ((frag = (byte_order == BFD_ENDIAN_BIG ? 0 : nfrags - 1));
+        nfrags--;
+        (frag += (byte_order == BFD_ENDIAN_BIG ? 1 : -1)))
+     {
+       if (!first)
+ 	{
+ 	  /* shift the previous fragment up 32 bits */
+ 	  ax_const_l (ax, 32);
+ 	  ax_simple (ax, aop_lsh);
+ 	}
+ 
+       dwarf2_tracepoint_var_access (ax, value, &fragments[frag]);
+ 
+       switch (value->kind)
+ 	{
+ 	case axs_lvalue_register:
+ 	  ax_reg (ax, value->u.reg);
+ 	  break;
+ 
+ 	case axs_lvalue_memory:
+ 	  {
+ 	    extern int trace_kludge;  /* Ugh. */
+ 
+ 	    gdb_assert (fragments[frag].bytes == 4);
+ 	    if (trace_kludge)
+ 	      ax_trace_quick (ax, 4);
+ 	    ax_simple (ax, aop_ref32);
+ 	  }
+ 	  break;
+ 	}
+ 
+       if (!first)
+ 	{
+ 	  /* or the new fragment into the previous */
+ 	  ax_zero_ext (ax, 32);
+ 	  ax_simple (ax, aop_bit_or);
+ 	}
+       first = 0;
+     }
+   value->kind = axs_rvalue;
+ }
+ 
  
  /* Return the value of SYMBOL in FRAME using the DWARF-2 expression
     evaluator to calculate the location.  */
*************** locexpr_read_needs_frame (struct symbol 
*** 735,760 ****
  				      dlbaton->per_cu);
  }
  
! /* Print a natural-language description of SYMBOL to STREAM.  */
! static int
! locexpr_describe_location (struct symbol *symbol, struct ui_file *stream)
  {
!   /* FIXME: be more extensive.  */
!   struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
!   int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
  
-   if (dlbaton->size == 1
-       && dlbaton->data[0] >= DW_OP_reg0
-       && dlbaton->data[0] <= DW_OP_reg31)
-     {
-       struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
-       struct gdbarch *gdbarch = get_objfile_arch (objfile);
-       int regno = gdbarch_dwarf2_reg_to_regnum (gdbarch,
- 						dlbaton->data[0] - DW_OP_reg0);
        fprintf_filtered (stream,
! 			"a variable in register %s",
  			gdbarch_register_name (gdbarch, regno));
-       return 1;
      }
  
    /* The location expression for a TLS variable looks like this (on a
--- 898,1001 ----
  				      dlbaton->per_cu);
  }
  
! /* Describe a single piece of a location, returning an updated
!    position in the bytecode sequence.  */
! 
! static gdb_byte *
! locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
! 				 CORE_ADDR addr, struct objfile *objfile,
! 				 gdb_byte *data, int size, unsigned int addr_size)
  {
!   struct gdbarch *gdbarch = get_objfile_arch (objfile);
!   int regno;
! 
!   if (data[0] >= DW_OP_reg0 && data[0] <= DW_OP_reg31)
!     {
!       regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, data[0] - DW_OP_reg0);
!       fprintf_filtered (stream, _("a variable in $%s"),
! 			gdbarch_register_name (gdbarch, regno));
!       data += 1;
!     }
!   else if (data[0] == DW_OP_regx)
!     {
!       ULONGEST reg;
! 
!       data = read_uleb128 (data + 1, data + size, &reg);
!       regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, reg);
!       fprintf_filtered (stream, _("a variable in $%s"),
! 			gdbarch_register_name (gdbarch, regno));
!     }
!   else if (data[0] == DW_OP_fbreg)
!     {
!       struct block *b;
!       struct symbol *framefunc;
!       int frame_reg = 0;
!       LONGEST frame_offset;
!       gdb_byte *base_data;
!       size_t base_size;
!       LONGEST base_offset = 0;
! 
!       b = block_for_pc (addr);
! 
!       if (!b)
! 	error (_("No block found for address for symbol \"%s\"."),
! 	       SYMBOL_PRINT_NAME (symbol));
! 
!       framefunc = block_linkage_function (b);
! 
!       if (!framefunc)
! 	error (_("No function found for block for symbol \"%s\"."),
! 	       SYMBOL_PRINT_NAME (symbol));
! 
!       dwarf_expr_frame_base_1 (framefunc, addr, &base_data, &base_size);
! 
!       if (base_data[0] >= DW_OP_breg0 && base_data[0] <= DW_OP_breg31)
! 	{
! 	  gdb_byte *buf_end;
! 	  
! 	  frame_reg = base_data[0] - DW_OP_breg0;
! 	  buf_end = read_sleb128 (base_data + 1,
! 				  base_data + base_size, &base_offset);
! 	  if (buf_end != base_data + base_size)
! 	    error (_("Unexpected opcode after DW_OP_breg%u for symbol \"%s\"."),
! 		   frame_reg, SYMBOL_PRINT_NAME (symbol));
! 	}
!       else if (base_data[0] >= DW_OP_reg0 && base_data[0] <= DW_OP_reg31)
! 	{
! 	  /* The frame base is just the register, with no offset.  */
! 	  frame_reg = base_data[0] - DW_OP_reg0;
! 	  base_offset = 0;
! 	}
!       else
! 	{
! 	  /* We don't know what to do with the frame base expression,
! 	     so we can't trace this variable; give up.  */
! 	  error (_("Cannot describe location of symbol \"%s\"; "
! 		   "DWARF 2 encoding not handled, "
! 		   "first opcode in base data is 0x%x."),
! 		 SYMBOL_PRINT_NAME (symbol), base_data[0]);
! 	}
! 
!       regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, frame_reg);
! 
!       data = read_sleb128 (data + 1, data + size, &frame_offset);
! 
!       fprintf_filtered (stream, _("a variable at frame base reg $%s offset %s+%s"),
! 			gdbarch_register_name (gdbarch, regno),
! 			plongest (base_offset), plongest (frame_offset));
!     }
!   else if (data[0] >= DW_OP_breg0 && data[0] <= DW_OP_breg31)
!     {
!       LONGEST offset;
! 
!       regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, data[0] - DW_OP_breg0);
! 
!       data = read_sleb128 (data + 1, data + size, &offset);
  
        fprintf_filtered (stream,
! 			_("a variable at offset %s from base reg $%s"),
! 			plongest (offset),
  			gdbarch_register_name (gdbarch, regno));
      }
  
    /* The location expression for a TLS variable looks like this (on a
*************** locexpr_describe_location (struct symbol
*** 769,805 ****
       The operand represents the offset at which the variable is within
       the thread local storage.  */
  
!   if (dlbaton->size > 1 
!       && dlbaton->data[dlbaton->size - 1] == DW_OP_GNU_push_tls_address)
!     if (dlbaton->data[0] == DW_OP_addr)
!       {
! 	struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
! 	struct gdbarch *gdbarch = get_objfile_arch (objfile);
! 	CORE_ADDR offset = dwarf2_read_address (gdbarch,
! 						&dlbaton->data[1],
! 						&dlbaton->data[dlbaton->size - 1],
! 						addr_size);
! 	fprintf_filtered (stream, 
! 			  "a thread-local variable at offset %s in the "
! 			  "thread-local storage for `%s'",
! 			  paddress (gdbarch, offset), objfile->name);
! 	return 1;
!       }
!   
  
!   fprintf_filtered (stream,
! 		    "a variable with complex or multiple locations (DWARF2)");
!   return 1;
  }
  
  
! /* Describe the location of SYMBOL as an agent value in VALUE, generating
!    any necessary bytecode in AX.
  
!    NOTE drow/2003-02-26: This function is extremely minimal, because
!    doing it correctly is extremely complicated and there is no
!    publicly available stub with tracepoint support for me to test
!    against.  When there is one this function should be revisited.  */
  
  static void
  locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
--- 1010,1102 ----
       The operand represents the offset at which the variable is within
       the thread local storage.  */
  
!   else if (size > 1
! 	   && data[size - 1] == DW_OP_GNU_push_tls_address
! 	   && data[0] == DW_OP_addr)
!     {
!       CORE_ADDR offset = dwarf2_read_address (gdbarch,
! 					      data + 1,
! 					      data + size - 1,
! 					      addr_size);
!       fprintf_filtered (stream, 
! 			_("a thread-local variable at offset %s "
! 			  "in the thread-local storage for `%s'"),
! 			paddress (gdbarch, offset), objfile->name);
  
!       data += 1 + addr_size + 1;
!     }
!   else
!     fprintf_filtered (stream,
! 		      _("a variable with complex or multiple locations (DWARF2)"));
! 
!   return data;
  }
  
+ /* Describe a single location, which may in turn consist of multiple
+    pieces.  */
  
! static void
! locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr,
! 			     struct ui_file *stream, gdb_byte *data, int size,
! 			     struct objfile *objfile, unsigned int addr_size)
! {
!   gdb_byte *end = data + size;
!   int piece_done = 0, first_piece = 1, bad = 0;
! 
!   /* A multi-piece description consists of multiple sequences of bytes
!      each followed by DW_OP_piece + length of piece.  */
!   while (data < end)
!     {
!       if (!piece_done)
! 	{
! 	  if (first_piece)
! 	    first_piece = 0;
! 	  else
! 	    fprintf_filtered (stream, _(", and "));
! 
! 	  data = locexpr_describe_location_piece (symbol, stream, addr, objfile,
! 						  data, size, addr_size);
! 	  piece_done = 1;
! 	}
!       else if (data[0] == DW_OP_piece)
! 	{
! 	  ULONGEST bytes;
! 	      
! 	  data = read_uleb128 (data + 1, end, &bytes);
! 
! 	  fprintf_filtered (stream, _(" [%s-byte piece]"), pulongest (bytes));
! 
! 	  piece_done = 0;
! 	}
!       else
! 	{
! 	  bad = 1;
! 	  break;
! 	}
!     }
! 
!   if (bad || data > end)
!     error (_("Corrupted DWARF2 expression for \"%s\"."),
! 	   SYMBOL_PRINT_NAME (symbol));
! }
  
! /* Print a natural-language description of SYMBOL to STREAM.  This
!    version is for a symbol with a single location.  */
! 
! static void
! locexpr_describe_location (struct symbol *symbol, CORE_ADDR addr,
! 			   struct ui_file *stream)
! {
!   struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
!   struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
!   unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
! 
!   locexpr_describe_location_1 (symbol, addr, stream, dlbaton->data, dlbaton->size,
! 			       objfile, addr_size);
! }
! 
! /* Describe the location of SYMBOL as an agent value in VALUE, generating
!    any necessary bytecode in AX.  */
  
  static void
  locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
*************** loclist_read_needs_frame (struct symbol 
*** 863,875 ****
    return 1;
  }
  
! /* Print a natural-language description of SYMBOL to STREAM.  */
! static int
! loclist_describe_location (struct symbol *symbol, struct ui_file *stream)
  {
!   /* FIXME: Could print the entire list of locations.  */
!   fprintf_filtered (stream, "a variable with multiple locations");
!   return 1;
  }
  
  /* Describe the location of SYMBOL as an agent value in VALUE, generating
--- 1160,1248 ----
    return 1;
  }
  
! /* Print a natural-language description of SYMBOL to STREAM.  This
!    version applies when there is a list of different locations, each
!    with a specified address range.  */
! 
! static void
! loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
! 			   struct ui_file *stream)
  {
!   struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
!   CORE_ADDR low, high;
!   gdb_byte *loc_ptr, *buf_end;
!   int length, first = 1;
!   struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
!   struct gdbarch *gdbarch = get_objfile_arch (objfile);
!   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
!   unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
!   CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
!   /* Adjust base_address for relocatable objects.  */
!   CORE_ADDR base_offset = ANOFFSET (objfile->section_offsets,
! 				    SECT_OFF_TEXT (objfile));
!   CORE_ADDR base_address = dlbaton->base_address + base_offset;
! 
!   loc_ptr = dlbaton->data;
!   buf_end = dlbaton->data + dlbaton->size;
! 
!   fprintf_filtered (stream, _("multi-location ("));
! 
!   /* Iterate through locations until we run out.  */
!   while (1)
!     {
!       if (buf_end - loc_ptr < 2 * addr_size)
! 	error (_("Corrupted DWARF expression for symbol \"%s\"."),
! 	       SYMBOL_PRINT_NAME (symbol));
! 
!       low = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
!       loc_ptr += addr_size;
! 
!       /* A base-address-selection entry.  */
!       if (low == base_mask)
! 	{
! 	  base_address = dwarf2_read_address (gdbarch,
! 					      loc_ptr, buf_end, addr_size);
! 	  fprintf_filtered (stream, _("[base address %s]"),
! 			    paddress (gdbarch, base_address));
! 	  loc_ptr += addr_size;
! 	  continue;
! 	}
! 
!       high = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
!       loc_ptr += addr_size;
! 
!       /* An end-of-list entry.  */
!       if (low == 0 && high == 0)
! 	{
! 	  /* Indicate the end of the list, for readability.  */
! 	  fprintf_filtered (stream, _(")"));
! 	  return;
! 	}
! 
!       /* Otherwise, a location expression entry.  */
!       low += base_address;
!       high += base_address;
! 
!       length = extract_unsigned_integer (loc_ptr, 2, byte_order);
!       loc_ptr += 2;
! 
!       /* Separate the different locations with a semicolon.  */
!       if (first)
! 	first = 0;
!       else
! 	fprintf_filtered (stream, _("; "));
! 
!       /* (It would improve readability to print only the minimum
! 	 necessary digits of the second number of the range.)  */
!       fprintf_filtered (stream, _("range %s-%s, "),
! 			paddress (gdbarch, low), paddress (gdbarch, high));
! 
!       /* Now describe this particular location.  */
!       locexpr_describe_location_1 (symbol, low, stream, loc_ptr, length,
! 				   objfile, addr_size);
! 
!       loc_ptr += length;
!     }
  }
  
  /* Describe the location of SYMBOL as an agent value in VALUE, generating
Index: printcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/printcmd.c,v
retrieving revision 1.173
diff -p -r1.173 printcmd.c
*** printcmd.c	5 Mar 2010 20:18:14 -0000	1.173
--- printcmd.c	16 Apr 2010 00:14:41 -0000
*************** sym_info (char *arg, int from_tty)
*** 1148,1167 ****
  static void
  address_info (char *exp, int from_tty)
  {
    struct gdbarch *gdbarch;
    int regno;
    struct symbol *sym;
    struct minimal_symbol *msymbol;
    long val;
    struct obj_section *section;
!   CORE_ADDR load_addr;
    int is_a_field_of_this;	/* C++: lookup_symbol sets this to nonzero
  				   if exp is a field of `this'. */
  
    if (exp == 0)
      error (_("Argument required."));
  
!   sym = lookup_symbol (exp, get_selected_block (0), VAR_DOMAIN,
  		       &is_a_field_of_this);
    if (sym == NULL)
      {
--- 1148,1168 ----
  static void
  address_info (char *exp, int from_tty)
  {
+   struct block *block;
    struct gdbarch *gdbarch;
    int regno;
    struct symbol *sym;
    struct minimal_symbol *msymbol;
    long val;
    struct obj_section *section;
!   CORE_ADDR load_addr, context_pc = 0;
    int is_a_field_of_this;	/* C++: lookup_symbol sets this to nonzero
  				   if exp is a field of `this'. */
  
    if (exp == 0)
      error (_("Argument required."));
  
!   sym = lookup_symbol (exp, get_selected_block (&context_pc), VAR_DOMAIN,
  		       &is_a_field_of_this);
    if (sym == NULL)
      {
*************** address_info (char *exp, int from_tty)
*** 1242,1248 ****
  	 Unfortunately DWARF 2 stores the frame-base (instead of the
  	 function) location in a function's symbol.  Oops!  For the
  	 moment enable this when/where applicable.  */
!       SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, gdb_stdout);
        break;
  
      case LOC_REGISTER:
--- 1243,1249 ----
  	 Unfortunately DWARF 2 stores the frame-base (instead of the
  	 function) location in a function's symbol.  Oops!  For the
  	 moment enable this when/where applicable.  */
!       SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, context_pc, gdb_stdout);
        break;
  
      case LOC_REGISTER:
Index: symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.150
diff -p -r1.150 symtab.h
*** symtab.h	26 Mar 2010 19:41:50 -0000	1.150
--- symtab.h	16 Apr 2010 00:14:41 -0000
*************** struct symbol_computed_ops
*** 516,523 ****
    int (*read_needs_frame) (struct symbol * symbol);
  
    /* Write to STREAM a natural-language description of the location of
!      SYMBOL.  */
!   int (*describe_location) (struct symbol * symbol, struct ui_file * stream);
  
    /* Tracepoint support.  Append bytecodes to the tracepoint agent
       expression AX that push the address of the object SYMBOL.  Set
--- 516,524 ----
    int (*read_needs_frame) (struct symbol * symbol);
  
    /* Write to STREAM a natural-language description of the location of
!      SYMBOL, in the context of ADDR.  */
!   void (*describe_location) (struct symbol * symbol, CORE_ADDR addr,
! 			     struct ui_file * stream);
  
    /* Tracepoint support.  Append bytecodes to the tracepoint agent
       expression AX that push the address of the object SYMBOL.  Set
Index: tracepoint.c
===================================================================
RCS file: /cvs/src/src/gdb/tracepoint.c,v
retrieving revision 1.178
diff -p -r1.178 tracepoint.c
*** tracepoint.c	13 Apr 2010 03:53:50 -0000	1.178
--- tracepoint.c	16 Apr 2010 00:14:41 -0000
*************** scope_info (char *args, int from_tty)
*** 2361,2367 ****
  	      printf_filtered ("optimized out.\n");
  	      continue;
  	    case LOC_COMPUTED:
! 	      SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, gdb_stdout);
  	      break;
  	    }
  	  if (SYMBOL_TYPE (sym))
--- 2361,2369 ----
  	      printf_filtered ("optimized out.\n");
  	      continue;
  	    case LOC_COMPUTED:
! 	      SYMBOL_COMPUTED_OPS (sym)->describe_location (sym,
! 							    BLOCK_START (block),
! 							    gdb_stdout);
  	      break;
  	    }
  	  if (SYMBOL_TYPE (sym))

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