This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
RFC: Return piece lists from Dwarf expression evaluation
- From: Jim Blandy <jimb at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: 09 Aug 2004 19:27:07 -0500
- Subject: RFC: Return piece lists from Dwarf expression evaluation
Here's an implementation of the dwarf2expr interface change I proposed
on gdb@ last week.
2004-08-09 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.
Index: gdb/dwarf2expr.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2expr.c,v
retrieving revision 1.12
diff -c -p -r1.12 dwarf2expr.c
*** gdb/dwarf2expr.c 21 May 2004 07:50:03 -0000 1.12
--- gdb/dwarf2expr.c 10 Aug 2004 00:17:03 -0000
*************** new_dwarf_expr_context (void)
*** 42,47 ****
--- 42,49 ----
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;
}
*************** void
*** 51,56 ****
--- 53,59 ----
free_dwarf_expr_context (struct dwarf_expr_context *ctx)
{
xfree (ctx->stack);
+ xfree (ctx->pieces);
xfree (ctx);
}
*************** dwarf_expr_fetch (struct dwarf_expr_cont
*** 100,105 ****
--- 103,131 ----
}
+ /* 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. */
*************** execute_stack_op (struct dwarf_expr_cont
*** 661,666 ****
--- 687,708 ----
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);
}
Index: gdb/dwarf2expr.h
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2expr.h,v
retrieving revision 1.5
diff -c -p -r1.5 dwarf2expr.h
*** gdb/dwarf2expr.h 8 Jun 2003 18:27:13 -0000 1.5
--- gdb/dwarf2expr.h 10 Aug 2004 00:17:03 -0000
*************** struct dwarf_expr_context
*** 74,79 ****
--- 74,122 ----
/* 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);
*** gdb/dwarf2loc.c.r~ 2004-08-09 18:46:46.000000000 -0500
--- gdb/dwarf2loc.c 2004-08-09 18:49:26.000000000 -0500
***************
*** 205,210 ****
--- 205,211 ----
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,234 ****
ctx->get_tls_address = dwarf_expr_tls_address;
dwarf_expr_eval (ctx, data, size);
!
! if (ctx->in_reg)
{
CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0);
int gdb_regnum = DWARF2_REG_TO_REGNUM (dwarf_regnum);
--- 228,242 ----
ctx->get_tls_address = dwarf_expr_tls_address;
dwarf_expr_eval (ctx, data, size);
! 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);