Unify ptrace options discovery code and make both GDB and
authorLuis Machado <luisgpm@br.ibm.com>
Thu, 22 Aug 2013 23:46:30 +0000 (23:46 +0000)
committerLuis Machado <luisgpm@br.ibm.com>
Thu, 22 Aug 2013 23:46:30 +0000 (23:46 +0000)
gdbserver use it.

gdb/
* Makefile.in (HFILES_NO_SRCDIR): Add nat/linux-nat.h and
nat/linux-waitpid.h.
(linux-waitpid.o): New object file rule.
* common/linux-ptrace.c: Include nat/linux-waitpid.h.
(current_ptrace_options): Moved from linux-nat.c.
(linux_ptrace_test_ret_to_nx): Use type casts for ptrace
parameters.
(linux_fork_to_function): New function.
(linux_grandchild_function): Likewise.
(linux_child_function): Likewise.
(linux_check_ptrace_features): New function, heavily
based on linux-nat.c:linux_test_for_tracefork.
(linux_enable_event_reporting): New function.
(ptrace_supports_feature): Likewise.
(linux_supports_tracefork): Likewise.
(linux_supports_traceclone): Likewise.
(linux_supports_tracevforkdone): Likewise.
(linux_supports_tracesysgood): Likewise.
* common/linux-ptrace.h (HAS_NOMMU): Moved from
gdbserver/linux-low.c.
(linux_enable_event_reporting): New declaration.
(linux_supports_tracefork): Likewise.
(linux_supports_traceclone): Likewise.
(linux_supports_tracevforkdone): Likewise.
(linux_supports_tracesysgood): Likewise.
* config.in (PTRACE_TYPE_ARG4): Regenerate.
* config/aarch64/linux.mh (NATDEPFILES): Add linux-waitpid.o.
* config/alpha/alpha-linux.mh (NATDEPFILES): Likewise.
* config/arm/linux.mh (NATDEPFILES): Likewise.
* config/i386/linux.mh (NATDEPFILES): Likewise.
* config/i386/linux64.mh (NATDEPFILES): Likewise.
* config/ia64/linux.mh (NATDEPFILES): Likewise.
* config/m32r/linux.mh (NATDEPFILES): Likewise.
* config/m68k/linux.mh (NATDEPFILES): Likewise.
* config/mips/linux.mh (NATDEPFILES): Likewise.
* config/pa/linux.mh (NATDEPFILES): Likewise..
* config/powerpc/linux.mh (NATDEPFILES): Likewise..
* config/powerpc/ppc64-linux.mh (NATDEPFILES): Likewise.
* config/powerpc/spu-linux.mh (NATDEPFILES): Likewise.
* config/sparc/linux.mh (NATDEPFILES): Likewise.
* config/sparc/linux64.mh (NATDEPFILES): Likewise.
* config/tilegx/linux.mh (NATDEPFILES): Likewise.
* config/xtensa/linux.mh (NATDEPFILES): Likewise.
* configure.ac (AC_CACHE_CHECK): Add void * to the list of
ptrace's 4th argument's types.
Check the type of PTRACE_TYPE_ARG4.
* configure: Regenerate.
* linux-nat.c: Include nat/linux-nat.h and nat/linux-waitpid.h.
(SYSCALL_SIGTRAP): Moved to nat/linux-nat.h.
(linux_supports_tracefork_flag): Remove.
(linux_supports_tracesysgood_flag): Likewise.
(linux_supports_tracevforkdone_flag): Likewise.
(current_ptrace_options): Moved to
common/linux-ptrace.c.
(linux_tracefork_child): Remove.
(my_waitpid): Remove.
(linux_test_for_tracefork): Renamed to
linux_check_ptrace_features and moved to common/linux-ptrace.c.
(linux_test_for_tracesysgood): Remove.
(linux_supports_tracesysgood): Remove.
(linux_supports_tracefork): Remove.
(linux_supports_tracevforkdone): Remove.
(linux_enable_tracesysgood): Remove.
(linux_enable_event_reporting): Remove.
(linux_init_ptrace): New function.
(linux_child_post_attach): Call linux_init_ptrace.
(linux_child_post_startup_inferior): Call linux_init_ptrace.
(linux_child_follow_fork): Call linux_supports_tracefork
and linux_supports_tracevforkdone.
(linux_child_insert_fork_catchpoint): Call
linux_supports_tracefork.
(linux_child_insert_vfork_catchpoint): Likewise.
(linux_child_set_syscall_catchpoint): Call
linux_supports_tracesysgood.
(lin_lwp_attach_lwp): Call linux_supports_tracefork.
* nat/linux-nat.h: New file.
* nat/linux-waitpid.c: New file.
* nat/linux-waitpid.h: New file.

gdb/gdbserver/
* Makefile.in: Explain why ../target and ../nat are not
listed as include file search paths.
(linux-waitpid.o): New object file rule.
* configure.srv (srv_native_linux_obj): New variable.
Replace all occurrences of linux native object files with
$srv_native_linux_obj.
* linux-low.c: Include nat/linux-nat.h and nat/linux-waitpid.h.
(HAS_NOMMU): Move defining logic to common/linux-ptrace.c.
(linux_enable_event_reporting): Remove declaration.
(my_waitpid): Moved to common/linux-waitpid.c.
(linux_wait_for_event): Pass ptid when calling
linux_enable_event_reporting.
(linux_supports_tracefork_flag): Remove.
(linux_enable_event_reporting): Likewise.
(linux_tracefork_grandchild): Remove.
(STACK_SIZE): Moved to common/linux-ptrace.c.
(linux_tracefork_child): Remove.
(linux_test_for_tracefork): Remove.
(linux_look_up_symbols): Call linux_supports_traceclone.
(initialize_low): Remove call to linux_test_for_tracefork.
* linux-low.h (PTRACE_TYPE_ARG3): Move to
common/linux-ptrace.h.
(PTRACE_TYPE_ARG4): Likewise.
Include linux-ptrace.h.

34 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/common/linux-ptrace.c
gdb/common/linux-ptrace.h
gdb/config.in
gdb/config/aarch64/linux.mh
gdb/config/alpha/alpha-linux.mh
gdb/config/arm/linux.mh
gdb/config/i386/linux.mh
gdb/config/i386/linux64.mh
gdb/config/ia64/linux.mh
gdb/config/m32r/linux.mh
gdb/config/m68k/linux.mh
gdb/config/mips/linux.mh
gdb/config/pa/linux.mh
gdb/config/powerpc/linux.mh
gdb/config/powerpc/ppc64-linux.mh
gdb/config/powerpc/spu-linux.mh
gdb/config/sparc/linux.mh
gdb/config/sparc/linux64.mh
gdb/config/tilegx/linux.mh
gdb/config/xtensa/linux.mh
gdb/configure
gdb/configure.ac
gdb/gdbserver/ChangeLog
gdb/gdbserver/Makefile.in
gdb/gdbserver/configure.srv
gdb/gdbserver/linux-low.c
gdb/gdbserver/linux-low.h
gdb/linux-nat.c
gdb/linux-nat.h
gdb/nat/linux-nat.h [new file with mode: 0644]
gdb/nat/linux-waitpid.c [new file with mode: 0644]
gdb/nat/linux-waitpid.h [new file with mode: 0644]

