[RFC] better dwarf checking for values on the stack

Doug Evans dje@google.com
Mon Sep 14 23:04:00 GMT 2009


On Mon, Sep 14, 2009 at 10:53 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Doug" == Doug Evans <dje@google.com> writes:
>
> Tom> It seems to me that the inferior-stack-ness of a value must be an
> Tom> attribute carried alongside the value on the dwarf stack.
>
> Doug> How about this?
>
> Yeah, I think this is the way to go.  Thanks.

Thanks.

I'll check this in in a few days if there are no further issues.

2009-09-14  Doug Evans  <dje@google.com>

	* dwarf2expr.h (dwarf_value_location): Add more comments describing
	enum values.
	(struct dwarf_stack_value): New struct.
	(struct dwarf_expr_context): Change type of `stack' from CORE_ADDR*
	to struct dwarf_stack_value*.
	(struct dwarf_expr_piece): Move `v.value' into its own struct, v.expr,
	all uses updated.  Add v.expr.in_stack_memory.
	(dwarf_expr_push): Update declaration.
	(dwarf_expr_fetch_in_stack_memory): Declare.
	* dwarf2expr.c (dwarf_expr_grow_stack): Update calculation of
	size of stack value.
	(dwarf_expr_push): New arg in_stack_memory, all callers updated.
	(dwarf_expr_fetch_in_stack_memory): New function.
	(add_piece): Set in_stack_memory for non-literal values.
	(execute_stack_op): Allow ops to specify where the value is on the
	program's stack.
	(execute_stack_op, case DW_OP_fbreg): Mark value as in stack memory.
	(execute_stack_op, case DW_OP_call_frame_cfa): Ditto.
	(execute_stack_op, case DW_OP_dup): Copy in_stack_memory flag.
	(execute_stack_op, cases DW_OP_pick, DW_OP_over): Ditto.
	(execute_stack_op, cases DW_OP_swap, DW_OP_rot): Update type of
	dwarf stack value.
	* dwarf2loc.c (read_pieced_value): Call read_stack for values known
	to be on the program's stack.
	(dwarf2_evaluate_loc_desc, case DWARF_VALUE_MEMORY): Call
	set_value_stack only for objects known to be in stack memory.
	* dwarf2-frame.c (execute_stack_op): New arg initial_in_stack_memory,
	all callers updated.
