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] Add SINGLE_STEP_THROUGH_DELAY


Hello,

Ref: gdb-patches: STEP_SKIPS_DELAY question, sort of
http://sources.redhat.com/ml/gdb-patches/2004-10/msg00015.html

I've taken Organ's infrun.c patch and implemented it for the MIPS. There are going to be teething problems I'm sure.

Andrew
2004-10-31  Orjan Friberg <organ.friberg@axis.com>
	    Andrew Cagney  <cagney@gnu.org>

	* gdbarch.sh (single_step_through_delay): Add.
	* gdbarch.h, gdbarch.c: Re-generate.
	* config/mips/tm-mips.h (STEP_SKIPS_DELAY_P, STEP_SKIPS_DELAY)
	(mips_step_skips_delay): Delete.
	* mips-tdep.c (mips_single_step_through_delay): Replace
	mips_step_skips_delay.
	(mips_gdbarch_init): Set single_step_through_delay.
	(mips_dump_tdep): Do not print STEP_SKIPS_DELAY.
	
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.348
diff -p -u -r1.348 gdbarch.sh
--- gdbarch.sh	2 Sep 2004 17:22:08 -0000	1.348
+++ gdbarch.sh	31 Oct 2004 17:28:10 -0000
@@ -611,6 +611,9 @@ f:=:CORE_ADDR:smash_text_address:CORE_AD
 # FIXME/cagney/2001-01-18: The logic is backwards.  It should be asking if the target can
 # single step.  If not, then implement single step using breakpoints.
 F:=:void:software_single_step:enum target_signal sig, int insert_breakpoints_p:sig, insert_breakpoints_p
