Don't return stale data from fbsd_pid_to_exec_file for kernel processes.
[deliverable/binutils-gdb.git] / gdb / fbsd-nat.c
index fa9516e2ecf121ca4b5c40d01d2dfd41314ca569..d0aaf8914568be09515633c81e89a57a86f262d2 100644 (file)
@@ -1,6 +1,6 @@
 /* Native-dependent code for FreeBSD.
 
-   Copyright (C) 2002-2016 Free Software Foundation, Inc.
+   Copyright (C) 2002-2018 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -18,6 +18,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "byte-vector.h"
 #include "gdbcore.h"
 #include "inferior.h"
 #include "regcache.h"
 #include <sys/types.h>
 #include <sys/procfs.h>
 #include <sys/ptrace.h>
+#include <sys/signal.h>
 #include <sys/sysctl.h>
-#ifdef HAVE_KINFO_GETVMMAP
 #include <sys/user.h>
+#ifdef HAVE_KINFO_GETVMMAP
 #include <libutil.h>
+#else
+#include "filestuff.h"
 #endif
 
 #include "elf-bfd.h"
 #include "fbsd-nat.h"
 
+#include <list>
+
 /* Return the name of a file that can be opened to get the symbols for
    the child process identified by PID.  */
 
@@ -57,7 +63,10 @@ fbsd_pid_to_exec_file (struct target_ops *self, int pid)
   mib[3] = pid;
   buflen = sizeof buf;
   if (sysctl (mib, 4, buf, &buflen, NULL, 0) == 0)
-    return buf;
+    /* The kern.proc.pathname.<pid> sysctl returns a length of zero
+       for processes without an associated executable such as kernel
+       processes.  */
+    return buflen == 0 ? NULL : buf;
 #endif
 
   xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
@@ -72,6 +81,14 @@ fbsd_pid_to_exec_file (struct target_ops *self, int pid)
 }
 
 #ifdef HAVE_KINFO_GETVMMAP
+/* Deleter for std::unique_ptr that invokes free.  */
+
+template <typename T>
+struct free_deleter
+{
+  void operator() (T *ptr) const { free (ptr); }
+};
+
 /* Iterate over all the memory regions in the current inferior,
    calling FUNC for each memory region.  OBFD is passed as the last
    argument to FUNC.  */
@@ -81,20 +98,17 @@ fbsd_find_memory_regions (struct target_ops *self,
                          find_memory_region_ftype func, void *obfd)
 {
   pid_t pid = ptid_get_pid (inferior_ptid);
-  struct kinfo_vmentry *vmentl, *kve;
+  struct kinfo_vmentry *kve;
   uint64_t size;
-  struct cleanup *cleanup;
   int i, nitems;
 
-  vmentl = kinfo_getvmmap (pid, &nitems);
+  std::unique_ptr<struct kinfo_vmentry, free_deleter<struct kinfo_vmentry>>
+    vmentl (kinfo_getvmmap (pid, &nitems));
   if (vmentl == NULL)
     perror_with_name (_("Couldn't fetch VM map entries."));
-  cleanup = make_cleanup (free, vmentl);
 
-  for (i = 0; i < nitems; i++)
+  for (i = 0, kve = vmentl.get (); i < nitems; i++, kve++)
     {
-      kve = &vmentl[i];
-
       /* Skip unreadable segments and those where MAP_NOCORE has been set.  */
       if (!(kve->kve_protection & KVME_PROT_READ)
          || kve->kve_flags & KVME_FLAG_NOCOREDUMP)
@@ -125,7 +139,6 @@ fbsd_find_memory_regions (struct target_ops *self,
            kve->kve_protection & KVME_PROT_WRITE,
            kve->kve_protection & KVME_PROT_EXEC, 1, obfd);
     }
-  do_cleanups (cleanup);
   return 0;
 }
 #else
@@ -159,26 +172,21 @@ fbsd_find_memory_regions (struct target_ops *self,
                          find_memory_region_ftype func, void *obfd)
 {
   pid_t pid = ptid_get_pid (inferior_ptid);
-  char *mapfilename;
-  FILE *mapfile;
   unsigned long start, end, size;
   char protection[4];
   int read, write, exec;
-  struct cleanup *cleanup;
 
-  mapfilename = xstrprintf ("/proc/%ld/map", (long) pid);
-  cleanup = make_cleanup (xfree, mapfilename);
-  mapfile = fopen (mapfilename, "r");
+  std::string mapfilename = string_printf ("/proc/%ld/map", (long) pid);
+  gdb_file_up mapfile (fopen (mapfilename.c_str (), "r"));
   if (mapfile == NULL)
-    error (_("Couldn't open %s."), mapfilename);
-  make_cleanup_fclose (mapfile);
+    error (_("Couldn't open %s."), mapfilename.c_str ());
 
   if (info_verbose)
     fprintf_filtered (gdb_stdout, 
-                     "Reading memory regions from %s\n", mapfilename);
+                     "Reading memory regions from %s\n", mapfilename.c_str ());
 
   /* Now iterate until end-of-file.  */
