2004-01-20 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / dummy-frame.c
index 5b638306fd3956ed7733e96f0308e92d7e3fecc8..3b10c51640b5f86ee0d73318c46f02904ee1987c 100644 (file)
 #include "inferior.h"
 #include "gdb_assert.h"
 #include "frame-unwind.h"
+#include "command.h"
+#include "gdbcmd.h"
+
+static void dummy_frame_this_id (struct frame_info *next_frame,
+                                void **this_prologue_cache,
+                                struct frame_id *this_id);
 
 /* Dummy frame.  This saves the processor state just prior to setting
    up the inferior function call.  Older targets save the registers
@@ -93,7 +99,7 @@ find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
              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().  */
+             UNWIND_DUMMY_ID().  */
          if (fp != dummyframe->fp && fp != dummyframe->sp)
            continue;
        }
@@ -104,16 +110,8 @@ find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
   return NULL;
 }
 
-struct dummy_frame *
-cached_find_dummy_frame (struct frame_info *frame, void **cache)
-{
-  if ((*cache) == NULL)
-    (*cache) = find_dummy_frame (get_frame_pc (frame), get_frame_base (frame));
-  return (*cache);
-}
-
 struct regcache *
-generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
+deprecated_find_dummy_frame_regcache (CORE_ADDR pc, CORE_ADDR fp)
 {
   struct dummy_frame *dummy = find_dummy_frame (pc, fp);
   if (dummy != NULL)
@@ -125,7 +123,7 @@ generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
 char *
 deprecated_generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
 {
-  struct regcache *regcache = generic_find_dummy_frame (pc, fp);
+  struct regcache *regcache = deprecated_find_dummy_frame_regcache (pc, fp);
   if (regcache == NULL)
     return NULL;
   return deprecated_grub_regcache_for_registers (regcache);
@@ -153,8 +151,9 @@ generic_pc_in_call_dummy (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR fp)
    figure out what the real PC (as in the resume address) is BEFORE
    calling this function (Oh, and I'm not even sure that this function
    is called with an decremented PC, the call to pc_in_call_dummy() in
-   that file is conditional on !CALL_DUMMY_BREAKPOINT_OFFSET_P yet
-   generic dummy targets set CALL_DUMMY_BREAKPOINT_OFFSET. True?).  */
+   that file is conditional on
+   !DEPRECATED_CALL_DUMMY_BREAKPOINT_OFFSET_P yet generic dummy
+   targets set DEPRECATED_CALL_DUMMY_BREAKPOINT_OFFSET. True?).  */
 
 int
 pc_in_dummy_frame (CORE_ADDR pc)
@@ -177,14 +176,14 @@ pc_in_dummy_frame (CORE_ADDR pc)
 CORE_ADDR
 deprecated_read_register_dummy (CORE_ADDR pc, CORE_ADDR fp, int regno)
 {
-  struct regcache *dummy_regs = generic_find_dummy_frame (pc, fp);
+  struct regcache *dummy_regs = deprecated_find_dummy_frame_regcache (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
+        function was eventually calling extract_unsigned_integer (nee
         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
@@ -282,37 +281,6 @@ discard_innermost_dummy (struct dummy_frame **stack)
   xfree (tbd);
 }
 
-/* Function: dummy_frame_pop.  Restore the machine state from a saved
-   dummy stack frame. */
-
-static void
-dummy_frame_pop (struct frame_info *fi, void **cache,
-                struct regcache *regcache)
-{
-  struct dummy_frame *dummy = cached_find_dummy_frame (fi, cache);
-
-  /* If it isn't, what are we even doing here?  */
-  gdb_assert (get_frame_type (fi) == DUMMY_FRAME);
-
-  if (dummy == NULL)
-    error ("Can't pop dummy frame!");
-
-  /* Discard all dummy frames up-to but not including this one.  */
-  while (dummy_frame_stack != dummy)
-    discard_innermost_dummy (&dummy_frame_stack);
-
-  /* Restore this one.  */
-  regcache_cpy (regcache, dummy->regcache);
-  flush_cached_frames ();
-
-  /* Now discard it.  */
-  discard_innermost_dummy (&dummy_frame_stack);
-
-  /* Note: target changed would be better.  Registers, memory and
-     frame are all invalid.  */
-  flush_cached_frames ();
-}
-
 void
 generic_pop_dummy_frame (void)
 {
@@ -329,27 +297,23 @@ generic_pop_dummy_frame (void)
   discard_innermost_dummy (&dummy_frame_stack);
 }
 
-/* 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
-dummy_frame_register_unwind (struct frame_info *frame, void **cache,
-                            int regnum, int *optimized,
-                            enum lval_type *lvalp, CORE_ADDR *addrp,
-                            int *realnum, void *bufferp)
+dummy_frame_prev_register (struct frame_info *next_frame,
+                          void **this_prologue_cache,
+                          int regnum, int *optimized,
+                          enum lval_type *lvalp, CORE_ADDR *addrp,
+                          int *realnum, void *bufferp)
 {
-  struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
+  struct dummy_frame *dummy;
+  struct frame_id id;
+
+  /* Call the ID method which, if at all possible, will set the
+     prologue cache.  */
+  dummy_frame_this_id (next_frame, this_prologue_cache, &id);
+  dummy = (*this_prologue_cache);
   gdb_assert (dummy != NULL);
 
   /* Describe the register's location.  Generic dummy frames always
@@ -370,52 +334,83 @@ dummy_frame_register_unwind (struct frame_info *frame, void **cache,
     }
 }
 
-/* Assuming that FRAME is a dummy, return the resume address for the
-   previous frame.  */
-
-static CORE_ADDR
-dummy_frame_pc_unwind (struct frame_info *frame,
-                      void **cache)
-{
-  struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
-  /* Oops!  In a dummy-frame but can't find the stack dummy.  Pretend
-     that the frame doesn't unwind.  Should this function instead
-     return a has-no-caller indication?  */
-  if (dummy == NULL)
-    return 0;
-  return dummy->pc;
-}
-
-
-/* Assuming that FRAME is a dummy, return the ID of the calling frame
-   (the frame that the dummy has the saved state of).  */
+/* Assuming that THIS frame is a dummy (remember, the NEXT and not
+   THIS frame is passed in), return the ID of THIS frame.  That ID is
+   determined by examining the NEXT frame's unwound registers using
+   the method unwind_dummy_id().  As a side effect, THIS dummy frame's
+   dummy cache is located and and saved in THIS_PROLOGUE_CACHE.  */
 
 static void
-dummy_frame_id_unwind (struct frame_info *frame,
-                      void **cache,
-                      struct frame_id *id)
+dummy_frame_this_id (struct frame_info *next_frame,
+                    void **this_prologue_cache,
+                    struct frame_id *this_id)
 {
-  struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
-  /* Oops!  In a dummy-frame but can't find the stack dummy.  Pretend
-     that the frame doesn't unwind.  Should this function instead
-     return a has-no-caller indication?  */
-  if (dummy == NULL)
-    (*id) = null_frame_id;
+  struct dummy_frame *dummy = (*this_prologue_cache);
+  if (dummy != NULL)
+    {
+      (*this_id) = dummy->id;
+      return;
+    }
+  /* When unwinding a normal frame, the stack structure is determined
+     by analyzing the frame's function's code (be it using brute force
+     prologue analysis, or the dwarf2 CFI).  In the case of a dummy
+     frame, that simply isn't possible.  The The PC is either the
+     program entry point, or some random address on the stack.  Trying
+     to use that PC to apply standard frame ID unwind techniques is
+     just asking for trouble.  */
+  if (gdbarch_unwind_dummy_id_p (current_gdbarch))
+    {
+      /* Use an architecture specific method to extract the prev's
+        dummy ID from the next frame.  Note that this method uses
+        frame_register_unwind to obtain the register values needed to
+        determine the dummy frame's ID.  */
+      (*this_id) = gdbarch_unwind_dummy_id (current_gdbarch, next_frame);
+    }
+  else if (frame_relative_level (next_frame) < 0)
+    {
+      /* We're unwinding a sentinel frame, the PC of which is pointing
+        at a stack dummy.  Fake up the dummy frame's ID using the
+        same sequence as is found a traditional unwinder.  Once all
+        architectures supply the unwind_dummy_id method, this code
+        can go away.  */
+      (*this_id) = frame_id_build (deprecated_read_fp (), read_pc ());
+    }
+  else if (legacy_frame_p (current_gdbarch)
+          && get_prev_frame (next_frame))
+    {
+      /* Things are looking seriously grim!  Assume that the legacy
+         get_prev_frame code has already created THIS frame and linked
+         it in to the frame chain (a pretty bold assumption), extract
+         the ID from THIS base / pc.  */
+      (*this_id) = frame_id_build (get_frame_base (get_prev_frame (next_frame)),
+                                  get_frame_pc (get_prev_frame (next_frame)));
+    }
   else
-    (*id) = dummy->id;
+    {
+      /* Ouch!  We're not trying to find the innermost frame's ID yet
+        we're trying to unwind to a dummy.  The architecture must
+        provide the unwind_dummy_id() method.  Abandon the unwind
+        process but only after first warning the user.  */
+      internal_warning (__FILE__, __LINE__,
+                       "Missing unwind_dummy_id architecture method");
+      (*this_id) = null_frame_id;
+      return;
+    }
+  (*this_prologue_cache) = find_dummy_frame ((*this_id).code_addr,
+                                            (*this_id).stack_addr);
 }
 
 static struct frame_unwind dummy_frame_unwind =
 {
-  dummy_frame_pop,
-  dummy_frame_pc_unwind,
-  dummy_frame_id_unwind,
-  dummy_frame_register_unwind
+  DUMMY_FRAME,
+  dummy_frame_this_id,
+  dummy_frame_prev_register
 };
 
 const struct frame_unwind *
-dummy_frame_p (CORE_ADDR pc)
+dummy_frame_sniffer (struct frame_info *next_frame)
 {
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
   if (DEPRECATED_PC_IN_CALL_DUMMY_P ()
       ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0)
       : pc_in_dummy_frame (pc))
@@ -423,3 +418,49 @@ dummy_frame_p (CORE_ADDR pc)
   else
     return NULL;
 }
+
+static void
+fprint_dummy_frames (struct ui_file *file)
+{
+  struct dummy_frame *s;
+  for (s = dummy_frame_stack; s != NULL; s = s->next)
+    {
+      gdb_print_host_address (s, file);
+      fprintf_unfiltered (file, ":");
+      fprintf_unfiltered (file, " pc=0x%s", paddr (s->pc));
+      fprintf_unfiltered (file, " fp=0x%s", paddr (s->fp));
+      fprintf_unfiltered (file, " sp=0x%s", paddr (s->sp));
+      fprintf_unfiltered (file, " top=0x%s", paddr (s->top));
+      fprintf_unfiltered (file, " id=");
+      fprint_frame_id (file, s->id);
+      fprintf_unfiltered (file, " call_lo=0x%s", paddr (s->call_lo));
+      fprintf_unfiltered (file, " call_hi=0x%s", paddr (s->call_hi));
+      fprintf_unfiltered (file, "\n");
+    }
+}
+
+static void
+maintenance_print_dummy_frames (char *args, int from_tty)
+{
+  if (args == NULL)
+    fprint_dummy_frames (gdb_stdout);
+  else
+    {
+      struct ui_file *file = gdb_fopen (args, "w");
+      if (file == NULL)
+       perror_with_name ("maintenance print dummy-frames");
+      fprint_dummy_frames (file);    
+      ui_file_delete (file);
+    }
+}
+
+extern void _initialize_dummy_frame (void);
+
+void
+_initialize_dummy_frame (void)
+{
+  add_cmd ("dummy-frames", class_maintenance, maintenance_print_dummy_frames,
+          "Print the contents of the internal dummy-frame stack.",
+          &maintenanceprintlist);
+
+}
This page took 0.036807 seconds and 4 git commands to generate.