2002-11-08 Andrew Cagney <ac131313@redhat.com>
[deliverable/binutils-gdb.git] / gdb / blockframe.c
index 2b789e6dbb1ad70e6ca05e5f397299eaf28043ad..c34d3e06a0e260dd242d9aa988b4c4a2c34bdfe4 100644 (file)
 #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 @@ pc_in_call_dummy_at_entry_point (CORE_ADDR pc, CORE_ADDR sp,
 }
 
 
-/*
- * 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 */
@@ -1373,63 +1128,6 @@ generic_func_frame_chain_valid (CORE_ADDR fp, struct frame_info *fi)
            && !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.
    If the value isn't here AND a value is needed, try the next inner
    most frame.  */
This page took 0.026949 seconds and 4 git commands to generate.