2004-08-02 Andrew Cagney <cagney@gnu.org>
authorAndrew Cagney <cagney@redhat.com>
Mon, 2 Aug 2004 17:39:53 +0000 (17:39 +0000)
committerAndrew Cagney <cagney@redhat.com>
Mon, 2 Aug 2004 17:39:53 +0000 (17:39 +0000)
* dummy-frame.c: Include "gdb_string.h".
(generic_save_call_dummy_addr, generic_push_dummy_frame)
(generic_save_dummy_frame_tos): Delete.
(dummy_frame_push): New function, replaces above.
* dummy-frame.h: Update copyright.
(dummy_frame_push): Declare.
* frame.h (generic_save_dummy_frame_tos, generic_push_dummy_frame)
(generic_save_call_dummy_addr): Delete declarations.
* infcall.c: Include "dummy-frame.h".
(call_function_by_hand): Add locals caller_regcache,
caller_regcache_cleanup and dummy_id.  Replace push_dummy_frame
with call to frame_save_as_regcache plus cleanup.  Delete calls to
generic_save_call_dummy_addr and generic_save_dummy_frame_tos.
Move clear_proceed_status to just before the resume, add call to
dummy_frame_push (discard cleanup).
* Makefile.in (infcall.o): Add $(dummy_frame_h).
(dummy-frame.o): Add $(gdb_string_h).

gdb/ChangeLog
gdb/Makefile.in
gdb/dummy-frame.c
gdb/dummy-frame.h
gdb/frame.h
gdb/infcall.c

index b42caa5..b80d61a 100644 (file)
@@ -1,3 +1,23 @@
+2004-08-02  Andrew Cagney  <cagney@gnu.org>
+
+       * dummy-frame.c: Include "gdb_string.h".
+       (generic_save_call_dummy_addr, generic_push_dummy_frame)
+       (generic_save_dummy_frame_tos): Delete.
+       (dummy_frame_push): New function, replaces above.
+       * dummy-frame.h: Update copyright.
+       (dummy_frame_push): Declare.
+       * frame.h (generic_save_dummy_frame_tos, generic_push_dummy_frame)
+       (generic_save_call_dummy_addr): Delete declarations.
+       * infcall.c: Include "dummy-frame.h".
+       (call_function_by_hand): Add locals caller_regcache,
+       caller_regcache_cleanup and dummy_id.  Replace push_dummy_frame
+       with call to frame_save_as_regcache plus cleanup.  Delete calls to
+       generic_save_call_dummy_addr and generic_save_dummy_frame_tos.
+       Move clear_proceed_status to just before the resume, add call to
+       dummy_frame_push (discard cleanup).
+       * Makefile.in (infcall.o): Add $(dummy_frame_h).
+       (dummy-frame.o): Add $(gdb_string_h).
+
 2004-08-01  Andrew Cagney  <cagney@gnu.org>
 
        * dummy-frame.h (dummy_frame_unwind): Replace dummy_frame_sniffer.
index 865d3a9..56d9ef6 100644 (file)
@@ -1828,7 +1828,7 @@ dsrec.o: dsrec.c $(defs_h) $(serial_h) $(srec_h) $(gdb_assert_h) \
        $(gdb_string_h)
 dummy-frame.o: dummy-frame.c $(defs_h) $(dummy_frame_h) $(regcache_h) \
        $(frame_h) $(inferior_h) $(gdb_assert_h) $(frame_unwind_h) \
-       $(command_h) $(gdbcmd_h)
+       $(command_h) $(gdbcmd_h) $(gdb_string_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) \
        $(mips_tdep_h)
@@ -2043,7 +2043,8 @@ ia64-tdep.o: ia64-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) \
        $(libunwind_frame_h) $(libunwind_ia64_h)
 infcall.o: infcall.c $(defs_h) $(breakpoint_h) $(target_h) $(regcache_h) \
        $(inferior_h) $(gdb_assert_h) $(block_h) $(gdbcore_h) $(language_h) \
-       $(objfiles_h) $(gdbcmd_h) $(command_h) $(gdb_string_h) $(infcall_h)
+       $(objfiles_h) $(gdbcmd_h) $(command_h) $(gdb_string_h) $(infcall_h) \
+       $(dummy_frame_h)
 infcmd.o: infcmd.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
        $(frame_h) $(inferior_h) $(environ_h) $(value_h) $(gdbcmd_h) \
        $(symfile_h) $(gdbcore_h) $(target_h) $(language_h) $(symfile_h) \
index 1945a00..53365f4 100644 (file)
@@ -31,6 +31,7 @@
 #include "frame-unwind.h"
 #include "command.h"
 #include "gdbcmd.h"
