From: Yao Qi <qiyaoltc@gmail.com>
To: gdb-patches@sourceware.org
Subject: [PATCH 05/12] Handle reinsert breakpoints for vforked child
Date: Thu, 02 Jun 2016 09:31:00 -0000 [thread overview]
Message-ID: <1464859846-15619-6-git-send-email-yao.qi@linaro.org> (raw)
In-Reply-To: <1464859846-15619-1-git-send-email-yao.qi@linaro.org>
When a thread is doing step-over with reinsert breakpoint, and the
instruction executed is a syscall doing vfork, both parent and child
share the memory, so the reinsert breakpoint in the space is visible
to both of them. Also, removing the reinsert breakpoints from the
child will effectively remove them from the parent. We should
carefully manipulate reinsert breakpoints for both processes.
What we are doing here is that
- uninsert reinsert breakpoints from the parent before cloning the
breakpoint list. We use "uninsert" instead of "remove", because
we need to "reinsert" them back after vfork is done. In fact,
"uninsert" removes them from both child and parent process space.
- reinsert breakpoints in parent process are still copied to child's
breakpoint list,
- remove them from child's breakpoint list as what we did for fork,
at this point, reinsert breakpoints are removed from the child and
the parent, but they are still tracked by the parent's breakpoint
list,
- once vfork is done, "reinsert" them back to the parent,
gdb/gdbserver:
2016-05-26 Yao Qi <yao.qi@linaro.org>
* linux-low.c (handle_extended_wait): Call
uninsert_reinsert_breakpoints for the parent process. Remove
reinsert breakpoints from the child process. Reinsert them to
the parent process when vfork is done.
* mem-break.c (uninsert_reinsert_breakpoints): New function.
(reinsert_reinsert_breakpoints): New function.
* mem-break.h (uninsert_reinsert_breakpoints): Declare
(reinsert_reinsert_breakpoints): Declare.
gdb/testsuite:
2016-05-26 Yao Qi <yao.qi@linaro.org>
* gdb.base/step-over-fork-1.exp: Extend the test for vfork.
---
gdb/gdbserver/linux-low.c | 38 +++++++++++++++++++++++++----
gdb/gdbserver/mem-break.c | 38 +++++++++++++++++++++++++++++
gdb/gdbserver/mem-break.h | 9 +++++++
gdb/testsuite/gdb.base/step-over-fork-1.exp | 2 +-
4 files changed, 81 insertions(+), 6 deletions(-)
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 3f2d08e..dd92e78 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -543,6 +543,22 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
parent_proc = get_thread_process (event_thr);
child_proc->attached = parent_proc->attached;
+
+ if (event_lwp->bp_reinsert != 0
+ && 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;
+ }
+
clone_all_breakpoints (&child_proc->breakpoints,
&child_proc->raw_breakpoints,
parent_proc->breakpoints);
@@ -570,12 +586,12 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
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. */
+ breakpoints, the list of reinsert breakpoints are cloned
+ from the parent's. Remove them from the child process.
+ In case of vfork, we'll reinsert them back once vforked
+ child is done. */
if (event_lwp->bp_reinsert != 0
- && can_software_single_step ()
- && event == PTRACE_EVENT_FORK)
+ && can_software_single_step ())
{
struct thread_info *saved_thread = current_thread;
@@ -639,6 +655,18 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
{
event_lwp->waitstatus.kind = TARGET_WAITKIND_VFORK_DONE;
+ 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);
+
+ current_thread = event_thr;
+ reinsert_reinsert_breakpoints ();
+ current_thread = saved_thread;
+
+ gdb_assert (has_reinsert_breakpoints (proc));
+ }
+
/* Report the event. */
return 0;
}
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
index c27e803..5c73326 100644
--- a/gdb/gdbserver/mem-break.c
+++ b/gdb/gdbserver/mem-break.c
@@ -1509,6 +1509,26 @@ uninsert_all_breakpoints (void)
uninsert_raw_breakpoint (bp);
}
+void
+uninsert_reinsert_breakpoints (void)
+{
+ struct process_info *proc = current_process ();
+ struct breakpoint *bp;
+
+ for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
+ {
+ if (bp->type == reinsert_breakpoint)
+ {
+ 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);
+ }
+ }
+}
+
static void
reinsert_raw_breakpoint (struct raw_breakpoint *bp)
{
@@ -1589,6 +1609,24 @@ reinsert_all_breakpoints (void)
}
void
+reinsert_reinsert_breakpoints (void)
+{
+ struct process_info *proc = current_process ();
+ struct breakpoint *bp;
+
+ for (bp = proc->breakpoints; bp != NULL; bp = bp->next)
+ {
+ if (bp->type == reinsert_breakpoint)
+ {
+ gdb_assert (bp->raw->inserted > 0);
+
+ if (bp->raw->refcount == 1)
+ reinsert_raw_breakpoint (bp->raw);
+ }
+ }
+}
+
+void
check_breakpoints (CORE_ADDR stop_pc)
{
struct process_info *proc = current_process ();
diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h
index b84dc1e..6a06c0c 100644
--- a/gdb/gdbserver/mem-break.h
+++ b/gdb/gdbserver/mem-break.h
@@ -158,6 +158,15 @@ void set_reinsert_breakpoint (CORE_ADDR stop_at);
void delete_reinsert_breakpoints (void);
+/* Reinsert all reinsert breakpoints of the current process. */
+
+void reinsert_reinsert_breakpoints (void);
+
+/* Uninsert all reinsert breakpoints of the current process. This
+ still leaves the reinsert breakpoints in the table. */
+
+void uninsert_reinsert_breakpoints (void);
+
/* Reinsert breakpoints at WHERE (and change their status to
inserted). */
diff --git a/gdb/testsuite/gdb.base/step-over-fork-1.exp b/gdb/testsuite/gdb.base/step-over-fork-1.exp
index 4a34e61..6791c8f 100644
--- a/gdb/testsuite/gdb.base/step-over-fork-1.exp
+++ b/gdb/testsuite/gdb.base/step-over-fork-1.exp
@@ -101,6 +101,6 @@ proc test { syscall } {
gdb_exit
}
-foreach_with_prefix syscall { "fork" } {
+foreach_with_prefix syscall { "fork" "vfork" } {
test $syscall
}
--
1.9.1
next prev parent reply other threads:[~2016-06-02 9:31 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-02 9:31 [PATCH 00/12 V2] Use reinsert breakpoint for vCont;s Yao Qi
2016-06-02 9:31 ` [PATCH 06/12] Pass breakpoint type in set_breakpoint_at Yao Qi
2016-06-13 15:07 ` Pedro Alves
2016-06-02 9:31 ` [PATCH 03/12] Step over exit with reinsert breakpoints Yao Qi
2016-06-13 14:37 ` Pedro Alves
2016-06-13 14:52 ` Yao Qi
2016-06-13 15:01 ` Pedro Alves
2016-06-17 9:50 ` Yao Qi
2016-06-02 9:31 ` [PATCH 07/12] Create sub classes of 'struct breakpoint' Yao Qi
2016-06-13 15:09 ` Pedro Alves
2016-06-02 9:31 ` [PATCH 08/12] Refactor clone_all_breakpoints Yao Qi
2016-06-13 15:14 ` Pedro Alves
2016-06-02 9:31 ` [PATCH 09/12] Make reinsert_breakpoint thread specific Yao Qi
[not found] ` <71a5322e-41e3-9e23-df73-e14b14c1d656@redhat.com>
2016-06-14 12:52 ` Yao Qi
2016-06-14 12:57 ` Pedro Alves
2016-06-02 9:31 ` [PATCH 01/12] Switch to current thread in finish_step_over Yao Qi
2016-06-13 14:25 ` Pedro Alves
2016-06-02 9:31 ` [PATCH 11/12] Use reinsert_breakpoint for vCont;s Yao Qi
2016-06-13 15:55 ` Pedro Alves
2016-06-14 13:14 ` Yao Qi
2016-06-14 15:48 ` Pedro Alves
2016-06-15 16:41 ` Yao Qi
2016-06-17 15:10 ` Pedro Alves
2016-06-20 18:09 ` Antoine Tremblay
2016-06-02 9:31 ` [PATCH 02/12] More assert checks on reinsert breakpoint Yao Qi
2016-06-13 14:25 ` Pedro Alves
2016-06-02 9:31 ` [PATCH 04/12] Delete reinsert breakpoints from forked child Yao Qi
2016-06-13 15:02 ` Pedro Alves
2016-06-13 16:53 ` Yao Qi
2016-06-13 17:29 ` Pedro Alves
2016-06-14 11:17 ` Yao Qi
2016-06-14 11:40 ` Pedro Alves
2016-06-17 9:53 ` Yao Qi
2016-06-02 9:31 ` [PATCH 12/12] Support vCont s and S actions with software single step Yao Qi
2016-06-13 15:56 ` Pedro Alves
2016-06-02 9:31 ` [PATCH 10/12] Switch current_thread to lwp's thread in install_software_single_step_breakpoints Yao Qi
2016-06-13 15:26 ` Pedro Alves
2016-06-02 9:31 ` Yao Qi [this message]
2016-06-13 15:07 ` [PATCH 05/12] Handle reinsert breakpoints for vforked child Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1464859846-15619-6-git-send-email-yao.qi@linaro.org \
--to=qiyaoltc@gmail.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox