* dwarf2loc.c (struct piece_closure) <arch>: New field.
	(dwarf2_evaluate_loc_desc): Update.
	(dwarf2_loc_desc_needs_frame): Likewise.
	(allocate_piece_closure): Initialize new field.
	(read_pieced_value): Update.
	(write_pieced_value): Update.
	(copy_pieced_value_closure): Update.
	* dwarf2expr.h (enum dwarf_value_location): New.
	(struct dwarf_expr_context) <in_reg>: Remove.
	<location, len, data>: New fields.
	(struct dwarf_expr_piece) <in_reg, value>: Remove.
	<location, v>: New fields.
	* dwarf2expr.c (add_piece): Remove in_reg, value arguments.
	Update.
	(require_composition): New function.
	(execute_stack_op): Update.
	<DW_OP_implicit_value, DW_OP_stack_value>: New cases.
	<DW_OP_reg0>: Set location, not in_reg.
	<DW_OP_regx>: Likewise.  Use require_composition.
	<DW_OP_fbreg>: Update.
	<DW_OP_piece>: Likewise.
	* dwarf2-frame.c (execute_stack_op): Update.
gdb/testsuite
	* gdb.dwarf2/valop.S: New file.
	* gdb.dwarf2/valop.exp: New file.
This commit is contained in:
Tom Tromey
2009-09-11 18:38:39 +00:00
parent a05e8785c7
commit cec03d703f
8 changed files with 822 additions and 80 deletions

View File

@ -125,8 +125,7 @@ dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
/* Add a new piece to CTX's piece list. */
static void
add_piece (struct dwarf_expr_context *ctx,
int in_reg, CORE_ADDR value, ULONGEST size)
add_piece (struct dwarf_expr_context *ctx, ULONGEST size)
{
struct dwarf_expr_piece *p;
@ -141,9 +140,15 @@ add_piece (struct dwarf_expr_context *ctx,
* sizeof (struct dwarf_expr_piece));
p = &ctx->pieces[ctx->num_pieces - 1];
p->in_reg = in_reg;
p->value = value;
p->location = ctx->location;
p->size = size;
if (p->location == DWARF_VALUE_LITERAL)
{
p->v.literal.data = ctx->data;
p->v.literal.length = ctx->len;
}
else
p->v.value = dwarf_expr_fetch (ctx, 0);
}
/* Evaluate the expression at ADDR (LEN bytes long) using the context
@ -287,6 +292,23 @@ signed_address_type (struct gdbarch *gdbarch, int addr_size)
}
}
/* Check that the current operator is either at the end of an
expression, or that it is followed by a composition operator. */
static void
require_composition (gdb_byte *op_ptr, gdb_byte *op_end, const char *op_name)
{
/* It seems like DW_OP_GNU_uninit should be handled here. However,
it doesn't seem to make sense for DW_OP_*_value, and it was not
checked at the other place that this function is called. */
if (op_ptr != op_end && *op_ptr != DW_OP_piece && *op_ptr != DW_OP_bit_piece)
error (_("DWARF-2 expression error: `%s' operations must be "
"used either alone or in conjuction with DW_OP_piece "
"or DW_OP_bit_piece."),
op_name);
}
/* The engine for the expression evaluator. Using the context in CTX,
evaluate the expression between OP_PTR and OP_END. */
@ -295,8 +317,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
gdb_byte *op_ptr, gdb_byte *op_end)
{
enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch);
ctx->in_reg = 0;
ctx->location = DWARF_VALUE_MEMORY;
ctx->initialized = 1; /* Default is initialized. */
if (ctx->recursion_depth > ctx->max_recursion_depth)
@ -436,20 +457,36 @@ execute_stack_op (struct dwarf_expr_context *ctx,
"used either alone or in conjuction with DW_OP_piece."));
result = op - DW_OP_reg0;
ctx->in_reg = 1;
ctx->location = DWARF_VALUE_REGISTER;
break;
case DW_OP_regx:
op_ptr = read_uleb128 (op_ptr, op_end, &reg);
if (op_ptr != op_end && *op_ptr != DW_OP_piece)
error (_("DWARF-2 expression error: DW_OP_reg operations must be "
"used either alone or in conjuction with DW_OP_piece."));
require_composition (op_ptr, op_end, "DW_OP_regx");
result = reg;
ctx->in_reg = 1;
ctx->location = DWARF_VALUE_REGISTER;
break;
case DW_OP_implicit_value:
{
ULONGEST len;
op_ptr = read_uleb128 (op_ptr, op_end, &len);
if (op_ptr + len > op_end)
error (_("DW_OP_implicit_value: too few bytes available."));
ctx->len = len;
ctx->data = op_ptr;
ctx->location = DWARF_VALUE_LITERAL;
op_ptr += len;
require_composition (op_ptr, op_end, "DW_OP_implicit_value");
}
goto no_push;
case DW_OP_stack_value:
ctx->location = DWARF_VALUE_STACK;
require_composition (op_ptr, op_end, "DW_OP_stack_value");
goto no_push;
case DW_OP_breg0:
case DW_OP_breg1:
case DW_OP_breg2:
@ -513,12 +550,15 @@ execute_stack_op (struct dwarf_expr_context *ctx,
specific this_base method. */
(ctx->get_frame_base) (ctx->baton, &datastart, &datalen);
dwarf_expr_eval (ctx, datastart, datalen);
if (ctx->location == DWARF_VALUE_LITERAL
|| ctx->location == DWARF_VALUE_STACK)
error (_("Not implemented: computing frame base using explicit value operator"));
result = dwarf_expr_fetch (ctx, 0);
if (ctx->in_reg)
if (ctx->location == DWARF_VALUE_REGISTER)
result = (ctx->read_reg) (ctx->baton, result);
result = result + offset;
ctx->stack_len = before_stack_len;
ctx->in_reg = 0;
ctx->location = DWARF_VALUE_MEMORY;
}
break;
case DW_OP_dup:
@ -758,12 +798,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
/* Record the piece. */
op_ptr = read_uleb128 (op_ptr, op_end, &size);
addr_or_regnum = dwarf_expr_fetch (ctx, 0);
add_piece (ctx, ctx->in_reg, addr_or_regnum, size);
add_piece (ctx, size);
/* Pop off the address/regnum, and clear the in_reg flag. */
dwarf_expr_pop (ctx);
ctx->in_reg = 0;
/* Pop off the address/regnum, and reset the location
type. */
if (ctx->location != DWARF_VALUE_LITERAL)
dwarf_expr_pop (ctx);
ctx->location = DWARF_VALUE_MEMORY;
}
goto no_push;