[PATCH 8/9] Use reinsert_breakpoint for vCont;s

Yao Qi
2016-06-30T14:09:55Z

V3: - install breakpoints in proceed_one_lwp, if the thread doesn't have
reinsert breakpoints installed yet,
- no longer stop all threads when installing breakpoints,
- delete reinsert breakpoints when GDBserver wants to report event,

> - Also, if in all-stop mode, if gdb does:
>
> vCont;s:1;c
>
> thus setting thread 1 stepping, and all others continuing,
> and then some other thread but thread 1 hits a breakpoint,
> what is removing the reinsert breakpoint of thread 1?

if thread 1 doesn't hit the reinsert breakpoint, we don't have to
remove them, because GDB will send vCont;s:1 next time, and GDBserver
can only install reinsert breakpoints if they are not installed yet.
if thread hits the reinsert breakpoint, but the event is not reported.
It becomes pending, and GDBserver will delete the reinsert breakpoints
next time when this pending event is reported back to GDB.

V2: fix spaces in changelog entry,
use maybe_hw_step,
cancel step-over if signal arrives (!maybe_internal_trap),

This patch is to teach GDBserver using software single step to handle
vCont;s. Simply speaking, if the thread's resume request is resume_step,
install reinsert breakpoint at the next pcs when GDBserver is about to
resume threads. These reinsert breakpoints of a thread are removed,
when GDBserver gets an event from that thread and reports this event back
to GDB.

gdb/gdbserver:

2016-06-30 Yao Qi <yao.qi@linaro.org>

* linux-low.c (resume_stopped_resumed_lwps): If resume request
is resume_step, call maybe_hw_step.
(linux_wait_1): Stop all threads, remove reinsert breakpoints,
and unstop them.
(linux_resume_one_lwp_throw): Don't assert the thread has reinsert
breakpoints or not.
(proceed_one_lwp): If resume request is resume_step, install
reinsert breakpoints and call maybe_hw_step.
---
gdb/gdbserver/linux-low.c | 34 ++++++++++++++++++++++++++--------
1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index abaf288..c9bb012 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -2563,7 +2563,10 @@ resume_stopped_resumed_lwps (struct inferior_list_entry *entry)
&& !lp->status_pending_p
&& thread->last_status.kind == TARGET_WAITKIND_IGNORE)
{
- int step = thread->last_resume_kind == resume_step;
+ int step = 0;
+
+ if (thread->last_resume_kind == resume_step)
+ step = maybe_hw_step (thread);

if (debug_threads)
debug_printf ("RSRL: resuming stopped-resumed LWP %s at %s: step=%d\n",
@@ -3622,6 +3625,20 @@ linux_wait_1 (ptid_t ptid,

/* Alright, we're going to report a stop. */

+ /* Remove reinsert breakpoints. */
+ if (can_software_single_step ()
+ && has_reinsert_breakpoints (current_thread))
+ {
+ /* Stop all threads before removing breakpoints out of memory,
+ so that threads other than EVENT_CHILD won't hit the
+ breakpoint in the staled memory. */
+ stop_all_lwps (0, event_child);
+
+ delete_reinsert_breakpoints (current_thread);
+
+ unstop_all_lwps (0, event_child);
+ }
+
if (!stabilizing_threads)
{
/* In all-stop, stop all threads. */
@@ -4275,12 +4292,6 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,

step = maybe_hw_step (thread);
}
- else
- {
- /* If the thread isn't doing step-over, there shouldn't be any
- reinsert breakpoints. */
- gdb_assert (!has_reinsert_breakpoints (thread));
- }

if (fast_tp_collecting == 1)
{
@@ -5088,7 +5099,14 @@ proceed_one_lwp (struct inferior_list_entry *entry, void *except)
if (debug_threads)
debug_printf (" stepping LWP %ld, client wants it stepping\n",
lwpid_of (thread));
- step = 1;
+
+ /* If resume_step is requested by GDB, install reinsert
+ breakpoints when the thread is about to be actually resumed if
+ the reinsert breakpoints weren't removed. */
+ if (can_software_single_step () && !has_reinsert_breakpoints (thread))
+ install_software_single_step_breakpoints (lwp);
+
+ step = maybe_hw_step (thread);
}
else if (lwp->bp_reinsert != 0)
{
--
1.9.1