aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/mem-break.c
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
commit2e7b624b851c34f6bc2ab75fcbc94db75f72eb3a (patch)
treeb0842176277f961eb6d56c90ab88b28f8cadd033 /gdb/gdbserver/mem-break.c
parent8a81c5d7a7cc3ec4d60032d2a911d2f6c3eb8328 (diff)
downloadgdb-2e7b624b851c34f6bc2ab75fcbc94db75f72eb3a.zip
gdb-2e7b624b851c34f6bc2ab75fcbc94db75f72eb3a.tar.gz
gdb-2e7b624b851c34f6bc2ab75fcbc94db75f72eb3a.tar.bz2
Handle reinsert breakpoints for vforked child
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-06-17 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.
Diffstat (limited to 'gdb/gdbserver/mem-break.c')
-rw-r--r--gdb/gdbserver/mem-break.c38
1 files changed, 38 insertions, 0 deletions
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 ();