aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/breakpoint.c10
-rw-r--r--gdb/breakpoint.h1
-rw-r--r--gdb/infrun.c3
-rw-r--r--gdb/record.c64
5 files changed, 81 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f93e6ba..ae0e585 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,12 @@
+2010-07-19 Hui Zhu <teawater@gmail.com>
+
+ * breakpoint.c (single_step_breakpoints_inserted): New
+ function.
+ * breakpoint.h (single_step_breakpoints_inserted): Extern.
+ * infrun.c (maybe_software_singlestep): Add check code.
+ * record.c (record_resume): Add code for software single step.
+ (record_wait): Ditto.
+
2010-07-18 Jan Kratochvil <jan.kratochvil@redhat.com>
* linux-nat.c (linux_handle_extended_wait): Move variable new_lp into
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index aa3072d..a9be450 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -10726,6 +10726,16 @@ insert_single_step_breakpoint (struct gdbarch *gdbarch,
paddress (gdbarch, next_pc));
}
+/* Check if the breakpoints used for software single stepping
+ were inserted or not. */
+
+int
+single_step_breakpoints_inserted (void)
+{
+ return (single_step_breakpoints[0] != NULL
+ || single_step_breakpoints[1] != NULL);
+}
+
/* Remove and delete any breakpoints used for software single step. */
void
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 6f5d050..18dfe22 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1000,6 +1000,7 @@ extern int remove_hw_watchpoints (void);
twice before remove is called. */
extern void insert_single_step_breakpoint (struct gdbarch *,
struct address_space *, CORE_ADDR);
+extern int single_step_breakpoints_inserted (void);
extern void remove_single_step_breakpoints (void);
extern void cancel_single_step_breakpoints (void);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 57f2ab8..dd89e78 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1515,7 +1515,8 @@ maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
{
int hw_step = 1;
- if (gdbarch_software_single_step_p (gdbarch)
+ if (execution_direction == EXEC_FORWARD
+ && gdbarch_software_single_step_p (gdbarch)
&& gdbarch_software_single_step (gdbarch, get_current_frame ()))
{
hw_step = 0;
diff --git a/gdb/record.c b/gdb/record.c
index 2443813..cd64c7a 100644
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -1011,9 +1011,43 @@ record_resume (struct target_ops *ops, ptid_t ptid, int step,
if (!RECORD_IS_REPLAY)
{
+ struct gdbarch *gdbarch = target_thread_architecture (ptid);
+
record_message (get_current_regcache (), signal);
- record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
- signal);
+
+ if (!step)
+ {
+ /* This is not hard single step. */
+ if (!gdbarch_software_single_step_p (gdbarch))
+ {
+ /* This is a normal continue. */
+ step = 1;
+ }
+ else
+ {
+ /* This arch support soft sigle step. */
+ if (single_step_breakpoints_inserted ())
+ {
+ /* This is a soft single step. */
+ record_resume_step = 1;
+ }
+ else
+ {
+ /* This is a continue.
+ Try to insert a soft single step breakpoint. */
+ if (!gdbarch_software_single_step (gdbarch,
+ get_current_frame ()))
+ {
+ /* This system don't want use soft single step.
+ Use hard sigle step. */
+ step = 1;
+ }
+ }
+ }
+ }
+
+ record_beneath_to_resume (record_beneath_to_resume_ops,
+ ptid, step, signal);
}
}
@@ -1089,12 +1123,16 @@ record_wait (struct target_ops *ops,
/* This is not a single step. */
ptid_t ret;
CORE_ADDR tmp_pc;
+ struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
while (1)
{
ret = record_beneath_to_wait (record_beneath_to_wait_ops,
ptid, status, options);
+ if (single_step_breakpoints_inserted ())
+ remove_single_step_breakpoints ();
+
if (record_resume_step)
return ret;
@@ -1134,8 +1172,12 @@ record_wait (struct target_ops *ops,
}
else
{
- /* This must be a single-step trap. Record the
- insn and issue another step. */
+ /* This is a single-step trap. Record the
+ insn and issue another step.
+ FIXME: this part can be a random SIGTRAP too.
+ But GDB cannot handle it. */
+ int step = 1;
+
if (!record_message_wrapper_safe (regcache,
TARGET_SIGNAL_0))
{
@@ -1144,8 +1186,20 @@ record_wait (struct target_ops *ops,
break;
}
+ if (gdbarch_software_single_step_p (gdbarch))
+ {
+ /* Try to insert the software single step breakpoint.
+ If insert success, set step to 0. */
+ set_executing (inferior_ptid, 0);
+ reinit_frame_cache ();
+ if (gdbarch_software_single_step (gdbarch,
+ get_current_frame ()))
+ step = 0;
+ set_executing (inferior_ptid, 1);
+ }
+
record_beneath_to_resume (record_beneath_to_resume_ops,
- ptid, 1,
+ ptid, step,
TARGET_SIGNAL_0);
continue;
}