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] Create dummy-frame.h


(I gave in),

See
http://sources.redhat.com/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=744
and
http://sources.redhat.com/ml/gdb/2002-09/msg00462.html

The attached patch moves all (well most) the dummy frame code out of blockframe.c / frame.h and into its own file dummy-frame.[hc]. The Makefile.in is then updated.

The patch is very strictly mechanical. It only does a cut/paste of the dummy-frame code (adding two extern declarations to dummy-frame.h for just the functions that need it).

I carefully carefully avoided trying to make any not-so-mechanical changes, such as:

- rename any functions to a more logical dummy_frame_XXXX()
- change any interfaces
- move any of the declarations in frame.h
- move deprecated_generic_get_saved_register()

committed,

enjoy, Andrew
2002-11-08  Andrew Cagney  <ac131313@redhat.com>

	* blockframe.c: Include "dummy-frame.h".
	(struct dummy_frame, dummy_frame_stack)
	(generic_find_dummy_frame, deprecated_generic_find_dummy_frame)
	(generic_pc_in_call_dummy, deprecated_read_register_dummy)
	(generic_push_dummy_frame, generic_save_dummy_frame_tos)
	(generic_save_call_dummy_addr, generic_pop_current_frame)
	(generic_pop_dummy_frame, generic_fix_call_dummy)
	(generic_fix_call_dummy, generic_call_dummy_register_unwind): Move
	dummy frame code from here...
	* dummy-frame.c: ...to here.  New file.
	* dummy-frame.h: New file.
	(generic_call_dummy_register_unwind): Declare.
	(generic_find_dummy_frame): Declare.
	* Makefile.in (SFILES): Add dummy-frame.c.
	(dummy-frame.o): Specify dependencies.
	(dummy_frame_h): Define.
	(COMMON_OBS): Add dummy-frame.o.
	(blockframe.o): Update dependencies.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.276
diff -u -r1.276 Makefile.in
--- Makefile.in	8 Nov 2002 03:35:13 -0000	1.276
+++ Makefile.in	8 Nov 2002 19:38:39 -0000
@@ -535,7 +535,8 @@
 	c-exp.y c-lang.c c-typeprint.c c-valprint.c \
 	charset.c cli-out.c coffread.c complaints.c completer.c corefile.c \
 	cp-abi.c cp-support.c cp-valprint.c \
-	dbxread.c demangle.c disasm.c doublest.c dwarfread.c dwarf2read.c \
+	dbxread.c demangle.c disasm.c doublest.c \
+	dummy-frame.c dwarfread.c dwarf2read.c \
 	elfread.c environ.c eval.c event-loop.c event-top.c expprint.c \
 	f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c frame.c \
 	gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
@@ -640,6 +641,7 @@
 disasm_h = disasm.h
 doublest_h = doublest.h $(floatformat_h)
 dst_h = dst.h
+dummy_frame_h = dummy-frame.h
 dwarf2cfi_h = dwarf2cfi.h
 environ_h = environ.h
 event_loop_h = event-loop.h
@@ -829,7 +831,7 @@
 TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR)
 
 COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
-	charset.o disasm.o \
+	charset.o disasm.o dummy-frame.o \
 	source.o values.o eval.o valops.o valarith.o valprint.o printcmd.o \
 	symtab.o symfile.o symmisc.o linespec.o infcmd.o infrun.o \
 	expprint.o environ.o stack.o thread.o \
@@ -1532,7 +1534,8 @@
 bcache.o: bcache.c $(defs_h) $(gdb_obstack_h) $(bcache_h) $(gdb_string_h)
 blockframe.o: blockframe.c $(defs_h) $(symtab_h) $(bfd_h) $(symfile_h) \
 	$(objfiles_h) $(frame_h) $(gdbcore_h) $(value_h) $(target_h) \
