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]

[patch/rfc] Add a sentinel frame


Hello,

This patch modifies^D^D^D^Dsimplifies the frame code so that there is an extra frame below the innermost frame. That extra frame maps any request for a register onto the regcache.

The thing to notice with this patch is how it eliminates the need to special case a level zero frame when fetching a frame's register. Instead, a register can be fetched using the recursive frame_register() method.

I'll look to commit this in a few days.

Follow on patches include:
- convert d10v to the current frame unwind mechanims
- deprecate methods such as POP_FRAME.

Andrew
2003-01-23  Andrew Cagney  <ac131313@redhat.com>

	* sentinel-frame.h, sentinel-frame.c: New files.
	* Makefile.in (frame.o): Update dependencies.
	(SFILES): Add sentinel-frame.c.
	(sentinel_frame_h): Define.
	(COMMON_OBS): Add sentinel-frame.o.
	(sentinel-frame.o): Specify dependencies.
	* frame.c: Include "sentinel-frame.h".
	(frame_register_unwind): Rewrite assuming that there is always a a
	->next frame.
	(frame_register, generic_unwind_get_saved_register): Ditto.
	(frame_read_unsigned_register, frame_read_signed_register): Ditto.
	(create_sentinel_frame, unwind_to_current_frame): New functions.
	(get_current_frame): Rewrite using create_sentinel_frame and
	unwind_to_current_frame.  When possible, always create a frame.
	(create_new_frame): Set next to the sentinel frame.
	(get_next_frame): Rewrite.  Don't go below the level 0 frame.
	(deprecated_update_frame_pc_hack): Update the next frame's PC and
	ID cache when necessary.
	(frame_saved_regs_id_unwind): Use frame_relative_level.
	(deprecated_generic_get_saved_register): Use frame_relative_level,
	get_frame_saved_regs, get_frame_pc, get_frame_base and
	get_next_frame.
	(frame_saved_regs_register_unwind): Use get_frame_saved_regs and
	frame_register.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.317
diff -u -r1.317 Makefile.in
--- Makefile.in	23 Jan 2003 07:30:17 -0000	1.317
+++ Makefile.in	23 Jan 2003 20:46:59 -0000
@@ -528,7 +528,9 @@
 	objfiles.c osabi.c \
 	p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \
 	regcache.c reggroups.c remote.c \
-	scm-exp.c scm-lang.c scm-valprint.c serial.c ser-unix.c source.c \
+	scm-exp.c scm-lang.c scm-valprint.c \
+	sentinel-frame.c \
+	serial.c ser-unix.c source.c \
 	stabsread.c stack.c std-regs.c symfile.c symmisc.c symtab.c \
 	target.c thread.c top.c tracepoint.c typeprint.c \
 	tui/tui.c tui/tui.h tui/tuiCommand.c tui/tuiCommand.h \
@@ -686,6 +688,7 @@
 remote_h = remote.h
 scm_lang_h = scm-lang.h $(scm_tags_h)
 scm_tags_h = scm-tags.h
+sentinel_frame_h = sentinel-frame.h
 ser_unix_h = ser-unix.h
 serial_h = serial.h
 sh_tdep_h = sh-tdep.h
@@ -832,7 +835,9 @@
 	varobj.o wrapper.o \
 	jv-lang.o jv-valprint.o jv-typeprint.o \
 	m2-lang.o p-lang.o p-typeprint.o p-valprint.o \
-	scm-exp.o scm-lang.o scm-valprint.o complaints.o typeprint.o \
+	scm-exp.o scm-lang.o scm-valprint.o \
+	sentinel-frame.o \
+	complaints.o typeprint.o \
 	c-typeprint.o f-typeprint.o m2-typeprint.o \
 	c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
 	nlmread.o serial.o mdebugread.o top.o utils.o \