-------------- next part --------------
2009-09-14  Doug Evans  <dje@google.com>

	* dwarf2expr.h (dwarf_value_location): Add more comments describing
	enum values.
	(struct dwarf_stack_value): New struct.
	(struct dwarf_expr_context): Change type of `stack' from CORE_ADDR*
	to struct dwarf_stack_value*.
	(struct dwarf_expr_piece): Move `v.value' into its own struct, v.expr,
	all uses updated.  Add v.expr.in_stack_memory.
	(dwarf_expr_push): Update declaration.
	(dwarf_expr_fetch_in_stack_memory): Declare.
	* dwarf2expr.c (dwarf_expr_grow_stack): Update calculation of
	size of stack value.
	(dwarf_expr_push): New arg in_stack_memory, all callers updated.
	(dwarf_expr_fetch_in_stack_memory): New function.
	(add_piece): Set in_stack_memory for non-literal values.
	(execute_stack_op): Allow ops to specify where the value is on the
	program's stack.
	(execute_stack_op, case DW_OP_fbreg): Mark value as in stack memory.
	(execute_stack_op, case DW_OP_call_frame_cfa): Ditto.
	(execute_stack_op, case DW_OP_dup): Copy in_stack_memory flag.
	(execute_stack_op, cases DW_OP_pick, DW_OP_over): Ditto.
	(execute_stack_op, cases DW_OP_swap, DW_OP_rot): Update type of
	dwarf stack value.
	* dwarf2loc.c (read_pieced_value): Call read_stack for values known
	to be on the program's stack.
	(dwarf2_evaluate_loc_desc, case DWARF_VALUE_MEMORY): Call
	set_value_stack only for objects known to be in stack memory.
	* dwarf2-frame.c (execute_stack_op): New arg initial_in_stack_memory,
	all callers updated.

Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.98
diff -u -p -r1.98 dwarf2-frame.c
--- dwarf2-frame.c	11 Sep 2009 18:38:39 -0000	1.98
+++ dwarf2-frame.c	14 Sep 2009 22:43:28 -0000
@@ -357,7 +357,8 @@ register %s (#%d) at %s"),
 
 static CORE_ADDR
 execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size,
-		  struct frame_info *this_frame, CORE_ADDR initial)
+		  struct frame_info *this_frame, CORE_ADDR initial,
+		  int initial_in_stack_memory)
 {
   struct dwarf_expr_context *ctx;
   CORE_ADDR result;
@@ -375,7 +376,7 @@ execute_stack_op (gdb_byte *exp, ULONGES
   ctx->get_frame_cfa = no_get_frame_cfa;
   ctx->get_tls_address = no_get_tls_address;
 
-  dwarf_expr_push (ctx, initial);
+  dwarf_expr_push (ctx, initial, initial_in_stack_memory);
   dwarf_expr_eval (ctx, exp, len);
   result = dwarf_expr_fetch (ctx, 0);
 
@@ -975,7 +976,7 @@ dwarf2_frame_cache (struct frame_info *t
     case CFA_EXP:
       cache->cfa =
 	execute_stack_op (fs->regs.cfa_exp, fs->regs.cfa_exp_len,
-			  cache->addr_size, this_frame, 0);
+			  cache->addr_size, this_frame, 0, 0);
       break;
 
     default:
@@ -1131,7 +1132,7 @@ dwarf2_frame_prev_register (struct frame
     case DWARF2_FRAME_REG_SAVED_EXP:
       addr = execute_stack_op (cache->reg[regnum].loc.exp,
 			       cache->reg[regnum].exp_len,
-			       cache->addr_size, this_frame, cache->cfa);
+			       cache->addr_size, this_frame, cache->cfa, 1);
       return frame_unwind_got_memory (this_frame, regnum, addr);
 
     case DWARF2_FRAME_REG_SAVED_VAL_OFFSET:
@@ -1141,7 +1142,7 @@ dwarf2_frame_prev_register (struct frame
     case DWARF2_FRAME_REG_SAVED_VAL_EXP:
       addr = execute_stack_op (cache->reg[regnum].loc.exp,
 			       cache->reg[regnum].exp_len,
-			       cache->addr_size, this_frame, cache->cfa);
+			       cache->addr_size, this_frame, cache->cfa, 1);
       return frame_unwind_got_constant (this_frame, regnum, addr);
 
     case DWARF2_FRAME_REG_UNSPECIFIED:
Index: dwarf2expr.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2expr.c,v
retrieving revision 1.37
diff -u -p -r1.37 dwarf2expr.c
--- dwarf2expr.c	11 Sep 2009 23:11:34 -0000	1.37
+++ dwarf2expr.c	14 Sep 2009 22:43:28 -0000
@@ -87,7 +87,7 @@ dwarf_expr_grow_stack (struct dwarf_expr
     {
       size_t newlen = ctx->stack_len + need + 10;
       ctx->stack = xrealloc (ctx->stack,
-			     newlen * sizeof (CORE_ADDR));
+			     newlen * sizeof (struct dwarf_stack_value));
       ctx->stack_allocated = newlen;
     }
 }
@@ -95,10 +95,15 @@ dwarf_expr_grow_stack (struct dwarf_expr
 /* Push VALUE onto CTX's stack.  */
 
 void
-dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value)
+dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value,
+		 int in_stack_memory)
 {
+  struct dwarf_stack_value *v;
+
   dwarf_expr_grow_stack (ctx, 1);
-  ctx->stack[ctx->stack_len++] = value;
+  v = &ctx->stack[ctx->stack_len++];
+  v->value = value;
+  v->in_stack_memory = in_stack_memory;
 }
 
 /* Pop the top item off of CTX's stack.  */
@@ -119,7 +124,19 @@ dwarf_expr_fetch (struct dwarf_expr_cont
   if (ctx->stack_len <= n)
      error (_("Asked for position %d of stack, stack only has %d elements on it."),
 	    n, ctx->stack_len);
-  return ctx->stack[ctx->stack_len - (1 + n)];
+  return ctx->stack[ctx->stack_len - (1 + n)].value;
+
+}
+
+/* Retrieve the in_stack_memory flag of the N'th item on CTX's stack.  */
+
+int
+dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n)
+{
+  if (ctx->stack_len <= n)
+     error (_("Asked for position %d of stack, stack only has %d elements on it."),
+	    n, ctx->stack_len);
+  return ctx->stack[ctx->stack_len - (1 + n)].in_stack_memory;
 
 }
 
@@ -148,7 +165,10 @@ add_piece (struct dwarf_expr_context *ct
       p->v.literal.length = ctx->len;
     }
   else
