* gdbarch.sh (displaced_step_hw_singlestep): New callback.
authorUlrich Weigand <uweigand@de.ibm.com>
Tue, 29 Sep 2009 00:53:04 +0000 (00:53 +0000)
committerUlrich Weigand <uweigand@de.ibm.com>
Tue, 29 Sep 2009 00:53:04 +0000 (00:53 +0000)
* gdbarch.c, gdbarch.h: Regenerate.
* arch-utils.c (default_displaced_step_hw_singlestep): New function.
* arch-utils.h (default_displaced_step_hw_singlestep): Add prototype.

* ppc-linux-tdep.c (ppc_displaced_step_hw_singlestep): New function.
(rs6000_gdbarch_init): Install it.

* infrun.c (displaced_step_fixup): Use new callback to determine
whether to "step" or "continue" displaced copy.
(resume): Likewise.  Do not call maybe_software_singlestep
for displaced stepping.
(maybe_software_singlestep): Do not handle displaced stepping.

gdb/ChangeLog
gdb/arch-utils.c
gdb/arch-utils.h
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/infrun.c
gdb/rs6000-tdep.c

index 2447062..e365828 100644 (file)
@@ -1,5 +1,21 @@
 2009-09-28  Ulrich Weigand  <uweigand@de.ibm.com>
 
+       * gdbarch.sh (displaced_step_hw_singlestep): New callback.
+       * gdbarch.c, gdbarch.h: Regenerate.
+       * arch-utils.c (default_displaced_step_hw_singlestep): New function.
+       * arch-utils.h (default_displaced_step_hw_singlestep): Add prototype.
+
+       * ppc-linux-tdep.c (ppc_displaced_step_hw_singlestep): New function.
+       (rs6000_gdbarch_init): Install it.
+
+       * infrun.c (displaced_step_fixup): Use new callback to determine
+       whether to "step" or "continue" displaced copy.
+       (resume): Likewise.  Do not call maybe_software_singlestep
+       for displaced stepping.
+       (maybe_software_singlestep): Do not handle displaced stepping.
+
+2009-09-28  Ulrich Weigand  <uweigand@de.ibm.com>
+
        * eval.c (evaluate_subexp_standard) [OP_OBJC_MSGCALL]: Support
        platforms that use function descriptors.  Prefer to use function
        pointer types instead of function types.
index 5cf4afd..b58c562 100644 (file)
@@ -67,6 +67,12 @@ simple_displaced_step_free_closure (struct gdbarch *gdbarch,
   xfree (closure);
 }
 
+int
+default_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
+                                     struct displaced_step_closure *closure)
+{
+  return !gdbarch_software_single_step_p (gdbarch);
+}
 
 CORE_ADDR
 displaced_step_at_entry_point (struct gdbarch *gdbarch)
index 9d95d3f..dddae55 100644 (file)
@@ -49,6 +49,11 @@ extern void
   simple_displaced_step_free_closure (struct gdbarch *gdbarch,
                                       struct displaced_step_closure *closure);
 
+/* Default implementation of gdbarch_displaced_hw_singlestep.  */
+extern int
+  default_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
+                                       struct displaced_step_closure *closure);
+
 /* Possible value for gdbarch_displaced_step_location:
    Place displaced instructions at the program's entry point,
    leaving space for inferior function call return breakpoints.  */
index 2ae3835..6c13dc8 100644 (file)
@@ -232,6 +232,7 @@ struct gdbarch
   gdbarch_skip_permanent_breakpoint_ftype *skip_permanent_breakpoint;
   ULONGEST max_insn_length;
   gdbarch_displaced_step_copy_insn_ftype *displaced_step_copy_insn;
+  gdbarch_displaced_step_hw_singlestep_ftype *displaced_step_hw_singlestep;
   gdbarch_displaced_step_fixup_ftype *displaced_step_fixup;
   gdbarch_displaced_step_free_closure_ftype *displaced_step_free_closure;
   gdbarch_displaced_step_location_ftype *displaced_step_location;
@@ -371,6 +372,7 @@ struct gdbarch startup_gdbarch =
   0,  /* skip_permanent_breakpoint */
   0,  /* max_insn_length */
   0,  /* displaced_step_copy_insn */