+# Return non-zero if the processor is executing a delay slot and a
+# further single-step is needed before the instruction finishes.
+M::int:single_step_through_delay:struct frame_info *frame:frame
 # FIXME: cagney/2003-08-28: Need to find a better way of selecting the
 # disassembler.  Perhaps objdump can handle it?
 f:TARGET_PRINT_INSN:int:print_insn:bfd_vma vma, struct disassemble_info *info:vma, info::0:
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.180
diff -p -u -r1.180 infrun.c
--- infrun.c	31 Oct 2004 16:14:00 -0000	1.180
+++ infrun.c	31 Oct 2004 17:28:11 -0000
@@ -714,24 +714,17 @@ proceed (CORE_ADDR addr, enum target_sig
 
   if (addr == (CORE_ADDR) -1)
     {
-      /* If there is a breakpoint at the address we will resume at,
-         step one instruction before inserting breakpoints
-         so that we do not stop right away (and report a second
-         hit at this breakpoint).  */
-
       if (read_pc () == stop_pc && breakpoint_here_p (read_pc ()))
+	/* There is a breakpoint at the address we will resume at,
+	   step one instruction before inserting breakpoints so that
+	   we do not stop right away (and report a second hit at this
+	   breakpoint).  */
 	oneproc = 1;
-
-#ifndef STEP_SKIPS_DELAY
-#define STEP_SKIPS_DELAY(pc) (0)
-#define STEP_SKIPS_DELAY_P (0)
-#endif
-      /* Check breakpoint_here_p first, because breakpoint_here_p is fast
-         (it just checks internal GDB data structures) and STEP_SKIPS_DELAY
-         is slow (it needs to read memory from the target).  */
-      if (STEP_SKIPS_DELAY_P
-	  && breakpoint_here_p (read_pc () + 4)
-	  && STEP_SKIPS_DELAY (read_pc ()))
+      else if (gdbarch_single_step_through_delay_p (current_gdbarch)
+              && gdbarch_single_step_through_delay (current_gdbarch,
+                                                    get_current_frame ()))
+	/* We stepped onto an instruction that needs to be stepped
+	   again before re-inserting the breakpoint, do so.  */
 	oneproc = 1;
     }
   else
@@ -1781,6 +1774,39 @@ handle_inferior_event (struct execution_
   stopped_by_random_signal = 0;
   breakpoints_failed = 0;
 
+  if (stop_signal == TARGET_SIGNAL_TRAP
+      && trap_expected
+      && gdbarch_single_step_through_delay_p (current_gdbarch)
+      && currently_stepping (ecs))
+    {
+      /* We're trying to step of a breakpoint.  Turns out that we're
+	 also on an instruction that needs to be stepped multiple
+	 times before it's been fully executing. E.g., architectures
+	 with a delay slot.  It needs to be stepped twice, once for
+	 the instruction and once for the delay slot.  */
+      int step_through_delay
+	= gdbarch_single_step_through_delay (current_gdbarch,
+					     get_current_frame ());
+      if (step_range_end == 0 && step_through_delay)
+	{
+	  /* The user issued a continue when stopped at a breakpoint.
+	     Set up for another trap and get out of here.  */
+         ecs->another_trap = 1;
+         keep_going (ecs);
+         return;
+	}
+      else if (step_through_delay)
+	{
+	  /* The user issued a step when stopped at a breakpoint.
+	     Maybe we should stop, maybe we should not - the delay
+	     slot *might* correspond to a line of source.  In any
+	     case, don't decide that here, just set ecs->another_trap,
+	     making sure we single-step again before breakpoints are
+	     re-inserted.  */
+	  ecs->another_trap = 1;
+	}
+    }
+
   /* Look at the cause of the stop, and decide what to do.
      The alternatives are:
      1) break; to really stop and return to the debugger,
Index: mips-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.c,v
retrieving revision 1.358
diff -p -u -r1.358 mips-tdep.c
--- mips-tdep.c	31 Oct 2004 16:14:00 -0000	1.358
+++ mips-tdep.c	31 Oct 2004 17:28:11 -0000
@@ -4142,16 +4142,19 @@ is_delayed (unsigned long insn)
 }
 
 int
-mips_step_skips_delay (CORE_ADDR pc)
+mips_single_step_through_delay (struct gdbarch *gdbarch,
+				struct frame_info *frame)
 {
+  CORE_ADDR pc = get_frame_pc (frame);
   char buf[MIPS_INSN32_SIZE];
 
   /* There is no branch delay slot on MIPS16.  */
   if (mips_pc_is_mips16 (pc))
     return 0;
 
-  if (target_read_memory (pc, buf, sizeof buf) != 0)
-    /* If error reading memory, guess that it is not a delayed branch.  */
+  if (!safe_frame_unwind_memory (frame, pc, buf, sizeof buf))
+    /* If error reading memory, guess that it is not a delayed
+       branch.  */
     return 0;
   return is_delayed (extract_unsigned_integer (buf, sizeof buf));
 }
@@ -5097,6 +5100,8 @@ mips_gdbarch_init (struct gdbarch_info i
       set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_solib_return_trampoline);
     }
 
+  set_gdbarch_single_step_through_delay (gdbarch, mips_single_step_through_delay);
+
   /* Hook in OS ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
@@ -5305,9 +5310,6 @@ mips_dump_tdep (struct gdbarch *current_
 		      "mips_dump_tdep: STEP_SKIPS_DELAY # %s\n",
 		      XSTRING (STEP_SKIPS_DELAY (PC)));
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: STEP_SKIPS_DELAY_P = %d\n",
-		      STEP_SKIPS_DELAY_P);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: STOPPED_BY_WATCHPOINT # %s\n",
 		      XSTRING (STOPPED_BY_WATCHPOINT (WS)));
   fprintf_unfiltered (file,
Index: config/mips/tm-mips.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-mips.h,v
retrieving revision 1.76
diff -p -u -r1.76 tm-mips.h
--- config/mips/tm-mips.h	31 Oct 2004 16:14:01 -0000	1.76
+++ config/mips/tm-mips.h	31 Oct 2004 17:28:11 -0000
@@ -33,12 +33,6 @@ struct symbol;
 struct type;
 struct value;
 
-/* Return non-zero if PC points to an instruction which will cause a step
-   to execute both the instruction at PC and an instruction at PC+4.  */
-extern int mips_step_skips_delay (CORE_ADDR);
-#define STEP_SKIPS_DELAY_P (1)
-#define STEP_SKIPS_DELAY(pc) (mips_step_skips_delay (pc))
-
 /* Special symbol found in blocks associated with routines.  We can
    hang mdebug_extra_func_info's off of this.  */
 

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