-    p->v.value = dwarf_expr_fetch (ctx, 0);
+    {
+      p->v.expr.value = dwarf_expr_fetch (ctx, 0);
+      p->v.expr.in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
+    }
 }
 
 /* Evaluate the expression at ADDR (LEN bytes long) using the context
@@ -329,6 +349,13 @@ execute_stack_op (struct dwarf_expr_cont
     {
       enum dwarf_location_atom op = *op_ptr++;
       CORE_ADDR result;
+      /* Assume the value is not in stack memory.
+	 Code that knows otherwise sets this to 1.
+	 Some arithmetic on stack addresses can probably be assumed to still
+	 be a stack address, but we skip this complication for now.
+	 This is just an optimization, so it's always ok to punt
+	 and leave this as 0.  */
+      int in_stack_memory = 0;
       ULONGEST uoffset, reg;
       LONGEST offset;
 
@@ -557,12 +584,15 @@ execute_stack_op (struct dwarf_expr_cont
 	    if (ctx->location == DWARF_VALUE_REGISTER)
 	      result = (ctx->read_reg) (ctx->baton, result);
 	    result = result + offset;
+	    in_stack_memory = 1;
 	    ctx->stack_len = before_stack_len;
 	    ctx->location = DWARF_VALUE_MEMORY;
 	  }
 	  break;
+
 	case DW_OP_dup:
 	  result = dwarf_expr_fetch (ctx, 0);
+	  in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
 	  break;
 
 	case DW_OP_drop:
@@ -572,11 +602,12 @@ execute_stack_op (struct dwarf_expr_cont
 	case DW_OP_pick:
 	  offset = *op_ptr++;
 	  result = dwarf_expr_fetch (ctx, offset);
+	  in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, offset);
 	  break;
 	  
 	case DW_OP_swap:
 	  {
-	    CORE_ADDR t1, t2;
+	    struct dwarf_stack_value t1, t2;
 
 	    if (ctx->stack_len < 2)
 	       error (_("Not enough elements for DW_OP_swap. Need 2, have %d."),
@@ -590,11 +621,12 @@ execute_stack_op (struct dwarf_expr_cont
 
 	case DW_OP_over:
 	  result = dwarf_expr_fetch (ctx, 1);
+	  in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 1);
 	  break;
 
 	case DW_OP_rot:
 	  {
-	    CORE_ADDR t1, t2, t3;
+	    struct dwarf_stack_value t1, t2, t3;
 
 	    if (ctx->stack_len < 3)
 	       error (_("Not enough elements for DW_OP_rot. Need 3, have %d."),
@@ -758,6 +790,7 @@ execute_stack_op (struct dwarf_expr_cont
 
 	case DW_OP_call_frame_cfa:
 	  result = (ctx->get_frame_cfa) (ctx->baton);
+	  in_stack_memory = 1;
 	  break;
 
 	case DW_OP_GNU_push_tls_address:
@@ -820,7 +853,7 @@ execute_stack_op (struct dwarf_expr_cont
 	}
 
       /* Most things push a result value.  */
-      dwarf_expr_push (ctx, result);
+      dwarf_expr_push (ctx, result, in_stack_memory);
     no_push:;
     }
 
Index: dwarf2expr.h
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2expr.h,v
retrieving revision 1.18
diff -u -p -r1.18 dwarf2expr.h
--- dwarf2expr.h	11 Sep 2009 18:38:39 -0000	1.18
+++ dwarf2expr.h	14 Sep 2009 22:43:28 -0000
@@ -26,22 +26,41 @@
 /* The location of a value.  */
 enum dwarf_value_location
 {
-  /* The piece is in memory.  */
+  /* The piece is in memory.
+     The value on the dwarf stack is its address.  */
   DWARF_VALUE_MEMORY,
-  /* The piece is in a register.  */
+
+  /* The piece is in a register.
+     The value on the dwarf stack is the register number.  */
   DWARF_VALUE_REGISTER,
-  /* The piece is on the stack.  */
+
+  /* The piece is on the dwarf stack.  */
   DWARF_VALUE_STACK,
+
   /* The piece is a literal.  */
   DWARF_VALUE_LITERAL
 };
 
+/* The dwarf expression stack.  */
+
+struct dwarf_stack_value
+{
+  CORE_ADDR value;
+
+  /* Non-zero if the piece is in memory and is known to be
+     on the program's stack.  It is always ok to set this to zero.
+     This is used, for example, to optimize memory access from the target.
+     It can vastly speed up backtraces on long latency connections when
+     "set stack-cache on".  */
+  int in_stack_memory;
+};
+
 /* The expression evaluator works with a dwarf_expr_context, describing
    its current state and its callbacks.  */
 struct dwarf_expr_context
 {
   /* The stack of values, allocated with xmalloc.  */
-  CORE_ADDR *stack;
+  struct dwarf_stack_value *stack;
 
   /* The number of values currently pushed on the stack, and the
      number of elements allocated to the stack.  */
@@ -111,7 +130,7 @@ struct dwarf_expr_context
      Each time DW_OP_piece is executed, we add a new element to the
      end of this array, recording the current top of the stack, the
      current location, and the size given as the operand to
-     DW_OP_piece.  We then pop the top value from the stack, rest the
+     DW_OP_piece.  We then pop the top value from the stack, reset the
      location, and resume evaluation.
 
      The Dwarf spec doesn't say whether DW_OP_piece pops the top value
@@ -140,8 +159,14 @@ struct dwarf_expr_piece
 
   union
   {
-    /* This piece's address or register number.  */
-    CORE_ADDR value;
+    struct
+    {
+      /* This piece's address or register number.  */
+      CORE_ADDR value;
+      /* Non-zero if the piece is known to be in memory and on
+	 the program's stack.  */
+      int in_stack_memory;
+    } expr;
 
     struct
     {
@@ -162,11 +187,13 @@ void free_dwarf_expr_context (struct dwa
 struct cleanup *
     make_cleanup_free_dwarf_expr_context (struct dwarf_expr_context *ctx);
 
-void dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value);
+void dwarf_expr_push (struct dwarf_expr_context *ctx, CORE_ADDR value,
+		      int in_stack_memory);
 void dwarf_expr_pop (struct dwarf_expr_context *ctx);
 void dwarf_expr_eval (struct dwarf_expr_context *ctx, unsigned char *addr,
 		      size_t len);
 CORE_ADDR dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n);
+int dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n);
 
 
 gdb_byte *read_uleb128 (gdb_byte *buf, gdb_byte *buf_end, ULONGEST * r);
Index: dwarf2loc.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2loc.c,v
retrieving revision 1.67
diff -u -p -r1.67 dwarf2loc.c
--- dwarf2loc.c	11 Sep 2009 18:38:39 -0000	1.67
+++ dwarf2loc.c	14 Sep 2009 22:43:28 -0000
@@ -265,14 +265,17 @@ read_pieced_value (struct value *v)
 	    struct gdbarch *arch = get_frame_arch (frame);
 	    bfd_byte regval[MAX_REGISTER_SIZE];
 	    int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch,
-							   p->v.value);
+							   p->v.expr.value);
 	    get_frame_register (frame, gdb_regnum, regval);
 	    memcpy (contents + offset, regval, p->size);
 	  }
 	  break;
 
 	case DWARF_VALUE_MEMORY:
-	  read_memory (p->v.value, contents + offset, p->size);
+	  if (p->v.expr.in_stack_memory)
+	    read_stack (p->v.expr.value, contents + offset, p->size);
+	  else
+	    read_memory (p->v.expr.value, contents + offset, p->size);
 	  break;
 
 	case DWARF_VALUE_STACK:
@@ -282,7 +285,7 @@ read_pieced_value (struct value *v)
 	    int addr_size = gdbarch_addr_bit (c->arch) / 8;
 	    store_unsigned_integer (bytes, addr_size,
 				    gdbarch_byte_order (c->arch),
-				    p->v.value);
+				    p->v.expr.value);
 	    n = p->size;
 	    if (n > addr_size)
 	      n = addr_size;
@@ -330,12 +333,12 @@ write_pieced_value (struct value *to, st
 	case DWARF_VALUE_REGISTER:
 	  {
 	    struct gdbarch *arch = get_frame_arch (frame);
-	    int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.value);
+	    int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.expr.value);
 	    put_frame_register (frame, gdb_regnum, contents + offset);
 	  }
 	  break;
 	case DWARF_VALUE_MEMORY:
-	  write_memory (p->v.value, contents + offset, p->size);
+	  write_memory (p->v.expr.value, contents + offset, p->size);
 	  break;
 	default:
 	  set_value_optimized_out (to, 1);
@@ -434,11 +437,13 @@ dwarf2_evaluate_loc_desc (struct symbol 
 	case DWARF_VALUE_MEMORY:
 	  {
 	    CORE_ADDR address = dwarf_expr_fetch (ctx, 0);
+	    int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
 
 	    retval = allocate_value (SYMBOL_TYPE (var));
 	    VALUE_LVAL (retval) = lval_memory;
 	    set_value_lazy (retval, 1);
-	    set_value_stack (retval, 1);
+	    if (in_stack_memory)
+	      set_value_stack (retval, 1);
 	    set_value_address (retval, address);
 	  }
 	  break;
@@ -485,10 +490,6 @@ dwarf2_evaluate_loc_desc (struct symbol 
 
   return retval;
 }
-
-
-
-
 

 /* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
 


More information about the Gdb-patches mailing list