+  default_displaced_step_hw_singlestep,  /* displaced_step_hw_singlestep */
   0,  /* displaced_step_fixup */
   NULL,  /* displaced_step_free_closure */
   NULL,  /* displaced_step_location */
@@ -464,6 +466,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->elf_make_msymbol_special = default_elf_make_msymbol_special;
   gdbarch->coff_make_msymbol_special = default_coff_make_msymbol_special;
   gdbarch->register_reggroup_p = default_register_reggroup_p;
+  gdbarch->displaced_step_hw_singlestep = default_displaced_step_hw_singlestep;
   gdbarch->displaced_step_fixup = NULL;
   gdbarch->displaced_step_free_closure = NULL;
   gdbarch->displaced_step_location = NULL;
@@ -627,6 +630,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of skip_permanent_breakpoint, has predicate */
   /* Skip verify of max_insn_length, has predicate */
   /* Skip verify of displaced_step_copy_insn, has predicate */
+  /* Skip verify of displaced_step_hw_singlestep, invalid_p == 0 */
   /* Skip verify of displaced_step_fixup, has predicate */
   if ((! gdbarch->displaced_step_free_closure) != (! gdbarch->displaced_step_copy_insn))
     fprintf_unfiltered (log, "\n\tdisplaced_step_free_closure");
@@ -791,6 +795,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: displaced_step_free_closure = <%s>\n",
                       host_address_to_string (gdbarch->displaced_step_free_closure));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: displaced_step_hw_singlestep = <%s>\n",