+#include "gdb_string.h"
 
 static int pc_in_dummy_frame (CORE_ADDR pc);
 
@@ -94,27 +95,24 @@ pc_in_dummy_frame (CORE_ADDR pc)
   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.  */
+/* Push the caller's state, along with the dummy frame info, onto a
+   dummy-frame stack.  */
 
 void
-generic_push_dummy_frame (void)
+dummy_frame_push (struct regcache *caller_regcache,
+                 const struct frame_id *dummy_id)
 {
   struct dummy_frame *dummy_frame;
-  CORE_ADDR fp = get_frame_base (get_current_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 */
 
+  /* 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 (gdbarch_inner_than (current_gdbarch, dummy_frame->top, fp))
-      /* stale -- destroy! */
+    /* FIXME: cagney/2004-08-02: Should just test IDs.  */
+    if (gdbarch_inner_than (current_gdbarch, dummy_frame->top,
+                           dummy_id->stack_addr))
+      /* Stale -- destroy!  */
       {
        dummy_frame_stack = dummy_frame->next;
        regcache_xfree (dummy_frame->regcache);
@@ -124,31 +122,19 @@ generic_push_dummy_frame (void)
     else
       dummy_frame = dummy_frame->next;
 
-  dummy_frame = xmalloc (sizeof (struct dummy_frame));
-  dummy_frame->regcache = frame_save_as_regcache (get_current_frame ());
-
-  dummy_frame->pc = read_pc ();
-  dummy_frame->top = 0;
-  dummy_frame->id = get_frame_id (get_current_frame ());
+  dummy_frame = XZALLOC (struct dummy_frame);
+  dummy_frame->regcache = caller_regcache;
+  dummy_frame->id = (*dummy_id);
+  /* FIXME: cagney/2004-08-02: Retain for compatibility - trust the
+     ID.  */
+  dummy_frame->pc = dummy_id->code_addr;
+  dummy_frame->top = dummy_id->stack_addr;
+  dummy_frame->call_lo = dummy_id->code_addr + 0;
+  dummy_frame->call_hi = dummy_id->code_addr + 1;
   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;
-}
-
 /* Return the dummy frame cache, it contains both the ID, and a
    pointer to the regcache.  */
 struct dummy_frame_cache
index 26c2522..7ce7973 100644 (file)
@@ -1,6 +1,6 @@
 /* Code dealing with dummy stack frames, for GDB, the GNU debugger.
 
-   Copyright 2002 Free Software Foundation, Inc.
+   Copyright 2002, 2004 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -27,6 +27,22 @@ struct regcache;
 struct frame_unwind;
 struct frame_id;
 
+/* Push the information needed to identify, and unwind from, a dummy
+   frame onto the dummy frame stack.  */
+
+/* NOTE: cagney/2004-08-02: This interface will eventually need to be
+   parameterized with the caller's thread - that will allow per-thread
+   dummy-frame stacks and, hence, per-thread inferior function
+   calls.  */
+
+/* NOTE: cagney/2004-08-02: In the case of ABIs using push_dummy_code
+   containing more than one instruction, this interface many need to
+   be expanded so that it knowns the lower/upper extent of the dummy
+   frame's code.  */
+
+extern void dummy_frame_push (struct regcache *regcache,
+                             const struct frame_id *dummy_id);
+
 /* If the PC falls in a dummy frame, return a dummy frame
    unwinder.  */
 
index 75b0c9e..942f7b1 100644 (file)
@@ -521,8 +521,6 @@ extern void *frame_obstack_zalloc (unsigned long size);
 /* Create a regcache, and copy the frame's registers into it.  */
 struct regcache *frame_save_as_regcache (struct frame_info *this_frame);
 
-extern void generic_save_dummy_frame_tos (CORE_ADDR sp);
-
 extern struct block *get_frame_block (struct frame_info *,
                                       CORE_ADDR *addr_in_block);
 
@@ -575,12 +573,8 @@ extern void print_frame_info (struct frame_info *, int print_level,
 
 extern struct frame_info *block_innermost_frame (struct block *);
 
-extern void generic_push_dummy_frame (void);
-
 extern int deprecated_pc_in_call_dummy (CORE_ADDR pc);
 
-extern void generic_save_call_dummy_addr (CORE_ADDR lo, CORE_ADDR hi);
-
 /* FIXME: cagney/2003-02-02: Should be deprecated or replaced with a
    function called get_frame_register_p().  This slightly weird (and
    older) variant of get_frame_register() returns zero (indicating the
index fce9cc0..ade9943 100644 (file)
@@ -35,6 +35,7 @@
 #include "command.h"
 #include "gdb_string.h"
 #include "infcall.h"
+#include "dummy-frame.h"
 
 /* NOTE: cagney/2003-04-16: What's the future of this code?
 
@@ -308,6 +309,9 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
   CORE_ADDR real_pc;
   struct type *ftype = check_typedef (SYMBOL_TYPE (function));
   CORE_ADDR bp_addr;
+  struct regcache *caller_regcache;
+  struct cleanup *caller_regcache_cleanup;
+  struct frame_id dummy_id;
 
   if (!target_has_execution)
     noprocess ();
@@ -325,23 +329,12 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
   inf_status = save_inferior_status (1);
   inf_status_cleanup = make_cleanup_restore_inferior_status (inf_status);
 
-  /* FIXME: cagney/2003-02-26: Step zero of this little tinker is to
-     extract the generic dummy frame code from the architecture
-     vector.  Hence this direct call.
-
-     A follow-on change is to modify this interface so that it takes
-     thread OR frame OR ptid as a parameter, and returns a dummy frame
-     handle.  The handle can then be used further down as a parameter
-     to generic_save_dummy_frame_tos().  Hmm, thinking about it, since
-     everything is ment to be using generic dummy frames, why not even
-     use some of the dummy frame code to here - do a regcache dup and
-     then pass the duped regcache, along with all the other stuff, at
-     one single point.
-
-     In fact, you can even save the structure's return address in the
-     dummy frame and fix one of those nasty lost struct return edge
-     conditions.  */
-  generic_push_dummy_frame ();
+  /* Save the caller's registers so that they can be restored once the
+     callee returns.  To allow nested calls the registers are (further
+     down) pushed onto a dummy frame stack.  Include a cleanup (which
+     is tossed once the regcache has been pushed).  */
+  caller_regcache = frame_save_as_regcache (get_current_frame ());
+  caller_regcache_cleanup = make_cleanup_regcache_xfree (caller_regcache);
 
   /* Ensure that the initial SP is correctly aligned.  */
   {
@@ -491,10 +484,6 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
       internal_error (__FILE__, __LINE__, "bad switch");
     }
 
-  /* Save where the breakpoint is going to be inserted so that the
-     dummy-frame code is later able to re-identify it.  */
-  generic_save_call_dummy_addr (bp_addr, bp_addr + 1);
-
   if (nargs < TYPE_NFIELDS (ftype))
     error ("too few arguments in function call");
 
@@ -660,36 +649,44 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
   else
     error ("This target does not support function calls");
 
+  /* Set up a frame ID for the dummy frame so we can pass it to
+     set_momentary_breakpoint.  We need to give the breakpoint a frame
+     ID so that the breakpoint code can correctly re-identify the
+     dummy breakpoint.  */
   /* Sanity.  The exact same SP value is returned by PUSH_DUMMY_CALL,
      saved as the dummy-frame TOS, and used by unwind_dummy_id to form
      the frame ID's stack address.  */
-  generic_save_dummy_frame_tos (sp);
+  dummy_id = frame_id_build (sp, bp_addr);
 
-  /* Now proceed, having reached the desired place.  */
-  clear_proceed_status ();
-    
   /* Create a momentary breakpoint at the return address of the
      inferior.  That way it breaks when it returns.  */
 
   {
     struct breakpoint *bpt;
     struct symtab_and_line sal;
-    struct frame_id frame;
     init_sal (&sal);           /* initialize to zeroes */
     sal.pc = bp_addr;
     sal.section = find_pc_overlay (sal.pc);
-    /* Set up a frame ID for the dummy frame so we can pass it to
-       set_momentary_breakpoint.  We need to give the breakpoint a
-       frame ID so that the breakpoint code can correctly re-identify
-       the dummy breakpoint.  */
     /* Sanity.  The exact same SP value is returned by
        PUSH_DUMMY_CALL, saved as the dummy-frame TOS, and used by
        unwind_dummy_id to form the frame ID's stack address.  */
-    frame = frame_id_build (sp, sal.pc);
-    bpt = set_momentary_breakpoint (sal, frame, bp_call_dummy);
+    bpt = set_momentary_breakpoint (sal, dummy_id, bp_call_dummy);
     bpt->disposition = disp_del;
   }
 
+  /* Everything's ready, push all the info needed to restore the
+     caller (and identify the dummy-frame) onto the dummy-frame
+     stack.  */
+  dummy_frame_push (caller_regcache, &dummy_id);
+  discard_cleanups (caller_regcache_cleanup);
+
+  /* - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP -
+     If you're looking to implement asynchronous dummy-frames, then
+     just below is the place to chop this function in two..  */
+
+  /* Now proceed, having reached the desired place.  */
+  clear_proceed_status ();
+    
   /* Execute a "stack dummy", a piece of code stored in the stack by
      the debugger to be executed in the inferior.