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.
This commit is contained in:
Yao Qi 2016-06-17 10:25:13 +01:00
parent f50bf8e515
commit 8a81c5d7a7
2 changed files with 26 additions and 0 deletions

View File

@ -1,3 +1,8 @@
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.

View File

@ -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;
}