From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 580 invoked by alias); 10 Aug 2004 06:30:00 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 547 invoked from network); 10 Aug 2004 06:29:59 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org with SMTP; 10 Aug 2004 06:29:59 -0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.10/8.12.10) with ESMTP id i7A6Twe1018663 for ; Tue, 10 Aug 2004 02:29:59 -0400 Received: from zenia.home.redhat.com (porkchop.devel.redhat.com [172.16.58.2]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id i7A6Tva22857; Tue, 10 Aug 2004 02:29:57 -0400 To: gdb-patches@sources.redhat.com Subject: Re: RFC: Return piece lists from Dwarf expression evaluation References: From: Jim Blandy Date: Tue, 10 Aug 2004 06:30:00 -0000 In-Reply-To: Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2004-08/txt/msg00351.txt.bz2 Jim Blandy 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 * 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;