Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Cc: Sergio Durigan Junior <sergiodj@redhat.com>, gdb-patches@sourceware.org
Subject: Always run the PTRACE_O_TRACESYSGOOD tests even if PTRACE_O_TRACEFORK is not supported. (was: Re: RFA [PATCH v4] Implement 'catch syscall' for gdbserver)
Date: Wed, 02 Oct 2013 19:41:00 -0000	[thread overview]
Message-ID: <524C76D4.1010301@redhat.com> (raw)
In-Reply-To: <1380467062.3567.52.camel@soleil>

On 09/29/2013 04:04 PM, Philippe Waroquiers wrote:

> Index: common/linux-ptrace.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/common/linux-ptrace.c,v
> retrieving revision 1.12
> diff -u -p -r1.12 linux-ptrace.c
> --- common/linux-ptrace.c	28 Aug 2013 14:09:31 -0000	1.12
> +++ common/linux-ptrace.c	29 Sep 2013 14:20:29 -0000
> @@ -361,16 +361,18 @@ linux_check_ptrace_features (void)
>        return;
>      }
>  
> -#ifdef GDBSERVER
> -  /* gdbserver does not support PTRACE_O_TRACESYSGOOD or
> -     PTRACE_O_TRACEVFORKDONE yet.  */
> -#else
> -  /* Check if the target supports PTRACE_O_TRACESYSGOOD.  */
> +  /* Check if the target supports PTRACE_O_TRACESYSGOOD.
> +     We keep PTRACE_O_TRACEFORK option activated as a fork
> +     event notification is expected after my_waitpid below.  */
>    ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
> -		(PTRACE_TYPE_ARG4) PTRACE_O_TRACESYSGOOD);
> +		(PTRACE_TYPE_ARG4) (PTRACE_O_TRACEFORK
> +				    | PTRACE_O_TRACESYSGOOD));

This coupling looks unfortunate.  Actually why wasn't this a
problem for the native target, even without GDBserver in the picture?
It just looks like a bug fix?  

In any case, there's another related bug here.  Above that we have:

  /* First, set the PTRACE_O_TRACEFORK option.  If this fails, we
     know for sure that it is not supported.  */
  ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
		(PTRACE_TYPE_ARG4) PTRACE_O_TRACEFORK);

  if (ret != 0)
    {
      ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0,
		    (PTRACE_TYPE_ARG4) 0);
      if (ret != 0)
	{
	  warning (_("linux_check_ptrace_features: failed to kill child"));
	  return;
	}

      ret = my_waitpid (child_pid, &status, 0);
      if (ret != child_pid)
	warning (_("linux_check_ptrace_features: failed "
		   "to wait for killed child"));
      else if (!WIFSIGNALED (status))
	warning (_("linux_check_ptrace_features: unexpected "
		   "wait status 0x%x from killed child"), status);

      return; <<<<<<<<<<<<<<<<<
    }

Note that early return.  If PTRACE_O_TRACEFORK isn't supported,
we're not checking PTRACE_O_TRACESYSGOOD.  This didn't use to be
a problem before the unification of this whole detection business
in linux-ptrace.c.  Before, the sysgood detection was
completely separate:

static void
linux_test_for_tracesysgood (int original_pid)
{
  int ret;
  sigset_t prev_mask;

  /* We don't want those ptrace calls to be interrupted.  */
  block_child_signals (&prev_mask);

  linux_supports_tracesysgood_flag = 0;

  ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACESYSGOOD);
  if (ret != 0)
    goto out;

  linux_supports_tracesysgood_flag = 1;
out:
  restore_child_signals_mask (&prev_mask);
}

Here's a patch that fixes these issues.
---- 
Subject: Always run the PTRACE_O_TRACESYSGOOD tests even if PTRACE_O_TRACEFORK is not supported.

If enabling PTRACE_O_TRACEFORK fails, we never test for
PTRACE_O_TRACESYSGOOD support.  Before PTRACE_O_TRACESYSGOOD is checked,
we have:

  /* First, set the PTRACE_O_TRACEFORK option.  If this fails, we
     know for sure that it is not supported.  */
  ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
		(PTRACE_TYPE_ARG4) PTRACE_O_TRACEFORK);

  if (ret != 0)
    {
      ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0,
		    (PTRACE_TYPE_ARG4) 0);
      if (ret != 0)
	{
	  warning (_("linux_check_ptrace_features: failed to kill child"));
	  return;
	}

      ret = my_waitpid (child_pid, &status, 0);
      if (ret != child_pid)
	warning (_("linux_check_ptrace_features: failed "
		   "to wait for killed child"));
      else if (!WIFSIGNALED (status))
	warning (_("linux_check_ptrace_features: unexpected "
		   "wait status 0x%x from killed child"), status);

      return; <<<<<<<<<<<<<<<<<
    }

