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]

[commit] Cleanup dummy-frame unwinder


Hello,

Being able to assume up-to-date frame code lets us consolidate the complexity of identifying a dummy-frame into a single dummy-frame sniffer.

This also fixes a latent bug: with the old code the sniffer could `hit' (based on the PC) but then the unwinder would `miss' (based also on dummy-frame ID). I'm not sure what happend next but the function involved definitly returned a NULL pointer. Now, when the stack is corrupted, the dummy-frame simply won't be recognized.

Andrew

PS: Next is clean up the interface between dummy-frame and infrun.

Index: ChangeLog
2004-08-01  Andrew Cagney  <cagney@gnu.org>

	* dummy-frame.h (dummy_frame_unwind): Replace dummy_frame_sniffer.
	* frame-unwind.c (frame_unwind_init): Use dummy_frame_unwind.
	* dummy-frame.c (find_dummy_frame): Delete.
	(struct dummy_frame_cache, dummy_frame_sniffer)
	(dummy_frame_prev_register, dummy_frame_this_id)
	(dummy_frame_unwinder, dummy_frame_unwind): Re-implement dummy
	frame unwinder using a dummy_frame_cache.

Index: dummy-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dummy-frame.c,v
retrieving revision 1.37
diff -p -u -r1.37 dummy-frame.c
--- dummy-frame.c	2 Aug 2004 03:36:24 -0000	1.37
+++ dummy-frame.c	2 Aug 2004 16:06:32 -0000
@@ -32,10 +32,6 @@
 #include "command.h"
 #include "gdbcmd.h"
 
-static void dummy_frame_this_id (struct frame_info *next_frame,
-				 void **this_prologue_cache,
-				 struct frame_id *this_id);
-
 static int pc_in_dummy_frame (CORE_ADDR pc);
 
 /* Dummy frame.  This saves the processor state just prior to setting
@@ -61,38 +57,6 @@ struct dummy_frame
 
 static struct dummy_frame *dummy_frame_stack = NULL;
 
-/* Function: find_dummy_frame(pc, fp, sp)
-
-   Search the stack of dummy frames for one matching the given PC and
-   FP/SP.  Unlike pc_in_dummy_frame(), this function doesn't need to
-   adjust for DECR_PC_AFTER_BREAK.  This is because it is only legal
-   to call this function after the PC has been adjusted.  */
-
-static struct dummy_frame *
-find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
-{
-  struct dummy_frame *dummyframe;
-
-  for (dummyframe = dummy_frame_stack; dummyframe != NULL;
-       dummyframe = dummyframe->next)
-    {
-      /* Does the PC fall within the dummy frame's breakpoint
-         instruction.  If not, discard this one.  */
-      if (!(pc >= dummyframe->call_lo && pc < dummyframe->call_hi))
-	continue;
-      /* Does the FP match?  */
-      /* "infcall.c" explicitly saved the top-of-stack before the
-	 inferior function call, assume unwind_dummy_id() returns that
-	 same stack value.  */
-      if (fp != dummyframe->top)
-	continue;
-      /* The FP matches this dummy frame.  */
-      return dummyframe;
-    }
-
-  return NULL;
-}
-
 /* Function: pc_in_call_dummy (pc)
 
    Return true if the PC falls in a dummy frame created by gdb for an
@@ -185,6 +149,63 @@ generic_save_call_dummy_addr (CORE_ADDR 
   dummy_frame_stack->call_hi = hi;
 }
 
+/* Return the dummy frame cache, it contains both the ID, and a
+   pointer to the regcache.  */
+struct dummy_frame_cache
+{
+  struct frame_id this_id;
+  struct regcache *prev_regcache;
+};
+
+int
+dummy_frame_sniffer (const struct frame_unwind *self,
+		     struct frame_info *next_frame,
+		     void **this_prologue_cache)
+{
+  struct dummy_frame *dummyframe;
+  struct frame_id this_id;
+
+  /* When unwinding a normal frame, the stack structure is determined
+     by analyzing the frame's function's code (be it using brute force
+     prologue analysis, or the dwarf2 CFI).  In the case of a dummy
+     frame, that simply isn't possible.  The PC is either the program
+     entry point, or some random address on the stack.  Trying to use
+     that PC to apply standard frame ID unwind techniques is just
+     asking for trouble.  */
+  /* Use an architecture specific method to extract the prev's dummy
+     ID from the next frame.  Note that this method uses
+     frame_register_unwind to obtain the register values needed to
+     determine the dummy frame's ID.  */
+  this_id = gdbarch_unwind_dummy_id (get_frame_arch (next_frame), next_frame);
+
+  /* Use that ID to find the corresponding cache entry.  */
+  for (dummyframe = dummy_frame_stack;
+       dummyframe != NULL;
+       dummyframe = dummyframe->next)
+    {
+      /* Does the PC fall within the dummy frame's breakpoint
+         instruction.  If not, discard this one.  */
+      if (!(this_id.code_addr >= dummyframe->call_lo
+	    && this_id.code_addr < dummyframe->call_hi))
+	continue;
+      /* Does the FP match?  "infcall.c" explicitly saved the
+	 top-of-stack before the inferior function call, assume
+	 unwind_dummy_id() returns that same stack value.  */
+      if (this_id.stack_addr != dummyframe->top)
+	continue;
+      /* The FP matches this dummy frame.  */
+      {
+	struct dummy_frame_cache *cache;
+	cache = FRAME_OBSTACK_ZALLOC (struct dummy_frame_cache);
+	cache->prev_regcache = dummyframe->regcache;
+	cache->this_id = this_id;
+	(*this_prologue_cache) = cache;
+	return 1;
+      }
+    }
+  return 0;
+}
+
 /* Given a call-dummy dummy-frame, return the registers.  Here the
    register value is taken from the local copy of the register buffer.  */
 
