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]

[wip] frame_unwind_p -> frame unwind sniffer


Hello,

The attached is a work-in-progress for sorting out the dwarf2 (and I guess other) problem of sometimes screwing up dwarf2 cfi selection.

It replaces the very simple:
struct unwinder *XXXX_frame_p (CORE_ADDR pc);
method with the sniffer:
struct unwinder *XXXX_sniffer (struct frame_info *next_frame);
The sniffer (name stollen from existing code) is given the next frame. That lets it poke around any which way it chooses to determine if CFI is available for this frame. It happens to call frame_unwind_address_in_block.


comments?

Apart from needing a test run (:-^) my intent is to pull a minimal part of this up into the 6.0 branch.

Andrew
2003-07-10  Andrew Cagney  <cagney@redhat.com>

	* blockframe.c (frame_unwind_address_in_block): New function.

	* frame.h (frame_unwind_address_in_block): Declare.

	* dwarf2-frame.c (dwarf2_frame_sniffer): New function.
	* dwarf2-frame.h (dwarf2_frame_sniffer): Declare.

	* frame.c (get_frame_id): Use frame_unwind_find_by_frame.
	(frame_register_unwind, create_new_frame): Ditto.
	(legacy_get_prev_frame, get_frame_type): Ditto.

	* frame-unwind.c (struct frame_unwind_table): Add "sniffer",
	delete "middle".
	(append_predicate): Add "sniffer" parameter, append the sniffer.
	(frame_unwind_init): Update append_predicate call.
	(frame_unwind_append_sniffer): New function.
	(frame_unwind_append_predicate): Update append_predicate call.
	(frame_unwind_find_by_frame): Replace frame_unwind_find_by_pc.

	* frame-unwind.h (frame_unwind_sniffer_ftype): Define.
	(frame_unwind_append_sniffer): Declare.
	(frame_unwind_find_by_frame): Replace frame_unwind_find_by_pc.

Index: blockframe.c
===================================================================
RCS file: /cvs/src/src/gdb/blockframe.c,v
retrieving revision 1.72
diff -u -r1.72 blockframe.c
--- blockframe.c	23 May 2003 17:05:19 -0000	1.72
+++ blockframe.c	10 Jul 2003 21:48:04 -0000
@@ -168,9 +168,26 @@
     return 0;
 }
 
-/* return the address of the PC for the given FRAME, ie the current PC value
-   if FRAME is the innermost frame, or the address adjusted to point to the
-   call instruction if not.  */
+/* Given the NEXT_FRAME, return the address of the PC for THIS FRAME,
+   ie the current PC value if FRAME is the innermost frame, or the
+   address adjusted to point to the call instruction if not.  */
+
+CORE_ADDR
+frame_unwind_address_in_block (struct frame_info *next_frame)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  /* If we are not in the innermost frame, and we are not interrupted
+     by a signal, frame->pc points to the instruction following the
+     call. As a consequence, we need to get the address of the
+     previous instruction. Unfortunately, this is not straightforward
+     to do, so we just use the address minus one, which is a good
+     enough approximation.  */
+  if (frame_relative_level (next_frame) >= 0
+      && get_frame_type (next_frame) == NORMAL_FRAME)
+    --pc;
+
+  return pc;
+}
 
 CORE_ADDR
 frame_address_in_block (struct frame_info *frame)
Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.7
diff -u -r1.7 dwarf2-frame.c
--- dwarf2-frame.c	8 Jun 2003 18:27:13 -0000	1.7
+++ dwarf2-frame.c	10 Jul 2003 21:48:04 -0000
@@ -721,6 +721,20 @@
 
   return NULL;
 }
+const struct frame_unwind *
+dwarf2_frame_sniffer (struct frame_info *next_frame)
+{
+  /* The way GDB works, this function can be called with the unwound
+     PC just after the last instruction of the function we're supposed
+     to return the unwind methods for.  In that case we won't find the
+     correct FDE; instead we find the FDE for the next function, or we
+     won't find an FDE at all.  The frame_unwind_address_in_block
+     method makes allowances for this.  */
+  CORE_ADDR pc = frame_unwind_address_in_block (next_frame);
+  if (dwarf2_frame_find_fde (&pc))
+    return &dwarf2_frame_unwind;
+  return NULL;
+}
 
 
 /* There is no explicitly defined relationship between the CFA and the
Index: dwarf2-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.h,v
retrieving revision 1.1
diff -u -r1.1 dwarf2-frame.h
--- dwarf2-frame.h	31 May 2003 19:18:05 -0000	1.1
+++ dwarf2-frame.h	10 Jul 2003 21:48:04 -0000
@@ -31,6 +31,12 @@
 
 const struct frame_unwind *dwarf2_frame_p (CORE_ADDR pc);
 
+/* Return the frame unwind methods for the function that called
+   NEXT_FRAME, or NULL if it can't be handled by DWARF2 CFI frame
+   unwinder.  */
+
+const struct frame_unwind *dwarf2_frame_sniffer (struct frame_info *next_frame);
+
 /* Return the frame base methods for the function that contains PC, or
    NULL if it can't be handled by the DWARF CFI frame unwinder.  */
 
