aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog29
-rw-r--r--gdb/dwarf2-frame.c11
-rw-r--r--gdb/dwarf2expr.c49
-rw-r--r--gdb/dwarf2expr.h43
-rw-r--r--gdb/dwarf2loc.c21
5 files changed, 122 insertions, 31 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 32f6ac0..0ef55f6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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>
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index a923edf..668c434 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -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:
diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
index 2b0f585..46bc9d7 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -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:;
}
diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
index 9d9b127..a9a8a05 100644
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -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 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);
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index c314a78..3a81202 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -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;
}
-
-
-
-
/* Helper functions and baton for dwarf2_loc_desc_needs_frame. */