public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 2/3] Move fbsd_resume and related functions below fork following helper code.
  2016-06-28 23:00 [PATCH 0/3] Fake VFORK_DONE events on FreeBSD John Baldwin
  2016-06-28 23:00 ` [PATCH 1/3] Honor detach-on-fork " John Baldwin
@ 2016-06-28 23:00 ` John Baldwin
  2016-06-28 23:00 ` [PATCH 3/3] Fake VFORK_DONE events when following only the parent after a vfork John Baldwin
  2016-07-01 14:07 ` [PATCH 0/3] Fake VFORK_DONE events on FreeBSD Pedro Alves
  3 siblings, 0 replies; 5+ messages in thread
From: John Baldwin @ 2016-06-28 23:00 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:

	* fbsd-nat.c (super_resume): Move earlier next to "super_wait".
	(resume_one_thread_cb): Move below fork following helper code.
	(resume_all_threads_cb): Likewise.
	(fbsd_resume): Likewise.
---
 gdb/ChangeLog  |   7 ++++
 gdb/fbsd-nat.c | 127 ++++++++++++++++++++++++++++-----------------------------
 2 files changed, 70 insertions(+), 64 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1c90732..09b75a5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,12 @@
 2016-06-24  John Baldwin  <jhb@FreeBSD.org>
 
+	* fbsd-nat.c (super_resume): Move earlier next to "super_wait".
+	(resume_one_thread_cb): Move below fork following helper code.
+	(resume_all_threads_cb): Likewise.
+	(fbsd_resume): Likewise.
+
+2016-06-24  John Baldwin  <jhb@FreeBSD.org>
+
 	* fbsd-nat.c (fbsd_follow_fork): Only detach child if
 	"detach_fork" is true.
 
diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c
index 0f375f5..4b2b41a 100644
--- a/gdb/fbsd-nat.c
+++ b/gdb/fbsd-nat.c
@@ -281,6 +281,10 @@ fbsd_xfer_partial (struct target_ops *ops, enum target_object object,
 #ifdef PT_LWPINFO
 static int debug_fbsd_lwp;
 
+static void (*super_resume) (struct target_ops *,
+			     ptid_t,
+			     int,
+			     enum gdb_signal);
 static ptid_t (*super_wait) (struct target_ops *,
 			     ptid_t,
 			     struct target_waitstatus *,
@@ -492,70 +496,6 @@ fbsd_update_thread_list (struct target_ops *ops)
 #endif
 }
 
-static void (*super_resume) (struct target_ops *,
-			     ptid_t,
-			     int,
-			     enum gdb_signal);
-
-static int
-resume_one_thread_cb (struct thread_info *tp, void *data)
-{
-  ptid_t *ptid = (ptid_t *) data;
-  int request;
-
-  if (ptid_get_pid (tp->ptid) != ptid_get_pid (*ptid))
-    return 0;
-
-  if (ptid_get_lwp (tp->ptid) == ptid_get_lwp (*ptid))
-    request = PT_RESUME;
-  else
-    request = PT_SUSPEND;
-
-  if (ptrace (request, ptid_get_lwp (tp->ptid), NULL, 0) == -1)
-    perror_with_name (("ptrace"));
-  return 0;
-}
-
-static int
-resume_all_threads_cb (struct thread_info *tp, void *data)
-{
-  ptid_t *filter = (ptid_t *) data;
-
-  if (!ptid_match (tp->ptid, *filter))
-    return 0;
-
-  if (ptrace (PT_RESUME, ptid_get_lwp (tp->ptid), NULL, 0) == -1)
-    perror_with_name (("ptrace"));
-  return 0;
-}
-
-/* Implement the "to_resume" target_ops method.  */
-
-static void
-fbsd_resume (struct target_ops *ops,
-	     ptid_t ptid, int step, enum gdb_signal signo)
-{
-
-  if (debug_fbsd_lwp)
-    fprintf_unfiltered (gdb_stdlog,
-			"FLWP: fbsd_resume for ptid (%d, %ld, %ld)\n",
-			ptid_get_pid (ptid), ptid_get_lwp (ptid),
-			ptid_get_tid (ptid));
-  if (ptid_lwp_p (ptid))
-    {
-      /* If ptid is a specific LWP, suspend all other LWPs in the process.  */
-      iterate_over_threads (resume_one_thread_cb, &ptid);
-    }
-  else
-    {
-      /* If ptid is a wildcard, resume all matching threads (they won't run
-	 until the process is continued however).  */
-      iterate_over_threads (resume_all_threads_cb, &ptid);
-      ptid = inferior_ptid;
-    }
-  super_resume (ops, ptid, step, signo);
-}
-
 #ifdef TDP_RFPPWAIT
 /*
   To catch fork events, PT_FOLLOW_FORK is set on every traced process
@@ -638,6 +578,65 @@ fbsd_is_child_pending (pid_t pid)
 }
 #endif
 
+static int
+resume_one_thread_cb (struct thread_info *tp, void *data)
+{
+  ptid_t *ptid = (ptid_t *) data;
+  int request;
+
+  if (ptid_get_pid (tp->ptid) != ptid_get_pid (*ptid))
+    return 0;
+
+  if (ptid_get_lwp (tp->ptid) == ptid_get_lwp (*ptid))
+    request = PT_RESUME;
+  else
+    request = PT_SUSPEND;
+
+  if (ptrace (request, ptid_get_lwp (tp->ptid), NULL, 0) == -1)
+    perror_with_name (("ptrace"));
+  return 0;
+}
+
+static int
+resume_all_threads_cb (struct thread_info *tp, void *data)
+{
+  ptid_t *filter = (ptid_t *) data;
+
+  if (!ptid_match (tp->ptid, *filter))
+    return 0;
+
+  if (ptrace (PT_RESUME, ptid_get_lwp (tp->ptid), NULL, 0) == -1)
+    perror_with_name (("ptrace"));
+  return 0;
+}
+
+/* Implement the "to_resume" target_ops method.  */
+
+static void
+fbsd_resume (struct target_ops *ops,
+	     ptid_t ptid, int step, enum gdb_signal signo)
+{
+
+  if (debug_fbsd_lwp)
+    fprintf_unfiltered (gdb_stdlog,
+			"FLWP: fbsd_resume for ptid (%d, %ld, %ld)\n",
+			ptid_get_pid (ptid), ptid_get_lwp (ptid),
+			ptid_get_tid (ptid));
+  if (ptid_lwp_p (ptid))
+    {
+      /* If ptid is a specific LWP, suspend all other LWPs in the process.  */
+      iterate_over_threads (resume_one_thread_cb, &ptid);
+    }
+  else
+    {
+      /* If ptid is a wildcard, resume all matching threads (they won't run
+	 until the process is continued however).  */
+      iterate_over_threads (resume_all_threads_cb, &ptid);
+      ptid = inferior_ptid;
+    }
+  super_resume (ops, ptid, step, signo);
+}
+
 /* Wait for the child specified by PTID to do something.  Return the
    process ID of the child, or MINUS_ONE_PTID in case of error; store
    the status in *OURSTATUS.  */
-- 
2.8.4

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] Honor detach-on-fork on FreeBSD.
  2016-06-28 23:00 [PATCH 0/3] Fake VFORK_DONE events on FreeBSD John Baldwin
@ 2016-06-28 23:00 ` John Baldwin
  2016-06-28 23:00 ` [PATCH 2/3] Move fbsd_resume and related functions below fork following helper code John Baldwin
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: John Baldwin @ 2016-06-28 23:00 UTC (permalink / raw)
  To: gdb-patches

Only detach from the new child process in the follow fork callback
if detach_fork is true.

gdb/ChangeLog:

	* fbsd-nat.c (fbsd_follow_fork): Only detach child if
	"detach_fork" is true.x
---
 gdb/ChangeLog  | 5 +++++
 gdb/fbsd-nat.c | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 22234be..1c90732 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2016-06-24  John Baldwin  <jhb@FreeBSD.org>
 
+	* fbsd-nat.c (fbsd_follow_fork): Only detach child if
+	"detach_fork" is true.
+
+2016-06-24  John Baldwin  <jhb@FreeBSD.org>
+
 	* fbsd-tdep.c: Include "auxv.h".
 	(fbsd_print_auxv_entry): New function.
 	(fbsd_init_abi): Install gdbarch "print_auxv_entry" method.
diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c
index dc65e29..0f375f5 100644
--- a/gdb/fbsd-nat.c
+++ b/gdb/fbsd-nat.c
@@ -792,7 +792,7 @@ static int
 fbsd_follow_fork (struct target_ops *ops, int follow_child,
 			int detach_fork)
 {
-  if (!follow_child)
+  if (!follow_child && detach_fork)
     {
       struct thread_info *tp = inferior_thread ();
       pid_t child_pid = ptid_get_pid (tp->pending_follow.value.related_pid);
-- 
2.8.4

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 0/3] Fake VFORK_DONE events on FreeBSD
@ 2016-06-28 23:00 John Baldwin
  2016-06-28 23:00 ` [PATCH 1/3] Honor detach-on-fork " John Baldwin
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: John Baldwin @ 2016-06-28 23:00 UTC (permalink / raw)
  To: gdb-patches

The FreeBSD native targets do not report a VFORK_DONE event at
all currently.  FreeBSD's ptrace doesn't currently report an event
when the vfork parent resumes, so this fixes the native targets to
report a fake event after a sleep similar to the approach used on
Linux.  While here I noticed that I botched the 'detach_fork' support
in the original fork tracing patches, so I fixed that as well.

I am working on adding a new ptrace event to report a real vfork
done event to FreeBSD.  Once that is merged to FreeBSD I will post
a patch for gdb to use that when available instead.

John Baldwin (3):
  Honor detach-on-fork on FreeBSD.
  Move fbsd_resume and related functions below fork following helper
    code.
  Fake VFORK_DONE events when following only the parent after a vfork.

 gdb/ChangeLog  |  30 ++++++++
 gdb/fbsd-nat.c | 239 +++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 195 insertions(+), 74 deletions(-)

-- 
2.8.4

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 3/3] Fake VFORK_DONE events when following only the parent after a vfork.
  2016-06-28 23:00 [PATCH 0/3] Fake VFORK_DONE events on FreeBSD John Baldwin
  2016-06-28 23:00 ` [PATCH 1/3] Honor detach-on-fork " John Baldwin
  2016-06-28 23:00 ` [PATCH 2/3] Move fbsd_resume and related functions below fork following helper code John Baldwin
@ 2016-06-28 23:00 ` John Baldwin
  2016-07-01 14:07 ` [PATCH 0/3] Fake VFORK_DONE events on FreeBSD Pedro Alves
  3 siblings, 0 replies; 5+ messages in thread
From: John Baldwin @ 2016-06-28 23:00 UTC (permalink / raw)
  To: gdb-patches

FreeBSD does not currently report a ptrace event for a parent process
after it resumes due to the child exiting the shared memory region after
a vfork.  Take the same approach used in linux-nat.c in this case of
sleeping for a while and then reporting a fake VFORK_DONE event.

gdb/ChangeLog:

	* fbsd-nat.c (struct fbsd_fork_child_info): Rename to ...
	(struct fbsd_fork_info): ... this.
	(struct fbsd_fork_info) <child>: Rename to ...
	(struct fbsd_fork_info) <ptid>: ... this.
	(fbsd_pending_children): Update type.
	(fbsd_remember_child): Update type and field name.
	(fbsd_is_child_pending): Likewise.
	(fbsd_pending_vfork_done): New variable.
	(fbsd_is_vfork_done_pending): New function.
	(fbsd_next_vfork_done): New function.
	(fbsd_resume): Don't resume processes with a pending vfork done
	event.
	(fbsd_wait): Report pending vfork done events.
	(fbsd_follow_fork): Delay and record a pending vfork done event
	for a vfork parent when detaching the child.
---
 gdb/ChangeLog  |  18 ++++++++++
 gdb/fbsd-nat.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 119 insertions(+), 9 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 09b75a5..0ea329a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,23 @@
 2016-06-24  John Baldwin  <jhb@FreeBSD.org>
 
+	* fbsd-nat.c (struct fbsd_fork_child_info): Rename to ...
+	(struct fbsd_fork_info): ... this.
+	(struct fbsd_fork_info) <child>: Rename to ...
+	(struct fbsd_fork_info) <ptid>: ... this.
+	(fbsd_pending_children): Update type.
+	(fbsd_remember_child): Update type and field name.
+	(fbsd_is_child_pending): Likewise.
+	(fbsd_pending_vfork_done): New variable.
+	(fbsd_is_vfork_done_pending): New function.
+	(fbsd_next_vfork_done): New function.
+	(fbsd_resume): Don't resume processes with a pending vfork done
+	event.
+	(fbsd_wait): Report pending vfork done events.
+	(fbsd_follow_fork): Delay and record a pending vfork done event
+	for a vfork parent when detaching the child.
+
+2016-06-24  John Baldwin  <jhb@FreeBSD.org>
+
 	* fbsd-nat.c (super_resume): Move earlier next to "super_wait".
 	(resume_one_thread_cb): Move below fork following helper code.
 	(resume_all_threads_cb): Likewise.
diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c
index 4b2b41a..f1dc743 100644
--- a/gdb/fbsd-nat.c
+++ b/gdb/fbsd-nat.c
@@ -530,13 +530,13 @@ fbsd_update_thread_list (struct target_ops *ops)
   sake.  FreeBSD versions newer than 9.1 contain both fixes.
 */
 
-struct fbsd_fork_child_info
+struct fbsd_fork_info
 {
-  struct fbsd_fork_child_info *next;
-  ptid_t child;			/* Pid of new child.  */
+  struct fbsd_fork_info *next;
+  ptid_t ptid;
 };
 
-static struct fbsd_fork_child_info *fbsd_pending_children;
+static struct fbsd_fork_info *fbsd_pending_children;
 
 /* Record a new child process event that is reported before the
    corresponding fork event in the parent.  */
@@ -544,9 +544,9 @@ static struct fbsd_fork_child_info *fbsd_pending_children;
 static void
 fbsd_remember_child (ptid_t pid)
 {
-  struct fbsd_fork_child_info *info = XCNEW (struct fbsd_fork_child_info);
+  struct fbsd_fork_info *info = XCNEW (struct fbsd_fork_info);
 
-  info->child = pid;
+  info->ptid = pid;
   info->next = fbsd_pending_children;
   fbsd_pending_children = info;
 }
@@ -557,25 +557,74 @@ fbsd_remember_child (ptid_t pid)
 static ptid_t
 fbsd_is_child_pending (pid_t pid)
 {
-  struct fbsd_fork_child_info *info, *prev;
+  struct fbsd_fork_info *info, *prev;
   ptid_t ptid;
 
   prev = NULL;
   for (info = fbsd_pending_children; info; prev = info, info = info->next)
     {
-      if (ptid_get_pid (info->child) == pid)
+      if (ptid_get_pid (info->ptid) == pid)
 	{
 	  if (prev == NULL)
 	    fbsd_pending_children = info->next;
 	  else
 	    prev->next = info->next;
-	  ptid = info->child;
+	  ptid = info->ptid;
 	  xfree (info);
 	  return ptid;
 	}
     }
   return null_ptid;
 }
+
+static struct fbsd_fork_info *fbsd_pending_vfork_done;
+
+/* Record a pending vfork done event.  */
+
+static void
+fbsd_add_vfork_done (ptid_t pid)
+{
+  struct fbsd_fork_info *info = XCNEW (struct fbsd_fork_info);
+
+  info->ptid = pid;
+  info->next = fbsd_pending_vfork_done;
+  fbsd_pending_vfork_done = info;
+}
+
+/* Check for a pending vfork done event for a specific PID.  */
+
+static int
+fbsd_is_vfork_done_pending (pid_t pid)
+{
+  struct fbsd_fork_info *info;
+
+  for (info = fbsd_pending_vfork_done; info != NULL; info = info->next)
+    {
+      if (ptid_get_pid (info->ptid) == pid)
+	return 1;
+    }
+  return 0;
+}
+
+/* Check for a pending vfork done event.  If one is found, remove it
+   from the list and return the PTID.  */
+
+static ptid
+fbsd_next_vfork_done (void)
+{
+  struct fbsd_fork_info *info;
+  ptid_t ptid;
+
+  if (fbsd_pending_vfork_done != NULL)
+    {
+      info = fbsd_pending_vfork_done;
+      fbsd_pending_vfork_done = info->next;
+      ptid = info->ptid;
+      xfree (info);
+      return ptid;
+    }
+  return null_ptid;
+}
 #endif
 
 static int
@@ -616,6 +665,17 @@ static void
 fbsd_resume (struct target_ops *ops,
 	     ptid_t ptid, int step, enum gdb_signal signo)
 {
+#ifdef TDP_RFPPWAIT
+  pid_t pid;
+
+  /* Don't PT_CONTINUE a process which has a pending vfork done event.  */
+  if (ptid_equal (minus_one_ptid, ptid))
+    pid = ptid_get_pid (inferior_ptid);
+  else
+    pid = ptid_get_pid (ptid);
+  if (fbsd_is_vfork_done_pending (pid))
+    return;
+#endif
 
   if (debug_fbsd_lwp)
     fprintf_unfiltered (gdb_stdlog,
@@ -650,6 +710,12 @@ fbsd_wait (struct target_ops *ops,
 
   while (1)
     {
+      wptid = fbsd_next_vfork_done ();
+      if (!ptid_equal (wptid, null_ptid))
+	{
+	  ourstatus->kind = TARGET_WAITKIND_VFORK_DONE;
+	  return wptid;
+	}
       wptid = super_wait (ops, ptid, ourstatus, target_options);
       if (ourstatus->kind == TARGET_WAITKIND_STOPPED)
 	{
@@ -794,6 +860,7 @@ fbsd_follow_fork (struct target_ops *ops, int follow_child,
   if (!follow_child && detach_fork)
     {
       struct thread_info *tp = inferior_thread ();
+      int has_vforked = tp->pending_follow.kind == TARGET_WAITKIND_VFORKED;
       pid_t child_pid = ptid_get_pid (tp->pending_follow.value.related_pid);
 
       /* Breakpoints have already been detached from the child by
@@ -801,6 +868,31 @@ fbsd_follow_fork (struct target_ops *ops, int follow_child,
 
       if (ptrace (PT_DETACH, child_pid, (PTRACE_TYPE_ARG3)1, 0) == -1)
 	perror_with_name (("ptrace"));
+
+      if (has_vforked)
+	{
+	  /* We can't insert breakpoints until the child process has
+	     finished with the shared memory region.  The parent
+	     process doesn't wait for the child process to exit or
+	     exec until after it has been resumed from the ptrace stop
+	     to report the fork.  Once it has been resumed it doesn't
+	     stop again before returning to userland, so there is no
+	     reliable way to wait on the parent.
+
+	     We can't stay attached to the child to wait for an exec
+	     or exit because it may invoke ptrace(PT_TRACE_ME)
+	     (e.g. if the parent process is a debugger forking a new
+	     child process).
+
+	     Take the same approach used in linux-nat.c of just
+	     sleeping and hoping the sleep is long enough.  */
+
+	  usleep (10000);
+
+	  /* Schedule a fake VFORK_DONE event to report on the next
+	     wait.  */
+	  fbsd_add_vfork_done (inferior_ptid);
+	}
     }
 
   return 0;
-- 
2.8.4

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] Fake VFORK_DONE events on FreeBSD
  2016-06-28 23:00 [PATCH 0/3] Fake VFORK_DONE events on FreeBSD John Baldwin
                   ` (2 preceding siblings ...)
  2016-06-28 23:00 ` [PATCH 3/3] Fake VFORK_DONE events when following only the parent after a vfork John Baldwin
@ 2016-07-01 14:07 ` Pedro Alves
  3 siblings, 0 replies; 5+ messages in thread
From: Pedro Alves @ 2016-07-01 14:07 UTC (permalink / raw)
  To: John Baldwin, gdb-patches

On 06/29/2016 12:00 AM, John Baldwin wrote:
> The FreeBSD native targets do not report a VFORK_DONE event at
> all currently.  FreeBSD's ptrace doesn't currently report an event
> when the vfork parent resumes, so this fixes the native targets to
> report a fake event after a sleep similar to the approach used on
> Linux.  While here I noticed that I botched the 'detach_fork' support
> in the original fork tracing patches, so I fixed that as well.
> 
> I am working on adding a new ptrace event to report a real vfork
> done event to FreeBSD.  Once that is merged to FreeBSD I will post
> a patch for gdb to use that when available instead.

LGTM.

- There's a tiny typo in the commit log of patch 1: "true.x".

- I suggest removing the reference to linux-nat.c in the comment in
  patch #3, because that workaround may be removed soon.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-07-01 14:07 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-28 23:00 [PATCH 0/3] Fake VFORK_DONE events on FreeBSD John Baldwin
2016-06-28 23:00 ` [PATCH 1/3] Honor detach-on-fork " John Baldwin
2016-06-28 23:00 ` [PATCH 2/3] Move fbsd_resume and related functions below fork following helper code John Baldwin
2016-06-28 23:00 ` [PATCH 3/3] Fake VFORK_DONE events when following only the parent after a vfork John Baldwin
2016-07-01 14:07 ` [PATCH 0/3] Fake VFORK_DONE events on FreeBSD Pedro Alves

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).