diff options
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/breakpoint.c | 10 | ||||
-rw-r--r-- | gdb/breakpoint.h | 1 | ||||
-rw-r--r-- | gdb/infrun.c | 3 | ||||
-rw-r--r-- | gdb/record.c | 64 |
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; } |