-	$(inferior_h) $(annotate_h) $(regcache_h) $(gdb_assert_h)
+	$(inferior_h) $(annotate_h) $(regcache_h) $(gdb_assert_h) \
+	$(dummy_frame_h)
 breakpoint.o: breakpoint.c $(defs_h) $(symtab_h) $(frame_h) $(breakpoint_h) \
 	$(gdbtypes_h) $(expression_h) $(gdbcore_h) $(gdbcmd_h) $(value_h) \
 	$(command_h) $(inferior_h) $(gdbthread_h) $(target_h) $(language_h) \
@@ -1627,6 +1630,8 @@
 dpx2-nat.o: dpx2-nat.c $(defs_h) $(gdbcore_h) $(gdb_string_h)
 dsrec.o: dsrec.c $(defs_h) $(serial_h) $(srec_h)
 # OBSOLETE dstread.o: dstread.c
+dummy-frame.o: dummy-frame.c $(defs_h) $(dummy_frame_h) $(regcache_h) \
+	$(frame_h) $(inferior_h) $(gdb_assert_h)
 dve3900-rom.o: dve3900-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
 	$(serial_h) $(inferior_h) $(command_h) $(gdb_string_h) $(regcache_h)
 dwarf2cfi.o: dwarf2cfi.c $(defs_h) $(gdbcore_h) $(symtab_h) $(symfile_h) \
Index: blockframe.c
===================================================================
RCS file: /cvs/src/src/gdb/blockframe.c,v
retrieving revision 1.44
diff -u -r1.44 blockframe.c
--- blockframe.c	2 Nov 2002 14:59:10 -0000	1.44
+++ blockframe.c	8 Nov 2002 19:38:40 -0000
@@ -35,17 +35,10 @@
 #include "annotate.h"
 #include "regcache.h"
 #include "gdb_assert.h"
+#include "dummy-frame.h"
 
 /* Prototypes for exported functions. */
 
-static void generic_call_dummy_register_unwind (struct frame_info *frame,
-						void **cache,
-						int regnum,
-						int *optimized,
-						enum lval_type *lval,
-						CORE_ADDR *addrp,
-						int *realnum,
-						void *raw_buffer);
 static void frame_saved_regs_register_unwind (struct frame_info *frame,
 					      void **cache,
 					      int regnum,
@@ -1107,244 +1100,6 @@
 }
 
 
