mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-17 13:10:12 +08:00
* dwarf2expr.h (struct dwarf_expr_context): New members
'num_pieces' and 'pieces', for returning the result of an expression that uses DW_OP_piece. (struct dwarf_expr_piece): New struct type. * dwarf2expr.c (new_dwarf_expr_context): Initialize num_pieces and pieces. (free_dwarf_expr_context): Free pieces, if any. (add_piece): New function. (execute_stack_op): Implement DW_OP_piece. * dwarf2loc.c (dwarf2_evaluate_loc_desc): If the result of the expression is a list of pieces, print an error message. (dwarf2_loc_desc_needs_frame): If the expression yields pieces, and any piece is in a register, then we need a frame.
This commit is contained in:
parent
8d2c00cb73
commit
87808bd699
@ -1,5 +1,19 @@
|
||||
2004-08-24 Jim Blandy <jimb@redhat.com>
|
||||
|
||||
* dwarf2expr.h (struct dwarf_expr_context): New members
|
||||
'num_pieces' and 'pieces', for returning the result of an
|
||||
expression that uses DW_OP_piece.
|
||||
(struct dwarf_expr_piece): New struct type.
|
||||
* dwarf2expr.c (new_dwarf_expr_context): Initialize num_pieces and
|
||||
pieces.
|
||||
(free_dwarf_expr_context): Free pieces, if any.
|
||||
(add_piece): New function.
|
||||
(execute_stack_op): Implement DW_OP_piece.
|
||||
* dwarf2loc.c (dwarf2_evaluate_loc_desc): If the result of the
|
||||
expression is a list of pieces, print an error message.
|
||||
(dwarf2_loc_desc_needs_frame): If the expression yields
|
||||
pieces, and any piece is in a register, then we need a frame.
|
||||
|
||||
* dwarf2loc.c (dwarf2_evaluate_loc_desc): Wait to fetch the top of
|
||||
the stack until we've decided what sort of result the evaluation
|
||||
has produced. Use separate variables, with more specific names.
|
||||
|
@ -42,6 +42,8 @@ new_dwarf_expr_context (void)
|
||||
retval->stack_len = 0;
|
||||
retval->stack_allocated = 10;
|
||||
retval->stack = xmalloc (retval->stack_allocated * sizeof (CORE_ADDR));
|
||||
retval->num_pieces = 0;
|
||||
retval->pieces = 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -51,6 +53,7 @@ void
|
||||
free_dwarf_expr_context (struct dwarf_expr_context *ctx)
|
||||
{
|
||||
xfree (ctx->stack);
|
||||
xfree (ctx->pieces);
|
||||
xfree (ctx);
|
||||
}
|
||||
|
||||
@ -100,6 +103,29 @@ 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)
|
||||
{
|
||||
struct dwarf_expr_piece *p;
|
||||
|
||||
ctx->num_pieces++;
|
||||
|
||||
if (ctx->pieces)
|
||||
ctx->pieces = xrealloc (ctx->pieces,
|
||||
(ctx->num_pieces
|
||||
* sizeof (struct dwarf_expr_piece)));
|
||||
else
|
||||
ctx->pieces = xmalloc (ctx->num_pieces
|
||||
* sizeof (struct dwarf_expr_piece));
|
||||
|
||||
p = &ctx->pieces[ctx->num_pieces - 1];
|
||||
p->in_reg = in_reg;
|
||||
p->value = value;
|
||||
p->size = size;
|
||||
}
|
||||
|
||||
/* Evaluate the expression at ADDR (LEN bytes long) using the context
|
||||
CTX. */
|
||||
|
||||
@ -661,6 +687,22 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
|
||||
case DW_OP_nop:
|
||||
goto no_push;
|
||||
|
||||
case DW_OP_piece:
|
||||
{
|
||||
ULONGEST size;
|
||||
CORE_ADDR addr_or_regnum;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Pop off the address/regnum, and clear the in_reg flag. */
|
||||
dwarf_expr_pop (ctx);
|
||||
ctx->in_reg = 0;
|
||||
}
|
||||
goto no_push;
|
||||
|
||||
default:
|
||||
error ("Unhandled dwarf expression opcode 0x%x", op);
|
||||
}
|
||||
|
@ -74,6 +74,49 @@ struct dwarf_expr_context
|
||||
/* Non-zero if the result is in a register. The register number
|
||||
will be on the expression stack. */
|
||||
int in_reg;
|
||||
|
||||
/* An array of pieces. PIECES points to its first element;
|
||||
NUM_PIECES is its length.
|
||||
|
||||
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 in_reg flag, and the size given as the operand to
|
||||
DW_OP_piece. We then pop the top value from the stack, clear the
|
||||
in_reg flag, and resume evaluation.
|
||||
|
||||
The Dwarf spec doesn't say whether DW_OP_piece pops the top value
|
||||
from the stack. We do, ensuring that clients of this interface
|
||||
expecting to see a value left on the top of the stack (say, code
|
||||
evaluating frame base expressions or CFA's specified with
|
||||
DW_CFA_def_cfa_expression) will get an error if the expression
|
||||
actually marks all the values it computes as pieces.
|
||||
|
||||
If an expression never uses DW_OP_piece, num_pieces will be zero.
|
||||
(It would be nice to present these cases as expressions yielding
|
||||
a single piece, with in_reg clear, so that callers need not
|
||||
distinguish between the no-DW_OP_piece and one-DW_OP_piece cases.
|
||||
But expressions with no DW_OP_piece operations have no value to
|
||||
place in a piece's 'size' field; the size comes from the
|
||||
surrounding data. So the two cases need to be handled
|
||||
separately.) */
|
||||
int num_pieces;
|
||||
struct dwarf_expr_piece *pieces;
|
||||
};
|
||||
|
||||
|
||||
/* A piece of an object, as recorded by DW_OP_piece. */
|
||||
struct dwarf_expr_piece
|
||||
{
|
||||
/* If IN_REG is zero, then the piece is in memory, and VALUE is its address.
|
||||
If IN_REG is non-zero, then the piece is in a register, and VALUE
|
||||
is the register number. */
|
||||
int in_reg;
|
||||
|
||||
/* This piece's address or register number. */
|
||||
CORE_ADDR value;
|
||||
|
||||
/* The length of the piece, in bytes. */
|
||||
ULONGEST size;
|
||||
};
|
||||
|
||||
struct dwarf_expr_context *new_dwarf_expr_context (void);
|
||||
|
@ -205,6 +205,7 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
|
||||
unsigned char *data, unsigned short size,
|
||||
struct objfile *objfile)
|
||||
{
|
||||
struct gdbarch *arch = get_frame_arch (frame);
|
||||
struct value *retval;
|
||||
struct dwarf_expr_baton baton;
|
||||
struct dwarf_expr_context *ctx;
|
||||
@ -227,8 +228,15 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
|
||||
ctx->get_tls_address = dwarf_expr_tls_address;
|
||||
|
||||
dwarf_expr_eval (ctx, data, size);
|
||||
|
||||
if (ctx->in_reg)
|
||||
if (ctx->num_pieces > 0)
|
||||
{
|
||||
/* We haven't implemented splicing together pieces from
|
||||
arbitrary sources yet. */
|
||||
error ("The value of variable '%s' is distributed across several\n"
|
||||
"locations, and GDB cannot access its value.\n",
|
||||
SYMBOL_NATURAL_NAME (var));
|
||||
}
|
||||
else if (ctx->in_reg)
|
||||
{
|
||||
CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0);
|
||||
int gdb_regnum = DWARF2_REG_TO_REGNUM (dwarf_regnum);
|
||||
@ -323,6 +331,17 @@ dwarf2_loc_desc_needs_frame (unsigned char *data, unsigned short size)
|
||||
|
||||
in_reg = ctx->in_reg;
|
||||
|
||||
if (ctx->num_pieces > 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* If the location has several pieces, and any of them are in
|
||||
registers, then we will need a frame to fetch them from. */
|
||||
for (i = 0; i < ctx->num_pieces; i++)
|
||||
if (ctx->pieces[i].in_reg)
|
||||
in_reg = 1;
|
||||
}
|
||||
|
||||
free_dwarf_expr_context (ctx);
|
||||
|
||||
return baton.needs_frame || in_reg;
|
||||
|
Loading…
Reference in New Issue
Block a user