-  while (fbsd_read_mapping (mapfile, &start, &end, &protection[0]))
+  while (fbsd_read_mapping (mapfile.get (), &start, &end, &protection[0]))
     {
       size = end - start;
 
@@ -201,7 +209,6 @@ fbsd_find_memory_regions (struct target_ops *self,
       func (start, size, read, write, exec, 1, obfd);
     }
 
-  do_cleanups (cleanup);
   return 0;
 }
 #endif
@@ -216,6 +223,135 @@ static enum target_xfer_status (*super_xfer_partial) (struct target_ops *ops,
                                                      ULONGEST len,
                                                      ULONGEST *xfered_len);
 
+#ifdef PT_LWPINFO
+/* Return the size of siginfo for the current inferior.  */
+
+#ifdef __LP64__
+union sigval32 {
+  int sival_int;
+  uint32_t sival_ptr;
+};
+
+/* This structure matches the naming and layout of `siginfo_t' in
+   <sys/signal.h>.  In particular, the `si_foo' macros defined in that
+   header can be used with both types to copy fields in the `_reason'
+   union.  */
+
+struct siginfo32
+{
+  int si_signo;
+  int si_errno;
+  int si_code;
+  __pid_t si_pid;
+  __uid_t si_uid;
+  int si_status;
+  uint32_t si_addr;
+  union sigval32 si_value;
+  union
+  {
+    struct
+    {
+      int _trapno;
+    } _fault;
+    struct
+    {
+      int _timerid;
+      int _overrun;
+    } _timer;
+    struct
+    {
+      int _mqd;
+    } _mesgq;
+    struct
+    {
+      int32_t _band;
+    } _poll;
+    struct
+    {
+      int32_t __spare1__;
+      int __spare2__[7];
+    } __spare__;
+  } _reason;
+};
+#endif
+
+static size_t
+fbsd_siginfo_size ()
+{
+#ifdef __LP64__
+  struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
+
+  /* Is the inferior 32-bit?  If so, use the 32-bit siginfo size.  */
+  if (gdbarch_long_bit (gdbarch) == 32)
+    return sizeof (struct siginfo32);
+#endif
+  return sizeof (siginfo_t);
+}
+
+/* Convert a native 64-bit siginfo object to a 32-bit object.  Note
+   that FreeBSD doesn't support writing to $_siginfo, so this only
+   needs to convert one way.  */
+
+static void
+fbsd_convert_siginfo (siginfo_t *si)
+{
+#ifdef __LP64__
+  struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
+
+  /* Is the inferior 32-bit?  If not, nothing to do.  */
+  if (gdbarch_long_bit (gdbarch) != 32)
+    return;
+
+  struct siginfo32 si32;
+
+  si32.si_signo = si->si_signo;
+  si32.si_errno = si->si_errno;
+  si32.si_code = si->si_code;
+  si32.si_pid = si->si_pid;
+  si32.si_uid = si->si_uid;
+  si32.si_status = si->si_status;
+  si32.si_addr = (uintptr_t) si->si_addr;
+
+  /* If sival_ptr is being used instead of sival_int on a big-endian
+     platform, then sival_int will be zero since it holds the upper
+     32-bits of the pointer value.  */
+#if _BYTE_ORDER == _BIG_ENDIAN
+  if (si->si_value.sival_int == 0)
+    si32.si_value.sival_ptr = (uintptr_t) si->si_value.sival_ptr;
+  else
+    si32.si_value.sival_int = si->si_value.sival_int;
+#else
+  si32.si_value.sival_int = si->si_value.sival_int;
+#endif
+
+  /* Always copy the spare fields and then possibly overwrite them for
+     signal-specific or code-specific fields.  */
+  si32._reason.__spare__.__spare1__ = si->_reason.__spare__.__spare1__;
+  for (int i = 0; i < 7; i++)
+    si32._reason.__spare__.__spare2__[i] = si->_reason.__spare__.__spare2__[i];
+  switch (si->si_signo) {
+  case SIGILL:
+  case SIGFPE:
+  case SIGSEGV:
+  case SIGBUS:
+    si32.si_trapno = si->si_trapno;
+    break;
+  }
+  switch (si->si_code) {
+  case SI_TIMER:
+    si32.si_timerid = si->si_timerid;
+    si32.si_overrun = si->si_overrun;
+    break;
+  case SI_MESGQ:
+    si32.si_mqd = si->si_mqd;
+    break;
+  }
+
+  memcpy(si, &si32, sizeof (si32));
+#endif
+}
+#endif
+
 /* Implement the "to_xfer_partial target_ops" method.  */
 
 static enum target_xfer_status
