From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29967 invoked by alias); 11 Aug 2009 20:49:19 -0000 Received: (qmail 29955 invoked by uid 22791); 11 Aug 2009 20:49:16 -0000 X-SWARE-Spam-Status: No, hits=-1.6 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mx2.redhat.com (HELO mx2.redhat.com) (66.187.237.31) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 11 Aug 2009 20:49:07 +0000 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n7BKn5lm019102 for ; Tue, 11 Aug 2009 16:49:05 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n7BKn4ZV001562; Tue, 11 Aug 2009 16:49:04 -0400 Received: from opsy.redhat.com (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n7BKn34b000633; Tue, 11 Aug 2009 16:49:03 -0400 Received: by opsy.redhat.com (Postfix, from userid 500) id 9D3473782B4; Tue, 11 Aug 2009 14:49:02 -0600 (MDT) To: gdb-patches@sourceware.org Subject: RFC: DW_OP_call_frame_cfa, again From: Tom Tromey Reply-To: Tom Tromey Date: Wed, 12 Aug 2009 00:52:00 -0000 Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-08/txt/msg00166.txt.bz2 Here is a new version of my patch to implement DW_OP_call_frame_cfa. Previous thread here: http://sourceware.org/ml/gdb-patches/2009-06/msg00191.html With followup the next month (I wish our mailing list archive handled this more nicely): http://sourceware.org/ml/gdb-patches/2009-07/msg00570.html This version implements Daniel's idea of checking the frame unwinder. If you read the followup message (above) you'll see that this patch is different from what I talked about there; that approach doesn't work since the DWARF frame base sniffer is not registered for many architectures. Jan suggested the current approach. This version includes a test case. Built and regtested on x86-64 (compile farm). I also ran the tests locally, since the new test is x86-only. FWIW, you can also easily generate this opcode using svn gcc with -gdwarf-3. One further issue is that this interacts poorly with the i386 epilogue unwinder. I punted on this issue for the time being. However, with GCC 4.5, I think the DWARF unwinder is supposed to work fine for epilogues -- so can we make the epilogue unwinder conditional? Is this special unwinder only needed for reverse execution? If so, could we make it conditional on when that mode is enabled? I don't think this particular issue affects whether this patch should go in. Let me know what you think. Tom 2009-08-11 Tom Tromey * frame.h (frame_unwinder_is): Rename from frame_base_is. * frame.c (frame_unwinder_is): Rename from frame_base_is. Rewrite. * dwarf2-frame.c (dwarf2_frame_cfa): Use frame_unwinder_is and get_frame_base. 2009-08-11 Tom Tromey * gdb.dwarf2/callframecfa.exp: New file. * gdb.dwarf2/callframecfa.S: New file. diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index 0f6da40..db53c75 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -310,6 +310,13 @@ no_get_frame_base (void *baton, gdb_byte **start, size_t *length) } static CORE_ADDR +no_get_frame_cfa (void *baton) +{ + internal_error (__FILE__, __LINE__, + _("Support for DW_OP_call_frame_cfa is unimplemented")); +} + +static CORE_ADDR no_get_tls_address (void *baton, CORE_ADDR offset) { internal_error (__FILE__, __LINE__, @@ -360,6 +367,7 @@ execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size, ctx->read_reg = read_reg; ctx->read_mem = read_mem; ctx->get_frame_base = no_get_frame_base; + ctx->get_frame_cfa = no_get_frame_cfa; ctx->get_tls_address = no_get_tls_address; dwarf_expr_push (ctx, initial); @@ -1247,6 +1255,14 @@ dwarf2_frame_base_sniffer (struct frame_info *this_frame) return NULL; } + +CORE_ADDR +dwarf2_frame_cfa (struct frame_info *this_frame) +{ + if (! frame_unwinder_is (this_frame, &dwarf2_frame_unwind)) + error (_("can't compute CFA for this frame")); + return get_frame_base (this_frame); +} const struct objfile_data *dwarf2_frame_objfile_data; diff --git a/gdb/dwarf2-frame.h b/gdb/dwarf2-frame.h index b203661..dd03d59 100644 --- a/gdb/dwarf2-frame.h +++ b/gdb/dwarf2-frame.h @@ -118,4 +118,8 @@ extern const struct frame_base * void dwarf2_frame_build_info (struct objfile *objfile); +/* Compute the DWARF CFA for a frame. */ + +CORE_ADDR dwarf2_frame_cfa (struct frame_info *this_frame); + #endif /* dwarf2-frame.h */ diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c index 8dbf976..8a962a4 100644 --- a/gdb/dwarf2expr.c +++ b/gdb/dwarf2expr.c @@ -700,6 +700,10 @@ execute_stack_op (struct dwarf_expr_context *ctx, } break; + case DW_OP_call_frame_cfa: + result = (ctx->get_frame_cfa) (ctx->baton); + break; + case DW_OP_GNU_push_tls_address: /* Variable is at a constant offset in the thread-local storage block into the objfile for the current thread and diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h index 7047922..97edf6c 100644 --- a/gdb/dwarf2expr.h +++ b/gdb/dwarf2expr.h @@ -55,6 +55,9 @@ struct dwarf_expr_context expression evaluation is complete. */ void (*get_frame_base) (void *baton, gdb_byte **start, size_t *length); + /* Return the CFA for the frame. */ + CORE_ADDR (*get_frame_cfa) (void *baton); + /* Return the thread-local storage address for DW_OP_GNU_push_tls_address. */ CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset); diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 071b5ac..930ba18 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -36,6 +36,7 @@ #include "dwarf2.h" #include "dwarf2expr.h" #include "dwarf2loc.h" +#include "dwarf2-frame.h" #include "gdb_string.h" #include "gdb_assert.h" @@ -194,6 +195,13 @@ dwarf_expr_frame_base (void *baton, gdb_byte **start, size_t * length) SYMBOL_NATURAL_NAME (framefunc)); } +static CORE_ADDR +dwarf_expr_frame_cfa (void *baton) +{ + struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; + return dwarf2_frame_cfa (debaton->frame); +} + /* Using the objfile specified in BATON, find the address for the current thread's thread-local storage with offset OFFSET. */ static CORE_ADDR @@ -234,6 +242,7 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, ctx->read_reg = dwarf_expr_read_reg; ctx->read_mem = dwarf_expr_read_mem; ctx->get_frame_base = dwarf_expr_frame_base; + ctx->get_frame_cfa = dwarf_expr_frame_cfa; ctx->get_tls_address = dwarf_expr_tls_address; dwarf_expr_eval (ctx, data, size); @@ -327,6 +336,15 @@ needs_frame_frame_base (void *baton, gdb_byte **start, size_t * length) nf_baton->needs_frame = 1; } +/* CFA accesses require a frame. */ +static CORE_ADDR +needs_frame_frame_cfa (void *baton) +{ + struct needs_frame_baton *nf_baton = baton; + nf_baton->needs_frame = 1; + return 1; +} + /* Thread-local accesses do require a frame. */ static CORE_ADDR needs_frame_tls_address (void *baton, CORE_ADDR offset) @@ -356,6 +374,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size, ctx->read_reg = needs_frame_read_reg; ctx->read_mem = needs_frame_read_mem; ctx->get_frame_base = needs_frame_frame_base; + ctx->get_frame_cfa = needs_frame_frame_cfa; ctx->get_tls_address = needs_frame_tls_address; dwarf_expr_eval (ctx, data, size); diff --git a/gdb/frame.c b/gdb/frame.c index 67e0607..2b5a5b6 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1843,6 +1843,15 @@ get_frame_args_address (struct frame_info *fi) return fi->base->this_args (fi, &fi->base_cache); } +/* Return true if the frame base for frame FI is BASE; false + otherwise. */ + +int +frame_unwinder_is (struct frame_info *fi, const struct frame_unwind *unwinder) +{ + return fi->unwind == unwinder; +} + /* Level of the selected frame: 0 for innermost, 1 for its caller, ... or -1 for a NULL frame. */ diff --git a/gdb/frame.h b/gdb/frame.h index febef5c..611c6d3 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -696,4 +696,10 @@ extern struct frame_info *deprecated_safe_get_selected_frame (void); extern struct frame_info *create_new_frame (CORE_ADDR base, CORE_ADDR pc); +/* Return true if the frame unwinder for frame FI is UNWINDER; false + otherwise. */ + +extern int frame_unwinder_is (struct frame_info *fi, + const struct frame_unwind *unwinder); + #endif /* !defined (FRAME_H) */