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]

[commit] Clean up incall <-> dummy-frame interface


Hello,

This replaces the three calls (they had to be called in sequence):

	generic_push_dummy_frame
        generic_save_call_dummy_addr
        generic_save_dummy_frame_tos

with a single simpler:

dummy_frame_push (saved_regcache, dummy_id)

is possible because we now assume up-to-date unwinders with a reliable dummy frame ID.

The interface isn't static, likely changes I'm aware of are:

+/* 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.  */

Tested on LE i386 GNU/Linux (with decr pc after break, and BE PPC NetBSD.

Next: is to clean up some redundancy still found in dummy-frame.c.

committed,
Andrew
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).

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.599
diff -p -u -r1.599 Makefile.in
--- Makefile.in	31 Jul 2004 19:36:32 -0000	1.599
+++ Makefile.in	2 Aug 2004 17:37:31 -0000
@@ -1828,7 +1828,7 @@ dsrec.o: dsrec.c $(defs_h) $(serial_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) $(inf
 	$(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: dummy-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dummy-frame.c,v
retrieving revision 1.38
diff -p -u -r1.38 dummy-frame.c
--- dummy-frame.c	2 Aug 2004 16:07:31 -0000	1.38
+++ dummy-frame.c	2 Aug 2004 17:37:31 -0000
@@ -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: dummy-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/dummy-frame.h,v
retrieving revision 1.16
diff -p -u -r1.16 dummy-frame.h
--- dummy-frame.h	2 Aug 2004 16:07:31 -0000	1.16
+++ dummy-frame.h	2 Aug 2004 17:37:31 -0000
@@ -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: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.140
diff -p -u -r1.140 frame.h
--- frame.h	2 Aug 2004 03:36:24 -0000	1.140
+++ frame.h	2 Aug 2004 17:37:31 -0000
@@ -521,8 +521,6 @@ extern void *frame_obstack_zalloc (unsig
 /* 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 fra
 
 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: infcall.c
===================================================================
RCS file: /cvs/src/src/gdb/infcall.c,v
retrieving revision 1.55
diff -p -u -r1.55 infcall.c
--- infcall.c	1 Aug 2004 21:12:56 -0000	1.55
+++ infcall.c	2 Aug 2004 17:37:31 -0000
@@ -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 *fun
   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 *fun
   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 *fun
       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 
   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.
 

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