@@ -228,10 +364,42 @@ fbsd_xfer_partial (struct target_ops *ops, enum target_object object,
 
   switch (object)
     {
+#ifdef PT_LWPINFO
+    case TARGET_OBJECT_SIGNAL_INFO:
+      {
+       struct ptrace_lwpinfo pl;
+       size_t siginfo_size;
+
+       /* FreeBSD doesn't support writing to $_siginfo.  */
+       if (writebuf != NULL)
+         return TARGET_XFER_E_IO;
+
+       if (inferior_ptid.lwp_p ())
+         pid = inferior_ptid.lwp ();
+
+       siginfo_size = fbsd_siginfo_size ();
+       if (offset > siginfo_size)
+         return TARGET_XFER_E_IO;
+
+       if (ptrace (PT_LWPINFO, pid, (PTRACE_TYPE_ARG3) &pl, sizeof (pl)) == -1)
+         return TARGET_XFER_E_IO;
+
+       if (!(pl.pl_flags & PL_FLAG_SI))
+         return TARGET_XFER_E_IO;
+
+       fbsd_convert_siginfo (&pl.pl_siginfo);
+       if (offset + len > siginfo_size)
+         len = siginfo_size - offset;
+
+       memcpy (readbuf, ((gdb_byte *) &pl.pl_siginfo) + offset, len);
+       *xfered_len = len;
+       return TARGET_XFER_OK;
+      }
+#endif
     case TARGET_OBJECT_AUXV:
       {
-       struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
-       unsigned char *buf;
+       gdb::byte_vector buf_storage;
+       gdb_byte *buf;
        size_t buflen;
        int mib[4];
 
@@ -249,8 +417,8 @@ fbsd_xfer_partial (struct target_ops *ops, enum target_object object,
        else
          {
            buflen = offset + len;
-           buf = XCNEWVEC (unsigned char, buflen);
-           cleanup = make_cleanup (xfree, buf);
+           buf_storage.resize (buflen);
+           buf = buf_storage.data ();
          }
        if (sysctl (mib, 4, buf, &buflen, NULL, 0) == 0)
          {
@@ -264,11 +432,9 @@ fbsd_xfer_partial (struct target_ops *ops, enum target_object object,
                else
                  buflen = 0;
              }
-           do_cleanups (cleanup);
            *xfered_len = buflen;
            return (buflen == 0) ? TARGET_XFER_EOF : TARGET_XFER_OK;
          }
-       do_cleanups (cleanup);
        return TARGET_XFER_E_IO;
       }
     default:
@@ -321,7 +487,7 @@ fbsd_fetch_kinfo_proc (pid_t pid, struct kinfo_proc *kp)
   FreeBSD's first thread support was via a "reentrant" version of libc
   (libc_r) that first shipped in 2.2.7.  This library multiplexed all
   of the threads in a process onto a single kernel thread.  This
-  library is supported via the bsd-uthread target.
+  library was supported via the bsd-uthread target.
 
   FreeBSD 5.1 introduced two new threading libraries that made use of
   multiple kernel threads.  The first (libkse) scheduled M user
@@ -368,7 +534,7 @@ fbsd_thread_alive (struct target_ops *ops, ptid_t ptid)
 /* Convert PTID to a string.  Returns the string in a static
    buffer.  */
 
-static char *
+static const char *
 fbsd_pid_to_str (struct target_ops *ops, ptid_t ptid)
 {
   lwpid_t lwp;
@@ -412,22 +578,46 @@ fbsd_thread_name (struct target_ops *self, struct thread_info *thr)
 }
 #endif
 
-#ifdef PT_LWP_EVENTS
-/* Enable LWP events for a specific process.
+/* Enable additional event reporting on new processes.
+
+   To catch fork events, PTRACE_FORK is set on every traced process
+   to enable stops on returns from fork or vfork.  Note that both the
+   parent and child will always stop, even if system call stops are
+   not enabled.
 
-   To catch LWP events, PT_LWP_EVENTS is set on every traced process.
+   To catch LWP events, PTRACE_EVENTS is set on every traced process.
    This enables stops on the birth for new LWPs (excluding the "main" LWP)
    and the death of LWPs (excluding the last LWP in a process).  Note
    that unlike fork events, the LWP that creates a new LWP does not
    report an event.  */
 
 static void
-fbsd_enable_lwp_events (pid_t pid)
+fbsd_enable_proc_events (pid_t pid)
 {
+#ifdef PT_GET_EVENT_MASK
+  int events;
+
+  if (ptrace (PT_GET_EVENT_MASK, pid, (PTRACE_TYPE_ARG3)&events,
+             sizeof (events)) == -1)
+    perror_with_name (("ptrace"));
+  events |= PTRACE_FORK | PTRACE_LWP;
+#ifdef PTRACE_VFORK
+  events |= PTRACE_VFORK;
+#endif
+  if (ptrace (PT_SET_EVENT_MASK, pid, (PTRACE_TYPE_ARG3)&events,
+             sizeof (events)) == -1)
+    perror_with_name (("ptrace"));
+#else
+#ifdef TDP_RFPPWAIT
+  if (ptrace (PT_FOLLOW_FORK, pid, (PTRACE_TYPE_ARG3)0, 1) == -1)
+    perror_with_name (("ptrace"));
+#endif
+#ifdef PT_LWP_EVENTS
   if (ptrace (PT_LWP_EVENTS, pid, (PTRACE_TYPE_ARG3)0, 1) == -1)
     perror_with_name (("ptrace"));
-}
 #endif
+#endif
+}
 
 /* Add threads for any new LWPs in a process.
 
@@ -438,8 +628,6 @@ fbsd_enable_lwp_events (pid_t pid)
 static void
 fbsd_add_threads (pid_t pid)
 {
-  struct cleanup *cleanup;
-  lwpid_t *lwps;
   int i, nlwps;
 
   gdb_assert (!in_thread_list (pid_to_ptid (pid)));
@@ -447,10 +635,9 @@ fbsd_add_threads (pid_t pid)
   if (nlwps == -1)
     perror_with_name (("ptrace"));
 
-  lwps = XCNEWVEC (lwpid_t, nlwps);
-  cleanup = make_cleanup (xfree, lwps);
+  gdb::unique_xmalloc_ptr<lwpid_t[]> lwps (XCNEWVEC (lwpid_t, nlwps));
 
-  nlwps = ptrace (PT_GETLWPLIST, pid, (caddr_t) lwps, nlwps);
+  nlwps = ptrace (PT_GETLWPLIST, pid, (caddr_t) lwps.get (), nlwps);
   if (nlwps == -1)
     perror_with_name (("ptrace"));
 
@@ -477,7 +664,6 @@ fbsd_add_threads (pid_t pid)
          add_thread (ptid);
        }
     }
-  do_cleanups (cleanup);
 }
 
 /* Implement the "to_update_thread_list" target_ops method.  */
@@ -530,13 +716,7 @@ fbsd_update_thread_list (struct target_ops *ops)
   sake.  FreeBSD versions newer than 9.1 contain both fixes.
 */
 
-struct fbsd_fork_info
-{
-  struct fbsd_fork_info *next;
-  ptid_t ptid;
-};
-
-static struct fbsd_fork_info *fbsd_pending_children;
+static std::list<ptid_t> fbsd_pending_children;
 
 /* Record a new child process event that is reported before the
    corresponding fork event in the parent.  */
@@ -544,11 +724,7 @@ static struct fbsd_fork_info *fbsd_pending_children;
 static void
 fbsd_remember_child (ptid_t pid)
 {
-  struct fbsd_fork_info *info = XCNEW (struct fbsd_fork_info);
-
-  info->ptid = pid;
-  info->next = fbsd_pending_children;
-  fbsd_pending_children = info;
+  fbsd_pending_children.push_front (pid);
 }
 
 /* Check for a previously-recorded new child process event for PID.
@@ -557,38 +733,26 @@ fbsd_remember_child (ptid_t pid)
 static ptid_t
 fbsd_is_child_pending (pid_t pid)
 {
-  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->ptid) == pid)
-       {
-         if (prev == NULL)
-           fbsd_pending_children = info->next;
-         else
-           prev->next = info->next;
-         ptid = info->ptid;
-         xfree (info);
-         return ptid;
-       }
-    }
+  for (auto it = fbsd_pending_children.begin ();
+       it != fbsd_pending_children.end (); it++)
+    if (it->pid () == pid)
+      {
+       ptid_t ptid = *it;
+       fbsd_pending_children.erase (it);
+       return ptid;
+      }
   return null_ptid;
 }
 
-static struct fbsd_fork_info *fbsd_pending_vfork_done;
+#ifndef PTRACE_VFORK
+static std::forward_list<ptid_t> 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;
+  fbsd_pending_vfork_done.push_front (pid);
 }
 
 /* Check for a pending vfork done event for a specific PID.  */
@@ -596,13 +760,10 @@ fbsd_add_vfork_done (ptid_t 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;
-    }
+  for (auto it = fbsd_pending_vfork_done.begin ();
+       it != fbsd_pending_vfork_done.end (); it++)
+    if (it->pid () == pid)
+      return 1;
   return 0;
 }
 
@@ -612,52 +773,16 @@ fbsd_is_vfork_done_pending (pid_t pid)
 static ptid_t
 fbsd_next_vfork_done (void)
 {
-  struct fbsd_fork_info *info;
-  ptid_t ptid;
-
-  if (fbsd_pending_vfork_done != NULL)
+  if (!fbsd_pending_vfork_done.empty ())
     {
-      info = fbsd_pending_vfork_done;
-      fbsd_pending_vfork_done = info->next;
-      ptid = info->ptid;
-      xfree (info);
+      ptid_t ptid = fbsd_pending_vfork_done.front ();
+      fbsd_pending_vfork_done.pop_front ();
       return ptid;
     }
   return null_ptid;
 }
 #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;
-}
+#endif
 
 /* Implement the "to_resume" target_ops method.  */
 