@@ -1692,7 +1697,8 @@
 frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
 	$(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(builtin_regs_h) \
 	$(gdb_obstack_h) $(dummy_frame_h) $(gdbcore_h) $(annotate_h) \
-	$(language_h) $(frame_unwind_h) $(command_h) $(gdbcmd_h)
+	$(language_h) $(frame_unwind_h) $(command_h) $(gdbcmd_h) \
+	$(sentinel_frame_h)
 frame-unwind.o: frame-unwind.c $(defs_h) $(frame_h) $(frame_unwind_h) \
 	$(gdb_assert_h) $(dummy_frame_h) $(legacy_frame_h)
 frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \
@@ -2125,6 +2131,8 @@
 scm-valprint.o: scm-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
 	$(expression_h) $(parser_defs_h) $(language_h) $(value_h) \
 	$(scm_lang_h) $(valprint_h) $(gdbcore_h)
+sentinel-frame.o: sentinel-frame.c $(defs_h) $(regcache_h) \
+	$(sentinel_frame_h) $(inferior_h) $(frame_unwind_h)
 ser-e7kpc.o: ser-e7kpc.c $(defs_h) $(serial_h) $(gdb_string_h)
 ser-go32.o: ser-go32.c $(defs_h) $(gdbcmd_h) $(serial_h) $(gdb_string_h)
 ser-pipe.o: ser-pipe.c $(defs_h) $(serial_h) $(ser_unix_h) $(gdb_vfork_h) \
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.62
diff -u -r1.62 frame.c
--- frame.c	21 Jan 2003 19:32:42 -0000	1.62
+++ frame.c	23 Jan 2003 20:46:59 -0000
@@ -31,6 +31,7 @@
 #include "builtin-regs.h"
 #include "gdb_obstack.h"
 #include "dummy-frame.h"
+#include "sentinel-frame.h"
 #include "gdbcore.h"
 #include "annotate.h"
 #include "language.h"
@@ -179,29 +180,11 @@
   gdb_assert (realnump != NULL);
   /* gdb_assert (bufferp != NULL); */
 
-  /* NOTE: cagney/2002-04-14: It would be nice if, instead of a
-     special case, there was always an inner frame dedicated to the
-     hardware registers.  Unfortunatly, there is too much unwind code
-     around that looks up/down the frame chain while making the
-     assumption that each frame level is using the same unwind code.  */
-
-  if (frame == NULL)
-    {
-      /* We're in the inner-most frame, get the value direct from the
-	 register cache.  */
-      *optimizedp = 0;
-      *lvalp = lval_register;
-      /* ULGH!  Code uses the offset into the raw register byte array
-         as a way of identifying a register.  */
-      *addrp = REGISTER_BYTE (regnum);
-      /* Should this code test ``register_cached (regnum) < 0'' and do
-         something like set realnum to -1 when the register isn't
-         available?  */
-      *realnump = regnum;
-      if (bufferp)
-	deprecated_read_register_gen (regnum, bufferp);
-      return;
-    }
+  /* NOTE: cagney/2002-11-27: A program trying to unwind a NULL frame
+     is broken.  There is always a frame.  If there, for some reason,
+     isn't, there is some pretty busted code as it should have
+     detected the problem before calling here.  */
+  gdb_assert (frame != NULL);
 
   /* Ask this frame to unwind its register.  */
   frame->unwind->reg (frame, &frame->unwind_cache, regnum,
@@ -247,25 +230,11 @@
       return;
     }
 
-  /* Reached the the bottom (youngest, inner most) of the frame chain
-     (youngest, inner most) frame, go direct to the hardware register
-     cache (do not pass go, do not try to cache the value, ...).  The
-     unwound value would have been cached in frame->next but that
-     doesn't exist.  This doesn't matter as the hardware register
-     cache is stopping any unnecessary accesses to the target.  */
-
-  /* NOTE: cagney/2002-04-14: It would be nice if, instead of a
-     special case, there was always an inner frame dedicated to the
-     hardware registers.  Unfortunatly, there is too much unwind code
-     around that looks up/down the frame chain while making the
-     assumption that each frame level is using the same unwind code.  */
-
-  if (frame == NULL)
-    frame_register_unwind (NULL, regnum, optimizedp, lvalp, addrp, realnump,
-			   bufferp);
-  else
-    frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
-			   realnump, bufferp);
+  /* Obtain the register value by unwinding the register from the next
+     (more inner frame).  */
+  gdb_assert (frame != NULL && frame->next != NULL);
+  frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
+			 realnump, bufferp);
 }
 
 void
