From: Don Breazeal <donb@codesourcery.com>
To: <gdb-patches@sourceware.org>
Subject: [PATCH 07/16 v3] Extended-remote arch-specific follow fork
Date: Fri, 31 Oct 2014 23:29:00 -0000 [thread overview]
Message-ID: <1414798134-11536-5-git-send-email-donb@codesourcery.com> (raw)
In-Reply-To: <1408580964-27916-1-git-send-email-donb@codesourcery.com>
This patch implements the architecture-specific pieces of follow-fork,
which in the current implementation copyies the parent's debug register
state into the new child's data structures. This is required for x86,
arm, aarch64, and mips.
I followed the native implementation as closely as I could by
implementing a new linux_target_ops function 'new_fork', which is
analogous to 'linux_nat_new_fork' in linux-nat.c. In gdbserver, the debug
registers are stored in the process list, instead of an
architecture-specific list, so the function arguments are process_info
pointers instead of an lwp_info and a pid as in the native implementation.
In the MIPS implementation the debug register mirror is stored differently
from x86, ARM, and aarch64, so instead of doing a simple structure assignment
I had to clone the list of watchpoint structures.
Tested using gdb.threads/watchpoint-fork.exp on x86, and ran manual tests
on a MIPS board and an ARM board.
I don't currently have access to an aarch64 board, so again if someone is
able to test this easily, please do.
Thanks
--Don
gdb/gdbserver/
2014-10-31 Don Breazeal <donb@codesourcery.com>
* linux-aarch64-low.c (aarch64_linux_new_fork): New function.
(the_low_target) <new_fork>: Initialize new member.
* linux-arm-low.c (arm_new_fork): New function.
(the_low_target) <new_fork>: Initialize new member.
* linux-low.c (handle_extended_wait): Call new target function
new_fork.
* linux-low.h (struct linux_target_ops) <new_fork>: New member.
* linux-mips-low.c (mips_add_watchpoint): New function
extracted from mips_insert_point.
(the_low_target) <new_fork>: Initialize new member.
(mips_linux_new_fork): New function.
(mips_insert_point): Call mips_add_watchpoint.
* linux-x86-low.c (x86_linux_new_fork): New function.
(the_low_target) <new_fork>: Initialize new member.
---
gdb/gdbserver/linux-aarch64-low.c | 28 +++++++++++++
gdb/gdbserver/linux-arm-low.c | 42 ++++++++++++++++++++
gdb/gdbserver/linux-low.c | 4 ++
gdb/gdbserver/linux-low.h | 3 +
gdb/gdbserver/linux-mips-low.c | 76 +++++++++++++++++++++++++++++++------
gdb/gdbserver/linux-x86-low.c | 29 ++++++++++++++
6 files changed, 170 insertions(+), 12 deletions(-)
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index 654b319..31ec0d7 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -1129,6 +1129,33 @@ aarch64_linux_new_thread (void)
return info;
}
+static void
+aarch64_linux_new_fork (struct process_info *parent,
+ struct process_info *child)
+{
+ /* These are allocated by linux_add_process. */
+ gdb_assert (parent->private != NULL
+ && parent->private->arch_private != NULL);
+ gdb_assert (child->private != NULL
+ && child->private->arch_private != NULL);
+
+ /* Linux kernel before 2.6.33 commit
+ 72f674d203cd230426437cdcf7dd6f681dad8b0d
+ will inherit hardware debug registers from parent
+ on fork/vfork/clone. Newer Linux kernels create such tasks with
+ zeroed debug registers.
+
+ GDB core assumes the child inherits the watchpoints/hw
+ breakpoints of the parent, and will remove them all from the
+ forked off process. Copy the debug registers mirrors into the
+ new process so that all breakpoints and watchpoints can be
+ removed together. The debug registers mirror will become zeroed
+ in the end before detaching the forked off process, thus making
+ this compatible with older Linux kernels too. */
+
+ *child->private->arch_private = *parent->private->arch_private;
+}
+
/* Called when resuming a thread.
If the debug regs have changed, update the thread's copies. */
@@ -1293,6 +1320,7 @@ struct linux_target_ops the_low_target =
NULL,
aarch64_linux_new_process,
aarch64_linux_new_thread,
+ aarch64_linux_new_fork,
aarch64_linux_prepare_to_resume,
};
diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
index 8b72523..fe9c34e 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -717,6 +717,47 @@ arm_new_thread (void)
return info;
}
+static void
+arm_new_fork (struct process_info *parent, struct process_info *child)
+{
+ struct arch_process_info *parent_proc_info = parent->private->arch_private;
+ struct arch_process_info *child_proc_info = child->private->arch_private;
+ struct lwp_info *child_lwp;
+ struct arch_lwp_info *child_lwp_info;
+ int i;
+
+ /* These are allocated by linux_add_process. */
+ gdb_assert (parent->private != NULL
+ && parent->private->arch_private != NULL);
+ gdb_assert (child->private != NULL
+ && child->private->arch_private != NULL);
+
+ /* Linux kernel before 2.6.33 commit
+ 72f674d203cd230426437cdcf7dd6f681dad8b0d
+ will inherit hardware debug registers from parent
+ on fork/vfork/clone. Newer Linux kernels create such tasks with
+ zeroed debug registers.
+
+ GDB core assumes the child inherits the watchpoints/hw
+ breakpoints of the parent, and will remove them all from the
+ forked off process. Copy the debug registers mirrors into the
+ new process so that all breakpoints and watchpoints can be
+ removed together. The debug registers mirror will become zeroed
+ in the end before detaching the forked off process, thus making
+ this compatible with older Linux kernels too. */
+
+ *child_proc_info = *parent_proc_info;
+
+ /* Mark all the hardware breakpoints and watchpoints as changed to
+ make sure that the registers will be updated. */
+ child_lwp = find_lwp_pid (ptid_of (child));
+ child_lwp_info = child_lwp->arch_private;
+ for (i = 0; i < MAX_BPTS; i++)
+ child_lwp_info->bpts_changed[i] = 1;
+ for (i = 0; i < MAX_WPTS; i++)
+ child_lwp_info->wpts_changed[i] = 1;
+}
+
/* Called when resuming a thread.
If the debug regs have changed, update the thread's copies. */
static void
@@ -920,6 +961,7 @@ struct linux_target_ops the_low_target = {
NULL, /* siginfo_fixup */
arm_new_process,
arm_new_thread,
+ arm_new_fork,
arm_prepare_to_resume,
};
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index db7ef09..4f6d664 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -438,6 +438,10 @@ handle_extended_wait (struct lwp_info *event_child, int wstat)
child_proc->tdesc = tdesc;
child_lwp->must_set_ptrace_flags = 1;
+ /* Clone arch-specific process data. */
+ if (the_low_target.new_fork != NULL)
+ the_low_target.new_fork (parent_proc, child_proc);
+
/* Save fork info for target processing. */
current_thread->pending_follow.kind = TARGET_WAITKIND_FORKED;
current_thread->pending_follow.value.related_pid = ptid;
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index a903430..53d1c24 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -185,6 +185,9 @@ struct linux_target_ops
allocate it here. */
struct arch_lwp_info * (*new_thread) (void);
+ /* Hook to call, if any, when a new fork is attached. */
+ void (*new_fork) (struct process_info *parent, struct process_info *child);
+
/* Hook to call prior to resuming a thread. */
void (*prepare_to_resume) (struct lwp_info *);
diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c
index 0fc8cb4..d5db79d 100644
--- a/gdb/gdbserver/linux-mips-low.c
+++ b/gdb/gdbserver/linux-mips-low.c
@@ -344,6 +344,68 @@ mips_linux_new_thread (void)
return info;
}
+/* Create a new mips_watchpoint and add it to the list. */
+
+static void
+mips_add_watchpoint (struct arch_process_info *private, CORE_ADDR addr,
+ int len, int watch_type)
+{
+ struct mips_watchpoint *new_watch;
+ struct mips_watchpoint **pw;
+
+ new_watch = xmalloc (sizeof (struct mips_watchpoint));
+ new_watch->addr = addr;
+ new_watch->len = len;
+ new_watch->type = watch_type;
+ new_watch->next = NULL;
+
+ pw = &private->current_watches;
+ while (*pw != NULL)
+ pw = &(*pw)->next;
+ *pw = new_watch;
+}
+
+/* Hook to call when a new fork is attached. */
+
+static void
+mips_linux_new_fork (struct process_info *parent,
+ struct process_info *child)
+{
+ struct arch_process_info *parent_private;
+ struct arch_process_info *child_private;
+ struct mips_watchpoint *wp;
+
+ /* These are allocated by linux_add_process. */
+ gdb_assert (parent->private != NULL
+ && parent->private->arch_private != NULL);
+ gdb_assert (child->private != NULL
+ && child->private->arch_private != NULL);
+
+ /* Linux kernel before 2.6.33 commit
+ 72f674d203cd230426437cdcf7dd6f681dad8b0d
+ will inherit hardware debug registers from parent
+ on fork/vfork/clone. Newer Linux kernels create such tasks with
+ zeroed debug registers.
+
+ GDB core assumes the child inherits the watchpoints/hw
+ breakpoints of the parent, and will remove them all from the
+ forked off process. Copy the debug registers mirrors into the
+ new process so that all breakpoints and watchpoints can be
+ removed together. The debug registers mirror will become zeroed
+ in the end before detaching the forked off process, thus making
+ this compatible with older Linux kernels too. */
+
+ parent_private = parent->private->arch_private;
+ child_private = child->private->arch_private;
+
+ child_private->watch_readback_valid = parent_private->watch_readback_valid;
+ child_private->watch_readback = parent_private->watch_readback;
+
+ for (wp = parent_private->current_watches; wp != NULL; wp = wp->next)
+ mips_add_watchpoint (child_private, wp->addr, wp->len, wp->type);
+
+ child_private->watch_mirror = parent_private->watch_mirror;
+}
/* This is the implementation of linux_target_ops method
prepare_to_resume. If the watch regs have changed, update the
thread's copies. */
@@ -397,8 +459,6 @@ mips_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
struct process_info *proc = current_process ();
struct arch_process_info *private = proc->private->arch_private;
struct pt_watch_regs regs;
- struct mips_watchpoint *new_watch;
- struct mips_watchpoint **pw;
int pid;
long lwpid;
enum target_hw_bp_type watch_type;
@@ -425,16 +485,7 @@ mips_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
return -1;
/* It fit. Stick it on the end of the list. */
- new_watch = xmalloc (sizeof (struct mips_watchpoint));
- new_watch->addr = addr;
- new_watch->len = len;
- new_watch->type = watch_type;
- new_watch->next = NULL;
-
- pw = &private->current_watches;
- while (*pw != NULL)
- pw = &(*pw)->next;
- *pw = new_watch;
+ mips_add_watchpoint (private, addr, len, watch_type);
private->watch_mirror = regs;
@@ -845,6 +896,7 @@ struct linux_target_ops the_low_target = {
NULL, /* siginfo_fixup */
mips_linux_new_process,
mips_linux_new_thread,
+ mips_linux_new_fork,
mips_linux_prepare_to_resume
};
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index 838e7c9..10b8a56 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -768,6 +768,34 @@ x86_linux_new_thread (void)
return info;
}
+/* Target routine for linux_new_fork. */
+
+static void
+x86_linux_new_fork (struct process_info *parent, struct process_info *child)
+{
+ /* These are allocated by linux_add_process. */
+ gdb_assert (parent->private != NULL
+ && parent->private->arch_private != NULL);
+ gdb_assert (child->private != NULL
+ && child->private->arch_private != NULL);
+
+ /* Linux kernel before 2.6.33 commit
+ 72f674d203cd230426437cdcf7dd6f681dad8b0d
+ will inherit hardware debug registers from parent
+ on fork/vfork/clone. Newer Linux kernels create such tasks with
+ zeroed debug registers.
+
+ GDB core assumes the child inherits the watchpoints/hw
+ breakpoints of the parent, and will remove them all from the
+ forked off process. Copy the debug registers mirrors into the
+ new process so that all breakpoints and watchpoints can be
+ removed together. The debug registers mirror will become zeroed
+ in the end before detaching the forked off process, thus making
+ this compatible with older Linux kernels too. */
+
+ *child->private->arch_private = *parent->private->arch_private;
+}
+
/* Called when resuming a thread.
If the debug regs have changed, update the thread's copies. */
@@ -3428,6 +3456,7 @@ struct linux_target_ops the_low_target =
x86_siginfo_fixup,
x86_linux_new_process,
x86_linux_new_thread,
+ x86_linux_new_fork,
x86_linux_prepare_to_resume,
x86_linux_process_qsupported,
x86_supports_tracepoints,
--
1.7.0.4
next prev parent reply other threads:[~2014-10-31 23:29 UTC|newest]
Thread overview: 110+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-07 18:00 [PATCH 00/10] Linux extended-remote fork events Don Breazeal
2014-08-07 18:00 ` [PATCH 04/10] Enhance extended ptrace event setup Don Breazeal
2014-08-13 17:50 ` Breazeal, Don
2014-08-07 18:00 ` [PATCH 01/10] Refactor native follow-fork Don Breazeal
2014-08-07 18:00 ` [PATCH 02/10] Refactor follow-fork message printing Don Breazeal
2014-08-07 18:00 ` [PATCH 06/10] Extended-remote follow fork Don Breazeal
2014-08-07 18:00 ` [PATCH 05/10] GDBserver clone breakpoint list Don Breazeal
2014-08-07 18:00 ` [PATCH 07/10] Extended-remote arch-specific follow fork Don Breazeal
2014-08-07 18:00 ` [PATCH 03/10] Refactor extended ptrace event status Don Breazeal
2014-08-07 18:01 ` [PATCH 10/10] Extended-remote fork event documentation Don Breazeal
2014-08-07 19:31 ` Eli Zaretskii
2014-08-08 15:35 ` Breazeal, Don
2014-08-07 18:01 ` [PATCH 09/10] Extended-remote fork catchpoints Don Breazeal
2014-08-07 18:01 ` [PATCH 08/10] Extended-remote follow vfork Don Breazeal
2014-08-21 0:29 ` [PATCH 01/16 v2] Refactor native follow-fork Don Breazeal
2014-09-05 14:20 ` Pedro Alves
2014-09-05 18:56 ` Breazeal, Don
2014-09-05 20:20 ` Breazeal, Don
2014-09-09 10:57 ` Pedro Alves
2014-09-08 23:54 ` Breazeal, Don
2014-09-09 11:09 ` Pedro Alves
2014-09-12 16:50 ` Breazeal, Don
2014-09-22 15:53 ` Breazeal, Don
2014-09-26 18:13 ` Pedro Alves
2014-09-29 18:08 ` Breazeal, Don
2014-09-30 10:56 ` Pedro Alves
2014-09-30 18:43 ` Breazeal, Don
2014-08-21 0:29 ` [Patch 00/16 v2] Linux extended-remote fork and exec events Don Breazeal
2014-09-04 20:57 ` Breazeal, Don
2014-10-31 23:29 ` Don Breazeal [this message]
2014-10-31 23:29 ` [PATCH 04/16 v3] Determine supported extended-remote features Don Breazeal
2014-11-13 12:59 ` Pedro Alves
2014-11-13 18:28 ` Breazeal, Don
2014-11-13 18:33 ` Pedro Alves
2014-11-13 19:08 ` Pedro Alves
2014-11-13 18:37 ` Breazeal, Don
2014-11-13 18:48 ` Pedro Alves
2014-12-06 0:30 ` Breazeal, Don
2015-01-12 22:36 ` Don Breazeal
2015-01-21 21:02 ` Breazeal, Don
2014-10-31 23:29 ` [PATCH 08/16 v3] Extended-remote follow vfork Don Breazeal
2014-10-31 23:29 ` [PATCH 00/16 v3] Linux extended-remote fork and exec events Don Breazeal
2014-11-12 15:54 ` Pedro Alves
2014-11-13 13:41 ` Pedro Alves
2014-11-13 13:51 ` Pedro Alves
2014-11-13 14:58 ` Pedro Alves
2014-11-13 19:14 ` Pedro Alves
2014-10-31 23:29 ` [PATCH 05/16 v3] GDBserver clone breakpoint list Don Breazeal
2014-10-31 23:29 ` [PATCH 06/16 v3] Extended-remote Linux follow fork Don Breazeal
2014-11-13 13:00 ` Pedro Alves
2014-11-13 18:53 ` Breazeal, Don
2014-11-13 18:59 ` Pedro Alves
2014-11-13 19:06 ` Breazeal, Don
2014-12-06 0:31 ` Breazeal, Don
2015-01-23 12:53 ` Pedro Alves
2015-01-23 17:18 ` Breazeal, Don
[not found] ` <1422222420-25421-1-git-send-email-donb@codesourcery.com>
2015-01-25 21:49 ` [PATCH v4 6/7] Remote follow vfork Don Breazeal
2015-02-10 16:39 ` Pedro Alves
2015-01-25 21:49 ` [PATCH v4 5/7] Arch-specific remote follow fork Don Breazeal
2015-02-10 16:37 ` Pedro Alves
2015-01-25 21:50 ` [PATCH v4 1/7] Identify remote fork event support Don Breazeal
2015-02-10 16:34 ` Pedro Alves
2015-01-25 21:50 ` [PATCH v4 2/7] Clone remote breakpoints Don Breazeal
2015-01-25 21:58 ` [PATCH v4 7/7] Remote fork catch Don Breazeal
2015-01-26 0:07 ` [PATCH v4 3/7 v3] Extended-remote Linux follow fork Don Breazeal
2015-02-10 16:36 ` Pedro Alves
2015-01-26 0:20 ` [PATCH v4 4/7] Target remote " Don Breazeal
2015-01-12 22:39 ` [PATCH 06/16 v3] Extended-remote Linux " Don Breazeal
2015-01-12 22:49 ` Breazeal, Don
2014-10-31 23:30 ` [PATCH 11/16 v3] Extended-remote Linux exit events Don Breazeal
2014-11-13 19:18 ` Pedro Alves
2014-10-31 23:30 ` [PATCH 09/16 v3] Extended-remote fork catchpoints Don Breazeal
2014-10-31 23:30 ` [PATCH 13/16 v3] Extended-remote exec catchpoints Don Breazeal
2014-10-31 23:30 ` [PATCH 12/16 v3] Extended-remote follow exec Don Breazeal
2014-10-31 23:30 ` [PATCH 10/16 v3] Extended-remote fork event documentation Don Breazeal
2014-10-31 23:31 ` [PATCH 16/16 v3] Non-stop follow exec tests Don Breazeal
2014-10-31 23:31 ` [PATCH 15/16 v3] Extended-remote exec event documentation Don Breazeal
2014-10-31 23:31 ` [PATCH 14/16 v3] Suppress spurious warnings with extended-remote follow exec Don Breazeal
2014-08-21 0:30 ` [PATCH 03/16 v2] Refactor ptrace extended event status Don Breazeal
2014-09-09 11:31 ` Pedro Alves
2014-09-19 18:14 ` [pushed] " Breazeal, Don
2014-08-21 0:30 ` [PATCH 02/16 v2] Refactor follow-fork message printing Don Breazeal
2014-09-26 19:52 ` Pedro Alves
2014-09-26 20:14 ` Breazeal, Don
2014-10-03 23:51 ` Breazeal, Don
2014-10-15 16:08 ` Pedro Alves
2014-10-22 23:47 ` Breazeal, Don
2014-10-24 12:35 ` Pedro Alves
2014-10-24 18:45 ` Breazeal, Don
2014-08-21 0:30 ` [PATCH 04/16 v2] Determine supported extended-remote features Don Breazeal
2014-10-15 16:17 ` Pedro Alves
2014-10-21 23:23 ` Breazeal, Don
2014-10-22 21:48 ` Pedro Alves
2014-10-31 23:38 ` Breazeal, Don
2014-08-21 0:31 ` [PATCH 06/16 v2] Extended-remote Linux follow fork Don Breazeal
2014-09-19 20:57 ` Breazeal, Don
2014-08-21 0:31 ` [PATCH 07/16 v2] Extended-remote arch-specific " Don Breazeal
2014-09-19 21:26 ` Breazeal, Don
2014-08-21 0:31 ` [PATCH 05/16 v2] GDBserver clone breakpoint list Don Breazeal
2014-10-15 17:40 ` Pedro Alves
2014-10-31 23:44 ` Breazeal, Don
2014-08-21 0:32 ` [PATCH 08/16 v2] Extended-remote follow vfork Don Breazeal
2014-08-21 0:33 ` [PATCH 09/16 v2] Extended-remote fork catchpoints Don Breazeal
2014-08-21 0:33 ` [PATCH 10/16 v2] Extended-remote fork event documentation Don Breazeal
2014-08-21 0:33 ` [PATCH 11/16 v2] Extended-remote Linux exit events Don Breazeal
2014-08-21 0:34 ` [PATCH 13/16 v2] Extended-remote exec catchpoints Don Breazeal
2014-08-21 0:34 ` [PATCH 12/16 v2] Extended-remote follow exec Don Breazeal
2014-08-21 0:35 ` [PATCH 14/16 v2] Suppress spurious warnings with extended-remote " Don Breazeal
2014-08-21 0:36 ` [PATCH 15/16 v2] Extended-remote exec event documentation Don Breazeal
2014-08-21 0:36 ` [PATCH 16/16 v2] Non-stop follow exec tests Don Breazeal
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=1414798134-11536-5-git-send-email-donb@codesourcery.com \
--to=donb@codesourcery.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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).