aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog16
-rw-r--r--gdb/arch-utils.c6
-rw-r--r--gdb/arch-utils.h5
-rw-r--r--gdb/gdbarch.c24
-rw-r--r--gdb/gdbarch.h14
-rwxr-xr-xgdb/gdbarch.sh11
-rw-r--r--gdb/infrun.c32
-rw-r--r--gdb/rs6000-tdep.c11
8 files changed, 103 insertions, 16 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2447062..e365828 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index 5cf4afd..b58c562 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -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)
diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h
index 9d95d3f..dddae55 100644
--- a/gdb/arch-utils.h
+++ b/gdb/arch-utils.h
@@ -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. */
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 2ae3835..6c13dc8 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -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);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 950b7ca..f7b0355 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -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.
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 1546342..cf43819 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -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.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 1a83a25..ff7c6b9 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -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)
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index fae5c28..26ae109 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -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);