@@ -317,17 +286,17 @@
      tests like ``if get_next_frame() == NULL'' and instead just rely
      on recursive frame calls (like the below code) when manipulating
      a frame chain.  */
-  gdb_assert (frame != NULL);
-  frame_unwind_unsigned_register (get_next_frame (frame), regnum, val);
+  gdb_assert (frame != NULL && frame->next != NULL);
+  frame_unwind_unsigned_register (frame->next, regnum, val);
 }
 
 void
 frame_read_signed_register (struct frame_info *frame, int regnum,
 			    LONGEST *val)
 {
-  /* See note in frame_read_unsigned_register().  */
-  gdb_assert (frame != NULL);
-  frame_unwind_signed_register (get_next_frame (frame), regnum, val);
+  /* See note above in frame_read_unsigned_register().  */
+  gdb_assert (frame != NULL && frame->next != NULL);
+  frame_unwind_signed_register (frame->next, regnum, val);
 }
 
 static void
@@ -355,25 +324,9 @@
   if (addrp == NULL)
     addrp = &addrx;
 
-  /* Reached the the bottom (youngest, inner most) of the frame chain
-     (youngest, inner most) frame, go direct to the hardware register
-     cache (do not pass go, do not try to cache the value, ...).  The
-     unwound value would have been cached in frame->next but that
-     doesn't exist.  This doesn't matter as the hardware register
-     cache is stopping any unnecessary accesses to the target.  */
-
-  /* NOTE: cagney/2002-04-14: It would be nice if, instead of a
-     special case, there was always an inner frame dedicated to the
-     hardware registers.  Unfortunatly, there is too much unwind code
-     around that looks up/down the frame chain while making the
-     assumption that each frame level is using the same unwind code.  */
-
-  if (frame == NULL)
-    frame_register_unwind (NULL, regnum, optimizedp, lvalp, addrp, &realnumx,
-			   raw_buffer);
-  else
-    frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
-			   &realnumx, raw_buffer);
+  gdb_assert (frame != NULL && frame->next != NULL);
+  frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
+			 &realnumx, raw_buffer);
 }
 
 void
@@ -463,6 +416,32 @@
   return builtin_reg_map_regnum_to_name (regnum);
 }
 
+/* Create a sentinel frame.  */
+
+struct frame_info *
+create_sentinel_frame (struct regcache *regcache)
+{
+  struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
+  frame->type = NORMAL_FRAME;
+  frame->level = -1;
+  /* Explicitly initialize the sentinel frame's cache.  Provide it
+     with the underlying regcache.  In the future additional
+     information, such as the frame's thread will be added.  */
+  frame->unwind_cache = sentinel_frame_cache (regcache);
+  /* For the moment there is only one sentinel frame implementation.  */
+  frame->unwind = sentinel_frame_unwind;
+  /* Link this frame back to itself.  The frame is self referential
+     (the unwound PC is the same as the pc), so make it so.  */
+  frame->next = frame;
+  /* Always unwind the PC as part of creating this frame.  This
+     ensures that the frame's PC points at something valid.  */
+  /* FIXME: cagney/2003-01-10: Problem here.  Unwinding a sentinel
+     frame's PC may require information such as the frame's thread's
+     stop reason.  Is it possible to get to that?  */
+  frame->pc = frame_pc_unwind (frame);
+  return frame;
+}
+
 /* Info about the innermost stack frame (contents of FP register) */
 
 static struct frame_info *current_frame;
@@ -495,17 +474,43 @@
   return fi->saved_regs;
 }
 
-/* Return the innermost (currently executing) stack frame.  */
+/* Return the innermost (currently executing) stack frame.  This is
+   split into two functions.  The function unwind_to_current_frame()
+   is wrapped in catch exceptions so that, even when the unwind of the
+   sentinel frame fails, the function still returns a stack frame.  */
+
+static int
+unwind_to_current_frame (struct ui_out *ui_out, void *args)
+{
+  struct frame_info *frame = get_prev_frame (args);
+  /* A sentinel frame can fail to unwind, eg, because it's PC value
+     lands in somewhere like start.  */
+  if (frame == NULL)
+    return 1;
+  current_frame = frame;
+  return 0;
+}
 
 struct frame_info *
 get_current_frame (void)
 {
+  if (!target_has_stack)
+    error ("No stack.");
+  if (!target_has_registers)
+    error ("No registers.");
+  if (!target_has_memory)
+    error ("No memory.");
   if (current_frame == NULL)
     {
-      if (target_has_stack)
-	current_frame = create_new_frame (read_fp (), read_pc ());
-      else
-	error ("No stack.");
+      struct frame_info *sentinel_frame =
+	create_sentinel_frame (current_regcache);
+      if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame,
+			    NULL, RETURN_MASK_ERROR) != 0)
+	{
+	  /* Oops! Fake a current frame?  Is this useful?  It has a PC
+             of zero, for instance.  */
+	  current_frame = sentinel_frame;
+	}
     }
   return current_frame;
 }
@@ -593,11 +598,11 @@
   gdb_assert (FRAME_INIT_SAVED_REGS_P ());
 
   /* Load the saved_regs register cache.  */
-  if (frame->saved_regs == NULL)
+  if (get_frame_saved_regs (frame) == NULL)
     FRAME_INIT_SAVED_REGS (frame);
 
-  if (frame->saved_regs != NULL
-      && frame->saved_regs[regnum] != 0)
+  if (get_frame_saved_regs (frame) != NULL
+      && get_frame_saved_regs (frame)[regnum] != 0)
     {
       if (regnum == SP_REGNUM)
 	{
@@ -608,7 +613,7 @@
 	  *realnump = -1;
 	  if (bufferp != NULL)
 	    store_address (bufferp, REGISTER_RAW_SIZE (regnum),
-			   frame->saved_regs[regnum]);
+			   get_frame_saved_regs (frame)[regnum]);
 	}
       else
 	{
@@ -616,7 +621,7 @@
              a local copy of its value.  */
 	  *optimizedp = 0;
 	  *lvalp = lval_memory;
-	  *addrp = frame->saved_regs[regnum];
+	  *addrp = get_frame_saved_regs (frame)[regnum];
 	  *realnump = -1;
 	  if (bufferp != NULL)
 	    {
@@ -635,13 +640,13 @@
 		{
 		  regs[regnum]
 		    = frame_obstack_zalloc (REGISTER_RAW_SIZE (regnum));
-		  read_memory (frame->saved_regs[regnum], regs[regnum],
+		  read_memory (get_frame_saved_regs (frame)[regnum], regs[regnum],
 			       REGISTER_RAW_SIZE (regnum));
 		}
 	      memcpy (bufferp, regs[regnum], REGISTER_RAW_SIZE (regnum));
 #else
 	      /* Read the value in from memory.  */
-	      read_memory (frame->saved_regs[regnum], bufferp,
+	      read_memory (get_frame_saved_regs (frame)[regnum], bufferp,
 			   REGISTER_RAW_SIZE (regnum));
 #endif
 	    }
@@ -650,21 +655,11 @@
     }
 
   /* No luck, assume this and the next frame have the same register
-     value.  If a value is needed, pass the request on down the chain;
-     otherwise just return an indication that the value is in the same
-     register as the next frame.  */
-  if (bufferp == NULL)
-    {
-      *optimizedp = 0;
-      *lvalp = lval_register;
-      *addrp = 0;
-      *realnump = regnum;
-    }
-  else
-    {
-      frame_register_unwind (frame->next, regnum, optimizedp, lvalp, addrp,
-			     realnump, bufferp);
-    }
+     value.  Pass the request down the frame chain to the next frame.
+     Hopefully that will find the register's location, either in a
+     register or in memory.  */
+  frame_register (frame, regnum, optimizedp, lvalp, addrp, realnump,
+		  bufferp);
 }
 
 static CORE_ADDR
@@ -684,7 +679,7 @@
   /* Start out by assuming it's NULL.  */
   (*id) = null_frame_id;
 
-  if (next_frame->next == NULL)
+  if (frame_relative_level (next_frame) <= 0)
     /* FIXME: 2002-11-09: Frameless functions can occure anywhere in
        the frame chain, not just the inner most frame!  The generic,
        per-architecture, frame code should handle this and the below
@@ -797,44 +792,50 @@
      the current frame itself: otherwise, we would be getting the
      previous frame's registers which were saved by the current frame.  */
 
-  while (frame && ((frame = frame->next) != NULL))
+  if (frame != NULL)
     {
-      if (get_frame_type (frame) == DUMMY_FRAME)
+      for (frame = get_next_frame (frame);
+	   frame_relative_level (frame) >= 0;
+	   frame = get_next_frame (frame))
 	{
-	  if (lval)		/* found it in a CALL_DUMMY frame */
-	    *lval = not_lval;
-	  if (raw_buffer)
-	    /* FIXME: cagney/2002-06-26: This should be via the
-	       gdbarch_register_read() method so that it, on the fly,
-	       constructs either a raw or pseudo register from the raw
-	       register cache.  */
-	    regcache_raw_read (generic_find_dummy_frame (frame->pc,
-							 frame->frame),
-			       regnum, raw_buffer);
-	  return;
-	}
-
-      FRAME_INIT_SAVED_REGS (frame);
-      if (frame->saved_regs != NULL
-	  && frame->saved_regs[regnum] != 0)
-	{
-	  if (lval)		/* found it saved on the stack */
-	    *lval = lval_memory;
-	  if (regnum == SP_REGNUM)
+	  if (get_frame_type (frame) == DUMMY_FRAME)
 	    {
-	      if (raw_buffer)	/* SP register treated specially */
-		store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
-			       frame->saved_regs[regnum]);
+	      if (lval)		/* found it in a CALL_DUMMY frame */
+		*lval = not_lval;
+	      if (raw_buffer)
+		/* FIXME: cagney/2002-06-26: This should be via the
+		   gdbarch_register_read() method so that it, on the
+		   fly, constructs either a raw or pseudo register
+		   from the raw register cache.  */
+		regcache_raw_read
+		  (generic_find_dummy_frame (get_frame_pc (frame),
+					     get_frame_base (frame)),
+		   regnum, raw_buffer);
+	      return;
 	    }
-	  else
+
+	  FRAME_INIT_SAVED_REGS (frame);
+	  if (get_frame_saved_regs (frame) != NULL
+	      && get_frame_saved_regs (frame)[regnum] != 0)
 	    {
-	      if (addrp)	/* any other register */
-		*addrp = frame->saved_regs[regnum];
-	      if (raw_buffer)
-		read_memory (frame->saved_regs[regnum], raw_buffer,
-			     REGISTER_RAW_SIZE (regnum));
+	      if (lval)		/* found it saved on the stack */
+		*lval = lval_memory;
+	      if (regnum == SP_REGNUM)
+		{
+		  if (raw_buffer)	/* SP register treated specially */
+		    store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
+				   get_frame_saved_regs (frame)[regnum]);
+		}
+	      else
+		{
+		  if (addrp)	/* any other register */
+		    *addrp = get_frame_saved_regs (frame)[regnum];
+		  if (raw_buffer)
+		    read_memory (get_frame_saved_regs (frame)[regnum], raw_buffer,
+				 REGISTER_RAW_SIZE (regnum));
+		}
+	      return;
 	    }
-	  return;
 	}
     }
 
@@ -884,6 +885,7 @@
 
   fi->frame = addr;
   fi->pc = pc;
+  fi->next = create_sentinel_frame (current_regcache);
   fi->type = frame_type_from_pc (pc);
 
   if (INIT_EXTRA_FRAME_INFO_P ())
@@ -896,12 +898,16 @@
 }
 
 /* Return the frame that FRAME calls (NULL if FRAME is the innermost
-   frame).  */
+   frame).  Be careful to not fall off the bottom of the frame chain
+   and onto the sentinel frame.  */
 
 struct frame_info *
 get_next_frame (struct frame_info *frame)
 {
-  return frame->next;
+  if (frame->level > 0)
+    return frame->next;
+  else
+    return NULL;
 }
 
 /* Flush the entire frame cache.  */
@@ -1415,6 +1421,7 @@
 deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
 {
   /* See comment in "frame.h".  */
+  gdb_assert (frame->next != NULL);
   frame->pc = pc;
 }
 
