Make reinsert_breakpoint thread specific
This patch makes reinsert_breakpoint thread specific, which means we insert and remove reinsert_breakpoint breakpoints for a specific thread. This motivation of this change is that I'll use reinsert_breakpoint for vCont;s on software single step target, so that GDBserver may insert one reinsert_breakpoint for one thread doing step-over, and insert one reinsert_breakpoint for another thread doing vCont;s. After the operation of one thread is finished, GDBserver must remove reinsert_breakpoint for that thread only. On the other hand, reinsert_breakpoint is used for step-over nowadays. GDBserver inserts reinsert_breakpoint, and wait only from the thread doing step-over. After the step-over is done, GDBserver removes the reinsert_breakpoint. If there is still any threads need step-over, do the same again until all threads are finished step-over. In other words, reinsert_breakpoint is globally thread specific, but in an implicit way. It is natural to make it explicitly thread specific. gdb/gdbserver: 2016-07-21 Yao Qi <yao.qi@linaro.org> * mem-break.c (struct reinsert_breakpoint) <ptid>: New field. (set_reinsert_breakpoint): New parameter ptid. Callers updated. (clone_one_breakpoint): Likewise. (delete_reinsert_breakpoints): Change parameter to thread. Callers updated. (has_reinsert_breakpoints): Likewise. (uninsert_reinsert_breakpoints): Likewise. (reinsert_reinsert_breakpoints): Likewise. * mem-break.h (set_reinsert_breakpoint): Update declaration. (delete_reinsert_breakpoints): Likewise. (reinsert_reinsert_breakpoints): Likewise. (uninsert_reinsert_breakpoints): Likewise. (has_reinsert_breakpoints): Likewise.
This commit is contained in:
parent
63c40ec727
commit
bec903c96b
4 changed files with 92 additions and 55 deletions
|
@ -1,3 +1,19 @@
|
|||
2016-07-21 Yao Qi <yao.qi@linaro.org>
|
||||
|
||||
* mem-break.c (struct reinsert_breakpoint) <ptid>: New field.
|
||||
(set_reinsert_breakpoint): New parameter ptid. Callers updated.
|
||||
(clone_one_breakpoint): Likewise.
|
||||
(delete_reinsert_breakpoints): Change parameter to thread.
|
||||
Callers updated.
|
||||
(has_reinsert_breakpoints): Likewise.
|
||||
(uninsert_reinsert_breakpoints): Likewise.
|
||||
(reinsert_reinsert_breakpoints): Likewise.
|
||||
* mem-break.h (set_reinsert_breakpoint): Update declaration.
|
||||
(delete_reinsert_breakpoints): Likewise.
|
||||
(reinsert_reinsert_breakpoints): Likewise.
|
||||
(uninsert_reinsert_breakpoints): Likewise.
|
||||
(has_reinsert_breakpoints): Likewise.
|
||||
|
||||
2016-07-21 Yao Qi <yao.qi@linaro.org>
|
||||
|
||||
* inferiors.c (get_thread_process): Make parameter const.
|
||||
|
|
|
@ -549,15 +549,11 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
|
|||
&& can_software_single_step ()
|
||||
&& event == PTRACE_EVENT_VFORK)
|
||||
{
|
||||
struct thread_info *saved_thread = current_thread;
|
||||
|
||||
current_thread = event_thr;
|
||||
/* If we leave reinsert breakpoints there, child will
|
||||
hit it, so uninsert reinsert breakpoints from parent
|
||||
(and child). Once vfork child is done, reinsert
|
||||
them back to parent. */
|
||||
uninsert_reinsert_breakpoints ();
|
||||
current_thread = saved_thread;
|
||||
uninsert_reinsert_breakpoints (event_thr);
|
||||
}
|
||||
|
||||
clone_all_breakpoints (child_thr, event_thr);
|
||||
|
@ -592,17 +588,13 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
|
|||
if (event_lwp->bp_reinsert != 0
|
||||
&& can_software_single_step ())
|
||||
{
|
||||
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;
|
||||
delete_reinsert_breakpoints (child_thr);
|
||||
|
||||
gdb_assert (has_reinsert_breakpoints (parent_proc));
|
||||
gdb_assert (!has_reinsert_breakpoints (child_proc));
|
||||
gdb_assert (has_reinsert_breakpoints (event_thr));
|
||||
gdb_assert (!has_reinsert_breakpoints (child_thr));
|
||||
}
|
||||
|
||||
/* Report the event. */
|
||||
|
@ -656,14 +648,9 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
|
|||
|
||||
if (event_lwp->bp_reinsert != 0 && can_software_single_step ())
|
||||
{
|
||||
struct thread_info *saved_thread = current_thread;
|
||||
struct process_info *proc = get_thread_process (event_thr);
|
||||
reinsert_reinsert_breakpoints (event_thr);
|
||||
|
||||
current_thread = event_thr;
|
||||
reinsert_reinsert_breakpoints ();
|
||||
current_thread = saved_thread;
|
||||
|
||||
gdb_assert (has_reinsert_breakpoints (proc));
|
||||
gdb_assert (has_reinsert_breakpoints (event_thr));
|
||||
}
|
||||
|
||||
/* Report the event. */
|
||||
|
@ -2632,11 +2619,9 @@ maybe_hw_step (struct thread_info *thread)
|
|||
return 1;
|
||||
else
|
||||
{
|
||||
struct process_info *proc = get_thread_process (thread);
|
||||
|
||||
/* GDBserver must insert reinsert breakpoint for software
|
||||
single step. */
|
||||
gdb_assert (has_reinsert_breakpoints (proc));
|
||||
gdb_assert (has_reinsert_breakpoints (thread));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -4224,7 +4209,7 @@ install_software_single_step_breakpoints (struct lwp_info *lwp)
|
|||
next_pcs = (*the_low_target.get_next_pcs) (regcache);
|
||||
|
||||
for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); ++i)
|
||||
set_reinsert_breakpoint (pc);
|
||||
set_reinsert_breakpoint (pc, current_ptid);
|
||||
|
||||
do_cleanups (old_chain);
|
||||
}
|
||||
|
@ -4367,7 +4352,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,
|
|||
{
|
||||
/* If the thread isn't doing step-over, there shouldn't be any
|
||||
reinsert breakpoints. */
|
||||
gdb_assert (!has_reinsert_breakpoints (proc));
|
||||
gdb_assert (!has_reinsert_breakpoints (thread));
|
||||
}
|
||||
|
||||
if (fast_tp_collecting == 1)
|
||||
|
@ -4860,8 +4845,8 @@ finish_step_over (struct lwp_info *lwp)
|
|||
threads but LWP stopped while doing that. */
|
||||
if (!can_hardware_single_step ())
|
||||
{
|
||||
gdb_assert (has_reinsert_breakpoints (current_process ()));
|
||||
delete_reinsert_breakpoints ();
|
||||
gdb_assert (has_reinsert_breakpoints (current_thread));
|
||||
delete_reinsert_breakpoints (current_thread);
|
||||
}
|
||||
|
||||
step_over_bkpt = null_ptid;
|
||||
|
|
|
@ -211,6 +211,9 @@ struct other_breakpoint
|
|||
struct reinsert_breakpoint
|
||||
{
|
||||
struct breakpoint base;
|
||||
|
||||
/* Thread the reinsert breakpoint belongs to. */
|
||||
ptid_t ptid;
|
||||
};
|
||||
|
||||
/* Return the breakpoint size from its kind. */
|
||||
|
@ -1476,17 +1479,21 @@ gdb_breakpoint_here (CORE_ADDR where)
|
|||
}
|
||||
|
||||
void
|
||||
set_reinsert_breakpoint (CORE_ADDR stop_at)
|
||||
set_reinsert_breakpoint (CORE_ADDR stop_at, ptid_t ptid)
|
||||
{
|
||||
struct breakpoint *bp;
|
||||
struct reinsert_breakpoint *bp;
|
||||
|
||||
bp = set_breakpoint_type_at (reinsert_breakpoint, stop_at, NULL);
|
||||
gdb_assert (ptid_get_pid (current_ptid) == ptid_get_pid (ptid));
|
||||
|
||||
bp = (struct reinsert_breakpoint *) set_breakpoint_type_at (reinsert_breakpoint,
|
||||
stop_at, NULL);
|
||||
bp->ptid = ptid;
|
||||
}
|
||||
|
||||
void
|
||||
delete_reinsert_breakpoints (void)
|
||||
delete_reinsert_breakpoints (struct thread_info *thread)
|
||||
{
|
||||
struct process_info *proc = current_process ();
|
||||
struct process_info *proc = get_thread_process (thread);
|
||||
struct breakpoint *bp, **bp_link;
|
||||
|
||||
bp = proc->breakpoints;
|
||||
|
@ -1494,11 +1501,17 @@ delete_reinsert_breakpoints (void)
|
|||
|
||||
while (bp)
|
||||
{
|
||||
if (bp->type == reinsert_breakpoint)
|
||||
if (bp->type == reinsert_breakpoint
|
||||
&& ptid_equal (((struct reinsert_breakpoint *) bp)->ptid,
|
||||
ptid_of (thread)))
|
||||
{
|
||||
struct thread_info *saved_thread = current_thread;
|
||||
|
||||
current_thread = thread;
|
||||
*bp_link = bp->next;
|
||||
release_breakpoint (proc, bp);
|
||||
bp = *bp_link;
|
||||
current_thread = saved_thread;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1578,21 +1591,29 @@ uninsert_all_breakpoints (void)
|
|||
}
|
||||
|
||||
void
|
||||
uninsert_reinsert_breakpoints (void)
|
||||
uninsert_reinsert_breakpoints (struct thread_info *thread)
|
||||
{
|
||||
struct process_info *proc = current_process ();
|
||||
struct process_info *proc = get_thread_process (thread);
|
||||
struct breakpoint *bp;
|
||||
|
||||
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
|
||||
{
|
||||
if (bp->type == reinsert_breakpoint)
|
||||
if (bp->type == reinsert_breakpoint
|
||||
&& ptid_equal (((struct reinsert_breakpoint *) bp)->ptid,
|
||||
ptid_of (thread)))
|
||||
{
|
||||
gdb_assert (bp->raw->inserted > 0);
|
||||
|
||||
/* Only uninsert the raw breakpoint if it only belongs to a
|
||||
reinsert breakpoint. */
|
||||
if (bp->raw->refcount == 1)
|
||||
uninsert_raw_breakpoint (bp->raw);
|
||||
{
|
||||
struct thread_info *saved_thread = current_thread;
|
||||
|
||||
current_thread = thread;
|
||||
uninsert_raw_breakpoint (bp->raw);
|
||||
current_thread = saved_thread;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1642,8 +1663,9 @@ reinsert_breakpoints_at (CORE_ADDR pc)
|
|||
}
|
||||
|
||||
int
|
||||
has_reinsert_breakpoints (struct process_info *proc)
|
||||
has_reinsert_breakpoints (struct thread_info *thread)
|
||||
{
|
||||
struct process_info *proc = get_thread_process (thread);
|
||||
struct breakpoint *bp, **bp_link;
|
||||
|
||||
bp = proc->breakpoints;
|
||||
|
@ -1651,7 +1673,9 @@ has_reinsert_breakpoints (struct process_info *proc)
|
|||
|
||||
while (bp)
|
||||
{
|
||||
if (bp->type == reinsert_breakpoint)
|
||||
if (bp->type == reinsert_breakpoint
|
||||
&& ptid_equal (((struct reinsert_breakpoint *) bp)->ptid,
|
||||
ptid_of (thread)))
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
|
@ -1677,19 +1701,27 @@ reinsert_all_breakpoints (void)
|
|||
}
|
||||
|
||||
void
|
||||
reinsert_reinsert_breakpoints (void)
|
||||
reinsert_reinsert_breakpoints (struct thread_info *thread)
|
||||
{
|
||||
struct process_info *proc = current_process ();
|
||||
struct process_info *proc = get_thread_process (thread);
|
||||
struct breakpoint *bp;
|
||||
|
||||
for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
|
||||
{
|
||||
if (bp->type == reinsert_breakpoint)
|
||||
if (bp->type == reinsert_breakpoint
|
||||
&& ptid_equal (((struct reinsert_breakpoint *) bp)->ptid,
|
||||
ptid_of (thread)))
|
||||
{
|
||||
gdb_assert (bp->raw->inserted > 0);
|
||||
|
||||
if (bp->raw->refcount == 1)
|
||||
reinsert_raw_breakpoint (bp->raw);
|
||||
{
|
||||
struct thread_info *saved_thread = current_thread;
|
||||
|
||||
current_thread = thread;
|
||||
reinsert_raw_breakpoint (bp->raw);
|
||||
current_thread = saved_thread;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2113,7 +2145,7 @@ clone_agent_expr (const struct agent_expr *src_ax)
|
|||
/* Deep-copy the contents of one breakpoint to another. */
|
||||
|
||||
static struct breakpoint *
|
||||
clone_one_breakpoint (const struct breakpoint *src)
|
||||
clone_one_breakpoint (const struct breakpoint *src, ptid_t ptid)
|
||||
{
|
||||
struct breakpoint *dest;
|
||||
struct raw_breakpoint *dest_raw;
|
||||
|
@ -2174,6 +2206,9 @@ clone_one_breakpoint (const struct breakpoint *src)
|
|||
= XCNEW (struct reinsert_breakpoint);
|
||||
|
||||
dest = (struct breakpoint *) reinsert_dest;
|
||||
/* Since reinsert breakpoint is thread specific, don't copy
|
||||
thread id from SRC, use ID instead. */
|
||||
reinsert_dest->ptid = ptid;
|
||||
}
|
||||
else
|
||||
gdb_assert_not_reached ("unhandled breakpoint type");
|
||||
|
@ -2201,7 +2236,7 @@ clone_all_breakpoints (struct thread_info *child_thread,
|
|||
|
||||
for (bp = parent_proc->breakpoints; bp != NULL; bp = bp->next)
|
||||
{
|
||||
new_bkpt = clone_one_breakpoint (bp);
|
||||
new_bkpt = clone_one_breakpoint (bp, ptid_of (child_thread));
|
||||
APPEND_TO_LIST (new_list, new_bkpt, bkpt_tail);
|
||||
APPEND_TO_LIST (new_raw_list, new_bkpt->raw, raw_bkpt_tail);
|
||||
}
|
||||
|
|
|
@ -152,31 +152,32 @@ struct breakpoint *set_breakpoint_at (CORE_ADDR where,
|
|||
|
||||
int delete_breakpoint (struct breakpoint *bkpt);
|
||||
|
||||
/* Set a reinsert breakpoint at STOP_AT. */
|
||||
/* Set a reinsert breakpoint at STOP_AT for thread represented by
|
||||
PTID. */
|
||||
|
||||
void set_reinsert_breakpoint (CORE_ADDR stop_at);
|
||||
void set_reinsert_breakpoint (CORE_ADDR stop_at, ptid_t ptid);
|
||||
|
||||
/* Delete all reinsert breakpoints. */
|
||||
/* Delete all reinsert breakpoints of THREAD. */
|
||||
|
||||
void delete_reinsert_breakpoints (void);
|
||||
void delete_reinsert_breakpoints (struct thread_info *thread);
|
||||
|
||||
/* Reinsert all reinsert breakpoints of the current process. */
|
||||
/* Reinsert all reinsert breakpoints of THREAD. */
|
||||
|
||||
void reinsert_reinsert_breakpoints (void);
|
||||
void reinsert_reinsert_breakpoints (struct thread_info *thread);
|
||||
|
||||
/* Uninsert all reinsert breakpoints of the current process. This
|
||||
still leaves the reinsert breakpoints in the table. */
|
||||
/* Uninsert all reinsert breakpoints of THREAD. This still leaves
|
||||
the reinsert breakpoints in the table. */
|
||||
|
||||
void uninsert_reinsert_breakpoints (void);
|
||||
void uninsert_reinsert_breakpoints (struct thread_info *thread);
|
||||
|
||||
/* Reinsert breakpoints at WHERE (and change their status to
|
||||
inserted). */
|
||||
|
||||
void reinsert_breakpoints_at (CORE_ADDR where);
|
||||
|
||||
/* Process PROC has reinsert breakpoints or not. */
|
||||
/* The THREAD has reinsert breakpoints or not. */
|
||||
|
||||
int has_reinsert_breakpoints (struct process_info *proc);
|
||||
int has_reinsert_breakpoints (struct thread_info *thread);
|
||||
|
||||
/* Uninsert breakpoints at WHERE (and change their status to
|
||||
uninserted). This still leaves the breakpoints in the table. */
|
||||
|
|
Loading…
Reference in a new issue