Note that early return.  If PTRACE_O_TRACEFORK isn't supported, we're
not checking PTRACE_O_TRACESYSGOOD.  This didn't use to be a problem
before the unification of this whole detection business in
linux-ptrace.c.  Before, the sysgood detection was completely
separate:

static void
linux_test_for_tracesysgood (int original_pid)
{
  int ret;
  sigset_t prev_mask;

  /* We don't want those ptrace calls to be interrupted.  */
  block_child_signals (&prev_mask);

  linux_supports_tracesysgood_flag = 0;

  ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACESYSGOOD);
  if (ret != 0)
    goto out;

  linux_supports_tracesysgood_flag = 1;
out:
  restore_child_signals_mask (&prev_mask);
}

So we need to get back the decoupling somehow.  I think it's cleaner
to split the seperate feature detections to separate functions.  This
patch does that.  The new functions are named for their counterparts
that existed before this code was moved to linux-ptrace.c.

Note I've used forward declarations for the new functions to make the
patch clearer, as otherwise the patch would look like I'd be adding a
bunch of new code.  A reorder can be done in a follow up patch.

Tested on x86_64 Fedora 17.

gdb/
2013-10-02  Pedro Alves  <palves@redhat.com>

	* common/linux-ptrace.c (linux_check_ptrace_features): Factor out
	the PTRACE_O_TRACESYSGOOD and PTRACE_O_TRACEFORK to separate
	functions.  Always test for PTRACE_O_TRACESYSGOOD even if
	PTRACE_O_TRACEFORK is not supported.
	(linux_test_for_tracesysgood): New function.
	(linux_test_for_tracefork): New function, factored out from
	linux_check_ptrace_features, and also don't kill child_pid here.
---

 gdb/common/linux-ptrace.c |   75 +++++++++++++++++++++++++--------------------
 1 file changed, 42 insertions(+), 33 deletions(-)

diff --git a/gdb/common/linux-ptrace.c b/gdb/common/linux-ptrace.c
index 3a8e25e..3ea2d6d 100644
--- a/gdb/common/linux-ptrace.c
+++ b/gdb/common/linux-ptrace.c
@@ -308,13 +308,15 @@ linux_child_function (gdb_byte *child_stack)
   _exit (0);
 }
 
+static void linux_test_for_tracesysgood (int child_pid);
+static void linux_test_for_tracefork (int child_pid);
+
 /* Determine ptrace features available on this target.  */
 
 static void
 linux_check_ptrace_features (void)
 {
   int child_pid, ret, status;
-  long second_pid;
 
   /* Initialize the options.  */
   current_ptrace_options = 0;
@@ -335,42 +337,60 @@ linux_check_ptrace_features (void)
     error (_("linux_check_ptrace_features: waitpid: unexpected status %d."),
 	   status);
 
-  /* First, set the PTRACE_O_TRACEFORK option.  If this fails, we
-     know for sure that it is not supported.  */
-  ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
-		(PTRACE_TYPE_ARG4) PTRACE_O_TRACEFORK);
+  linux_test_for_tracesysgood (child_pid);
 
-  if (ret != 0)
+  linux_test_for_tracefork (child_pid);
+
+  /* Clean things up and kill any pending children.  */
+  do
     {
       ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0,
 		    (PTRACE_TYPE_ARG4) 0);
       if (ret != 0)
-	{
-	  warning (_("linux_check_ptrace_features: failed to kill child"));
-	  return;
-	}
-
-      ret = my_waitpid (child_pid, &status, 0);
-      if (ret != child_pid)
-	warning (_("linux_check_ptrace_features: failed "
-		   "to wait for killed child"));
-      else if (!WIFSIGNALED (status))
-	warning (_("linux_check_ptrace_features: unexpected "
-		   "wait status 0x%x from killed child"), status);
-
-      return;
+	warning (_("linux_check_ptrace_features: failed to kill child"));
+      my_waitpid (child_pid, &status, 0);
     }
+  while (WIFSTOPPED (status));
+}
 
+/* Determine if PTRACE_O_TRACESYSGOOD can be used to catch
+   syscalls.  */
+
+static void
+linux_test_for_tracesysgood (int child_pid)
+{
 #ifdef GDBSERVER
-  /* gdbserver does not support PTRACE_O_TRACESYSGOOD or
-     PTRACE_O_TRACEVFORKDONE yet.  */
+  /* gdbserver does not support PTRACE_O_TRACESYSGOOD.  */
 #else
+  int ret;
   /* Check if the target supports PTRACE_O_TRACESYSGOOD.  */
   ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
 		(PTRACE_TYPE_ARG4) PTRACE_O_TRACESYSGOOD);
   if (ret == 0)
     current_ptrace_options |= PTRACE_O_TRACESYSGOOD;
