* 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.
This commit is contained in:
Doug Evans 2009-09-15 16:20:53 +00:00
parent 7d4f32d36a
commit 44353522ec
5 changed files with 122 additions and 31 deletions

View 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>

View 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:

View 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:;
}

View File

@ -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);

View 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;
}
/* Helper functions and baton for dwarf2_loc_desc_needs_frame. */