index 8d939d96e551411aee36e4ca1f965cabd784f751..de6a83500e5c71bbb2b3c67bbdd566c2b0f1d0bf 100644 (file)
@@ -1,3 +1,84 @@
+2013-08-22  Luis Machado  <lgustavo@codesourcery.com>
+
+       * Makefile.in (HFILES_NO_SRCDIR): Add nat/linux-nat.h and
+       nat/linux-waitpid.h.
+       (linux-waitpid.o): New object file rule.
+       * common/linux-ptrace.c: Include nat/linux-waitpid.h.
+       (current_ptrace_options): Moved from linux-nat.c.
+       (linux_ptrace_test_ret_to_nx): Use type casts for ptrace
+       parameters.
+       (linux_fork_to_function): New function.
+       (linux_grandchild_function): Likewise.
+       (linux_child_function): Likewise.
+       (linux_check_ptrace_features): New function, heavily
+       based on linux-nat.c:linux_test_for_tracefork.
+       (linux_enable_event_reporting): New function.
+       (ptrace_supports_feature): Likewise.
+       (linux_supports_tracefork): Likewise.
+       (linux_supports_traceclone): Likewise.
+       (linux_supports_tracevforkdone): Likewise.
+       (linux_supports_tracesysgood): Likewise.
+       * common/linux-ptrace.h (HAS_NOMMU): Moved from
+       gdbserver/linux-low.c.
+       (linux_enable_event_reporting): New declaration.
+       (linux_supports_tracefork): Likewise.
+       (linux_supports_traceclone): Likewise.
+       (linux_supports_tracevforkdone): Likewise.
+       (linux_supports_tracesysgood): Likewise.
+       * config.in (PTRACE_TYPE_ARG4): Regenerate.
+       * config/aarch64/linux.mh (NATDEPFILES): Add linux-waitpid.o.
+       * config/alpha/alpha-linux.mh (NATDEPFILES): Likewise.
+       * config/arm/linux.mh (NATDEPFILES): Likewise.
+       * config/i386/linux.mh (NATDEPFILES): Likewise.
+       * config/i386/linux64.mh (NATDEPFILES): Likewise.
+       * config/ia64/linux.mh (NATDEPFILES): Likewise.
+       * config/m32r/linux.mh (NATDEPFILES): Likewise.
+       * config/m68k/linux.mh (NATDEPFILES): Likewise.
+       * config/mips/linux.mh (NATDEPFILES): Likewise.
+       * config/pa/linux.mh (NATDEPFILES): Likewise..
+       * config/powerpc/linux.mh (NATDEPFILES): Likewise..
+       * config/powerpc/ppc64-linux.mh (NATDEPFILES): Likewise.
+       * config/powerpc/spu-linux.mh (NATDEPFILES): Likewise.
+       * config/sparc/linux.mh (NATDEPFILES): Likewise.
+       * config/sparc/linux64.mh (NATDEPFILES): Likewise.
+       * config/tilegx/linux.mh (NATDEPFILES): Likewise.
+       * config/xtensa/linux.mh (NATDEPFILES): Likewise.
+       * configure.ac (AC_CACHE_CHECK): Add void * to the list of
+       ptrace's 4th argument's types.
+       Check the type of PTRACE_TYPE_ARG4.
+       * configure: Regenerate.
+       * linux-nat.c: Include nat/linux-nat.h and nat/linux-waitpid.h.
+       (SYSCALL_SIGTRAP): Moved to nat/linux-nat.h.
+       (linux_supports_tracefork_flag): Remove.
+       (linux_supports_tracesysgood_flag): Likewise.
+       (linux_supports_tracevforkdone_flag): Likewise.
+       (current_ptrace_options): Moved to
+       common/linux-ptrace.c.
+       (linux_tracefork_child): Remove.
+       (my_waitpid): Remove.
+       (linux_test_for_tracefork): Renamed to
+       linux_check_ptrace_features and moved to common/linux-ptrace.c.
+       (linux_test_for_tracesysgood): Remove.
+       (linux_supports_tracesysgood): Remove.
+       (linux_supports_tracefork): Remove.
+       (linux_supports_tracevforkdone): Remove.
+       (linux_enable_tracesysgood): Remove.
+       (linux_enable_event_reporting): Remove.
+       (linux_init_ptrace): New function.
+       (linux_child_post_attach): Call linux_init_ptrace.
+       (linux_child_post_startup_inferior): Call linux_init_ptrace.
+       (linux_child_follow_fork): Call linux_supports_tracefork
+       and linux_supports_tracevforkdone.
+       (linux_child_insert_fork_catchpoint): Call
+       linux_supports_tracefork.
+       (linux_child_insert_vfork_catchpoint): Likewise.
+       (linux_child_set_syscall_catchpoint): Call
+       linux_supports_tracesysgood.
+       (lin_lwp_attach_lwp): Call linux_supports_tracefork.
+       * nat/linux-nat.h: New file.
+       * nat/linux-waitpid.c: New file.
+       * nat/linux-waitpid.h: New file.
+
 2013-08-22  Samuel Bronson  <naesten@gmail.com>
 
        ARM Linux support for `catch syscall'.
index 45cddafa3c40c28aa8012889ce35adb3ab0eb86e..c75ec38bd4162f2b28f34410f4b3328a8d473bb3 100644 (file)
@@ -855,7 +855,7 @@ common/format.h common/host-defs.h utils.h common/queue.h common/gdb_string.h \
 common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \
 gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h common/linux-btrace.h \
 ctf.h common/i386-cpuid.h common/i386-gcc-cpuid.h target/resume.h \
-target/wait.h target/waitstatus.h
+target/wait.h target/waitstatus.h nat/linux-nat.h nat/linux-waitpid.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -2037,6 +2037,15 @@ waitstatus.o: ${srcdir}/target/waitstatus.c
        $(COMPILE) $(srcdir)/target/waitstatus.c
        $(POSTCOMPILE)
 
+# gdb/nat/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+linux-waitpid.o: ${srcdir}/nat/linux-waitpid.c
+       $(COMPILE) $(srcdir)/nat/linux-waitpid.c
+       $(POSTCOMPILE)
+
 #
 # gdb/tui/ dependencies
 #
index d5ac061ccb7861fd26a8025da124088e2ee881e0..c4808ab0776afd4b8a4832315854351a9909c306 100644 (file)
 
 #include "linux-ptrace.h"
 #include "linux-procfs.h"
+#include "nat/linux-waitpid.h"
 #include "buffer.h"
 #include "gdb_assert.h"
 #include "gdb_wait.h"
 
+/* Stores the currently supported ptrace options.  A value of
+   -1 means we did not check for features yet.  A value of 0 means
+   there are no supported features.  */
+static int current_ptrace_options = -1;
+
 /* Find all possible reasons we could fail to attach PID and append these
    newline terminated reason strings to initialized BUFFER.  '\0' termination
    of BUFFER must be done by the caller.  */
@@ -97,7 +103,8 @@ linux_ptrace_test_ret_to_nx (void)
       return;
 
     case 0:
-      l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
+      l = ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) NULL,
+                 (PTRACE_TYPE_ARG4) NULL);
       if (l != 0)
        warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_TRACEME: %s"),
                 strerror (errno));
@@ -163,9 +170,11 @@ linux_ptrace_test_ret_to_nx (void)
 
   errno = 0;
 #if defined __i386__
-  l = ptrace (PTRACE_PEEKUSER, child, (void *) (uintptr_t) (EIP * 4), NULL);
+  l = ptrace (PTRACE_PEEKUSER, child, (PTRACE_TYPE_ARG3) (uintptr_t) (EIP * 4),
+             (PTRACE_TYPE_ARG4) NULL);
 #elif defined __x86_64__
-  l = ptrace (PTRACE_PEEKUSER, child, (void *) (uintptr_t) (RIP * 8), NULL);
+  l = ptrace (PTRACE_PEEKUSER, child, (PTRACE_TYPE_ARG3) (uintptr_t) (RIP * 8),
+             (PTRACE_TYPE_ARG4) NULL);
 #else
 # error "!__i386__ && !__x86_64__"
 #endif
@@ -178,7 +187,8 @@ linux_ptrace_test_ret_to_nx (void)
   pc = (void *) (uintptr_t) l;
 
   kill (child, SIGKILL);
-  ptrace (PTRACE_KILL, child, NULL, NULL);
+  ptrace (PTRACE_KILL, child, (PTRACE_TYPE_ARG3) NULL,
+         (PTRACE_TYPE_ARG4) NULL);
 
   errno = 0;
   got_pid = waitpid (child, &kill_status, 0);
@@ -222,6 +232,292 @@ linux_ptrace_test_ret_to_nx (void)
 #endif /* defined __i386__ || defined __x86_64__ */
 }
 
+/* Helper function to fork a process and make the child process call
+   the function FUNCTION, passing CHILD_STACK as parameter.
+
+   For MMU-less targets, clone is used instead of fork, and
+   CHILD_STACK is used as stack space for the cloned child.  If NULL,
+   stack space is allocated via malloc (and subsequently passed to
+   FUNCTION).  For MMU targets, CHILD_STACK is ignored.  */
+
+static int
+linux_fork_to_function (gdb_byte *child_stack, void (*function) (gdb_byte *))
+{
+  int child_pid;
+
+  /* Sanity check the function pointer.  */
+  gdb_assert (function != NULL);
+
+#if defined(__UCLIBC__) && defined(HAS_NOMMU)
+#define STACK_SIZE 4096
+
+    if (child_stack == NULL)
+      child_stack = xmalloc (STACK_SIZE * 4);
+
+    /* Use CLONE_VM instead of fork, to support uClinux (no MMU).  */
+    #ifdef __ia64__
+      child_pid = __clone2 (function, child_stack, STACK_SIZE,
+                           CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
+    #else /* !__ia64__ */
+      child_pid = clone (function, child_stack + STACK_SIZE,
+                        CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
+  #endif /* !__ia64__ */
+#else /* !defined(__UCLIBC) && defined(HAS_NOMMU) */
+  child_pid = fork ();
+
+  if (child_pid == 0)
+    function (NULL);
+#endif /* defined(__UCLIBC) && defined(HAS_NOMMU) */
+
+  if (child_pid == -1)
+    perror_with_name (("fork"));
+
+  return child_pid;
+}
+
+/* A helper function for linux_check_ptrace_features, called after
+   the child forks a grandchild.  */
+
+static void
+linux_grandchild_function (gdb_byte *child_stack)
+{
+  /* Free any allocated stack.  */
+  xfree (child_stack);
+
+  /* This code is only reacheable by the grandchild (child's child)
+     process.  */
+  _exit (0);
+}
+
+/* A helper function for linux_check_ptrace_features, called after
+   the parent process forks a child.  The child allows itself to
+   be traced by its parent.  */
+
+static void
+linux_child_function (gdb_byte *child_stack)
+{
+  ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0);
+  kill (getpid (), SIGSTOP);
+
+  /* Fork a grandchild.  */
+  linux_fork_to_function (child_stack, linux_grandchild_function);
+
+  /* This code is only reacheable by the child (grandchild's parent)
+     process.  */
+  _exit (0);
+}
+
+/* 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;
+
+  /* Fork a child so we can do some testing.  The child will call
+     linux_child_function and will get traced.  The child will
+     eventually fork a grandchild so we can test fork event
+     reporting.  */
+  child_pid = linux_fork_to_function (NULL, linux_child_function);
+
+  ret = my_waitpid (child_pid, &status, 0);
+  if (ret == -1)
+    perror_with_name (("waitpid"));
+  else if (ret != child_pid)
+    error (_("linux_check_ptrace_features: waitpid: unexpected result %d."),
+          ret);
+  if (! WIFSTOPPED (status))
+    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);
+
+  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;
+    }
+
+#ifdef GDBSERVER
+  /* gdbserver does not support PTRACE_O_TRACESYSGOOD or
+     PTRACE_O_TRACEVFORKDONE yet.  */
+#else
+  /* 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;
+
+  /* Check if the target supports PTRACE_O_TRACEVFORKDONE.  */
+  ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
+               (PTRACE_TYPE_ARG4) (PTRACE_O_TRACEFORK
+                                   | PTRACE_O_TRACEVFORKDONE));
+  if (ret == 0)
+    current_ptrace_options |= PTRACE_O_TRACEVFORKDONE;
+#endif
+
+  /* Setting PTRACE_O_TRACEFORK did not cause an error, however we
+     don't know for sure that the feature is available; old
+     versions of PTRACE_SETOPTIONS ignored unknown options.
+     Therefore, we attach to the child process, use PTRACE_SETOPTIONS
+     to enable fork tracing, and let it fork.  If the process exits,
+     we assume that we can't use PTRACE_O_TRACEFORK; if we get the
+     fork notification, and we can extract the new child's PID, then
+     we assume that we can.
+
+     We do not explicitly check for vfork tracing here.  It is
+     assumed that vfork tracing is available whenever fork tracing
+     is available.  */
+  ret = ptrace (PTRACE_CONT, child_pid, (PTRACE_TYPE_ARG3) 0,
+               (PTRACE_TYPE_ARG4) 0);
+  if (ret != 0)
+    warning (_("linux_check_ptrace_features: failed to resume child"));
+
+  ret = my_waitpid (child_pid, &status, 0);
+
+  /* Check if we received a fork event notification.  */
+  if (ret == child_pid && WIFSTOPPED (status)
+      && status >> 16 == PTRACE_EVENT_FORK)
+    {
+      /* We did receive a fork event notification.  Make sure its PID
+        is reported.  */
+      second_pid = 0;
+      ret = ptrace (PTRACE_GETEVENTMSG, child_pid, (PTRACE_TYPE_ARG3) 0,
+                   (PTRACE_TYPE_ARG4) &second_pid);
+      if (ret == 0 && second_pid != 0)
+       {
+         int second_status;
+
+         /* We got the PID from the grandchild, which means fork
+            tracing is supported.  */
+#ifdef GDBSERVER
+         /* Do not enable all the options for now since gdbserver does not
+            properly support them.  This restriction will be lifted when
+            gdbserver is augmented to support them.  */
+         current_ptrace_options |= PTRACE_O_TRACECLONE;
+#else
+         current_ptrace_options |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK
+           | PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXEC;
+
+         /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to
+            support read-only process state.  */
+#endif
+
+         /* Do some cleanup and kill the grandchild.  */
+         my_waitpid (second_pid, &second_status, 0);
+         ret = ptrace (PTRACE_KILL, second_pid, (PTRACE_TYPE_ARG3) 0,
+                       (PTRACE_TYPE_ARG4) 0);
+         if (ret != 0)
+           warning (_("linux_check_ptrace_features: "
+                      "failed to kill second child"));
+         my_waitpid (second_pid, &status, 0);
+       }
+    }
+  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.  */
+
+void
+linux_enable_event_reporting (pid_t pid)
+{
+  /* Check if we have initialized the ptrace features for this
+     target.  If not, do it now.  */
+  if (current_ptrace_options == -1)
+    linux_check_ptrace_features ();
+
+  /* Set the options.  */
+  ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0,
+         (PTRACE_TYPE_ARG4) (uintptr_t) current_ptrace_options);
+}
+
+/* Returns non-zero if PTRACE_OPTIONS is contained within
+   CURRENT_PTRACE_OPTIONS, therefore supported.  Returns 0
+   otherwise.  */
+
+static int
+ptrace_supports_feature (int ptrace_options)
+{
+  gdb_assert (current_ptrace_options >= 0);
+
+  return ((current_ptrace_options & ptrace_options) == ptrace_options);
+}
+
+/* Returns non-zero if PTRACE_EVENT_FORK is supported by ptrace,
+   0 otherwise.  Note that if PTRACE_EVENT_FORK is supported so is
+   PTRACE_EVENT_CLONE, PTRACE_EVENT_EXEC and PTRACE_EVENT_VFORK,
+   since they were all added to the kernel at the same time.  */
+
+int
+linux_supports_tracefork (void)
+{
+  return ptrace_supports_feature (PTRACE_O_TRACEFORK);
+}
+
+/* Returns non-zero if PTRACE_EVENT_CLONE is supported by ptrace,
+   0 otherwise.  Note that if PTRACE_EVENT_CLONE is supported so is
+   PTRACE_EVENT_FORK, PTRACE_EVENT_EXEC and PTRACE_EVENT_VFORK,
+   since they were all added to the kernel at the same time.  */
+
+int
+linux_supports_traceclone (void)
+{
+  return ptrace_supports_feature (PTRACE_O_TRACECLONE);
+}
+
+/* Returns non-zero if PTRACE_O_TRACEVFORKDONE is supported by
+   ptrace, 0 otherwise.  */
+
+int
+linux_supports_tracevforkdone (void)
+{
+  return ptrace_supports_feature (PTRACE_O_TRACEVFORKDONE);
+}
+
+/* Returns non-zero if PTRACE_O_TRACESYSGOOD is supported by ptrace,
+   0 otherwise.  */
+
+int
+linux_supports_tracesysgood (void)
+{
+  return ptrace_supports_feature (PTRACE_O_TRACESYSGOOD);
+}
+
 /* Display possible problems on this system.  Display them only once per GDB
    execution.  */
 
index 8f02c82ea06c5ecd376ef4ef748f966a1a94e31f..39c943e456f301557fc33136026d6b0c8de27431 100644 (file)
@@ -22,6 +22,22 @@ struct buffer;
 
 #include <sys/ptrace.h>
 
+#ifdef __UCLIBC__
+#if !(defined(__UCLIBC_HAS_MMU__) || defined(__ARCH_HAS_MMU__))
+/* PTRACE_TEXT_ADDR and friends.  */
+#include <asm/ptrace.h>
+#define HAS_NOMMU
+#endif
+#endif
+
+#if !defined(PTRACE_TYPE_ARG3)
+#define PTRACE_TYPE_ARG3 void *
+#endif
+
+#if !defined(PTRACE_TYPE_ARG4)
+#define PTRACE_TYPE_ARG4 void *
+#endif
+
 #ifndef PTRACE_GETSIGINFO
 # define PTRACE_GETSIGINFO 0x4202
 # define PTRACE_SETSIGINFO 0x4203
@@ -69,5 +85,10 @@ struct buffer;
 
 extern void linux_ptrace_attach_warnings (pid_t pid, struct buffer *buffer);
 extern void linux_ptrace_init_warnings (void);
+extern void linux_enable_event_reporting (pid_t pid);
+extern int linux_supports_tracefork (void);
+extern int linux_supports_traceclone (void);
+extern int linux_supports_tracevforkdone (void);
+extern int linux_supports_tracesysgood (void);
 
 #endif /* COMMON_LINUX_PTRACE_H */
index 76abd04a09dce9e93af5b5d571670ba84d17c7b6..03b097266f575ce35560c48ef952cc74b738eab0 100644 (file)
 /* Define to the type of arg 3 for ptrace. */
 #undef PTRACE_TYPE_ARG3
 
+/* Define to the type of arg 4 for ptrace. */
+#undef PTRACE_TYPE_ARG4
+
 /* Define to the type of arg 5 for ptrace. */
 #undef PTRACE_TYPE_ARG5
 
index 2b2202e8cf46b312ce4666fce79241fa979458c7..18a12abd1b14e716f6bfd0a5873510feee0d0167 100644 (file)
@@ -21,7 +21,7 @@
 NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o aarch64-linux-nat.o \
        proc-service.o linux-thread-db.o linux-nat.o linux-fork.o \
-       linux-procfs.o linux-ptrace.o linux-osdata.o
+       linux-procfs.o linux-ptrace.o linux-osdata.o linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES= -ldl $(RDYNAMIC)
index 9eb9e4b72913f31c7908b8480e4645cf3a5bd825..81819a16bb02759e130dba0bacd5fae9d7ea569c 100644 (file)
@@ -2,7 +2,8 @@
 NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o alpha-linux-nat.o \
        fork-child.o proc-service.o linux-thread-db.o \
-       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
+       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
+       linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
index c0a1c66804a9b63d0545492c304db9ab1df16dd9..63c3eae45cd93f18031d3533797b370d37c16d07 100644 (file)
@@ -3,7 +3,8 @@
 NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o arm-linux-nat.o \
        proc-service.o linux-thread-db.o \
-       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
+       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
+       linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES= -ldl $(RDYNAMIC)
index 7c64e836325293d19c317ce875403aa9cb47f22c..10a25849117322a184b5661fb47906f768b0ab10 100644 (file)
@@ -5,7 +5,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
        i386-nat.o i386-linux-nat.o \
        proc-service.o linux-thread-db.o \
        linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
-       linux-btrace.o
+       linux-btrace.o linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
index 8d782c1a3356ed9932cdfe58c233152f1d2d89b8..686c363510dee5f4f3c4f0ab4fc3898705ec4de4 100644 (file)
@@ -3,7 +3,8 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
        i386-nat.o amd64-nat.o amd64-linux-nat.o \
        linux-nat.o linux-osdata.o \
        proc-service.o linux-thread-db.o linux-fork.o \
-       linux-procfs.o linux-ptrace.o linux-btrace.o
+       linux-procfs.o linux-ptrace.o linux-btrace.o \
+       linux-waitpid.o
 NAT_FILE= config/nm-linux.h
 NAT_CDEPS = $(srcdir)/proc-service.list
 
index 1a4c68e093769234b79e3040ed15baf8978d15d2..a2aff442f69069afd6e4ca8bb7cde2347ef680c3 100644 (file)
@@ -5,7 +5,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
        core-regset.o ia64-linux-nat.o \
        proc-service.o linux-thread-db.o \
        linux-nat.o linux-osdata.o linux-fork.o \
-       linux-procfs.o linux-ptrace.o
+       linux-procfs.o linux-ptrace.o linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
index b4618064bffc7d2e1379fe90f96fce265f3a84d9..e9bb82cbc5a89cdb6776a30e66a5b0dbb86e0010 100644 (file)
@@ -3,7 +3,8 @@
 NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o                         \
        m32r-linux-nat.o proc-service.o linux-thread-db.o       \
-       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
+       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
+       linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES= -ldl $(RDYNAMIC)
index e3aaf382c8c8e31ed0ee286d8252398e3080d639..bcec2958a14ff2089669ac2185236fd57945cc97 100644 (file)
@@ -4,7 +4,8 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o \
        m68klinux-nat.o \
        proc-service.o linux-thread-db.o \
-       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
+       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
+       linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
index a4f23e3c9d75f1f2845c2488580a0d809a20daec..021838e0af7d38cb554f9d125cb13dc61659b149 100644 (file)
@@ -3,7 +3,8 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o mips-linux-nat.o \
        linux-thread-db.o proc-service.o \
        linux-nat.o linux-osdata.o linux-fork.o \
-       linux-procfs.o linux-ptrace.o mips-linux-watch.o
+       linux-procfs.o linux-ptrace.o linux-waitpid.o \
+       mips-linux-watch.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
index fa46db6ebe5187e35b56fcd3a43b0e606cdbefa3..f1c0c32783b0eb1fdd3fa41bf4a737fc3ecdb1cc 100644 (file)
@@ -3,7 +3,7 @@ NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o \
        hppa-linux-nat.o proc-service.o linux-thread-db.o \
        linux-nat.o linux-osdata.o linux-fork.o \
-       linux-procfs.o linux-ptrace.o
+       linux-procfs.o linux-ptrace.o linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
index b0d4ce7c55c38a8c35961224e936a88efe3ff35c..a807d3fac063a86c60f45ded9392a58f325e3a3e 100644 (file)
@@ -5,7 +5,8 @@ XM_CLIBS=
 NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o \
        ppc-linux-nat.o proc-service.o linux-thread-db.o \
-       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
+       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
+       linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
index 367a81853b530ef729421a3282153915594cf490..4b91408fbe678ef51b8af6c936d3542e61c3f5d2 100644 (file)
@@ -5,7 +5,8 @@ XM_CLIBS=
 NAT_FILE= config/nm-linux.h
 NATDEPFILES= inf-ptrace.o fork-child.o \
        ppc-linux-nat.o proc-service.o linux-thread-db.o \
-       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
+       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
+       linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The PowerPC has severe limitations on TOC size, and uses them even
index 1bc279a8138515bdec10e85657d35637006b23cb..7ce7a5ff141c320e5274ad9fcba9d55fcf16f885 100644 (file)
@@ -4,5 +4,5 @@
 # PPU side of the Cell BE and debugging the SPU side.
 
 NATDEPFILES = spu-linux-nat.o fork-child.o inf-ptrace.o \
-             linux-procfs.o linux-ptrace.o
+             linux-procfs.o linux-ptrace.o linux-waitpid.o
 
index 6a2cefd7b5c8f87fda17145a08281dfa4232e223..d80259176d7774c1d4f5d9bf2aacc4e6e349561c 100644 (file)
@@ -4,7 +4,7 @@ NATDEPFILES= sparc-nat.o sparc-linux-nat.o \
        core-regset.o fork-child.o inf-ptrace.o \
        proc-service.o linux-thread-db.o \
        linux-nat.o linux-osdata.o linux-fork.o \
-       linux-procfs.o linux-ptrace.o
+       linux-procfs.o linux-ptrace.o linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
index d1e1a97162f5545acda336d0c54bf11176fb6b19..c83097ec54da66fbc8bd9d9d3ee13f7e3221325b 100644 (file)
@@ -5,7 +5,7 @@ NATDEPFILES= sparc-nat.o sparc64-nat.o sparc64-linux-nat.o \
        fork-child.o inf-ptrace.o \
        proc-service.o linux-thread-db.o \
        linux-nat.o linux-osdata.o linux-fork.o \
-       linux-procfs.o linux-ptrace.o
+       linux-procfs.o linux-ptrace.o linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 # The dynamically loaded libthread_db needs access to symbols in the
index 56ef694b1f3fa897a44102d06b319e28480aa4ca..1ed9c33c1207394629a472edec0d300e465722d2 100644 (file)
@@ -5,7 +5,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
        tilegx-linux-nat.o \
        proc-service.o linux-thread-db.o \
        linux-nat.o linux-osdata.o linux-fork.o \
-       linux-procfs.o linux-ptrace.o
+       linux-procfs.o linux-ptrace.o linux-waitpid.o
 
 # The dynamically loaded libthread_db needs access to symbols in the
 # gdb executable.
index deffe25ed4281945c5288d18138876cdc4789101..8ef84b46cdf9aac53134369ee3e3e4ee34de3165 100644 (file)
@@ -4,7 +4,8 @@ NAT_FILE= config/nm-linux.h
 
 NATDEPFILES= inf-ptrace.o fork-child.o xtensa-linux-nat.o \
        linux-thread-db.o proc-service.o \
-       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
+       linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
+       linux-waitpid.o
 NAT_CDEPS = $(srcdir)/proc-service.list
 
 LOADLIBES = -ldl $(RDYNAMIC)
index 80678256bfab7990d036d0f9dad3ff1520e720d4..a722b9308318908cd8002dbf4c670eb4b01783a7 100755 (executable)
@@ -10336,7 +10336,7 @@ else
 for gdb_arg1 in 'int' 'long'; do
  for gdb_arg2 in 'pid_t' 'int' 'long'; do
   for gdb_arg3 in 'int *' 'caddr_t' 'int' 'long' 'void *'; do
-   for gdb_arg4 in 'int' 'long'; do
+   for gdb_arg4 in 'int' 'long' 'void *'; do
      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 $gdb_ptrace_headers
@@ -10399,6 +10399,11 @@ cat >>confdefs.h <<_ACEOF
 #define PTRACE_TYPE_ARG3 $3
 _ACEOF
 
+
+cat >>confdefs.h <<_ACEOF
+#define PTRACE_TYPE_ARG4 $4
+_ACEOF
+
 if test -n "$5"; then
 
 cat >>confdefs.h <<_ACEOF
index 667821f1ecc1064ec54e44a538544db2917a2f38..0982cac82a449605517fcb1478a13904fedeb549 100644 (file)
@@ -1207,7 +1207,7 @@ AC_CACHE_CHECK([types of arguments for ptrace], gdb_cv_func_ptrace_args, [
 for gdb_arg1 in 'int' 'long'; do
  for gdb_arg2 in 'pid_t' 'int' 'long'; do
   for gdb_arg3 in 'int *' 'caddr_t' 'int' 'long' 'void *'; do
-   for gdb_arg4 in 'int' 'long'; do
+   for gdb_arg4 in 'int' 'long' 'void *'; do
      AC_TRY_COMPILE($gdb_ptrace_headers, [
 extern $gdb_cv_func_ptrace_ret
   ptrace ($gdb_arg1, $gdb_arg2, $gdb_arg3, $gdb_arg4);
@@ -1234,6 +1234,8 @@ IFS=$ac_save_IFS
 shift
 AC_DEFINE_UNQUOTED(PTRACE_TYPE_ARG3, $[3],
   [Define to the type of arg 3 for ptrace.])
+AC_DEFINE_UNQUOTED(PTRACE_TYPE_ARG4, $[4],
+  [Define to the type of arg 4 for ptrace.])
 if test -n "$[5]"; then
   AC_DEFINE_UNQUOTED(PTRACE_TYPE_ARG5, $[5],
     [Define to the type of arg 5 for ptrace.])
index 19687863034ffbf5072e0e100f8df35c68ddfff2..fe3660c020dc2bda6892724fd9a98d969bb9493c 100644 (file)
@@ -1,3 +1,30 @@
+2013-08-22  Luis Machado  <lgustavo@codesourcery.com>
+
+       * Makefile.in: Explain why ../target and ../nat are not
+       listed as include file search paths.
+       (linux-waitpid.o): New object file rule.
+       * configure.srv (srv_native_linux_obj): New variable.
+       Replace all occurrences of linux native object files with
+       $srv_native_linux_obj.
+       * linux-low.c: Include nat/linux-nat.h and nat/linux-waitpid.h.
+       (HAS_NOMMU): Move defining logic to common/linux-ptrace.c.
+       (linux_enable_event_reporting): Remove declaration.
+       (my_waitpid): Moved to common/linux-waitpid.c.
+       (linux_wait_for_event): Pass ptid when calling
+       linux_enable_event_reporting.
+       (linux_supports_tracefork_flag): Remove.
+       (linux_enable_event_reporting): Likewise.
+       (linux_tracefork_grandchild): Remove.
+       (STACK_SIZE): Moved to common/linux-ptrace.c.
+       (linux_tracefork_child): Remove.
+       (linux_test_for_tracefork): Remove.
+       (linux_look_up_symbols): Call linux_supports_traceclone.
+       (initialize_low): Remove call to linux_test_for_tracefork.
+       * linux-low.h (PTRACE_TYPE_ARG3): Move to
+       common/linux-ptrace.h.
+       (PTRACE_TYPE_ARG4): Likewise.
+       Include linux-ptrace.h.
+
 2013-08-21  Pedro Alves  <palves@redhat.com>
 
        * config.in: Renegerate.
index 2cdbf47bffb05a43001af54ff4dbd3038fbf08b1..45e03a2353aee587ffa42ea8e5186e780d0ac669 100644 (file)
@@ -100,6 +100,11 @@ GNULIB_H = $(GNULIB_BUILDDIR)/import/string.h @GNULIB_STDINT_H@
 # -I. for config files.
 # -I${srcdir} for our headers.
 # -I$(srcdir)/../regformats for regdef.h.
+#
+# We do not include ../target or ../nat in here because headers
+# in those directories should be included with the subdirectory.
+# e.g.: "target/wait.h".
+#
 INCLUDE_CFLAGS = -I. -I${srcdir} -I$(srcdir)/../common \
        -I$(srcdir)/../regformats -I$(srcdir)/../ -I$(INCLUDE_DIR) \
        $(INCGNU)
@@ -562,6 +567,12 @@ linux-btrace.o: ../common/linux-btrace.c $(linux_btrace_h) $(server_h)
 mips-linux-watch.o: ../common/mips-linux-watch.c $(mips_linux_watch_h) $(server_h)
        $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $<
 
+# Native object files rules from ../nat
+
+linux-waitpid.o: ../nat/linux-waitpid.c
+       $(COMPILE) $<
+       $(POSTCOMPILE)
+
 # We build vasprintf with -DHAVE_CONFIG_H because we want that unit to
 # include our config.h file.  Otherwise, some system headers do not get
 # included, and the compiler emits a warning about implicitly defined
index b9dfd6c6cb6e18bb2468a2e7543a97f806baf46d..b3c04210fe7e6b480f5f065e956a0ab1da2745d9 100644 (file)
@@ -39,16 +39,18 @@ srv_amd64_xmlfiles="i386/amd64.xml i386/amd64-avx.xml i386/x32.xml i386/x32-avx.
 srv_i386_linux_xmlfiles="i386/i386-linux.xml i386/i386-avx-linux.xml i386/i386-mmx-linux.xml i386/32bit-linux.xml $srv_i386_32bit_xmlfiles"
 srv_amd64_linux_xmlfiles="i386/amd64-linux.xml i386/amd64-avx-linux.xml i386/64bit-linux.xml i386/x32-linux.xml i386/x32-avx-linux.xml $srv_i386_64bit_xmlfiles"
 
+
+# Linux object files.  This is so we don't have to repeat
+# these files over and over again.
+srv_linux_obj="linux-low.o linux-osdata.o linux-procfs.o linux-ptrace.o linux-waitpid.o"
+
 # Input is taken from the "${target}" variable.
 
 case "${target}" in
   aarch64*-*-linux*)
                        srv_regobj="aarch64.o"
                        srv_tgtobj="linux-aarch64-low.o"
-                       srv_tgtobj="${srv_tgtobj} linux-low.o"
-                       srv_tgtobj="${srv_tgtobj} linux-osdata.o"
-                       srv_tgtobj="${srv_tgtobj} linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="${srv_tgtobj} $srv_linux_obj"
                        srv_xmlfiles="aarch64.xml"
                        srv_xmlfiles="${srv_xmlfiles} aarch64-core.xml"
                        srv_xmlfiles="${srv_xmlfiles} aarch64-fpu.xml"
@@ -60,8 +62,7 @@ case "${target}" in
                        srv_regobj="${srv_regobj} arm-with-vfpv2.o"
                        srv_regobj="${srv_regobj} arm-with-vfpv3.o"
                        srv_regobj="${srv_regobj} arm-with-neon.o"
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-arm-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-arm-low.o"
                        srv_xmlfiles="arm-with-iwmmxt.xml"
                        srv_xmlfiles="${srv_xmlfiles} arm-with-vfpv2.xml"
                        srv_xmlfiles="${srv_xmlfiles} arm-with-vfpv3.xml"
@@ -83,20 +84,17 @@ case "${target}" in
                        srv_mingwce=yes
                        ;;
   bfin-*-*linux*)      srv_regobj=reg-bfin.o
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-bfin-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-bfin-low.o"
                        srv_linux_usrregs=yes
                        srv_linux_thread_db=yes
                        ;;
   crisv32-*-linux*)    srv_regobj=reg-crisv32.o
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-crisv32-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-crisv32-low.o"
                        srv_linux_regsets=yes
                        srv_linux_thread_db=yes
                        ;;
   cris-*-linux*)       srv_regobj=reg-cris.o
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-cris-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-cris-low.o"
                        srv_linux_usrregs=yes
                        srv_linux_thread_db=yes
                        ;;
@@ -110,8 +108,8 @@ case "${target}" in
                            srv_regobj="$srv_regobj $srv_amd64_linux_regobj"
                            srv_xmlfiles="${srv_xmlfiles} $srv_amd64_linux_xmlfiles"
                        fi
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-x86-low.o i386-low.o i387-fp.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-x86-low.o i386-low.o i387-fp.o"
+                       srv_tgtobj="${srv_tgtobj} linux-btrace.o"
                        srv_linux_usrregs=yes
                        srv_linux_regsets=yes
                        srv_linux_thread_db=yes
@@ -146,13 +144,11 @@ case "${target}" in
                        srv_qnx="yes"
                        ;;
   ia64-*-linux*)       srv_regobj=reg-ia64.o
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-ia64-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-ia64-low.o"
                        srv_linux_usrregs=yes
                        ;;
   m32r*-*-linux*)      srv_regobj=reg-m32r.o
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-m32r-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-m32r-low.o"
                        srv_linux_usrregs=yes
                        srv_linux_thread_db=yes
                        ;;
@@ -161,8 +157,7 @@ case "${target}" in
                         else
                           srv_regobj=reg-m68k.o
                         fi
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-m68k-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-m68k-low.o"
                        srv_linux_usrregs=yes
                        srv_linux_regsets=yes
                        srv_linux_thread_db=yes
@@ -172,8 +167,7 @@ case "${target}" in
                         else
                           srv_regobj=reg-m68k.o
                         fi
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-m68k-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-m68k-low.o"
                        srv_linux_usrregs=yes
                        srv_linux_regsets=yes
                        srv_linux_thread_db=yes
@@ -182,8 +176,7 @@ case "${target}" in
                        srv_regobj="${srv_regobj} mips-dsp-linux.o"
                        srv_regobj="${srv_regobj} mips64-linux.o"
                        srv_regobj="${srv_regobj} mips64-dsp-linux.o"
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-mips-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-mips-low.o"
                        srv_tgtobj="${srv_tgtobj} mips-linux-watch.o"
                        srv_xmlfiles="mips-linux.xml"
                        srv_xmlfiles="${srv_xmlfiles} mips-dsp-linux.xml"
@@ -202,8 +195,7 @@ case "${target}" in
                        srv_linux_thread_db=yes
                        ;;
   nios2*-*-linux*)     srv_regobj="nios2-linux.o"
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-nios2-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-nios2-low.o"
                        srv_xmlfiles="nios2-linux.xml"
                        srv_xmlfiles="${srv_xmlfiles} nios2-cpu.xml"
                        srv_linux_regsets=yes
@@ -225,8 +217,7 @@ case "${target}" in
                        srv_regobj="${srv_regobj} powerpc-isa205-64l.o"
                        srv_regobj="${srv_regobj} powerpc-isa205-altivec64l.o"
                        srv_regobj="${srv_regobj} powerpc-isa205-vsx64l.o"
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-ppc-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-ppc-low.o"
                        srv_xmlfiles="rs6000/powerpc-32l.xml"
                        srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec32l.xml"
                        srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-cell32l.xml"
@@ -271,8 +262,7 @@ case "${target}" in
                        srv_regobj="${srv_regobj} s390x-linux64.o"
                        srv_regobj="${srv_regobj} s390x-linux64v1.o"
                        srv_regobj="${srv_regobj} s390x-linux64v2.o"
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-s390-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-s390-low.o"
                        srv_xmlfiles="s390-linux32.xml"
                        srv_xmlfiles="${srv_xmlfiles} s390-linux32v1.xml"
                        srv_xmlfiles="${srv_xmlfiles} s390-linux32v2.xml"
@@ -292,15 +282,13 @@ case "${target}" in
                        srv_linux_thread_db=yes
                        ;;
   sh*-*-linux*)                srv_regobj=reg-sh.o
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-sh-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-sh-low.o"
                        srv_linux_usrregs=yes
                        srv_linux_regsets=yes
                        srv_linux_thread_db=yes
                        ;;
   sparc*-*-linux*)     srv_regobj=reg-sparc64.o
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-sparc-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-sparc-low.o"
                        srv_linux_regsets=yes
                        srv_linux_thread_db=yes
                        ;;
@@ -316,15 +304,14 @@ case "${target}" in
                        srv_xmlfiles="${srv_xmlfiles} tic6x-core.xml"
                        srv_xmlfiles="${srv_xmlfiles} tic6x-gp.xml"
                        srv_xmlfiles="${srv_xmlfiles} tic6x-c6xp.xml"
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-tic6x-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-tic6x-low.o"
                        srv_linux_regsets=yes
                        srv_linux_usrregs=yes
                        srv_linux_thread_db=yes
                        ;;
   x86_64-*-linux*)     srv_regobj="$srv_amd64_linux_regobj $srv_i386_linux_regobj"
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-x86-low.o i386-low.o i387-fp.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-x86-low.o i386-low.o i387-fp.o"
+                       srv_tgtobj="${srv_tgtobj} linux-btrace.o"
                        srv_xmlfiles="$srv_i386_linux_xmlfiles $srv_amd64_linux_xmlfiles"
                        srv_linux_usrregs=yes # This is for i386 progs.
                        srv_linux_regsets=yes
@@ -343,14 +330,12 @@ case "${target}" in
                        ;;
 
   xtensa*-*-linux*)    srv_regobj=reg-xtensa.o
-                       srv_tgtobj="linux-low.o linux-osdata.o linux-xtensa-low.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-xtensa-low.o"
                        srv_linux_regsets=yes
                        ;;
   tilegx-*-linux*)     srv_regobj=reg-tilegx.o
                        srv_regobj="${srv_regobj} reg-tilegx32.o"
-                       srv_tgtobj="linux-low.o linux-tile-low.o linux-osdata.o linux-procfs.o"
-                       srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+                       srv_tgtobj="$srv_linux_obj linux-osdata.o"
                        srv_linux_regsets=yes
                        srv_linux_thread_db=yes
                        ;;
index 217cd2efee8606797983f6bbefe492eeb1ca2660..12208dcc1e11752d8b63d4dfccc572c06252015b 100644 (file)
@@ -21,6 +21,8 @@
 #include "linux-osdata.h"
 #include "agent.h"
 
+#include "nat/linux-nat.h"
+#include "nat/linux-waitpid.h"
 #include "gdb_wait.h"
 #include <stdio.h>
 #include <sys/ptrace.h>
 #define __SIGRTMIN 32
 #endif
 
-#ifdef __UCLIBC__
-#if !(defined(__UCLIBC_HAS_MMU__) || defined(__ARCH_HAS_MMU__))
-/* PTRACE_TEXT_ADDR and friends.  */
-#include <asm/ptrace.h>
-#define HAS_NOMMU
-#endif
-#endif
-
 /* Some targets did not define these ptrace constants from the start,
    so gdbserver defines them locally here.  In the future, these may
    be removed after they are added to asm/ptrace.h.  */
@@ -236,7 +230,6 @@ static void proceed_all_lwps (void);
 static int finish_step_over (struct lwp_info *lwp);
 static CORE_ADDR get_stop_pc (struct lwp_info *lwp);
 static int kill_lwp (unsigned long lwpid, int signo);
-static void linux_enable_event_reporting (int pid);
 
 /* True if the low target can hardware single-step.  Such targets
    don't need a BREAKPOINT_REINSERT_ADDR callback.  */
@@ -376,81 +369,6 @@ linux_add_process (int pid, int attached)
   return proc;
 }
 
-/* Wrapper function for waitpid which handles EINTR, and emulates
-   __WALL for systems where that is not available.  */
-
-static int
-my_waitpid (int pid, int *status, int flags)
-{
-  int ret, out_errno;
-
-  if (debug_threads)
-    fprintf (stderr, "my_waitpid (%d, 0x%x)\n", pid, flags);
-
-  if (flags & __WALL)
-    {
-      sigset_t block_mask, org_mask, wake_mask;
-      int wnohang;
-
-      wnohang = (flags & WNOHANG) != 0;
-      flags &= ~(__WALL | __WCLONE);
-      flags |= WNOHANG;
-
-      /* Block all signals while here.  This avoids knowing about
-        LinuxThread's signals.  */
-      sigfillset (&block_mask);
-      sigprocmask (SIG_BLOCK, &block_mask, &org_mask);
-
-      /* ... except during the sigsuspend below.  */
-      sigemptyset (&wake_mask);
-
-      while (1)
-       {
-         /* Since all signals are blocked, there's no need to check
-            for EINTR here.  */
-         ret = waitpid (pid, status, flags);
-         out_errno = errno;
-
-         if (ret == -1 && out_errno != ECHILD)
-           break;
-         else if (ret > 0)
-           break;
-
-         if (flags & __WCLONE)
-           {
-             /* We've tried both flavors now.  If WNOHANG is set,
-                there's nothing else to do, just bail out.  */
-             if (wnohang)
-               break;
-
-             if (debug_threads)
-               fprintf (stderr, "blocking\n");
-
-             /* Block waiting for signals.  */
-             sigsuspend (&wake_mask);
-           }
-
-         flags ^= __WCLONE;
-       }
-
-      sigprocmask (SIG_SETMASK, &org_mask, NULL);
-    }
-  else
-    {
-      do
-       ret = waitpid (pid, status, flags);
-      while (ret == -1 && errno == EINTR);
-      out_errno = errno;
-    }
-
-  if (debug_threads)
-    fprintf (stderr, "my_waitpid (%d, 0x%x): status(%x), %d\n",
-            pid, flags, status ? *status : -1, ret);
-
-  errno = out_errno;
-  return ret;
-}
-
 /* Handle a GNU/Linux extended wait response.  If we see a clone
    event, we need to add the new LWP to our list (and not report the
    trap to higher layers).  */
@@ -4659,168 +4577,6 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
   return 0;
 }
 
-/* Non-zero if the kernel supports PTRACE_O_TRACEFORK.  */
-static int linux_supports_tracefork_flag;
-
-static void
-linux_enable_event_reporting (int pid)
-{
-  if (!linux_supports_tracefork_flag)
-    return;
-
-  ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0,
-         (PTRACE_TYPE_ARG4) PTRACE_O_TRACECLONE);
-}
-
-/* Helper functions for linux_test_for_tracefork, called via clone ().  */
-
-static int
-linux_tracefork_grandchild (void *arg)
-{
-  _exit (0);
-}
-
-#define STACK_SIZE 4096
-
-static int
-linux_tracefork_child (void *arg)
-{
-  ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0);
-  kill (getpid (), SIGSTOP);
-
-#if !(defined(__UCLIBC__) && defined(HAS_NOMMU))
-
-  if (fork () == 0)
-    linux_tracefork_grandchild (NULL);
-
-#else /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-
-#ifdef __ia64__
-  __clone2 (linux_tracefork_grandchild, arg, STACK_SIZE,
-           CLONE_VM | SIGCHLD, NULL);
-#else
-  clone (linux_tracefork_grandchild, (char *) arg + STACK_SIZE,
-        CLONE_VM | SIGCHLD, NULL);
-#endif
-
-#endif /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-
-  _exit (0);
-}
-
-/* Determine if PTRACE_O_TRACEFORK can be used to follow fork events.  Make
-   sure that we can enable the option, and that it had the desired
-   effect.  */
-
-static void
-linux_test_for_tracefork (void)
-{
-  int child_pid, ret, status;
-  long second_pid;
-#if defined(__UCLIBC__) && defined(HAS_NOMMU)
-  char *stack = xmalloc (STACK_SIZE * 4);
-#endif /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-
-  linux_supports_tracefork_flag = 0;
-
-#if !(defined(__UCLIBC__) && defined(HAS_NOMMU))
-
-  child_pid = fork ();
-  if (child_pid == 0)
-    linux_tracefork_child (NULL);
-
-#else /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-
-  /* Use CLONE_VM instead of fork, to support uClinux (no MMU).  */
-#ifdef __ia64__
-  child_pid = __clone2 (linux_tracefork_child, stack, STACK_SIZE,
-                       CLONE_VM | SIGCHLD, stack + STACK_SIZE * 2);
-#else /* !__ia64__ */
-  child_pid = clone (linux_tracefork_child, stack + STACK_SIZE,
-                    CLONE_VM | SIGCHLD, stack + STACK_SIZE * 2);
-#endif /* !__ia64__ */
-
-#endif /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-
-  if (child_pid == -1)
-    perror_with_name ("clone");
-
-  ret = my_waitpid (child_pid, &status, 0);
-  if (ret == -1)
-    perror_with_name ("waitpid");
-  else if (ret != child_pid)
-    error ("linux_test_for_tracefork: waitpid: unexpected result %d.", ret);
-  if (! WIFSTOPPED (status))
-    error ("linux_test_for_tracefork: waitpid: unexpected status %d.", status);
-
-  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_test_for_tracefork: failed to kill child");
-         return;
-       }
-
-      ret = my_waitpid (child_pid, &status, 0);
-      if (ret != child_pid)
-       warning ("linux_test_for_tracefork: failed to wait for killed child");
-      else if (!WIFSIGNALED (status))
-       warning ("linux_test_for_tracefork: unexpected wait status 0x%x from "
-                "killed child", status);
-
-      return;
-    }
-
-  ret = ptrace (PTRACE_CONT, child_pid, (PTRACE_TYPE_ARG3) 0,
-               (PTRACE_TYPE_ARG4) 0);
-  if (ret != 0)
-    warning ("linux_test_for_tracefork: failed to resume child");
-
-  ret = my_waitpid (child_pid, &status, 0);
-
-  if (ret == child_pid && WIFSTOPPED (status)
-      && status >> 16 == PTRACE_EVENT_FORK)
-    {
-      second_pid = 0;
-      ret = ptrace (PTRACE_GETEVENTMSG, child_pid, (PTRACE_TYPE_ARG3) 0,
-                   &second_pid);
-      if (ret == 0 && second_pid != 0)
-       {
-         int second_status;
-
-         linux_supports_tracefork_flag = 1;
-         my_waitpid (second_pid, &second_status, 0);
-         ret = ptrace (PTRACE_KILL, second_pid, (PTRACE_TYPE_ARG3) 0,
-                       (PTRACE_TYPE_ARG4) 0);
-         if (ret != 0)
-           warning ("linux_test_for_tracefork: failed to kill second child");
-         my_waitpid (second_pid, &status, 0);
-       }
-    }
-  else
-    warning ("linux_test_for_tracefork: unexpected result from waitpid "
-            "(%d, status 0x%x)", ret, status);
-
-  do
-    {
-      ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0,
-                   (PTRACE_TYPE_ARG4) 0);
-      if (ret != 0)
-       warning ("linux_test_for_tracefork: failed to kill child");
-      my_waitpid (child_pid, &status, 0);
-    }
-  while (WIFSTOPPED (status));
-
-#if defined(__UCLIBC__) && defined(HAS_NOMMU)
-  free (stack);
-#endif /* defined(__UCLIBC__) && defined(HAS_NOMMU) */
-}
-
-
 static void
 linux_look_up_symbols (void)
 {
@@ -4830,10 +4586,10 @@ linux_look_up_symbols (void)
   if (proc->private->thread_db != NULL)
     return;
 
-  /* If the kernel supports tracing forks then it also supports tracing
-     clones, and then we don't need to use the magic thread event breakpoint
-     to learn about threads.  */
-  thread_db_init (!linux_supports_tracefork_flag);
+  /* If the kernel supports tracing clones, then we don't need to
+     use the magic thread event breakpoint to learn about
+     threads.  */
+  thread_db_init (!linux_supports_traceclone ());
 #endif
 }
 
@@ -6097,7 +5853,6 @@ initialize_low (void)
   set_breakpoint_data (the_low_target.breakpoint,
                       the_low_target.breakpoint_len);
   linux_init_signals ();
-  linux_test_for_tracefork ();
   linux_ptrace_init_warnings ();
 
   sigchld_action.sa_handler = sigchld_handler;
index e051ab6c82f49b7a5e32fc46f858071bcd22e8a3..4bf0dc37d66ded2a537ad12b0ebbeef1ac1d593f 100644 (file)
@@ -22,8 +22,9 @@
 #include "gdbthread.h"
 #include "gdb_proc_service.h"
 
-#define PTRACE_TYPE_ARG3 void *
-#define PTRACE_TYPE_ARG4 void *
+/* Included for ptrace type definitions.  */
+#include "linux-ptrace.h"
+
 #define PTRACE_XFER_TYPE long
 
 #ifdef HAVE_LINUX_REGSETS
index db23433d5fa25d68c983f52f392cf820b4f7fb8d..46e3dbfec4c9d7ecd6c944e5e2a7df8473e1da30 100644 (file)
@@ -20,6 +20,8 @@
 #include "defs.h"
 #include "inferior.h"
 #include "target.h"
+#include "nat/linux-nat.h"
+#include "nat/linux-waitpid.h"
 #include "gdb_string.h"
 #include "gdb_wait.h"
 #include "gdb_assert.h"
@@ -171,11 +173,6 @@ blocked.  */
 #define O_LARGEFILE 0
 #endif
 
-/* Unlike other extended result codes, WSTOPSIG (status) on
-   PTRACE_O_TRACESYSGOOD syscall events doesn't return SIGTRAP, but
-   instead SIGTRAP with bit 7 set.  */
-#define SYSCALL_SIGTRAP (SIGTRAP | 0x80)
-
 /* The single-threaded native GNU/Linux target_ops.  We save a pointer for
    the use of the multi-threaded target.  */
 static struct target_ops *linux_ops;
@@ -226,24 +223,6 @@ struct simple_pid_list
 };
 struct simple_pid_list *stopped_pids;
 
-/* This variable is a tri-state flag: -1 for unknown, 0 if PTRACE_O_TRACEFORK
-   can not be used, 1 if it can.  */
-
-static int linux_supports_tracefork_flag = -1;
-
-/* This variable is a tri-state flag: -1 for unknown, 0 if
-   PTRACE_O_TRACESYSGOOD can not be used, 1 if it can.  */
-
-static int linux_supports_tracesysgood_flag = -1;
-
-/* If we have PTRACE_O_TRACEFORK, this flag indicates whether we also have
-   PTRACE_O_TRACEVFORKDONE.  */
-
-static int linux_supports_tracevforkdone_flag = -1;
-
-/* Stores the current used ptrace() options.  */
-static int current_ptrace_options = 0;
-
 /* Async mode support.  */
 
 /* The read/write ends of the pipe registered as waitable file in the
@@ -349,244 +328,26 @@ pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp)
   return 0;
 }
 
-\f
-/* A helper function for linux_test_for_tracefork, called after fork ().  */
-
-static void
-linux_tracefork_child (void)
-{
-  ptrace (PTRACE_TRACEME, 0, 0, 0);
-  kill (getpid (), SIGSTOP);
-  fork ();
-  _exit (0);
-}
-
-/* Wrapper function for waitpid which handles EINTR.  */
-
-static int
-my_waitpid (int pid, int *statusp, int flags)
-{
-  int ret;
-
-  do
-    {
-      ret = waitpid (pid, statusp, flags);
-    }
-  while (ret == -1 && errno == EINTR);
-
-  return ret;
-}
-
-/* Determine if PTRACE_O_TRACEFORK can be used to follow fork events.
-
-   First, we try to enable fork tracing on ORIGINAL_PID.  If this fails,
-   we know that the feature is not available.  This may change the tracing
-   options for ORIGINAL_PID, but we'll be setting them shortly anyway.
-
-   However, if it succeeds, we don't know for sure that the feature is
-   available; old versions of PTRACE_SETOPTIONS ignored unknown options.  We
-   create a child process, attach to it, use PTRACE_SETOPTIONS to enable
-   fork tracing, and let it fork.  If the process exits, we assume that we
-   can't use TRACEFORK; if we get the fork notification, and we can extract
-   the new child's PID, then we assume that we can.  */
+/* Initialize ptrace warnings and check for supported ptrace
+   features given PID.  */
 
 static void
-linux_test_for_tracefork (int original_pid)
+linux_init_ptrace (pid_t pid)
 {
-  int child_pid, ret, status;
-  long second_pid;
-
-  linux_supports_tracefork_flag = 0;
-  linux_supports_tracevforkdone_flag = 0;
-
-  ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACEFORK);
-  if (ret != 0)
-    return;
-
-  child_pid = fork ();
-  if (child_pid == -1)
-    perror_with_name (("fork"));
-
-  if (child_pid == 0)
-    linux_tracefork_child ();
-
-  ret = my_waitpid (child_pid, &status, 0);
-  if (ret == -1)
-    perror_with_name (("waitpid"));
-  else if (ret != child_pid)
-    error (_("linux_test_for_tracefork: waitpid: unexpected result %d."), ret);
-  if (! WIFSTOPPED (status))
-    error (_("linux_test_for_tracefork: waitpid: unexpected status %d."),
-          status);
-
-  ret = ptrace (PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACEFORK);
-  if (ret != 0)
-    {
-      ret = ptrace (PTRACE_KILL, child_pid, 0, 0);
-      if (ret != 0)
-       {
-         warning (_("linux_test_for_tracefork: failed to kill child"));
-         return;
-       }
-
-      ret = my_waitpid (child_pid, &status, 0);
-      if (ret != child_pid)
-       warning (_("linux_test_for_tracefork: failed "
-                  "to wait for killed child"));
-      else if (!WIFSIGNALED (status))
-       warning (_("linux_test_for_tracefork: unexpected "
-                  "wait status 0x%x from killed child"), status);
-
-      return;
-    }
-
-  /* Check whether PTRACE_O_TRACEVFORKDONE is available.  */
-  ret = ptrace (PTRACE_SETOPTIONS, child_pid, 0,
-               PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORKDONE);
-  linux_supports_tracevforkdone_flag = (ret == 0);
-
-  ret = ptrace (PTRACE_CONT, child_pid, 0, 0);
-  if (ret != 0)
-    warning (_("linux_test_for_tracefork: failed to resume child"));
-
-  ret = my_waitpid (child_pid, &status, 0);
-
-  if (ret == child_pid && WIFSTOPPED (status)
-      && status >> 16 == PTRACE_EVENT_FORK)
-    {
-      second_pid = 0;
-      ret = ptrace (PTRACE_GETEVENTMSG, child_pid, 0, &second_pid);
-      if (ret == 0 && second_pid != 0)
-       {
-         int second_status;
-
-         linux_supports_tracefork_flag = 1;
-         my_waitpid (second_pid, &second_status, 0);
-         ret = ptrace (PTRACE_KILL, second_pid, 0, 0);
-         if (ret != 0)
-           warning (_("linux_test_for_tracefork: "
-                      "failed to kill second child"));
-         my_waitpid (second_pid, &status, 0);
-       }
-    }
-  else
-    warning (_("linux_test_for_tracefork: unexpected result from waitpid "
-            "(%d, status 0x%x)"), ret, status);
-
-  do
-    {
-      ret = ptrace (PTRACE_KILL, child_pid, 0, 0);
-      if (ret != 0)
-       warning ("linux_test_for_tracefork: failed to kill child");
-      my_waitpid (child_pid, &status, 0);
-    }
-  while (WIFSTOPPED (status));
-}
-
-/* Determine if PTRACE_O_TRACESYSGOOD can be used to follow syscalls.
-
-   We try to enable syscall tracing on ORIGINAL_PID.  If this fails,
-   we know that the feature is not available.  This may change the tracing
-   options for ORIGINAL_PID, but we'll be setting them shortly anyway.  */
-
-static void
-linux_test_for_tracesysgood (int original_pid)
-{
-  int ret;
-
-  linux_supports_tracesysgood_flag = 0;
-
-  ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACESYSGOOD);
-  if (ret != 0)
-    return;
-
-  linux_supports_tracesysgood_flag = 1;
-}
-
-/* Determine wether we support PTRACE_O_TRACESYSGOOD option available.
-   This function also sets linux_supports_tracesysgood_flag.  */
-
-static int
-linux_supports_tracesysgood (int pid)
-{
-  if (linux_supports_tracesysgood_flag == -1)
-    linux_test_for_tracesysgood (pid);
-  return linux_supports_tracesysgood_flag;
-}
-
-/* Return non-zero iff we have tracefork functionality available.
-   This function also sets linux_supports_tracefork_flag.  */
-
-static int
-linux_supports_tracefork (int pid)
-{
-  if (linux_supports_tracefork_flag == -1)
-    linux_test_for_tracefork (pid);
-  return linux_supports_tracefork_flag;
-}
-
-static int
-linux_supports_tracevforkdone (int pid)
-{
-  if (linux_supports_tracefork_flag == -1)
-    linux_test_for_tracefork (pid);
-  return linux_supports_tracevforkdone_flag;
-}
-
-static void
-linux_enable_tracesysgood (ptid_t ptid)
-{
-  int pid = ptid_get_lwp (ptid);
-
-  if (pid == 0)
-    pid = ptid_get_pid (ptid);
-
-  if (linux_supports_tracesysgood (pid) == 0)
-    return;
-
-  current_ptrace_options |= PTRACE_O_TRACESYSGOOD;
-
-  ptrace (PTRACE_SETOPTIONS, pid, 0, current_ptrace_options);
-}
-
-\f
-void
-linux_enable_event_reporting (ptid_t ptid)
-{
-  int pid = ptid_get_lwp (ptid);
-
-  if (pid == 0)
-    pid = ptid_get_pid (ptid);
-
-  if (! linux_supports_tracefork (pid))
-    return;
-
-  current_ptrace_options |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK
-    | PTRACE_O_TRACEEXEC | PTRACE_O_TRACECLONE;
-
-  if (linux_supports_tracevforkdone (pid))
-    current_ptrace_options |= PTRACE_O_TRACEVFORKDONE;
-
-  /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to support
-     read-only process state.  */
-
-  ptrace (PTRACE_SETOPTIONS, pid, 0, current_ptrace_options);
+  linux_enable_event_reporting (pid);
+  linux_ptrace_init_warnings ();
 }
 
 static void
 linux_child_post_attach (int pid)
 {
-  linux_enable_event_reporting (pid_to_ptid (pid));
-  linux_enable_tracesysgood (pid_to_ptid (pid));
-  linux_ptrace_init_warnings ();
+  linux_init_ptrace (pid);
 }
 
 static void
 linux_child_post_startup_inferior (ptid_t ptid)
 {
-  linux_enable_event_reporting (ptid);
-  linux_enable_tracesysgood (ptid);
-  linux_ptrace_init_warnings ();
+  linux_init_ptrace (ptid_get_pid (ptid));
 }
 
 /* Return the number of known LWPs in the tgid given by PID.  */
@@ -772,9 +533,9 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          parent_inf->pspace->breakpoints_not_allowed = detach_fork;
 
          parent_lp = find_lwp_pid (pid_to_ptid (parent_pid));
-         gdb_assert (linux_supports_tracefork_flag >= 0);
+         gdb_assert (linux_supports_tracefork () >= 0);
 
-         if (linux_supports_tracevforkdone (0))
+         if (linux_supports_tracevforkdone ())
            {
              if (debug_linux_nat)
                fprintf_unfiltered (gdb_stdlog,
@@ -945,7 +706,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 static int
 linux_child_insert_fork_catchpoint (int pid)
 {
-  return !linux_supports_tracefork (pid);
+  return !linux_supports_tracefork ();
 }
 
 static int
@@ -957,7 +718,7 @@ linux_child_remove_fork_catchpoint (int pid)
 static int
 linux_child_insert_vfork_catchpoint (int pid)
 {
-  return !linux_supports_tracefork (pid);
+  return !linux_supports_tracefork ();
 }
 
 static int
@@ -969,7 +730,7 @@ linux_child_remove_vfork_catchpoint (int pid)
 static int
 linux_child_insert_exec_catchpoint (int pid)
 {
-  return !linux_supports_tracefork (pid);
+  return !linux_supports_tracefork ();
 }
 
 static int
@@ -982,7 +743,7 @@ static int
 linux_child_set_syscall_catchpoint (int pid, int needed, int any_count,
                                    int table_size, int *table)
 {
-  if (!linux_supports_tracesysgood (pid))
+  if (!linux_supports_tracesysgood ())
     return 1;
 
   /* On GNU/Linux, we ignore the arguments.  It means that we only
@@ -1429,7 +1190,7 @@ lin_lwp_attach_lwp (ptid_t ptid)
 
       if (ptrace (PTRACE_ATTACH, lwpid, 0, 0) < 0)
        {
-         if (linux_supports_tracefork_flag)
+         if (linux_supports_tracefork ())
            {
              /* If we haven't stopped all threads when we get here,
                 we may have seen a thread listed in thread_db's list,
index cb8f1dacce801949718ac6c9942a0794b4fe8b20..044f646b389576974ca2526e8a4339731cde3f9a 100644 (file)
@@ -127,9 +127,6 @@ extern void lin_thread_get_thread_signals (sigset_t *mask);
 void linux_proc_pending_signals (int pid, sigset_t *pending,
                                 sigset_t *blocked, sigset_t *ignored);
 
-/* linux-nat functions for handling fork events.  */
-extern void linux_enable_event_reporting (ptid_t ptid);
-
 extern int lin_lwp_attach_lwp (ptid_t ptid);
 
 extern void linux_stop_lwp (struct lwp_info *lwp);
diff --git a/gdb/nat/linux-nat.h b/gdb/nat/linux-nat.h
new file mode 100644 (file)
index 0000000..4d84aa5
--- /dev/null
@@ -0,0 +1,28 @@
+/* Code for native debugging support for GNU/Linux (LWP layer).
+
+   Copyright (C) 2000-2013 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef LINUX_NAT_H
+#define LINUX_NAT_H
+
+/* Unlike other extended result codes, WSTOPSIG (status) on
+   PTRACE_O_TRACESYSGOOD syscall events doesn't return SIGTRAP, but
+   instead SIGTRAP with bit 7 set.  */
+#define SYSCALL_SIGTRAP (SIGTRAP | 0x80)
+
+#endif /* LINUX_NAT_H */
diff --git a/gdb/nat/linux-waitpid.c b/gdb/nat/linux-waitpid.c
new file mode 100644 (file)
index 0000000..2debea4
--- /dev/null
@@ -0,0 +1,120 @@
+/* Wrapper implementation for waitpid for GNU/Linux (LWP layer).
+
+   Copyright (C) 2001-2013 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef GDBSERVER
+#include "server.h"
+#else
+#include "defs.h"
+#include "signal.h"
+#endif
+
+#include "nat/linux-nat.h"
+#include "nat/linux-waitpid.h"
+#include "gdb_wait.h"
+
+/* Print debugging output based on the format string FORMAT and
+   its parameters.  */
+
+static inline void
+linux_debug (const char *format, ...)
+{
+#ifdef GDBSERVER
+  if (debug_threads)
+    {
+      va_list args;
+      va_start (args, format);
+      vfprintf (stderr, format, args);
+      fprintf (stderr, "\n");
+      va_end (args);
+    }
+#else
+  /* GDB-specific debugging output.  */
+#endif
+}
+
+/* Wrapper function for waitpid which handles EINTR, and emulates
+   __WALL for systems where that is not available.  */
+
+int
+my_waitpid (int pid, int *status, int flags)
+{
+  int ret, out_errno;
+
+  linux_debug ("my_waitpid (%d, 0x%x)\n", pid, flags);
+
+  if (flags & __WALL)
+    {
+      sigset_t block_mask, org_mask, wake_mask;
+      int wnohang;
+
+      wnohang = (flags & WNOHANG) != 0;
+      flags &= ~(__WALL | __WCLONE);
+      flags |= WNOHANG;
+
+      /* Block all signals while here.  This avoids knowing about
+        LinuxThread's signals.  */
+      sigfillset (&block_mask);
+      sigprocmask (SIG_BLOCK, &block_mask, &org_mask);
+
+      /* ... except during the sigsuspend below.  */
+      sigemptyset (&wake_mask);
+
+      while (1)
+       {
+         /* Since all signals are blocked, there's no need to check
+            for EINTR here.  */
+         ret = waitpid (pid, status, flags);
+         out_errno = errno;
+
+         if (ret == -1 && out_errno != ECHILD)
+           break;
+         else if (ret > 0)
+           break;
+
+         if (flags & __WCLONE)
+           {
+             /* We've tried both flavors now.  If WNOHANG is set,
+                there's nothing else to do, just bail out.  */
+             if (wnohang)
+               break;
+
+             linux_debug ("blocking\n");
+
+             /* Block waiting for signals.  */
+             sigsuspend (&wake_mask);
+           }
+         flags ^= __WCLONE;
+       }
+
+      sigprocmask (SIG_SETMASK, &org_mask, NULL);
+    }
+  else
+    {
+      do
+       ret = waitpid (pid, status, flags);
+      while (ret == -1 && errno == EINTR);
+      out_errno = errno;
+    }
+
+  linux_debug ("my_waitpid (%d, 0x%x): status(%x), %d\n",
+              pid, flags, status ? *status : -1, ret);
+
+  errno = out_errno;
+  return ret;
+}
diff --git a/gdb/nat/linux-waitpid.h b/gdb/nat/linux-waitpid.h
new file mode 100644 (file)
index 0000000..0df29d8
--- /dev/null
@@ -0,0 +1,27 @@
+/* Wrapper for waitpid for GNU/Linux (LWP layer).
+
+   Copyright (C) 2000-2013 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef LINUX_WAITPID_H
+#define LINUX_WAITPID_H
+
+/* Wrapper function for waitpid which handles EINTR, and emulates
+   __WALL for systems where that is not available.  */
+extern int my_waitpid (int pid, int *status, int flags);
+
+#endif /* LINUX_WAITPID_H */