2004-10-31 Orjan Friberg <organ.friberg@axis.com>
authorAndrew Cagney <cagney@redhat.com>
Sun, 31 Oct 2004 17:38:16 +0000 (17:38 +0000)
committerAndrew Cagney <cagney@redhat.com>
Sun, 31 Oct 2004 17:38:16 +0000 (17:38 +0000)
    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.

gdb/ChangeLog
gdb/config/mips/tm-mips.h
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/infrun.c
gdb/mips-tdep.c

index f8bb86afc3168bbbef0da8aa858c3f05c9f6e1b3..e50e86d5a8ebad25ee71a186504d324d0b98bc1f 100644 (file)
@@ -1,3 +1,15 @@
+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.
+       
 2004-10-31  Mark Kettenis  <kettenis@gnu.org>
 
        * tramp-frame.c (tramp_frame_prepend_unwinder): Set unwinder type
index 083034296532b9d1ae31948d6cb9fad1850eede5..09af61d30319e9e39bc4a099e8e040e01b7f46ba 100644 (file)
@@ -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 7eb4aeb14be4a2eab254481cb4b7e9448afb41bf..e822fa6866e5712a2afa24e73d61ed0b448ff098 100644 (file)
@@ -211,6 +211,7 @@ struct gdbarch
   gdbarch_addr_bits_remove_ftype *addr_bits_remove;
   gdbarch_smash_text_address_ftype *smash_text_address;
   gdbarch_software_single_step_ftype *software_single_step;
+  gdbarch_single_step_through_delay_ftype *single_step_through_delay;
   gdbarch_print_insn_ftype *print_insn;
   gdbarch_skip_trampoline_code_ftype *skip_trampoline_code;
   gdbarch_skip_solib_resolver_ftype *skip_solib_resolver;
@@ -337,6 +338,7 @@ struct gdbarch startup_gdbarch =
   0,  /* addr_bits_remove */
   0,  /* smash_text_address */
   0,  /* software_single_step */
+  0,  /* single_step_through_delay */
   0,  /* print_insn */
   0,  /* skip_trampoline_code */
   generic_skip_solib_resolver,  /* skip_solib_resolver */
@@ -591,6 +593,7 @@ verify_gdbarch (struct gdbarch *current_gdbarch)
   /* Skip verify of addr_bits_remove, invalid_p == 0 */
   /* Skip verify of smash_text_address, invalid_p == 0 */
   /* Skip verify of software_single_step, has predicate */
+  /* Skip verify of single_step_through_delay, has predicate */
   if (current_gdbarch->print_insn == 0)
     fprintf_unfiltered (log, "\n\tprint_insn");
   /* Skip verify of skip_trampoline_code, invalid_p == 0 */
@@ -1516,6 +1519,12 @@ gdbarch_dump (struct gdbarch *current_gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: short_bit = %s\n",
                       paddr_d (current_gdbarch->short_bit));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_single_step_through_delay_p() = %d\n",
+                      gdbarch_single_step_through_delay_p (current_gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: single_step_through_delay = <0x%lx>\n",
+                      (long) current_gdbarch->single_step_through_delay);
 #ifdef SKIP_PROLOGUE
   fprintf_unfiltered (file,
                       "gdbarch_dump: %s # %s\n",
@@ -3345,6 +3354,30 @@ set_gdbarch_software_single_step (struct gdbarch *gdbarch,
   gdbarch->software_single_step = software_single_step;
 }
 
+int
+gdbarch_single_step_through_delay_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->single_step_through_delay != NULL;
+}
+
+int
+gdbarch_single_step_through_delay (struct gdbarch *gdbarch, struct frame_info *frame)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->single_step_through_delay != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_single_step_through_delay called\n");
+  return gdbarch->single_step_through_delay (gdbarch, frame);
+}
+
+void
+set_gdbarch_single_step_through_delay (struct gdbarch *gdbarch,
+                                       gdbarch_single_step_through_delay_ftype single_step_through_delay)
+{
+  gdbarch->single_step_through_delay = single_step_through_delay;
+}
+
 int
 gdbarch_print_insn (struct gdbarch *gdbarch, bfd_vma vma, struct disassemble_info *info)
 {
index 78b27ba4ef7940869b6077db74c81c221c10b6f3..8ff296c07125fc58baa8f581c88325daec561157 100644 (file)
@@ -1218,6 +1218,15 @@ extern void set_gdbarch_software_single_step (struct gdbarch *gdbarch, gdbarch_s
 #define SOFTWARE_SINGLE_STEP(sig, insert_breakpoints_p) (gdbarch_software_single_step (current_gdbarch, sig, insert_breakpoints_p))
 #endif
 
+/* Return non-zero if the processor is executing a delay slot and a
+   further single-step is needed before the instruction finishes. */
+
+extern int gdbarch_single_step_through_delay_p (struct gdbarch *gdbarch);
+
+typedef int (gdbarch_single_step_through_delay_ftype) (struct gdbarch *gdbarch, struct frame_info *frame);
+extern int gdbarch_single_step_through_delay (struct gdbarch *gdbarch, struct frame_info *frame);
+extern void set_gdbarch_single_step_through_delay (struct gdbarch *gdbarch, gdbarch_single_step_through_delay_ftype *single_step_through_delay);
+
 /* FIXME: cagney/2003-08-28: Need to find a better way of selecting the
    disassembler.  Perhaps objdump can handle it? */
 
index 3ffb85e24dabffb090b26fb567058e71b9b8a09f..fec4c7a12f6954b2f62178831d8440fec6e644e6 100755 (executable)
@@ -611,6 +611,9 @@ f:=:CORE_ADDR:smash_text_address:CORE_ADDR addr:addr::core_addr_identity::0
 # 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 d35ecde14ed255f3dacab55215bc47c48531ce51..396a61647fbda10d9c9904d089a96ecd9d35cdc4 100644 (file)
@@ -714,24 +714,17 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
 
   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_control_state *ecs)
   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 047abe5d3ad6e966d55b1978144098f22a2fa296..686b8b1c4f3e75f9f04d4c674de442f6823b4e4b 100644 (file)
@@ -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 info, struct gdbarch_list *arches)
       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);
 
@@ -5304,9 +5309,6 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                      "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)));