Index: frame-unwind.c
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.c,v
retrieving revision 1.4
diff -u -r1.4 frame-unwind.c
--- frame-unwind.c	8 Jun 2003 18:27:13 -0000	1.4
+++ frame-unwind.c	10 Jul 2003 21:48:04 -0000
@@ -30,17 +30,21 @@
 struct frame_unwind_table
 {
   frame_unwind_p_ftype **p;
-  int middle;
+  frame_unwind_sniffer_ftype **sniffer;
   int nr;
 };
 
 /* Append a predicate to the end of the table.  */
 static void
-append_predicate (struct frame_unwind_table *table, frame_unwind_p_ftype *p)
+append_predicate (struct frame_unwind_table *table, frame_unwind_p_ftype *p,
+		  frame_unwind_sniffer_ftype *sniffer)
 {
   table->p = xrealloc (table->p, ((table->nr + 1)
 				  * sizeof (frame_unwind_p_ftype *)));
+  table->sniffer = xrealloc (table->sniffer, ((table->nr + 1)
+					      * sizeof (frame_unwind_sniffer_ftype *)));
   table->p[table->nr] = p;
+  table->sniffer[table->nr] = sniffer;
   table->nr++;
 }
 
@@ -48,7 +52,7 @@
 frame_unwind_init (struct gdbarch *gdbarch)
 {
   struct frame_unwind_table *table = XCALLOC (1, struct frame_unwind_table);
-  append_predicate (table, dummy_frame_p);
+  append_predicate (table, dummy_frame_p, NULL);
   return table;
 }
 
@@ -74,15 +78,31 @@
       table = frame_unwind_init (gdbarch);
       set_gdbarch_data (gdbarch, frame_unwind_data, table);
     }
-  append_predicate (table, p);
+  append_predicate (table, p, NULL);
 }
 