@@ -665,7 +790,7 @@ static void
 fbsd_resume (struct target_ops *ops,
             ptid_t ptid, int step, enum gdb_signal signo)
 {
-#ifdef TDP_RFPPWAIT
+#if defined(TDP_RFPPWAIT) && !defined(PTRACE_VFORK)
   pid_t pid;
 
   /* Don't PT_CONTINUE a process which has a pending vfork done event.  */
@@ -685,13 +810,37 @@ fbsd_resume (struct target_ops *ops,
   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);
+      struct thread_info *tp;
+      int request;
+
+      ALL_NON_EXITED_THREADS (tp)
+        {
+         if (ptid_get_pid (tp->ptid) != ptid_get_pid (ptid))
+           continue;
+
+         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"));
+       }
     }
   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);
+      struct thread_info *tp;
+
+      ALL_NON_EXITED_THREADS (tp)
+        {
+         if (!ptid_match (tp->ptid, ptid))
+           continue;
+
+         if (ptrace (PT_RESUME, ptid_get_lwp (tp->ptid), NULL, 0) == -1)
+           perror_with_name (("ptrace"));
+       }
       ptid = inferior_ptid;
     }
   super_resume (ops, ptid, step, signo);
@@ -710,12 +859,14 @@ fbsd_wait (struct target_ops *ops,
 
   while (1)
     {
+#ifndef PTRACE_VFORK
       wptid = fbsd_next_vfork_done ();
       if (!ptid_equal (wptid, null_ptid))
        {
          ourstatus->kind = TARGET_WAITKIND_VFORK_DONE;
          return wptid;
        }
+#endif
       wptid = super_wait (ops, ptid, ourstatus, target_options);
       if (ourstatus->kind == TARGET_WAITKIND_STOPPED)
        {
@@ -791,12 +942,18 @@ fbsd_wait (struct target_ops *ops,
 #ifdef TDP_RFPPWAIT
          if (pl.pl_flags & PL_FLAG_FORKED)
            {
+#ifndef PTRACE_VFORK
              struct kinfo_proc kp;
+#endif
              ptid_t child_ptid;
              pid_t child;
 
              child = pl.pl_child_pid;
              ourstatus->kind = TARGET_WAITKIND_FORKED;
+#ifdef PTRACE_VFORK
+             if (pl.pl_flags & PL_FLAG_VFORKED)
+               ourstatus->kind = TARGET_WAITKIND_VFORKED;
+#endif
 
              /* Make sure the other end of the fork is stopped too.  */
              child_ptid = fbsd_is_child_pending (child);
@@ -815,11 +972,16 @@ fbsd_wait (struct target_ops *ops,
                  child_ptid = ptid_build (child, pl.pl_lwpid, 0);
                }
 
+             /* Enable additional events on the child process.  */
+             fbsd_enable_proc_events (ptid_get_pid (child_ptid));
+
+#ifndef PTRACE_VFORK
              /* For vfork, the child process will have the P_PPWAIT
                 flag set.  */
              fbsd_fetch_kinfo_proc (child, &kp);
              if (kp.ki_flag & P_PPWAIT)
                ourstatus->kind = TARGET_WAITKIND_VFORKED;
+#endif
              ourstatus->value.related_pid = child_ptid;
 
              return wptid;
@@ -833,6 +995,14 @@ fbsd_wait (struct target_ops *ops,
              fbsd_remember_child (wptid);
              continue;
            }
+
+#ifdef PTRACE_VFORK
+         if (pl.pl_flags & PL_FLAG_VFORK_DONE)
+           {
+             ourstatus->kind = TARGET_WAITKIND_VFORK_DONE;
+             return wptid;
+           }
+#endif
 #endif
 
 #ifdef PL_FLAG_EXEC
@@ -894,7 +1064,6 @@ 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
@@ -903,7 +1072,8 @@ 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)
+#ifndef PTRACE_VFORK
+      if (tp->pending_follow.kind == TARGET_WAITKIND_VFORKED)
        {
          /* We can't insert breakpoints until the child process has
             finished with the shared memory region.  The parent
@@ -929,6 +1099,7 @@ fbsd_follow_fork (struct target_ops *ops, int follow_child,
             wait.  */
          fbsd_add_vfork_done (inferior_ptid);
        }
+#endif
     }
 
   return 0;
@@ -957,20 +1128,6 @@ fbsd_remove_vfork_catchpoint (struct target_ops *self, int pid)
 {
   return 0;
 }
-
-/* Enable fork tracing for a specific process.
-   
-   To catch fork events, PT_FOLLOW_FORK is set on every traced process
-   to enable stops on returns from fork or vfork.  Note that both the
-   parent and child will always stop, even if system call stops are
-   not enabled.  */
-
-static void
-fbsd_enable_follow_fork (pid_t pid)
-{
-  if (ptrace (PT_FOLLOW_FORK, pid, (PTRACE_TYPE_ARG3)0, 1) == -1)
-    perror_with_name (("ptrace"));
-}
 #endif
 
 /* Implement the "to_post_startup_inferior" target_ops method.  */
@@ -978,12 +1135,7 @@ fbsd_enable_follow_fork (pid_t pid)
 static void
 fbsd_post_startup_inferior (struct target_ops *self, ptid_t pid)
 {
-#ifdef TDP_RFPPWAIT
-  fbsd_enable_follow_fork (ptid_get_pid (pid));
-#endif
-#ifdef PT_LWP_EVENTS
-  fbsd_enable_lwp_events (ptid_get_pid (pid));
-#endif
+  fbsd_enable_proc_events (ptid_get_pid (pid));
 }
 
 /* Implement the "to_post_attach" target_ops method.  */
@@ -991,12 +1143,7 @@ fbsd_post_startup_inferior (struct target_ops *self, ptid_t pid)
 static void
 fbsd_post_attach (struct target_ops *self, int pid)
 {
-#ifdef TDP_RFPPWAIT
-  fbsd_enable_follow_fork (pid);
-#endif
-#ifdef PT_LWP_EVENTS
-  fbsd_enable_lwp_events (pid);
-#endif
+  fbsd_enable_proc_events (pid);
   fbsd_add_threads (pid);
 }
 
@@ -1019,8 +1166,9 @@ fbsd_remove_exec_catchpoint (struct target_ops *self, int pid)
 
 #ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE
 static int
-fbsd_set_syscall_catchpoint (struct target_ops *self, int pid, int needed,
-                            int any_count, int table_size, int *table)
+fbsd_set_syscall_catchpoint (struct target_ops *self, int pid, bool needed,
+                            int any_count,
+                            gdb::array_view<const int> syscall_counts)
 {
 
   /* Ignore the arguments.  inf-ptrace.c will use PT_SYSCALL which
@@ -1072,9 +1220,6 @@ fbsd_nat_add_target (struct target_ops *t)
   add_target (t);
 }
 
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-extern initialize_file_ftype _initialize_fbsd_nat;
-
 void
 _initialize_fbsd_nat (void)
 {
This page took 0.032802 seconds and 4 git commands to generate.