-/*
- * GENERIC DUMMY FRAMES
- * 
- * The following code serves to maintain the dummy stack frames for
- * inferior function calls (ie. when gdb calls into the inferior via
- * call_function_by_hand).  This code saves the machine state before 
- * the call in host memory, so we must maintain an independent stack 
- * and keep it consistant etc.  I am attempting to make this code 
- * generic enough to be used by many targets.
- *
- * The cheapest and most generic way to do CALL_DUMMY on a new target
- * is probably to define CALL_DUMMY to be empty, CALL_DUMMY_LENGTH to
- * zero, and CALL_DUMMY_LOCATION to AT_ENTRY.  Then you must remember
- * to define PUSH_RETURN_ADDRESS, because no call instruction will be
- * being executed by the target.  Also FRAME_CHAIN_VALID as
- * generic_{file,func}_frame_chain_valid and FIX_CALL_DUMMY as
- * generic_fix_call_dummy.  */
-
-/* Dummy 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 dummy_frame
-{
-  struct dummy_frame *next;
-
-  CORE_ADDR pc;
-  CORE_ADDR fp;
-  CORE_ADDR sp;
-  CORE_ADDR top;
-  struct regcache *regcache;
-
-  /* Address range of the call dummy code.  Look for PC in the range
-     [LO..HI) (after allowing for DECR_PC_AFTER_BREAK).  */
-  CORE_ADDR call_lo;
-  CORE_ADDR call_hi;
-};
-
-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_CALL_DUMMY, 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 regcache *
-generic_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?  */
-      if (dummyframe->top != 0)
-	{
-	  /* If the target architecture explicitly saved the
-	     top-of-stack before the inferior function call, assume
-	     that that same architecture will always pass in an FP
-	     (frame base) value that eactly matches that saved TOS.
-	     Don't check the saved SP and SP as they can lead to false
-	     hits.  */
-	  if (fp != dummyframe->top)
-	    continue;
-	}
-      else
-	{
-	  /* An older target that hasn't explicitly or implicitly
-             saved the dummy frame's top-of-stack.  Try matching the
-             FP against the saved SP and FP.  NOTE: If you're trying
-             to fix a problem with GDB not correctly finding a dummy
-             frame, check the comments that go with FRAME_ALIGN() and
-             SAVE_DUMMY_FRAME_TOS().  */
-	  if (fp != dummyframe->fp && fp != dummyframe->sp)
-	    continue;
-	}
-      /* The FP matches this dummy frame.  */
-      return dummyframe->regcache;
-    }
-
-  return 0;
-}
-
-char *
-deprecated_generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
-{
-  struct regcache *regcache = generic_find_dummy_frame (pc, fp);
-  if (regcache == NULL)
-    return NULL;
-  return deprecated_grub_regcache_for_registers (regcache);
-}
-
-/* Function: pc_in_call_dummy (pc, sp, fp)
-
-   Return true if the PC falls in a dummy frame created by gdb for an
-   inferior call.  The code below which allows DECR_PC_AFTER_BREAK is
-   for infrun.c, which may give the function a PC without that
-   subtracted out.  */
-
-int
-generic_pc_in_call_dummy (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR fp)
-{
-  struct dummy_frame *dummyframe;
-  for (dummyframe = dummy_frame_stack;
-       dummyframe != NULL;
-       dummyframe = dummyframe->next)
-    {
-      if ((pc >= dummyframe->call_lo)
-	  && (pc < dummyframe->call_hi + DECR_PC_AFTER_BREAK))
-	return 1;
-    }
-  return 0;
-}
-
-/* Function: read_register_dummy 
-   Find a saved register from before GDB calls a function in the inferior */
-
-CORE_ADDR
-deprecated_read_register_dummy (CORE_ADDR pc, CORE_ADDR fp, int regno)
-{
-  struct regcache *dummy_regs = generic_find_dummy_frame (pc, fp);
-
-  if (dummy_regs)
-    {
-      /* NOTE: cagney/2002-08-12: Replaced a call to
-	 regcache_raw_read_as_address() with a call to
-	 regcache_cooked_read_unsigned().  The old, ...as_address
-	 function was eventually calling extract_unsigned_integer (via
-	 extract_address) to unpack the registers value.  The below is
-	 doing an unsigned extract so that it is functionally
-	 equivalent.  The read needs to be cooked as, otherwise, it
-	 will never correctly return the value of a register in the
-	 [NUM_REGS .. NUM_REGS+NUM_PSEUDO_REGS) range.  */
-      ULONGEST val;
-      regcache_cooked_read_unsigned (dummy_regs, regno, &val);
-      return val;
-    }
-  else
-    return 0;
-}
-
-/* Save all the registers on the dummy frame stack.  Most ports save the
-   registers on the target stack.  This results in lots of unnecessary memory
-   references, which are slow when debugging via a serial line.  Instead, we
-   save all the registers internally, and never write them to the stack.  The
-   registers get restored when the called function returns to the entry point,
-   where a breakpoint is laying in wait.  */
-
-void
-generic_push_dummy_frame (void)
-{
-  struct dummy_frame *dummy_frame;
-  CORE_ADDR fp = (get_current_frame ())->frame;
-
-  /* check to see if there are stale dummy frames, 
-     perhaps left over from when a longjump took us out of a 
-     function that was called by the debugger */
-
-  dummy_frame = dummy_frame_stack;
-  while (dummy_frame)
-    if (INNER_THAN (dummy_frame->fp, fp))	/* stale -- destroy! */
-      {
-	dummy_frame_stack = dummy_frame->next;
-	regcache_xfree (dummy_frame->regcache);
-	xfree (dummy_frame);
-	dummy_frame = dummy_frame_stack;
-      }
-    else
-      dummy_frame = dummy_frame->next;
-
-  dummy_frame = xmalloc (sizeof (struct dummy_frame));
-  dummy_frame->regcache = regcache_xmalloc (current_gdbarch);
-
-  dummy_frame->pc = read_pc ();
-  dummy_frame->sp = read_sp ();
-  dummy_frame->top = 0;
-  dummy_frame->fp = fp;
-  regcache_cpy (dummy_frame->regcache, current_regcache);
-  dummy_frame->next = dummy_frame_stack;
-  dummy_frame_stack = dummy_frame;
-}
-
-void
-generic_save_dummy_frame_tos (CORE_ADDR sp)
-{
-  dummy_frame_stack->top = sp;
-}
-
-/* Record the upper/lower bounds on the address of the call dummy.  */
-
-void
-generic_save_call_dummy_addr (CORE_ADDR lo, CORE_ADDR hi)
-{
-  dummy_frame_stack->call_lo = lo;
-  dummy_frame_stack->call_hi = hi;
-}
-
-/* Restore the machine state from either the saved dummy stack or a
-   real stack frame. */
-
-void
-generic_pop_current_frame (void (*popper) (struct frame_info * frame))
-{
-  struct frame_info *frame = get_current_frame ();
-
-  if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
-    generic_pop_dummy_frame ();
-  else
-    (*popper) (frame);
-}
-
-/* Function: pop_dummy_frame
-   Restore the machine state from a saved dummy stack frame. */
-
-void
-generic_pop_dummy_frame (void)
-{
-  struct dummy_frame *dummy_frame = dummy_frame_stack;
-
-  /* FIXME: what if the first frame isn't the right one, eg..
-     because one call-by-hand function has done a longjmp into another one? */
-
-  if (!dummy_frame)
-    error ("Can't pop dummy frame!");
-  dummy_frame_stack = dummy_frame->next;
-  regcache_cpy (current_regcache, dummy_frame->regcache);
-  flush_cached_frames ();
-
-  regcache_xfree (dummy_frame->regcache);
-  xfree (dummy_frame);
-}
-
 /* Function: frame_chain_valid 
    Returns true for a user frame or a call_function_by_hand dummy frame,
    and false for the CRT0 start-up frame.  Purpose is to terminate backtrace */
@@ -1371,63 +1126,6 @@
 	    && (INNER_THAN (fi->frame, fp) || fi->frame == fp)
 	    && !inside_main_func ((fi)->pc)
 	    && !inside_entry_func ((fi)->pc));
-}
-
-/* Function: fix_call_dummy
-   Stub function.  Generic dummy frames typically do not need to fix
-   the frame being created */
-
-void
-generic_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
-			struct value **args, struct type *type, int gcc_p)
-{
-  return;
-}
-
-/* Given a call-dummy dummy-frame, return the registers.  Here the
-   register value is taken from the local copy of the register buffer.  */
-
-static void
-generic_call_dummy_register_unwind (struct frame_info *frame, void **cache,
-				    int regnum, int *optimized,
-				    enum lval_type *lvalp, CORE_ADDR *addrp,
-				    int *realnum, void *bufferp)
-{
-  gdb_assert (frame != NULL);
-  gdb_assert (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame));
-
-  /* Describe the register's location.  Generic dummy frames always
-     have the register value in an ``expression''.  */
-  *optimized = 0;
-  *lvalp = not_lval;
-  *addrp = 0;
-  *realnum = -1;
-
-  /* If needed, find and return the value of the register.  */
-  if (bufferp != NULL)
-    {
-      struct regcache *registers;
-#if 1
-      /* Get the address of the register buffer that contains all the
-	 saved registers for this dummy frame.  Cache that address.  */
-      registers = (*cache);
-      if (registers == NULL)
-	{
-	  registers = generic_find_dummy_frame (frame->pc, frame->frame);
-	  (*cache) = registers;
-	}
-#else
-      /* Get the address of the register buffer that contains the
-         saved registers and then extract the value from that.  */
-      registers = generic_find_dummy_frame (frame->pc, frame->frame);
-#endif
-      gdb_assert (registers != 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 (registers, regnum, bufferp);
-    }
 }
 
 /* Return the register saved in the simplistic ``saved_regs'' cache.
Index: dummy-frame.c
===================================================================
RCS file: dummy-frame.c
diff -N dummy-frame.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dummy-frame.c	8 Nov 2002 19:38:40 -0000
@@ -0,0 +1,308 @@
+/* Code dealing with dummy 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 "dummy-frame.h"
+#include "regcache.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdb_assert.h"
+
+/* Dummy 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 dummy_frame
+{
+  struct dummy_frame *next;
+
+  CORE_ADDR pc;
+  CORE_ADDR fp;
+  CORE_ADDR sp;
+  CORE_ADDR top;
+  struct regcache *regcache;
+
+  /* Address range of the call dummy code.  Look for PC in the range
+     [LO..HI) (after allowing for DECR_PC_AFTER_BREAK).  */
+  CORE_ADDR call_lo;
+  CORE_ADDR call_hi;
+};
+
+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_CALL_DUMMY, 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.  */
+
+struct regcache *
+generic_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?  */
+      if (dummyframe->top != 0)
+	{
+	  /* If the target architecture explicitly saved the
+	     top-of-stack before the inferior function call, assume
+	     that that same architecture will always pass in an FP
+	     (frame base) value that eactly matches that saved TOS.
+	     Don't check the saved SP and SP as they can lead to false
+	     hits.  */
+	  if (fp != dummyframe->top)
+	    continue;
+	}
+      else
+	{
+	  /* An older target that hasn't explicitly or implicitly
+             saved the dummy frame's top-of-stack.  Try matching the
+             FP against the saved SP and FP.  NOTE: If you're trying
+             to fix a problem with GDB not correctly finding a dummy
+             frame, check the comments that go with FRAME_ALIGN() and
+             SAVE_DUMMY_FRAME_TOS().  */
+	  if (fp != dummyframe->fp && fp != dummyframe->sp)
+	    continue;
+	}
+      /* The FP matches this dummy frame.  */
+      return dummyframe->regcache;
+    }
+
+  return 0;
+}
+
+char *
+deprecated_generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
+{
+  struct regcache *regcache = generic_find_dummy_frame (pc, fp);
+  if (regcache == NULL)
+    return NULL;
+  return deprecated_grub_regcache_for_registers (regcache);
+}
+
+/* Function: pc_in_call_dummy (pc, sp, fp)
+
+   Return true if the PC falls in a dummy frame created by gdb for an
+   inferior call.  The code below which allows DECR_PC_AFTER_BREAK is
+   for infrun.c, which may give the function a PC without that
+   subtracted out.  */
+
+int
+generic_pc_in_call_dummy (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR fp)
+{
+  struct dummy_frame *dummyframe;
+  for (dummyframe = dummy_frame_stack;
+       dummyframe != NULL;
+       dummyframe = dummyframe->next)
+    {
+      if ((pc >= dummyframe->call_lo)
+	  && (pc < dummyframe->call_hi + DECR_PC_AFTER_BREAK))
+	return 1;
+    }
+  return 0;
+}
+
+/* Function: read_register_dummy 
+   Find a saved register from before GDB calls a function in the inferior */
+
+CORE_ADDR
+deprecated_read_register_dummy (CORE_ADDR pc, CORE_ADDR fp, int regno)
+{
+  struct regcache *dummy_regs = generic_find_dummy_frame (pc, fp);
+
+  if (dummy_regs)
+    {
+      /* NOTE: cagney/2002-08-12: Replaced a call to
+	 regcache_raw_read_as_address() with a call to
+	 regcache_cooked_read_unsigned().  The old, ...as_address
+	 function was eventually calling extract_unsigned_integer (via
+	 extract_address) to unpack the registers value.  The below is
+	 doing an unsigned extract so that it is functionally
+	 equivalent.  The read needs to be cooked as, otherwise, it
+	 will never correctly return the value of a register in the
+	 [NUM_REGS .. NUM_REGS+NUM_PSEUDO_REGS) range.  */
+      ULONGEST val;
+      regcache_cooked_read_unsigned (dummy_regs, regno, &val);
+      return val;
+    }
+  else
+    return 0;
+}
+
+/* Save all the registers on the dummy frame stack.  Most ports save the
+   registers on the target stack.  This results in lots of unnecessary memory
+   references, which are slow when debugging via a serial line.  Instead, we
+   save all the registers internally, and never write them to the stack.  The
+   registers get restored when the called function returns to the entry point,
+   where a breakpoint is laying in wait.  */
+
+void
+generic_push_dummy_frame (void)
+{
+  struct dummy_frame *dummy_frame;
+  CORE_ADDR fp = (get_current_frame ())->frame;
+
+  /* check to see if there are stale dummy frames, 
+     perhaps left over from when a longjump took us out of a 
+     function that was called by the debugger */
+
+  dummy_frame = dummy_frame_stack;
+  while (dummy_frame)
+    if (INNER_THAN (dummy_frame->fp, fp))	/* stale -- destroy! */
+      {
+	dummy_frame_stack = dummy_frame->next;
+	regcache_xfree (dummy_frame->regcache);
+	xfree (dummy_frame);
+	dummy_frame = dummy_frame_stack;
+      }
+    else
+      dummy_frame = dummy_frame->next;
+
+  dummy_frame = xmalloc (sizeof (struct dummy_frame));
+  dummy_frame->regcache = regcache_xmalloc (current_gdbarch);
+
+  dummy_frame->pc = read_pc ();
+  dummy_frame->sp = read_sp ();
+  dummy_frame->top = 0;
+  dummy_frame->fp = fp;
+  regcache_cpy (dummy_frame->regcache, current_regcache);
+  dummy_frame->next = dummy_frame_stack;
+  dummy_frame_stack = dummy_frame;
+}
+
+void
+generic_save_dummy_frame_tos (CORE_ADDR sp)
+{
+  dummy_frame_stack->top = sp;
+}
+
+/* Record the upper/lower bounds on the address of the call dummy.  */
+
+void
+generic_save_call_dummy_addr (CORE_ADDR lo, CORE_ADDR hi)
+{
+  dummy_frame_stack->call_lo = lo;
+  dummy_frame_stack->call_hi = hi;
+}
+
+/* Restore the machine state from either the saved dummy stack or a
+   real stack frame. */
+
+void
+generic_pop_current_frame (void (*popper) (struct frame_info * frame))
+{
+  struct frame_info *frame = get_current_frame ();
+
+  if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
+    generic_pop_dummy_frame ();
+  else
+    (*popper) (frame);
+}
+
+/* Function: pop_dummy_frame
+   Restore the machine state from a saved dummy stack frame. */
+
+void
+generic_pop_dummy_frame (void)
+{
+  struct dummy_frame *dummy_frame = dummy_frame_stack;
+
+  /* FIXME: what if the first frame isn't the right one, eg..
+     because one call-by-hand function has done a longjmp into another one? */
+
+  if (!dummy_frame)
+    error ("Can't pop dummy frame!");
+  dummy_frame_stack = dummy_frame->next;
+  regcache_cpy (current_regcache, dummy_frame->regcache);
+  flush_cached_frames ();
+
+  regcache_xfree (dummy_frame->regcache);
+  xfree (dummy_frame);
+}
+
+/* Function: fix_call_dummy
+   Stub function.  Generic dummy frames typically do not need to fix
+   the frame being created */
+
+void
+generic_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+			struct value **args, struct type *type, int gcc_p)
+{
+  return;
+}
+
+/* Given a call-dummy dummy-frame, return the registers.  Here the
+   register value is taken from the local copy of the register buffer.  */
+
+void
+generic_call_dummy_register_unwind (struct frame_info *frame, void **cache,
+				    int regnum, int *optimized,
+				    enum lval_type *lvalp, CORE_ADDR *addrp,
+				    int *realnum, void *bufferp)
+{
+  gdb_assert (frame != NULL);
+  gdb_assert (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame));
+
+  /* Describe the register's location.  Generic dummy frames always
+     have the register value in an ``expression''.  */
+  *optimized = 0;
+  *lvalp = not_lval;
+  *addrp = 0;
+  *realnum = -1;
+
+  /* If needed, find and return the value of the register.  */
+  if (bufferp != NULL)
+    {
+      struct regcache *registers;
+#if 1
+      /* Get the address of the register buffer that contains all the
+	 saved registers for this dummy frame.  Cache that address.  */
+      registers = (*cache);
+      if (registers == NULL)
+	{
+	  registers = generic_find_dummy_frame (frame->pc, frame->frame);
+	  (*cache) = registers;
+	}
+#else
+      /* Get the address of the register buffer that contains the
+         saved registers and then extract the value from that.  */
+      registers = generic_find_dummy_frame (frame->pc, frame->frame);
+#endif
+      gdb_assert (registers != 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 (registers, regnum, bufferp);
+    }
+}
+
Index: dummy-frame.h
===================================================================
RCS file: dummy-frame.h
diff -N dummy-frame.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ dummy-frame.h	8 Nov 2002 19:38:40 -0000
@@ -0,0 +1,66 @@
+/* Code dealing with dummy stack frames, for GDB, the GNU debugger.
+
+   Copyright 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.  */
+
+#if !defined (DUMMY_FRAME_H)
+#define DUMMY_FRAME_H 1
+
+struct frame_info;
+struct regcache;
+
+/* GENERIC DUMMY FRAMES
+  
+   The following code serves to maintain the dummy stack frames for
+   inferior function calls (ie. when gdb calls into the inferior via
+   call_function_by_hand).  This code saves the machine state before
+   the call in host memory, so we must maintain an independent stack
+   and keep it consistant etc.  I am attempting to make this code
+   generic enough to be used by many targets.
+ 
+   The cheapest and most generic way to do CALL_DUMMY on a new target
+   is probably to define CALL_DUMMY to be empty, CALL_DUMMY_LENGTH to
+   zero, and CALL_DUMMY_LOCATION to AT_ENTRY.  Then you must remember
+   to define PUSH_RETURN_ADDRESS, because no call instruction will be
+   being executed by the target.  Also FRAME_CHAIN_VALID as
+   generic_{file,func}_frame_chain_valid and FIX_CALL_DUMMY as
+   generic_fix_call_dummy.  */
+
+/* Assuming that FRAME is a dummy, return a register value for the
+   previous frame.  */
+
+extern void generic_call_dummy_register_unwind (struct frame_info *frame,
+						void **unwind_cache,
+						int regnum,
+						int *optimized,
+						enum lval_type *lvalp,
+						CORE_ADDR *addrp,
+						int *realnump,
+						void *valuep);
+
+/* Return the regcache that belongs to the dummy-frame identifed by PC
+   and FP, or NULL if no such frame exists.  */
+/* FIXME: cagney/2002-11-08: The function only exists because of
+   deprecated_generic_get_saved_register.  Eliminate that function and
+   this, to, can go.  */
+
+extern struct regcache *generic_find_dummy_frame (CORE_ADDR pc,
+						  CORE_ADDR fp);
+
+#endif /* !defined (DUMMY_FRAME_H)  */

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