+                      host_address_to_string (gdbarch->displaced_step_hw_singlestep));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: displaced_step_location = <%s>\n",
                       host_address_to_string (gdbarch->displaced_step_location));
   fprintf_unfiltered (file,
@@ -3145,6 +3152,23 @@ set_gdbarch_displaced_step_copy_insn (struct gdbarch *gdbarch,
 }
 
 int
+gdbarch_displaced_step_hw_singlestep (struct gdbarch *gdbarch, struct displaced_step_closure *closure)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->displaced_step_hw_singlestep != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_displaced_step_hw_singlestep called\n");
+  return gdbarch->displaced_step_hw_singlestep (gdbarch, closure);
+}
+
+void
+set_gdbarch_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
+                                          gdbarch_displaced_step_hw_singlestep_ftype displaced_step_hw_singlestep)
+{
+  gdbarch->displaced_step_hw_singlestep = displaced_step_hw_singlestep;
+}
+
+int
 gdbarch_displaced_step_fixup_p (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
index 950b7ca..f7b0355 100644 (file)
@@ -734,6 +734,20 @@ typedef struct displaced_step_closure * (gdbarch_displaced_step_copy_insn_ftype)
 extern struct displaced_step_closure * gdbarch_displaced_step_copy_insn (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, struct regcache *regs);
 extern void set_gdbarch_displaced_step_copy_insn (struct gdbarch *gdbarch, gdbarch_displaced_step_copy_insn_ftype *displaced_step_copy_insn);
 
+/* Return true if GDB should use hardware single-stepping to execute
+   the displaced instruction identified by CLOSURE.  If false,
+   GDB will simply restart execution at the displaced instruction
+   location, and it is up to the target to ensure GDB will receive
+   control again (e.g. by placing a software breakpoint instruction
+   into the displaced instruction buffer).
+  
+   The default implementation returns false on all targets that
+   provide a gdbarch_software_single_step routine, and true otherwise. */
+
+typedef int (gdbarch_displaced_step_hw_singlestep_ftype) (struct gdbarch *gdbarch, struct displaced_step_closure *closure);
+extern int gdbarch_displaced_step_hw_singlestep (struct gdbarch *gdbarch, struct displaced_step_closure *closure);
+extern void set_gdbarch_displaced_step_hw_singlestep (struct gdbarch *gdbarch, gdbarch_displaced_step_hw_singlestep_ftype *displaced_step_hw_singlestep);
+
 /* Fix up the state resulting from successfully single-stepping a
    displaced instruction, to give the result we would have gotten from
    stepping the instruction in its original location.
index 1546342..cf43819 100755 (executable)
@@ -654,6 +654,17 @@ V:ULONGEST:max_insn_length:::0:0
 # here.
 M:struct displaced_step_closure *:displaced_step_copy_insn:CORE_ADDR from, CORE_ADDR to, struct regcache *regs:from, to, regs
 
+# Return true if GDB should use hardware single-stepping to execute
+# the displaced instruction identified by CLOSURE.  If false,
+# GDB will simply restart execution at the displaced instruction
+# location, and it is up to the target to ensure GDB will receive
+# control again (e.g. by placing a software breakpoint instruction
+# into the displaced instruction buffer).
+#
+# The default implementation returns false on all targets that
+# provide a gdbarch_software_single_step routine, and true otherwise.
+m:int:displaced_step_hw_singlestep:struct displaced_step_closure *closure:closure::default_displaced_step_hw_singlestep::0
+
 # Fix up the state resulting from successfully single-stepping a
 # displaced instruction, to give the result we would have gotten from
 # stepping the instruction in its original location.
index 1a83a25..ff7c6b9 100644 (file)
@@ -1002,10 +1002,11 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
              displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
            }
 
-         if (gdbarch_software_single_step_p (gdbarch))
-           target_resume (ptid, 0, TARGET_SIGNAL_0);
-         else
+         if (gdbarch_displaced_step_hw_singlestep
+               (gdbarch, displaced_step_closure))
            target_resume (ptid, 1, TARGET_SIGNAL_0);
+         else
+           target_resume (ptid, 0, TARGET_SIGNAL_0);
 
          /* Done, we're stepping a thread.  */
          break;
@@ -1114,19 +1115,15 @@ maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   int hw_step = 1;
 
-  if (gdbarch_software_single_step_p (gdbarch))
+  if (gdbarch_software_single_step_p (gdbarch)
+      && gdbarch_software_single_step (gdbarch, get_current_frame ()))
     {
-      if (use_displaced_stepping (gdbarch))
-        hw_step = 0;
-      else if (gdbarch_software_single_step (gdbarch, get_current_frame ()))
-       {
-         hw_step = 0;
-         /* Do not pull these breakpoints until after a `wait' in
-            `wait_for_inferior' */
-         singlestep_breakpoints_inserted_p = 1;
-         singlestep_ptid = inferior_ptid;
-         singlestep_pc = pc;
-       }
+      hw_step = 0;
+      /* Do not pull these breakpoints until after a `wait' in
+        `wait_for_inferior' */
+      singlestep_breakpoints_inserted_p = 1;
+      singlestep_ptid = inferior_ptid;
+      singlestep_pc = pc;
     }
   return hw_step;
 }
@@ -1208,10 +1205,13 @@ a command like `return' or `jump' to continue execution."));
          discard_cleanups (old_cleanups);
          return;
        }
+
+      step = gdbarch_displaced_step_hw_singlestep
+              (gdbarch, displaced_step_closure);
     }
 
   /* Do we need to do it the hard way, w/temp breakpoints?  */
-  if (step)
+  else if (step)
     step = maybe_software_singlestep (gdbarch, pc);
 
   if (should_resume)
index fae5c28..26ae109 100644 (file)
@@ -1058,6 +1058,15 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
                                    from + offset);
 }
 
+/* Always use hardware single-stepping to execute the
+   displaced instruction.  */
+static int
+ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
+                                 struct displaced_step_closure *closure)
+{
+  return 1;
+}
+
 /* Instruction masks used during single-stepping of atomic sequences.  */
 #define LWARX_MASK 0xfc0007fe
 #define LWARX_INSTRUCTION 0x7c000028
@@ -3898,6 +3907,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Setup displaced stepping.  */
   set_gdbarch_displaced_step_copy_insn (gdbarch,
                                        simple_displaced_step_copy_insn);
+  set_gdbarch_displaced_step_hw_singlestep (gdbarch,
+                                           ppc_displaced_step_hw_singlestep);
   set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
   set_gdbarch_displaced_step_free_closure (gdbarch,
                                           simple_displaced_step_free_closure);