This is the mail archive of the gdb-patches@sourceware.org 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]

RFC: DW_OP_call_frame_cfa, again


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  <tromey@redhat.com>

	* 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  <tromey@redhat.com>

	* 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)  */


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