* dwarf2expr.h (dwarf_value_location): Add more comments describing
authorDoug Evans <dje@google.com>
Tue, 15 Sep 2009 16:20:53 +0000 (16:20 +0000)
committerDoug Evans <dje@google.com>
Tue, 15 Sep 2009 16:20:53 +0000 (16:20 +0000)
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 whether 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.

gdb/ChangeLog
gdb/dwarf2-frame.c
gdb/dwarf2expr.c
gdb/dwarf2expr.h
gdb/dwarf2loc.c

index 32f6ac0..0ef55f6 100644 (file)
@@ -1,5 +1,34 @@
 2009-09-15  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 whether 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.
+
        * target.c (memory_xfer_partial): Pass correct length to dcache_update.
 
 2009-09-15  Jan Kratochvil  <jan.kratochvil@redhat.com>
index a923edf..668c434 100644 (file)
@@ -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, ULONGEST len, int addr_size,
   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 *this_frame, void **this_cache)
     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_info *this_frame, void **this_cache,
     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_info *this_frame, void **this_cache,
     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 2b0f585..46bc9d7 100644 (file)
@@ -87,7 +87,7 @@ dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need)
     {
       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_context *ctx, size_t need)
 /* 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_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)];
+  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 *ctx, ULONGEST size)
       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_context *ctx,
     {
       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_context *ctx,
            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_context *ctx,
        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_context *ctx,
 
        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_context *ctx,
 
        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_context *ctx,
        }
 
       /* Most things push a result value.  */
-      dwarf_expr_push (ctx, result);
+      dwarf_expr_push (ctx, result, in_stack_memory);
     no_push:;
     }
 
index 9d9b127..a9a8a05 100644 (file)
 /* 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 dwarf_expr_context *ctx);
 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 c314a78..3a81202 100644 (file)
@@ -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, struct value *from)
        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 *var, struct frame_info *frame,
        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 *var, struct frame_info *frame,
 
   return retval;
 }
-
-
-
-
 \f
 /* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */