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]

[unwind-20030108-branch] Move legacy to legacy-frame.[hc]


Hello,

This patch moves much of the legacy frame code to the new files legacy-frame.[hc].

In addition it fixes a few problems with trying to chain the sentinel frame - that frame didn't have its PC set :-(

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

	* frame.c (create_sentinel_frame): Initialize sentinel frame's PC.

	* frame.c: Include "ui-out.h".
	* sentinel-frame.c (struct frame_unwind_cache): Add pc field.

	* sentinel-frame.h (sentinel_frame_cache): Add a pc parameter.

	* frame.c (deprecated_generic_get_saved_register): Move from here.
	* legacy-frame.c (deprecated_generic_get_saved_register): to here.

	* legacy-frame.c: Include "regcache.h", "dummy-frame.h", and
	"target.h".

	* frame.c (set_unwind_by_pc): Update.
	(frame_saved_regs_id_unwind): Delete function.
	(frame_saved_regs_register_unwind): Delete function.
	(frame_saved_regs_pc_unwind): Delete function.
	(legacy_get_prev_frame): Rename deprecated_get_prev_frame.
	(get_prev_frame): Update call.
	(get_prev_frame): Move check for inside_main_func to before
	setting of prev_p.  Add check for inside_entry_file, but after
	prev_p.

	* Makefile.in (frame.o): Update dependencies.

	* frame.c: Include "legacy-frame.h".

	* Makefile.in (SFILES): Add legacy-frame.c.
	(legacy_frame_h): Define.
	(COMMON_OBS): Add legacy-frame.o.
	(legacy-frame.o): Specify dependencies.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.311.2.1
diff -u -r1.311.2.1 Makefile.in
--- Makefile.in	10 Jan 2003 15:22:39 -0000	1.311.2.1
+++ Makefile.in	10 Jan 2003 21:54:08 -0000
@@ -512,7 +512,7 @@
 	inf-loop.c infcmd.c inflow.c infrun.c \
 	jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \
 	kod.c kod-cisco.c \
-	language.c linespec.c \
+	language.c legacy-frame.c linespec.c \
 	m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c \
 	macrotab.c macroexp.c macrocmd.c macroscope.c main.c maint.c \
 	mdebugread.c memattr.c mem-break.c minsyms.c mipsread.c \
@@ -649,6 +649,7 @@
 jv_lang_h = jv-lang.h
 kod_h = kod.h
 language_h = language.h
+legacy_frame_h = legacy-frame.h
 linespec_h = linespec.h
 m2_lang_h = m2-lang.h
 m68k_tdep_h = m68k-tdep.h
@@ -834,7 +835,7 @@
 	frame.o doublest.o \
 	gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \
 	sentinel-frame.o \
-	reggroups.o
+	reggroups.o legacy-frame.o
 
 OBS = $(COMMON_OBS) $(ANNOTATE_OBS)
 
@@ -1681,8 +1682,9 @@
 	$(terminal_h) $(gdbthread_h) $(command_h)
 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) $(sentinel_frame_h) $(ui_out_h)
+	$(gdb_obstack_h) $(dummy_frame_h) $(sentinel_frame_h) \
+	$(legacy_frame_h) $(gdbcore_h) $(annotate_h) $(language_h) \
+	$(ui_out_h)
 frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \
 	$(arch_utils_h) $(regcache_h)
 gcore.o: gcore.c $(defs_h) $(cli_decode_h) $(inferior_h) $(gdbcore_h) \
@@ -1832,6 +1834,8 @@
 	$(parser_defs_h) $(jv_lang_h)
 lin-lwp.o: lin-lwp.c $(defs_h) $(gdb_assert_h) $(gdb_string_h) $(gdb_wait_h) \
 	$(gdbthread_h) $(inferior_h) $(target_h) $(regcache_h) $(gdbcmd_h)
+legacy-frame.o: legacy-frame.c $(defs_h) $(legacy_frame_h) $(gdb_assert_h) \
+	$(frame_h) $(gdbcore_h) $(regcache_h) $(target_h) $(dummy_frame_h)
 linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \
 	$(symfile_h) $(objfiles_h) $(demangle_h) $(value_h) $(completer_h) \
 	$(cp_abi_h) $(source_h) $(parser_defs_h)
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.56.2.1
diff -u -r1.56.2.1 frame.c
--- frame.c	10 Jan 2003 15:22:39 -0000	1.56.2.1
+++ frame.c	10 Jan 2003 21:54:08 -0000
@@ -32,6 +32,7 @@
 #include "gdb_obstack.h"
 #include "dummy-frame.h"
 #include "sentinel-frame.h"
+#include "legacy-frame.h"
 #include "gdbcore.h"
 #include "annotate.h"
 #include "language.h"
@@ -410,6 +411,12 @@
   frame->pc_unwind = sentinel_frame_pc_unwind;
   frame->id_unwind = sentinel_frame_id_unwind;
   frame->register_unwind = sentinel_frame_register_unwind;
+  /* Always unwind the PC as part of creating this frame.  This
+     ensures that the frame's PC points into something valid.  */
+  /* FIXME: cagney/2003-01-10: Problem here.  Unwinding a sentinel
+     frame's PC may require information such as the frame thread's
+     stop reason.  Is it possible to get to that?  */
+  frame->pc = frame_pc_unwind (frame);
   return frame;
 }
 
@@ -450,7 +457,12 @@
 static int
 unwind_to_current_frame (struct ui_out *ui_out, void *args)
 {
-  current_frame = get_prev_frame (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;
 }
 
@@ -468,7 +480,7 @@
       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)
+			    NULL, RETURN_MASK_ERROR) != 0)
 	{
 	  /* Oops! Fake a current frame?  Is this useful?  It has a PC
              of zero, for instance.  */
@@ -537,271 +549,6 @@
     }
 }
 
-/* Return the register saved in the simplistic ``saved_regs'' cache.
-   If the value isn't here AND a value is needed, try the next inner
-   most frame.  */
-
-struct frame_unwind_cache
-{
-  void *regs[1];
-};
-
-static void
-frame_saved_regs_register_unwind (struct frame_info *frame,
-				  struct frame_unwind_cache **cache,
-				  int regnum, int *optimizedp,
-				  enum lval_type *lvalp, CORE_ADDR *addrp,
-				  int *realnump, void *bufferp)
-{
-  /* There is always a frame at this point.  And THIS is the frame
-     we're interested in.  */
-  gdb_assert (frame != NULL);
-  /* If we're using generic dummy frames, we'd better not be in a call
-     dummy.  (generic_call_dummy_register_unwind ought to have been called
-     instead.)  */
-  gdb_assert (!(DEPRECATED_USE_GENERIC_DUMMY_FRAMES
-		&& (get_frame_type (frame) == DUMMY_FRAME)));
-
-  /* Load the saved_regs register cache.  */
-  if (frame->saved_regs == NULL)
-    FRAME_INIT_SAVED_REGS (frame);
-
-  if (frame->saved_regs != NULL
-      && frame->saved_regs[regnum] != 0)
-    {
-      if (regnum == SP_REGNUM)
-	{
-	  /* SP register treated specially.  */
-	  *optimizedp = 0;
-	  *lvalp = not_lval;
-	  *addrp = 0;
-	  *realnump = -1;
-	  if (bufferp != NULL)
-	    store_address (bufferp, REGISTER_RAW_SIZE (regnum),
-			   frame->saved_regs[regnum]);
-	}
-      else
-	{
-	  /* Any other register is saved in memory, fetch it but cache
-             a local copy of its value.  */
-	  *optimizedp = 0;
-	  *lvalp = lval_memory;
-	  *addrp = frame->saved_regs[regnum];
-	  *realnump = -1;
-	  if (bufferp != NULL)
-	    {
-#if 1
-	      /* Save each register value, as it is read in, in a
-                 frame based cache.  */
-	      if ((*cache) == NULL)
-		{
-		  int sizeof_cache = ((NUM_REGS + NUM_PSEUDO_REGS)
-				      * sizeof (void *));
-		  (*cache) = frame_obstack_zalloc (sizeof_cache);
-		}
-	      if ((*cache)->regs[regnum] == NULL)
-		{
-		  (*cache)->regs[regnum]
-		    = frame_obstack_zalloc (REGISTER_RAW_SIZE (regnum));
-		  read_memory (frame->saved_regs[regnum],
-			       (*cache)->regs[regnum],
-			       REGISTER_RAW_SIZE (regnum));
-		}
-	      memcpy (bufferp, (*cache)->regs[regnum],
-		      REGISTER_RAW_SIZE (regnum));
-#else
-	      /* Read the value in from memory.  */
-	      read_memory (frame->saved_regs[regnum], bufferp,
-			   REGISTER_RAW_SIZE (regnum));
-#endif
-	    }
-	}
-      return;
-    }
-
-  /* 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);
-    }
-}
-
-static CORE_ADDR
-frame_saved_regs_pc_unwind (struct frame_info *frame,
-			    struct frame_unwind_cache **cache)
-{
-  return FRAME_SAVED_PC (frame);
-}
-	
-static void
-frame_saved_regs_id_unwind (struct frame_info *next_frame,
-			    struct frame_unwind_cache **cache,
-			    struct frame_id *id)
-{
-  int fromleaf;
-
-  if (next_frame->next == NULL)
-    /* 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
-       should simply be removed.  */
-    fromleaf = FRAMELESS_FUNCTION_INVOCATION (next_frame);
-  else
-    fromleaf = 0;
-
-  if (fromleaf)
-    /* A frameless inner-most frame.  The `FP' (which isn't an
-       architecture frame-pointer register!) of the caller is the same
-       as the callee.  */
-    /* FIXME: 2002-11-09: There isn't any reason to special case this
-       edge condition.  Instead the per-architecture code should hande
-       it locally.  */
-    id->base = get_frame_base (next_frame);
-  else
-    {
-      /* Two macros defined in tm.h specify the machine-dependent
-         actions to be performed here.
-
-         First, get the frame's chain-pointer.
-
-         If that is zero, the frame is the outermost frame or a leaf
-         called by the outermost frame.  This means that if start
-         calls main without a frame, we'll return 0 (which is fine
-         anyway).
-
-         Nope; there's a problem.  This also returns when the current
-         routine is a leaf of main.  This is unacceptable.  We move
-         this to after the ffi test; I'd rather have backtraces from
-         start go curfluy than have an abort called from main not show
-         main.  */
-      id->base = FRAME_CHAIN (next_frame);
-
-      if (!frame_chain_valid (id->base, next_frame))
-	{
-	  *id = null_frame_id;
-	  return;
-	}
-    }
-  if (id->base == 0)
-    {
-      *id = null_frame_id;
-      return;
-    }
-
-  /* FIXME: cagney/2002-06-08: This should probably return the frame's
-     function and not the PC (a.k.a. resume address).  */
-  id->pc = frame_pc_unwind (next_frame);
-  return;
-}
-	
-/* Function: get_saved_register
-   Find register number REGNUM relative to FRAME and put its (raw,
-   target format) contents in *RAW_BUFFER.  
-
-   Set *OPTIMIZED if the variable was optimized out (and thus can't be
-   fetched).  Note that this is never set to anything other than zero
-   in this implementation.
-
-   Set *LVAL to lval_memory, lval_register, or not_lval, depending on
-   whether the value was fetched from memory, from a register, or in a
-   strange and non-modifiable way (e.g. a frame pointer which was
-   calculated rather than fetched).  We will use not_lval for values
-   fetched from generic dummy frames.
-
-   Set *ADDRP to the address, either in memory or as a REGISTER_BYTE
-   offset into the registers array.  If the value is stored in a dummy
-   frame, set *ADDRP to zero.
-
-   To use this implementation, define a function called
-   "get_saved_register" in your target code, which simply passes all
-   of its arguments to this function.
-
-   The argument RAW_BUFFER must point to aligned memory.  */
-
-void
-deprecated_generic_get_saved_register (char *raw_buffer, int *optimized,
-				       CORE_ADDR *addrp,
-				       struct frame_info *frame, int regnum,
-				       enum lval_type *lval)
-{
-  if (!target_has_registers)
-    error ("No registers.");
-
-  /* Normal systems don't optimize out things with register numbers.  */
-  if (optimized != NULL)
-    *optimized = 0;
-
-  if (addrp)			/* default assumption: not found in memory */
-    *addrp = 0;
-
-  /* Note: since the current frame's registers could only have been
-     saved by frames INTERIOR TO the current frame, we skip examining
-     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 (get_frame_type (frame) == DUMMY_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 (raw_buffer)	/* SP register treated specially */
-		store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
-			       frame->saved_regs[regnum]);
-	    }
-	  else
-	    {
-	      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));
-	    }
-	  return;
-	}
-    }
-
-  /* If we get thru the loop to this point, it means the register was
-     not saved in any frame.  Return the actual live-register value.  */
-
-  if (lval)			/* found it in a live register */
-    *lval = lval_register;
-  if (addrp)
-    *addrp = REGISTER_BYTE (regnum);
-  if (raw_buffer)
-    deprecated_read_register_gen (regnum, raw_buffer);
-}
-
 /* Using the PC, select a mechanism for unwinding a frame returning
    the previous frame.  The register unwind function should, on
    demand, initialize the ->context object.  */
@@ -818,9 +565,9 @@
 	 calls this function to find out where the saved registers are.
 	 Hopefully this is robust enough to stop any core dumps and
 	 return vaguely correct values..  */
-      *unwind_register = frame_saved_regs_register_unwind;
-      *unwind_pc = frame_saved_regs_pc_unwind;
-      *unwind_id = frame_saved_regs_id_unwind;
+      *unwind_register = legacy_frame_register_unwind;
+      *unwind_pc = legacy_frame_pc_unwind;
+      *unwind_id = legacy_frame_id_unwind;
     }
   else if (DEPRECATED_PC_IN_CALL_DUMMY_P ()
 	   ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0)
@@ -832,9 +579,9 @@
     }
   else
     {
-      *unwind_register = frame_saved_regs_register_unwind;
-      *unwind_pc = frame_saved_regs_pc_unwind;
-      *unwind_id = frame_saved_regs_id_unwind;
+      *unwind_register = legacy_frame_register_unwind;
+      *unwind_pc = legacy_frame_pc_unwind;
+      *unwind_id = legacy_frame_id_unwind;
     }
 }
 
@@ -933,17 +680,12 @@
    method.  */
 
 static struct frame_info *
-deprecated_get_prev_frame (struct frame_info *next_frame)
+legacy_get_prev_frame (struct frame_info *next_frame)
 {
   CORE_ADDR address = 0;
   struct frame_info *prev;
   int fromleaf;
 
-  /* Only try to do the unwind once.  */
-  if (next_frame->prev_p)
-    return next_frame->prev;
-  next_frame->prev_p = 1;
-
   /* On some machines it is possible to call a function without
      setting up a stack frame for it.  On these machines, we
      define this macro to take two args; a frameinfo pointer
@@ -1080,7 +822,7 @@
      function does have somewhere to cache that PC value.  */
 
   if (DEPRECATED_INIT_FRAME_PC_FIRST_P ())
-    prev->pc = (DEPRECATED_INIT_FRAME_PC_FIRST (fromleaf, prev));
+    deprecated_update_frame_pc_hack (prev, DEPRECATED_INIT_FRAME_PC_FIRST (fromleaf, prev));
 
   if (INIT_EXTRA_FRAME_INFO_P ())
     INIT_EXTRA_FRAME_INFO (fromleaf, prev);
@@ -1089,14 +831,14 @@
      FRAME_SAVED_PC may use that queue to figure out its value (see
      tm-sparc.h).  We want the pc saved in the inferior frame. */
   if (DEPRECATED_INIT_FRAME_PC_P ())
-    prev->pc = DEPRECATED_INIT_FRAME_PC (fromleaf, prev);
+    deprecated_update_frame_pc_hack (prev, DEPRECATED_INIT_FRAME_PC (fromleaf, prev));
 
   /* If ->frame and ->pc are unchanged, we are in the process of
      getting ourselves into an infinite backtrace.  Some architectures
      check this in FRAME_CHAIN or thereabouts, but it seems like there
      is no reason this can't be an architecture-independent check.  */
-  if (prev->frame == next_frame->frame
-      && prev->pc == next_frame->pc)
+  if (get_frame_base (prev) == get_frame_base (next_frame)
+      && get_frame_pc (prev) == get_frame_pc (next_frame))
     {
       next_frame->prev = NULL;
       obstack_free (&frame_cache_obstack, prev);
@@ -1107,8 +849,8 @@
      (and probably other architectural information).  The PC lets you
      check things like the debug info at that point (dwarf2cfi?) and
      use that to decide how the frame should be unwound.  */
-  set_unwind_by_pc (prev->pc, &prev->register_unwind, &prev->pc_unwind,
-		    &prev->id_unwind);
+  set_unwind_by_pc (get_frame_pc (prev), &prev->register_unwind,
+		    &prev->pc_unwind, &prev->id_unwind);
 
   /* NOTE: cagney/2002-11-18: The code segments, found in
      create_new_frame and get_prev_frame(), that initializes the
@@ -1120,8 +862,8 @@
      before the INIT function has been called.  */
   if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES
       && (DEPRECATED_PC_IN_CALL_DUMMY_P ()
-	  ? DEPRECATED_PC_IN_CALL_DUMMY (prev->pc, 0, 0)
-	  : pc_in_dummy_frame (prev->pc)))
+	  ? DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (prev), 0, 0)
+	  : pc_in_dummy_frame (get_frame_pc (prev))))
     prev->type = DUMMY_FRAME;
   else
     {
@@ -1132,8 +874,8 @@
 	 Unforunatly, its the INIT code that sets the PC (Hmm, catch
 	 22).  */
       char *name;
-      find_pc_partial_function (prev->pc, &name, NULL, NULL);
-      if (PC_IN_SIGTRAMP (prev->pc, name))
+      find_pc_partial_function (get_frame_pc (prev), &name, NULL, NULL);
+      if (PC_IN_SIGTRAMP (get_frame_pc (prev), name))
 	prev->type = SIGTRAMP_FRAME;
       /* FIXME: cagney/2002-11-11: Leave prev->type alone.  Some
          architectures are forcing the frame's type in INIT so we
@@ -1182,27 +924,41 @@
       return current_frame;
     }
 
-  if ((DEPRECATED_INIT_FRAME_PC_P ()
-       || DEPRECATED_INIT_FRAME_PC_FIRST_P ())
-      && next_frame->level >= 0)
-    /* Don't try to unwind the sentinal frame using the old code.  */
-    return deprecated_get_prev_frame (next_frame);
-
   /* There is always a frame.  If this assertion fails, suspect that
      something should be calling get_selected_frame() or
      get_current_frame().  */
   gdb_assert (next_frame != NULL);
 
+  if (next_frame->level >= 0
+      /* && !backtrace_below_main */
+      && inside_main_func (get_frame_pc (next_frame)))
+    /* Don't unwind past main(), always unwind the sentinel frame.
+       Note, this is done _before_ the frame has been marked as
+       previously unwound.  That way if the user later decides to
+       allow unwinds past main(), they can just happen.  */
+    return 0;
+
   /* Only try to do the unwind once.  */
   if (next_frame->prev_p)
     return next_frame->prev;
   next_frame->prev_p = 1;
 
-  if (next_frame->level >= 0
-      /* && !backtrace_below_main */
-      && inside_main_func (next_frame->pc))
-    /* Don't unwind past main(), always unwind the sentinel frame.  */
-    return 0;
+  /* If we're inside the entry file, it isn't valid.  */
+  /* NOTE: drow/2002-12-25: should there be a way to disable this
+     check?  It assumes a single small entry file, and the way some
+     debug readers (e.g.  dbxread) figure out which object is the
+     entry file is somewhat hokey.  */
+  /* NOTE: cagney/2003-01-10: If there is a way of disabling this test
+     then it should probably be moved to before the ->prev_p test,
+     above.  */
+  if (inside_entry_file (get_frame_pc (next_frame)))
+      return NULL;
+
+  if ((DEPRECATED_INIT_FRAME_PC_P ()
+       || DEPRECATED_INIT_FRAME_PC_FIRST_P ())
+      && next_frame->level >= 0)
+    /* Don't try to unwind the sentinal frame using the old code.  */
+    return legacy_get_prev_frame (next_frame);
 
   /* Allocate the new frame but do not wire it in.  Some (bad) code in
      INIT_EXTRA_FRAME_INFO tries to look along frame->next to pull
Index: legacy-frame.c
===================================================================
RCS file: legacy-frame.c
diff -N legacy-frame.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ legacy-frame.c	10 Jan 2003 21:54:08 -0000
@@ -0,0 +1,301 @@
+/* Code dealing with legacy 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.  */
+
+
+#include "defs.h"
+#include "legacy-frame.h"
+#include "gdb_assert.h"
+#include "frame.h"
+#include "gdbcore.h"
+#include "regcache.h"
+#include "target.h"
+#include "dummy-frame.h"	/* For generic_find_dummy_frame.  */
+
+/* Legacy frame.  This saves the processor state just prior to setting
+   up the inferior function call.  Older targets save the registers
+   on the target stack (but that really slows down function calls).  */
+
+struct frame_unwind_cache
+{
+  void *regs[1];
+};
+
+/* Given a legacy-frame, return the register register saved in the
+   simplistic ``saved_regs'' cache.  If the value isn't here AND a
+   value is needed, try the next inner most frame.  */
+
+void
+legacy_frame_register_unwind (struct frame_info *frame,
+			     struct frame_unwind_cache **cache,
+			     int regnum, int *optimizedp,
+			     enum lval_type *lvalp, CORE_ADDR *addrp,
+			     int *realnump, void *bufferp)
+{
+  /* There is always a frame at this point.  And THIS is the frame
+     we're interested in.  */
+  gdb_assert (frame != NULL);
+
+  /* If we're using generic dummy frames, we'd better not be in a call
+     dummy.  (generic_call_dummy_register_unwind ought to have been called
+     instead.)  */
+  gdb_assert (!(DEPRECATED_USE_GENERIC_DUMMY_FRAMES
+		&& (get_frame_type (frame) == DUMMY_FRAME)));
+
+  /* Load the saved_regs register cache.  */
+  if (get_frame_saved_regs (frame) == NULL)
+    FRAME_INIT_SAVED_REGS (frame);
+
+  if (get_frame_saved_regs (frame) != NULL
+      && get_frame_saved_regs (frame)[regnum] != 0)
+    {
+      if (regnum == SP_REGNUM)
+	{
+	  /* SP register treated specially.  */
+	  *optimizedp = 0;
+	  *lvalp = not_lval;
+	  *addrp = 0;
+	  *realnump = -1;
+	  if (bufferp != NULL)
+	    store_address (bufferp, REGISTER_RAW_SIZE (regnum),
+			   get_frame_saved_regs (frame)[regnum]);
+	}
+      else
+	{
+	  /* Any other register is saved in memory, fetch it but cache
+             a local copy of its value.  */
+	  *optimizedp = 0;
+	  *lvalp = lval_memory;
+	  *addrp = get_frame_saved_regs (frame)[regnum];
+	  *realnump = -1;
+	  if (bufferp != NULL)
+	    {
+#if 1
+	      /* Save each register value, as it is read in, in a
+                 frame based cache.  */
+	      if ((*cache) == NULL)
+		{
+		  int sizeof_cache = ((NUM_REGS + NUM_PSEUDO_REGS)
+				      * sizeof (void *));
+		  (*cache) = frame_obstack_zalloc (sizeof_cache);
+		}
+	      if ((*cache)->regs[regnum] == NULL)
+		{
+		  (*cache)->regs[regnum]
+		    = frame_obstack_zalloc (REGISTER_RAW_SIZE (regnum));
+		  read_memory (get_frame_saved_regs (frame)[regnum],
+			       (*cache)->regs[regnum],
+			       REGISTER_RAW_SIZE (regnum));
+		}
+	      memcpy (bufferp, (*cache)->regs[regnum],
+		      REGISTER_RAW_SIZE (regnum));
+#else
+	      /* Read the value in from memory.  */
+	      read_memory (get_frame_saved_regs (frame)[regnum], bufferp,
+			   REGISTER_RAW_SIZE (regnum));
+#endif
+	    }
+	}
+      return;
+    }
+
+  /* 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 = REGISTER_BYTE (regnum);
+      *realnump = regnum;
+    }
+  else
+    {
+      frame_register (frame, regnum, optimizedp, lvalp, addrp,
+		      realnump, bufferp);
+    }
+}
+
+CORE_ADDR
+legacy_frame_pc_unwind (struct frame_info *frame,
+			struct frame_unwind_cache **cache)
+{
+  return FRAME_SAVED_PC (frame);
+}
+
+void
+legacy_frame_id_unwind (struct frame_info *frame,
+			struct frame_unwind_cache **cache,
+			struct frame_id *id)
+{
+  int fromleaf;
+
+  if (get_next_frame (frame) == NULL)
+    /* 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
+       should simply be removed.  */
+    fromleaf = FRAMELESS_FUNCTION_INVOCATION (frame);
+  else
+    fromleaf = 0;
+
+  if (fromleaf)
+    /* A frameless inner-most frame.  The `FP' (which isn't an
+       architecture frame-pointer register!) of the caller is the same
+       as the callee.  */
+    /* FIXME: 2002-11-09: There isn't any reason to special case this
+       edge condition.  Instead the per-architecture code should hande
+       it locally.  */
+    id->base = get_frame_base (frame);
+  else
+    {
+      /* Two macros defined in tm.h specify the machine-dependent
+         actions to be performed here.
+
+         First, get the frame's chain-pointer.
+
+         If that is zero, the frame is the outermost frame or a leaf
+         called by the outermost frame.  This means that if start
+         calls main without a frame, we'll return 0 (which is fine
+         anyway).
+
+         Nope; there's a problem.  This also returns when the current
+         routine is a leaf of main.  This is unacceptable.  We move
+         this to after the ffi test; I'd rather have backtraces from
+         start go curfluy than have an abort called from main not show
+         main.  */
+      id->base = FRAME_CHAIN (frame);
+
+      if (!frame_chain_valid (id->base, frame))
+	{
+	  *id = null_frame_id;
+	  return;
+	}
+    }
+  if (id->base == 0)
+    {
+      *id = null_frame_id;
+      return;
+    }
+
+  /* FIXME: cagney/2002-06-08: This should probably return the frame's
+     function and not the PC (a.k.a. resume address).  */
+  id->pc = frame_pc_unwind (frame);
+  return;
+}
+
+/* Function: deprecated_generic_get_saved_register.
+
+   Find register number REGNUM relative to FRAME and put its (raw,
+   target format) contents in *RAW_BUFFER.
+
+   Set *OPTIMIZED if the variable was optimized out (and thus can't be
+   fetched).  Note that this is never set to anything other than zero
+   in this implementation.
+
+   Set *LVAL to lval_memory, lval_register, or not_lval, depending on
+   whether the value was fetched from memory, from a register, or in a
+   strange and non-modifiable way (e.g. a frame pointer which was
+   calculated rather than fetched).  We will use not_lval for values
+   fetched from generic dummy frames.
+
+   Set *ADDRP to the address, either in memory or as a REGISTER_BYTE
+   offset into the registers array.  If the value is stored in a dummy
+   frame, set *ADDRP to zero.
+
+   To use this implementation, define a function called
+   "get_saved_register" in your target code, which simply passes all
+   of its arguments to this function.
+
+   The argument RAW_BUFFER must point to aligned memory.  */
+
+void
+deprecated_generic_get_saved_register (char *raw_buffer, int *optimized,
+				       CORE_ADDR *addrp,
+				       struct frame_info *frame, int regnum,
+				       enum lval_type *lval)
+{
+  if (!target_has_registers)
+    error ("No registers.");
+
+  /* Normal systems don't optimize out things with register numbers.  */
+  if (optimized != NULL)
+    *optimized = 0;
+
+  if (addrp)			/* default assumption: not found in memory */
+    *addrp = 0;
+
+  /* Note: since the current frame's registers could only have been
+     saved by frames INTERIOR TO the current frame, we skip examining
+     the current frame itself: otherwise, we would be getting the
+     previous frame's registers which were saved by the current frame.  */
+
+  while (frame && ((frame = get_next_frame (frame)) != NULL))
+    {
+      if (get_frame_type (frame) == DUMMY_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 (get_frame_pc (frame),
+							 get_frame_base (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 (raw_buffer)	/* SP register treated specially */
+		store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
+			       frame->saved_regs[regnum]);
+	    }
+	  else
+	    {
+	      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));
+	    }
+	  return;
+	}
+    }
+
+  /* If we get thru the loop to this point, it means the register was
+     not saved in any frame.  Return the actual live-register value.  */
+
+  if (lval)			/* found it in a live register */
+    *lval = lval_register;
+  if (addrp)
+    *addrp = REGISTER_BYTE (regnum);
+  if (raw_buffer)
+    deprecated_read_register_gen (regnum, raw_buffer);
+}
Index: legacy-frame.h
===================================================================
RCS file: legacy-frame.h
diff -N legacy-frame.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ legacy-frame.h	10 Jan 2003 21:54:08 -0000
@@ -0,0 +1,61 @@
+/* Code dealing with legacy 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 (LEGACY_FRAME_H)
+#define LEGACY_FRAME_H 1
+
+struct frame_info;
+struct regcache;
+struct frame_id;
+struct frame_unwind_cache;
+
+/* LEGACY FRAMES
+  
+   The original extra frame info implementation of the`struct
+   frame_info' object.  These frames always initialize the entire
+   frame object using extra frame info.  */
+
+/* Assuming that FRAME is a legacy, return a register value for the
+   previous frame.  */
+
+extern void legacy_frame_register_unwind (struct frame_info *frame,
+					  struct frame_unwind_cache **unwind_cache,
+					  int regnum,
+					  int *optimized,
+					  enum lval_type *lvalp,
+					  CORE_ADDR *addrp,
+					  int *realnump,
+					  void *valuep);
+
+/* Assuming that FRAME is a legacy, return the resume address for the
+   previous frame.  */
+
+extern CORE_ADDR legacy_frame_pc_unwind (struct frame_info *frame,
+					 struct frame_unwind_cache **unwind_cache);
+
+/* Assuming that FRAME is a legacy, return the ID of the calling frame
+   (the frame that the legacy has the saved state of).  */
+
+extern void legacy_frame_id_unwind (struct frame_info *frame,
+				    struct frame_unwind_cache **unwind_cache,
+				    struct frame_id *id);
+
+#endif

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