-const struct frame_unwind *
-frame_unwind_find_by_pc (struct gdbarch *gdbarch, CORE_ADDR pc)
+void
+frame_unwind_append_sniffer (struct gdbarch *gdbarch,
+			     frame_unwind_sniffer_ftype *sniffer)
 {
-  int i;
   struct frame_unwind_table *table =
     gdbarch_data (gdbarch, frame_unwind_data);
+  if (table == NULL)
+    {
+      /* ULGH, called during architecture initialization.  Patch
+         things up.  */
+      table = frame_unwind_init (gdbarch);
+      set_gdbarch_data (gdbarch, frame_unwind_data, table);
+    }
+  append_predicate (table, NULL, sniffer);
+}
+
+const struct frame_unwind *
+frame_unwind_find_by_frame (struct frame_info *next_frame)
+{
+  int i;
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
   if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
     /* Seriously old code.  Don't even try to use this new mechanism.
        (Note: The variable USE_GENERIC_DUMMY_FRAMES is deprecated, not
@@ -91,7 +111,13 @@
     return legacy_saved_regs_unwind;
   for (i = 0; i < table->nr; i++)
     {
-      const struct frame_unwind *desc = table->p[i] (pc);
+      const struct frame_unwind *desc;
+      if (table->p[i] != NULL)
+	desc = table->p[i] (frame_pc_unwind (next_frame));
+      else if (table->sniffer[i] != NULL)
+	desc = table->sniffer[i] (next_frame);
+      else
+	internal_error (__FILE__, __LINE__, "Missing sniffer?");
       if (desc != NULL)
 	return desc;
     }
Index: frame-unwind.h
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.h,v
retrieving revision 1.7
diff -u -r1.7 frame-unwind.h
--- frame-unwind.h	5 Apr 2003 03:55:59 -0000	1.7
+++ frame-unwind.h	10 Jul 2003 21:48:04 -0000
@@ -30,25 +30,12 @@
 
 #include "frame.h"		/* For enum frame_type.  */
 
-/* Return the frame unwind methods for the function that contains PC,
-   or NULL if this this unwinder can't handle this frame.  */
-
+/* For compatibility with the old frame code.  See end of header for
+   new methods.  */
 typedef const struct frame_unwind *(frame_unwind_p_ftype) (CORE_ADDR pc);
-
-/* Add a frame unwinder to the list.  The predicates are polled in the
-   order that they are appended.  The initial list contains the dummy
-   frame's predicate.  */
-
 extern void frame_unwind_append_predicate (struct gdbarch *gdbarch,
 					   frame_unwind_p_ftype *p);
 
-/* Iterate through the list of frame unwinders until one returns an
-   implementation.  */
-
-extern const struct frame_unwind *frame_unwind_find_by_pc (struct gdbarch
-							   *gdbarch,
-							   CORE_ADDR pc);
-
 /* The following unwind functions assume a chain of frames forming the
    sequence: (outer) prev <-> this <-> next (inner).  All the
    functions are called with called with the next frame's `struct
@@ -138,5 +125,23 @@
   frame_this_id_ftype *this_id;
   frame_prev_register_ftype *prev_register;
 };
+
+/* Given the NEXT frame, take a wiff of THIS frame's registers (namely
+   the PC and attributes) and if it is the applicable unwinder return
+   the unwind methods, or NULL if it is not.  */
+
+typedef const struct frame_unwind *(frame_unwind_sniffer_ftype) (struct frame_info *next_frame);
+
+/* Add a frame sniffer to the list.  The predicates are polled in the
+   order that they are appended.  The initial list contains the dummy
+   frame sniffer.  */
+
+extern void frame_unwind_append_sniffer (struct gdbarch *gdbarch,
+					 frame_unwind_sniffer_ftype *sniffer);
+
+/* Iterate through the next frame's sniffers until one returns with an
+   unwinder implementation.  */
+
+extern const struct frame_unwind *frame_unwind_find_by_frame (struct frame_info *next_frame);
 
 #endif
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.130
diff -u -r1.130 frame.c
--- frame.c	7 Jul 2003 20:07:12 -0000	1.130
+++ frame.c	10 Jul 2003 21:48:05 -0000
@@ -229,8 +229,7 @@
       /* Find the unwinder.  */
       if (fi->unwind == NULL)
 	{
-	  fi->unwind = frame_unwind_find_by_pc (current_gdbarch,
-						get_frame_pc (fi));
+	  fi->unwind = frame_unwind_find_by_frame (fi->next);
 	  /* FIXME: cagney/2003-04-02: Rather than storing the frame's
 	     type in the frame, the unwinder's type should be returned
 	     directly.  Unfortunatly, legacy code, called by
@@ -517,8 +516,7 @@
   /* Find the unwinder.  */
   if (frame->unwind == NULL)
     {
-      frame->unwind = frame_unwind_find_by_pc (current_gdbarch,
-					       get_frame_pc (frame));
+      frame->unwind = frame_unwind_find_by_frame (frame->next);
       /* FIXME: cagney/2003-04-02: Rather than storing the frame's
 	 type in the frame, the unwinder's type should be returned
 	 directly.  Unfortunatly, legacy code, called by
@@ -1206,7 +1204,7 @@
 
   /* Select/initialize both the unwind function and the frame's type
      based on the PC.  */
-  fi->unwind = frame_unwind_find_by_pc (current_gdbarch, pc);
+  fi->unwind = frame_unwind_find_by_frame (fi->next);
   if (fi->unwind->type != UNKNOWN_FRAME)
     fi->type = fi->unwind->type;
   else
@@ -1365,8 +1363,7 @@
 
       /* Set the unwind functions based on that identified PC.  Ditto
          for the "type" but strongly prefer the unwinder's frame type.  */
-      prev->unwind = frame_unwind_find_by_pc (current_gdbarch,
-					      get_frame_pc (prev));
+      prev->unwind = frame_unwind_find_by_frame (prev->next);
       if (prev->unwind->type == UNKNOWN_FRAME)
 	prev->type = frame_type_from_pc (get_frame_pc (prev));
       else
@@ -1514,8 +1511,7 @@
              to the new frame code.  Implement FRAME_CHAIN the way the
              new frame will.  */
 	  /* Find PREV frame's unwinder.  */
-	  prev->unwind = frame_unwind_find_by_pc (current_gdbarch,
-						  frame_pc_unwind (this_frame));
+	  prev->unwind = frame_unwind_find_by_frame (this_frame->next);
 	  /* FIXME: cagney/2003-04-02: Rather than storing the frame's
 	     type in the frame, the unwinder's type should be returned
 	     directly.  Unfortunatly, legacy code, called by
@@ -1676,8 +1672,7 @@
      If there isn't a FRAME_CHAIN, the code above will have already
      done this.  */
   if (prev->unwind == NULL)
-    prev->unwind = frame_unwind_find_by_pc (current_gdbarch,
-					    get_frame_pc (prev));
+    prev->unwind = frame_unwind_find_by_frame (prev->next);
 
   /* If the unwinder provides a frame type, use it.  Otherwize
      continue on to that heuristic mess.  */
@@ -2118,8 +2113,7 @@
     {
       /* Initialize the frame's unwinder because it is that which
          provides the frame's type.  */
-      frame->unwind = frame_unwind_find_by_pc (current_gdbarch,
-					       get_frame_pc (frame));
+      frame->unwind = frame_unwind_find_by_frame (frame->next);
       /* FIXME: cagney/2003-04-02: Rather than storing the frame's
 	 type in the frame, the unwinder's type should be returned
 	 directly.  Unfortunatly, legacy code, called by
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.104
diff -u -r1.104 frame.h
--- frame.h	7 Jul 2003 14:36:58 -0000	1.104
+++ frame.h	10 Jul 2003 21:48:05 -0000
@@ -527,6 +527,7 @@
 extern struct symbol *get_frame_function (struct frame_info *);
 
 extern CORE_ADDR frame_address_in_block (struct frame_info *);
+extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *);
 
 extern CORE_ADDR get_pc_function_start (CORE_ADDR);
 

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