public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Don Breazeal <donb@codesourcery.com>
To: <gdb-patches@sourceware.org>
Subject: [PATCH 07/16 v2] Extended-remote arch-specific follow fork
Date: Thu, 21 Aug 2014 00:31:00 -0000	[thread overview]
Message-ID: <1408580964-27916-8-git-send-email-donb@codesourcery.com> (raw)
In-Reply-To: <1407434395-19089-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.

I ran manual tests on an ARM board, but on the boards I had access to at
the time, hardware watchpoints did not work, even in the unmodified version
of the debugger.  The kernel on one of the boards should have been new
enough to provide the support.  I didn't debug it further at the time.  If
someone is able to test this easily, please do.  Otherwise I plan to 
come back to this.

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-08-20  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     |   26 +++++++++++++
 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, 154 insertions(+), 12 deletions(-)

diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index 6066e15..915bc21 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -1132,6 +1132,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.  */
 
@@ -1296,6 +1323,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 c4cfbd4..bfc9c24 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -717,6 +717,31 @@ arm_new_thread (void)
   return info;
 }
 
+static void
+arm_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.  */
 static void
@@ -920,6 +945,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 3fb45b1..852d02e 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -442,6 +442,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_inferior->pending_follow.kind = TARGET_WAITKIND_FORKED;
 	  current_inferior->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 1b2160b..693a653 100644
--- a/gdb/gdbserver/linux-mips-low.c
+++ b/gdb/gdbserver/linux-mips-low.c
@@ -343,6 +343,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.  */
@@ -396,8 +458,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;
@@ -424,16 +484,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;
 
@@ -844,6 +895,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 7a8a473..48466ac 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -770,6 +770,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.  */
 
@@ -3432,6 +3460,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

  parent reply	other threads:[~2014-08-21  0:31 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 07/10] Extended-remote arch-specific follow fork Don Breazeal
2014-08-07 18:00 ` [PATCH 05/10] GDBserver clone breakpoint list Don Breazeal
2014-08-07 18:00 ` [PATCH 03/10] Refactor extended ptrace event status Don Breazeal
2014-08-07 18:00 ` [PATCH 06/10] Extended-remote follow fork Don Breazeal
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 04/10] Enhance extended ptrace event setup Don Breazeal
2014-08-13 17:50   ` Breazeal, Don
2014-08-07 18:01 ` [PATCH 08/10] Extended-remote follow vfork Don Breazeal
2014-08-07 18:01 ` [PATCH 09/10] Extended-remote fork catchpoints 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-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   ` [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 07/16 v3] Extended-remote arch-specific follow fork 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 08/16 v3] Extended-remote follow vfork Don Breazeal
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 5/7] Arch-specific remote " Don Breazeal
2015-02-10 16:37                     ` Pedro Alves
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:50                   ` [PATCH v4 2/7] Clone remote breakpoints Don Breazeal
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: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 10/16 v3] Extended-remote fork event documentation Don Breazeal
2014-10-31 23:30   ` [PATCH 12/16 v3] Extended-remote follow exec Don Breazeal
2014-10-31 23:30   ` [PATCH 13/16 v3] Extended-remote exec catchpoints Don Breazeal
2014-10-31 23:31   ` [PATCH 15/16 v3] Extended-remote exec 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 14/16 v3] Suppress spurious warnings with extended-remote follow exec 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: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: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 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: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:31 ` Don Breazeal [this message]
2014-09-19 21:26   ` [PATCH 07/16 v2] Extended-remote arch-specific follow fork Breazeal, Don
2014-08-21  0:31 ` [PATCH 06/16 v2] Extended-remote Linux " Don Breazeal
2014-09-19 20:57   ` Breazeal, Don
2014-08-21  0:32 ` [PATCH 08/16 v2] Extended-remote follow vfork Don Breazeal
2014-08-21  0:33 ` [PATCH 11/16 v2] Extended-remote Linux exit events Don Breazeal
2014-08-21  0:33 ` [PATCH 10/16 v2] Extended-remote fork event documentation Don Breazeal
2014-08-21  0:33 ` [PATCH 09/16 v2] Extended-remote fork catchpoints Don Breazeal
2014-08-21  0:34 ` [PATCH 12/16 v2] Extended-remote follow exec Don Breazeal
2014-08-21  0:34 ` [PATCH 13/16 v2] Extended-remote exec catchpoints Don Breazeal
2014-08-21  0:35 ` [PATCH 14/16 v2] Suppress spurious warnings with extended-remote follow exec Don Breazeal
2014-08-21  0:36 ` [PATCH 16/16 v2] Non-stop follow exec tests Don Breazeal
2014-08-21  0:36 ` [PATCH 15/16 v2] Extended-remote exec event documentation 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=1408580964-27916-8-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).