aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYao Qi <yao.qi@linaro.org>2016-06-17 10:25:13 +0100
committerYao Qi <yao.qi@linaro.org>2016-06-17 10:38:55 +0100
commit8a81c5d7a7cc3ec4d60032d2a911d2f6c3eb8328 (patch)
treec6849aedb5beed40808eed179f4d75eb620bc2e2
parentf50bf8e5153e3cdddd1ad5d3f7d16f2b4e5adb3c (diff)
downloadgdb-8a81c5d7a7cc3ec4d60032d2a911d2f6c3eb8328.zip
gdb-8a81c5d7a7cc3ec4d60032d2a911d2f6c3eb8328.tar.gz
gdb-8a81c5d7a7cc3ec4d60032d2a911d2f6c3eb8328.tar.bz2
Delete reinsert breakpoints from forked child
When a thread is stepping over a syscall instruction with software single step, GDBserver inserts reinsert breakpoints at the next pcs. If the syscall call is fork, the forked child has reinsert breakpoint in its space, and GDBserver clones parent's breakpoint list to child's. When GDBserver resumes the child, its bp_reinsert is zero, but has reinsert breakpoints, so the following assert is triggered if I apply the patch extending step-over-syscall.exp. gdb/gdbserver/linux-low.c:4292: A problem internal to GDBserver has been detected.^M void linux_resume_one_lwp_throw(lwp_info*, int, int, siginfo_t*): Assertion `!has_reinsert_breakpoints (proc)' failed. gdb/gdbserver: 2016-06-17 Yao Qi <yao.qi@linaro.org> * linux-low.c (handle_extended_wait): If the parent is doing step-over, remove the reinsert breakpoints from the forked child.
-rw-r--r--gdb/gdbserver/ChangeLog5
-rw-r--r--gdb/gdbserver/linux-low.c21
2 files changed, 26 insertions, 0 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index fd70f59..734d70d 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,10 @@
2016-06-17 Yao Qi <yao.qi@linaro.org>
+ * linux-low.c (handle_extended_wait): If the parent is doing
+ step-over, remove the reinsert breakpoints from the forked child.
+
+2016-06-17 Yao Qi <yao.qi@linaro.org>
+
* linux-low.c (unsuspend_all_lwps): Declare.
(linux_low_filter_event): If thread exited, call finish_step_over.
If step-over is finished, unsuspend other threads.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 95104d2..3f2d08e 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -569,6 +569,27 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
event_lwp->status_pending_p = 1;
event_lwp->status_pending = wstat;
+ /* If the parent thread is doing step-over with reinsert
+ breakpoints, the reinsert breakpoints are still in forked
+ child's process space and cloned to its breakpoint list
+ from the parent's. Remove them from the child process. */
+ if (event_lwp->bp_reinsert != 0
+ && can_software_single_step ()
+ && event == PTRACE_EVENT_FORK)
+ {
+ struct thread_info *saved_thread = current_thread;
+
+ /* The child process is forked and stopped, so it is safe
+ to access its memory without stopping all other threads
+ from other processes. */
+ current_thread = child_thr;
+ delete_reinsert_breakpoints ();
+ current_thread = saved_thread;
+
+ gdb_assert (has_reinsert_breakpoints (parent_proc));
+ gdb_assert (!has_reinsert_breakpoints (child_proc));
+ }
+
/* Report the event. */
return 0;
}