Index: sentinel-frame.c
===================================================================
RCS file: sentinel-frame.c
diff -N sentinel-frame.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sentinel-frame.c	23 Jan 2003 20:46:59 -0000
@@ -0,0 +1,113 @@
+/* Code dealing with register stack frames, for GDB, the GNU debugger.
+
+   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software
+   Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+
+#include "defs.h"
+#include "regcache.h"
+#include "sentinel-frame.h"
+#include "inferior.h"
+#include "frame-unwind.h"
+
+struct frame_unwind_cache
+{
+  struct regcache *regcache;
+};
+
+void *
+sentinel_frame_cache (struct regcache *regcache)
+{
+  struct frame_unwind_cache *cache = 
+    FRAME_OBSTACK_ZALLOC (struct frame_unwind_cache);
+  cache->regcache = regcache;
+  return cache;
+}
+
+/* Here the register value is taken direct from the register cache.  */
+
+void
+sentinel_frame_register_unwind (struct frame_info *frame,
+				void **unwind_cache,
+				int regnum, int *optimized,
+				enum lval_type *lvalp, CORE_ADDR *addrp,
+				int *realnum, void *bufferp)
+{
+  struct frame_unwind_cache *cache = *unwind_cache;
+  /* Describe the register's location.  A reg-frame maps all registers
+     onto the corresponding hardware register.  */
+  *optimized = 0;
+  *lvalp = lval_register;
+  *addrp = REGISTER_BYTE (regnum);
+  *realnum = regnum;
+
+  /* If needed, find and return the value of the register.  */
+  if (bufferp != NULL)
+    {
+      /* Return the actual value.  */
+      /* 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 (cache->regcache, regnum, bufferp);
+    }
+}
+
+CORE_ADDR
+sentinel_frame_pc_unwind (struct frame_info *frame,
+			  void **cache)
+{
+  /* FIXME: cagney/2003-01-08: This should be using a per-architecture
+     method that doesn't suffer from DECR_PC_AFTER_BREAK problems.
+     Such a method would take unwind_cache, regcache and stop reason
+     parameters.  */
+  return read_pc ();
+}
+
+void
+sentinel_frame_id_unwind (struct frame_info *frame,
+			  void **cache,
+			  struct frame_id *id)
+{
+  /* FIXME: cagney/2003-01-08: This should be using a per-architecture
+     method that doesn't suffer from DECR_PC_AFTER_BREAK problems.
+     Such a method would take unwind_cache, regcache and stop reason
+     parameters.  */
+  id->base = read_fp ();
+  id->pc = read_pc ();
+}
+
+static void
+sentinel_frame_pop (struct frame_info *frame,
+		    void **cache,
+		    struct regcache *regcache)
+{
+  internal_error (__FILE__, __LINE__, "Function sentinal_frame_pop called");
+}
+
+const struct frame_unwind sentinel_frame_unwinder =
+{
+  sentinel_frame_pop,
+  sentinel_frame_pc_unwind,
+  sentinel_frame_id_unwind,
+  sentinel_frame_register_unwind
+};
+
+const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder;
Index: sentinel-frame.h
===================================================================
RCS file: sentinel-frame.h
diff -N sentinel-frame.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sentinel-frame.h	23 Jan 2003 20:46:59 -0000
@@ -0,0 +1,41 @@
+/* Code dealing with register stack frames, for GDB, the GNU debugger.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#if !defined (SENTINEL_FRAME_H)
+#define SENTINEL_FRAME_H 1
+
+struct frame_unwind;
+struct regcache;
+
+/* Implement the sentinel frame.  The sentinel frame terminates the
+   inner most end of the frame chain.  If unwound, it returns the
+   information need to construct an inner-most frame.  */
+
+/* Pump prime the sentinel frame's cache.  Since this needs the
+   REGCACHE provide that here.  */
+
+extern void *sentinel_frame_cache (struct regcache *regcache);
+
+/* At present there is only one type of sentinel frame.  */
+
+extern const struct frame_unwind *const sentinel_frame_unwind;
+
+#endif /* !defined (SENTINEL_FRAME_H)  */

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