+#endif
+}
+
+/* Determine if PTRACE_O_TRACEFORK can be used to follow fork
+   events.  */
 
+static void
+linux_test_for_tracefork (int child_pid)
+{
+  int ret, status;
+  long second_pid;
+
+  /* First, set the PTRACE_O_TRACEFORK option.  If this fails, we
+     know for sure that it is not supported.  */
+  ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
+		(PTRACE_TYPE_ARG4) PTRACE_O_TRACEFORK);
+
+  if (ret != 0)
+    return;
+
+#ifdef GDBSERVER
+  /* gdbserver does not support PTRACE_O_TRACEVFORKDONE yet.  */
+#else
   /* Check if the target supports PTRACE_O_TRACEVFORKDONE.  */
   ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
 		(PTRACE_TYPE_ARG4) (PTRACE_O_TRACEFORK
@@ -439,17 +459,6 @@ linux_check_ptrace_features (void)
   else
     warning (_("linux_check_ptrace_features: unexpected result from waitpid "
 	     "(%d, status 0x%x)"), ret, status);
-
-  /* Clean things up and kill any pending children.  */
-  do
-    {
-      ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0,
-		    (PTRACE_TYPE_ARG4) 0);
-      if (ret != 0)
-	warning (_("linux_check_ptrace_features: failed to kill child"));
-      my_waitpid (child_pid, &status, 0);
-    }
-  while (WIFSTOPPED (status));
 }
 
 /* Enable reporting of all currently supported ptrace events.  */


  parent reply	other threads:[~2013-10-02 19:41 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-21 20:55 RFA [PATCH v3] Implement 'catch syscall' for gdbserver Philippe Waroquiers
2013-09-21 21:03 ` Eli Zaretskii
2013-09-23 11:51 ` Agovic, Sanimir
2013-09-23 19:32   ` Philippe Waroquiers
2013-09-24  7:07     ` Agovic, Sanimir
2013-09-25 16:55       ` Sergio Durigan Junior
2013-09-25 22:55         ` Philippe Waroquiers
2013-09-27 13:25 ` [COMMIT PATCH] remote.c: Remove unnecessary fields from 'struct stop_reply'. (was: Re: RFA [PATCH v3] Implement 'catch syscall' for gdbserver) Pedro Alves
2013-09-27 19:30 ` RFA [PATCH v3] Implement 'catch syscall' for gdbserver Pedro Alves
2013-09-27 20:13   ` Philippe Waroquiers
2013-09-27 20:55 ` Sergio Durigan Junior
2013-09-29 15:04   ` RFA [PATCH v4] Implement 'catch syscall' for gdbserver (was Re: RFA [PATCH v3] Implement 'catch syscall' for gdbserver) Philippe Waroquiers
2013-10-01  5:16     ` Sergio Durigan Junior
2013-10-02 21:02       ` Sergio Durigan Junior
2013-10-02 19:41     ` Pedro Alves [this message]
2013-10-02 22:08       ` Always run the PTRACE_O_TRACESYSGOOD tests even if PTRACE_O_TRACEFORK is not supported. (was: Re: RFA [PATCH v4] " Philippe Waroquiers
2013-10-03 10:16         ` Always run the PTRACE_O_TRACESYSGOOD tests even if PTRACE_O_TRACEFORK is not supported Pedro Alves
2013-10-03 18:40     ` RFA [PATCH v4] Implement 'catch syscall' for gdbserver (was Re: RFA [PATCH v3] Implement 'catch syscall' for gdbserver) Pedro Alves
2013-10-03 19:53       ` Tom Tromey
2013-10-04 17:41         ` Pedro Alves
2013-10-03 22:02       ` Philippe Waroquiers
2013-10-04 17:29         ` Pedro Alves
2013-10-05  9:15           ` Pedro Alves
2013-10-09 21:54             ` Philippe Waroquiers
2013-10-09 22:05               ` Sergio Durigan Junior
2013-10-09 22:09                 ` Philippe Waroquiers
2013-10-04  4:22     ` Luis Machado
2013-10-04 17:40       ` Pedro Alves
2013-10-04 18:55         ` Stan Shebs
2013-10-07 19:07           ` 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=524C76D4.1010301@redhat.com \
    --to=palves@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=philippe.waroquiers@skynet.be \
    --cc=sergiodj@redhat.com \
    /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