This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: Return piece lists from Dwarf expression evaluation


Jim Blandy <jimb@redhat.com> writes:
> Here's an implementation of the dwarf2expr interface change I proposed
> on gdb@ last week.

Here's a revision of that patch that properly handles the 'needs
frame' case.

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.
        (dwarf2_loc_desc_needs_frame): If the expression yields
        pieces, and any piece is in a register, then we need a frame.

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-10 01:01:11.000000000 -0500
*************** dwarf2_evaluate_loc_desc (struct symbol 
*** 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;
*************** dwarf2_evaluate_loc_desc (struct symbol 
*** 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);
*************** dwarf2_loc_desc_needs_frame (unsigned ch
*** 323,328 ****
--- 331,347 ----
  
    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;



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]