@@ -195,14 +216,9 @@ dummy_frame_prev_register (struct frame_
 			   enum lval_type *lvalp, CORE_ADDR *addrp,
 			   int *realnum, void *bufferp)
 {
-  struct dummy_frame *dummy;
-  struct frame_id id;
-
-  /* Call the ID method which, if at all possible, will set the
-     prologue cache.  */
-  dummy_frame_this_id (next_frame, this_prologue_cache, &id);
-  dummy = (*this_prologue_cache);
-  gdb_assert (dummy != NULL);
+  /* The dummy-frame sniffer always fills in the cache.  */
+  struct dummy_frame_cache *cache = (*this_prologue_cache);
+  gdb_assert (cache != NULL);
 
   /* Describe the register's location.  Generic dummy frames always
      have the register value in an ``expression''.  */
@@ -218,7 +234,7 @@ dummy_frame_prev_register (struct frame_
       /* Use the regcache_cooked_read() method so that it, on the fly,
          constructs either a raw or pseudo register from the raw
          register cache.  */
-      regcache_cooked_read (dummy->regcache, regnum, bufferp);
+      regcache_cooked_read (cache->prev_regcache, regnum, bufferp);
     }
 }
 
@@ -233,45 +249,24 @@ dummy_frame_this_id (struct frame_info *
 		     void **this_prologue_cache,
 		     struct frame_id *this_id)
 {
-  struct dummy_frame *dummy = (*this_prologue_cache);
-  if (dummy != NULL)
-    {
-      (*this_id) = dummy->id;
-      return;
-    }
-  /* When unwinding a normal frame, the stack structure is determined
-     by analyzing the frame's function's code (be it using brute force
-     prologue analysis, or the dwarf2 CFI).  In the case of a dummy
-     frame, that simply isn't possible.  The PC is either the program
-     entry point, or some random address on the stack.  Trying to use
-     that PC to apply standard frame ID unwind techniques is just
-     asking for trouble.  */
-  /* Use an architecture specific method to extract the prev's dummy
-     ID from the next frame.  Note that this method uses
-     frame_register_unwind to obtain the register values needed to
-     determine the dummy frame's ID.  */
-  gdb_assert (gdbarch_unwind_dummy_id_p (current_gdbarch));
-  (*this_id) = gdbarch_unwind_dummy_id (current_gdbarch, next_frame);
-  (*this_prologue_cache) = find_dummy_frame ((*this_id).code_addr,
-					     (*this_id).stack_addr);
+  /* The dummy-frame sniffer always fills in the cache.  */
+  struct dummy_frame_cache *cache = (*this_prologue_cache);
+  gdb_assert (cache != NULL);
+  (*this_id) = cache->this_id;
 }
 
-static struct frame_unwind dummy_frame_unwind =
+static const struct frame_unwind dummy_frame_unwinder =
 {
   DUMMY_FRAME,
   dummy_frame_this_id,
-  dummy_frame_prev_register
+  dummy_frame_prev_register,
+  NULL,
+  dummy_frame_sniffer,
 };
 
-const struct frame_unwind *
-dummy_frame_sniffer (struct frame_info *next_frame)
-{
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
-  if (pc_in_dummy_frame (pc))
-    return &dummy_frame_unwind;
-  else
-    return NULL;
-}
+const struct frame_unwind *const dummy_frame_unwind = {
+  &dummy_frame_unwinder
+};
 
 static void
 fprint_dummy_frames (struct ui_file *file)
Index: dummy-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/dummy-frame.h,v
retrieving revision 1.15
diff -p -u -r1.15 dummy-frame.h
--- dummy-frame.h	1 May 2004 22:41:34 -0000	1.15
+++ dummy-frame.h	2 Aug 2004 16:06:32 -0000
@@ -30,6 +30,6 @@ struct frame_id;
 /* If the PC falls in a dummy frame, return a dummy frame
    unwinder.  */
 
-extern const struct frame_unwind *dummy_frame_sniffer (struct frame_info *next_frame);
+extern const struct frame_unwind *const dummy_frame_unwind;
 
 #endif /* !defined (DUMMY_FRAME_H)  */
Index: frame-unwind.c
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.c,v
retrieving revision 1.14
diff -p -u -r1.14 frame-unwind.c
--- frame-unwind.c	31 Jul 2004 21:41:50 -0000	1.14
+++ frame-unwind.c	2 Aug 2004 16:06:32 -0000
@@ -50,7 +50,7 @@ frame_unwind_init (struct obstack *obsta
   /* Start the table out with a few default sniffers.  OSABI code
      can't override this.  */
   table->list = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry);
-  table->list->sniffer = dummy_frame_sniffer;
+  table->list->unwinder = dummy_frame_unwind;
   /* The insertion point for OSABI sniffers.  */
   table->osabi_head = &table->list->next;
   return table;

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