btrace: Fix memory leak in btrace_clear.
[deliverable/binutils-gdb.git] / gdb / nto-procfs.c
index 7854d2a987e698934b2114bb54ec767848e6d9c7..7fb7095745fda2d15a32ce5e424018a357fa6fa7 100644 (file)
@@ -1,7 +1,7 @@
 /* Machine independent support for QNX Neutrino /proc (process file system)
 /* Machine independent support for QNX Neutrino /proc (process file system)
-   for GDB.  Written by Colin Burgess at QNX Software Systems Limited. 
+   for GDB.  Written by Colin Burgess at QNX Software Systems Limited.
 
 
-   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2003-2017 Free Software Foundation, Inc.
 
    Contributed by QNX Software Systems Ltd.
 
 
    Contributed by QNX Software Systems Ltd.
 
@@ -9,7 +9,7 @@
 
    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
 
    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 2 of the License, or
+   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,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -18,9 +18,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    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, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 
 
 #include "defs.h"
 
 #include <sys/procfs.h>
 #include <sys/neutrino.h>
 #include <sys/syspage.h>
 #include <sys/procfs.h>
 #include <sys/neutrino.h>
 #include <sys/syspage.h>
-#include "gdb_dirent.h"
+#include <dirent.h>
 #include <sys/netmgr.h>
 #include <sys/netmgr.h>
+#include <sys/auxv.h>
 
 
-#include "exceptions.h"
-#include "gdb_string.h"
 #include "gdbcore.h"
 #include "inferior.h"
 #include "target.h"
 #include "gdbcore.h"
 #include "inferior.h"
 #include "target.h"
 #include "nto-tdep.h"
 #include "command.h"
 #include "regcache.h"
 #include "nto-tdep.h"
 #include "command.h"
 #include "regcache.h"
+#include "solib.h"
+#include "inf-child.h"
+#include "common/filestuff.h"
 
 #define NULL_PID               0
 #define _DEBUG_FLAG_TRACE      (_DEBUG_FLAG_TRACE_EXEC|_DEBUG_FLAG_TRACE_RD|\
                _DEBUG_FLAG_TRACE_WR|_DEBUG_FLAG_TRACE_MODIFY)
 
 
 #define NULL_PID               0
 #define _DEBUG_FLAG_TRACE      (_DEBUG_FLAG_TRACE_EXEC|_DEBUG_FLAG_TRACE_RD|\
                _DEBUG_FLAG_TRACE_WR|_DEBUG_FLAG_TRACE_MODIFY)
 
-static struct target_ops procfs_ops;
-
 int ctl_fd;
 
 int ctl_fd;
 
-static void (*ofunc) ();
+static sighandler_t ofunc;
 
 static procfs_run run;
 
 
 static procfs_run run;
 
-static void procfs_open (char *, int);
-
-static int procfs_can_run (void);
-
-static ptid_t procfs_wait (ptid_t, struct target_waitstatus *);
-
-static int procfs_xfer_memory (CORE_ADDR, char *, int, int,
-                              struct mem_attrib *attrib,
-                              struct target_ops *);
-
-static void procfs_fetch_registers (int);
-
-static void notice_signals (void);
-
-static void init_procfs_ops (void);
-
 static ptid_t do_attach (ptid_t ptid);
 
 static ptid_t do_attach (ptid_t ptid);
 
-static int procfs_can_use_hw_breakpoint (int, int, int);
-
-static int procfs_insert_hw_breakpoint (CORE_ADDR, char *);
+static int procfs_can_use_hw_breakpoint (struct target_ops *self,
+                                        enum bptype, int, int);
 
 
-static int procfs_remove_hw_breakpoint (CORE_ADDR addr, char *);
+static int procfs_insert_hw_watchpoint (struct target_ops *self,
+                                       CORE_ADDR addr, int len,
+                                       enum target_hw_bp_type type,
+                                       struct expression *cond);
 
 
-static int procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type);
+static int procfs_remove_hw_watchpoint (struct target_ops *self,
+                                       CORE_ADDR addr, int len,
+                                       enum target_hw_bp_type type,
+                                       struct expression *cond);
 
 
-static int procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type);
+static int procfs_stopped_by_watchpoint (struct target_ops *ops);
 
 
-static int procfs_stopped_by_watchpoint (void);
-
-/* These two globals are only ever set in procfs_open(), but are
+/* These two globals are only ever set in procfs_open_1, but are
    referenced elsewhere.  'nto_procfs_node' is a flag used to say
    whether we are local, or we should get the current node descriptor
    for the remote QNX node.  */
    referenced elsewhere.  'nto_procfs_node' is a flag used to say
    whether we are local, or we should get the current node descriptor
    for the remote QNX node.  */
-static char nto_procfs_path[PATH_MAX] = { "/proc" };
+static char *nodestr;
 static unsigned nto_procfs_node = ND_LOCAL_NODE;
 
 /* Return the current QNX Node, or error out.  This is a simple
 static unsigned nto_procfs_node = ND_LOCAL_NODE;
 
 /* Return the current QNX Node, or error out.  This is a simple
@@ -102,10 +87,11 @@ nto_node (void)
 {
   unsigned node;
 
 {
   unsigned node;
 
-  if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0)
+  if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0
+      || nodestr == NULL)
     return ND_LOCAL_NODE;
 
     return ND_LOCAL_NODE;
 
-  node = netmgr_strtond (nto_procfs_path, 0);
+  node = netmgr_strtond (nodestr, 0);
   if (node == -1)
     error (_("Lost the QNX node.  Debug session probably over."));
 
   if (node == -1)
     error (_("Lost the QNX node.  Debug session probably over."));
 
@@ -118,26 +104,33 @@ procfs_is_nto_target (bfd *abfd)
   return GDB_OSABI_QNXNTO;
 }
 
   return GDB_OSABI_QNXNTO;
 }
 
-/* This is called when we call 'target procfs <arg>' from the (gdb) prompt.
-   For QNX6 (nto), the only valid arg will be a QNX node string, 
-   eg: "/net/some_node".  If arg is not a valid QNX node, we will
-   default to local.  */
+/* This is called when we call 'target native' or 'target procfs
+   <arg>' from the (gdb) prompt.  For QNX6 (nto), the only valid arg
+   will be a QNX node string, eg: "/net/some_node".  If arg is not a
+   valid QNX node, we will default to local.  */
 static void
 static void
-procfs_open (char *arg, int from_tty)
+procfs_open_1 (struct target_ops *ops, const char *arg, int from_tty)
 {
 {
-  char *nodestr;
   char *endstr;
   char buffer[50];
   int fd, total_size;
   procfs_sysinfo *sysinfo;
   char *endstr;
   char buffer[50];
   int fd, total_size;
   procfs_sysinfo *sysinfo;
+  struct cleanup *cleanups;
+  char nto_procfs_path[PATH_MAX];
+
+  /* Offer to kill previous inferiors before opening this target.  */
+  target_preopen (from_tty);
 
   nto_is_nto_target = procfs_is_nto_target;
 
   /* Set the default node used for spawning to this one,
      and only override it if there is a valid arg.  */
 
 
   nto_is_nto_target = procfs_is_nto_target;
 
   /* Set the default node used for spawning to this one,
      and only override it if there is a valid arg.  */
 
+  xfree (nodestr);
+  nodestr = NULL;
+
   nto_procfs_node = ND_LOCAL_NODE;
   nto_procfs_node = ND_LOCAL_NODE;
-  nodestr = arg ? xstrdup (arg) : arg;
+  nodestr = (arg != NULL) ? xstrdup (arg) : NULL;
 
   init_thread_list ();
 
 
   init_thread_list ();
 
@@ -162,10 +155,8 @@ procfs_open (char *arg, int from_tty)
            *endstr = 0;
        }
     }
            *endstr = 0;
        }
     }
-  snprintf (nto_procfs_path, PATH_MAX - 1, "%s%s", nodestr ? nodestr : "",
-           "/proc");
-  if (nodestr)
-    xfree (nodestr);
+  snprintf (nto_procfs_path, PATH_MAX - 1, "%s%s",
+           (nodestr != NULL) ? nodestr : "", "/proc");
 
   fd = open (nto_procfs_path, O_RDONLY);
   if (fd == -1)
 
   fd = open (nto_procfs_path, O_RDONLY);
   if (fd == -1)
@@ -174,24 +165,23 @@ procfs_open (char *arg, int from_tty)
                       safe_strerror (errno));
       error (_("Invalid procfs arg"));
     }
                       safe_strerror (errno));
       error (_("Invalid procfs arg"));
     }
+  cleanups = make_cleanup_close (fd);
 
   sysinfo = (void *) buffer;
   if (devctl (fd, DCMD_PROC_SYSINFO, sysinfo, sizeof buffer, 0) != EOK)
     {
       printf_filtered ("Error getting size: %d (%s)\n", errno,
                       safe_strerror (errno));
 
   sysinfo = (void *) buffer;
   if (devctl (fd, DCMD_PROC_SYSINFO, sysinfo, sizeof buffer, 0) != EOK)
     {
       printf_filtered ("Error getting size: %d (%s)\n", errno,
                       safe_strerror (errno));
-      close (fd);
       error (_("Devctl failed."));
     }
   else
     {
       total_size = sysinfo->total_size;
       sysinfo = alloca (total_size);
       error (_("Devctl failed."));
     }
   else
     {
       total_size = sysinfo->total_size;
       sysinfo = alloca (total_size);
-      if (!sysinfo)
+      if (sysinfo == NULL)
        {
          printf_filtered ("Memory error: %d (%s)\n", errno,
                           safe_strerror (errno));
        {
          printf_filtered ("Memory error: %d (%s)\n", errno,
                           safe_strerror (errno));
-         close (fd);
          error (_("alloca failed."));
        }
       else
          error (_("alloca failed."));
        }
       else
@@ -200,21 +190,20 @@ procfs_open (char *arg, int from_tty)
            {
              printf_filtered ("Error getting sysinfo: %d (%s)\n", errno,
                               safe_strerror (errno));
            {
              printf_filtered ("Error getting sysinfo: %d (%s)\n", errno,
                               safe_strerror (errno));
-             close (fd);
              error (_("Devctl failed."));
            }
          else
            {
              if (sysinfo->type !=
              error (_("Devctl failed."));
            }
          else
            {
              if (sysinfo->type !=
-                 nto_map_arch_to_cputype (TARGET_ARCHITECTURE->arch_name))
-               {
-                 close (fd);
-                 error (_("Invalid target CPU."));
-               }
+                 nto_map_arch_to_cputype (gdbarch_bfd_arch_info
+                                          (target_gdbarch ())->arch_name))
+               error (_("Invalid target CPU."));
            }
        }
     }
            }
        }
     }
-  close (fd);
+  do_cleanups (cleanups);
+
+  inf_child_open_target (ops, arg, from_tty);
   printf_filtered ("Debugging using %s\n", nto_procfs_path);
 }
 
   printf_filtered ("Debugging using %s\n", nto_procfs_path);
 }
 
@@ -229,90 +218,207 @@ procfs_set_thread (ptid_t ptid)
 
 /*  Return nonzero if the thread TH is still alive.  */
 static int
 
 /*  Return nonzero if the thread TH is still alive.  */
 static int
-procfs_thread_alive (ptid_t ptid)
+procfs_thread_alive (struct target_ops *ops, ptid_t ptid)
 {
   pid_t tid;
 {
   pid_t tid;
+  pid_t pid;
+  procfs_status status;
+  int err;
 
   tid = ptid_get_tid (ptid);
 
   tid = ptid_get_tid (ptid);
-  if (devctl (ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0) == EOK)
-    return 1;
-  return 0;
+  pid = ptid_get_pid (ptid);
+
+  if (kill (pid, 0) == -1)
+    return 0;
+
+  status.tid = tid;
+  if ((err = devctl (ctl_fd, DCMD_PROC_TIDSTATUS,
+                    &status, sizeof (status), 0)) != EOK)
+    return 0;
+
+  /* Thread is alive or dead but not yet joined,
+     or dead and there is an alive (or dead unjoined) thread with
+     higher tid.
+
+     If the tid is not the same as requested, requested tid is dead.  */
+  return (status.tid == tid) && (status.state != STATE_DEAD);
 }
 
 }
 
-void
-procfs_find_new_threads (void)
+static void
+update_thread_private_data_name (struct thread_info *new_thread,
+                                const char *newname)
+{
+  int newnamelen;
+  struct private_thread_info *pti;
+
+  gdb_assert (newname != NULL);
+  gdb_assert (new_thread != NULL);
+  newnamelen = strlen (newname);
+  if (!new_thread->priv)
+    {
+      new_thread->priv = xmalloc (offsetof (struct private_thread_info,
+                                              name)
+                                    + newnamelen + 1);
+      memcpy (new_thread->priv->name, newname, newnamelen + 1);
+    }
+  else if (strcmp (newname, new_thread->priv->name) != 0)
+    {
+      /* Reallocate if neccessary.  */
+      int oldnamelen = strlen (new_thread->priv->name);
+
+      if (oldnamelen < newnamelen)
+       new_thread->priv = xrealloc (new_thread->priv,
+                                       offsetof (struct private_thread_info,
+                                                 name)
+                                       + newnamelen + 1);
+      memcpy (new_thread->priv->name, newname, newnamelen + 1);
+    }
+}
+
+static void 
+update_thread_private_data (struct thread_info *new_thread, 
+                           pthread_t tid, int state, int flags)
+{
+  struct private_thread_info *pti;
+  procfs_info pidinfo;
+  struct _thread_name *tn;
+  procfs_threadctl tctl;
+
+#if _NTO_VERSION > 630
+  gdb_assert (new_thread != NULL);
+
+  if (devctl (ctl_fd, DCMD_PROC_INFO, &pidinfo,
+             sizeof(pidinfo), 0) != EOK)
+    return;
+
+  memset (&tctl, 0, sizeof (tctl));
+  tctl.cmd = _NTO_TCTL_NAME;
+  tn = (struct _thread_name *) (&tctl.data);
+
+  /* Fetch name for the given thread.  */
+  tctl.tid = tid;
+  tn->name_buf_len = sizeof (tctl.data) - sizeof (*tn);
+  tn->new_name_len = -1; /* Getting, not setting.  */
+  if (devctl (ctl_fd, DCMD_PROC_THREADCTL, &tctl, sizeof (tctl), NULL) != EOK)
+    tn->name_buf[0] = '\0';
+
+  tn->name_buf[_NTO_THREAD_NAME_MAX] = '\0';
+
+  update_thread_private_data_name (new_thread, tn->name_buf);
+
+  pti = (struct private_thread_info *) new_thread->priv;
+  pti->tid = tid;
+  pti->state = state;
+  pti->flags = flags;
+#endif /* _NTO_VERSION */
+}
+
+static void
+procfs_update_thread_list (struct target_ops *ops)
 {
   procfs_status status;
   pid_t pid;
   ptid_t ptid;
 {
   procfs_status status;
   pid_t pid;
   ptid_t ptid;
+  pthread_t tid;
+  struct thread_info *new_thread;
 
   if (ctl_fd == -1)
     return;
 
 
   if (ctl_fd == -1)
     return;
 
+  prune_threads ();
+
   pid = ptid_get_pid (inferior_ptid);
 
   pid = ptid_get_pid (inferior_ptid);
 
-  for (status.tid = 1;; ++status.tid)
+  status.tid = 1;
+
+  for (tid = 1;; ++tid)
     {
     {
-      if (devctl (ctl_fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0)
-         != EOK && status.tid != 0)
+      if (status.tid == tid 
+         && (devctl (ctl_fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0)
+             != EOK))
        break;
        break;
-      ptid = ptid_build (pid, 0, status.tid);
-      if (!in_thread_list (ptid))
-       add_thread (ptid);
+      if (status.tid != tid)
+       /* The reason why this would not be equal is that devctl might have 
+          returned different tid, meaning the requested tid no longer exists
+          (e.g. thread exited).  */
+       continue;
+      ptid = ptid_build (pid, 0, tid);
+      new_thread = find_thread_ptid (ptid);
+      if (!new_thread)
+       new_thread = add_thread (ptid);
+      update_thread_private_data (new_thread, tid, status.state, 0);
+      status.tid++;
     }
   return;
 }
 
     }
   return;
 }
 
-void
+static void
+do_closedir_cleanup (void *dir)
+{
+  closedir (dir);
+}
+
+static void
 procfs_pidlist (char *args, int from_tty)
 {
   DIR *dp = NULL;
   struct dirent *dirp = NULL;
 procfs_pidlist (char *args, int from_tty)
 {
   DIR *dp = NULL;
   struct dirent *dirp = NULL;
-  int fd = -1;
-  char buf[512];
+  char buf[PATH_MAX];
   procfs_info *pidinfo = NULL;
   procfs_debuginfo *info = NULL;
   procfs_status *status = NULL;
   pid_t num_threads = 0;
   pid_t pid;
   char name[512];
   procfs_info *pidinfo = NULL;
   procfs_debuginfo *info = NULL;
   procfs_status *status = NULL;
   pid_t num_threads = 0;
   pid_t pid;
   char name[512];
+  struct cleanup *cleanups;
+  char procfs_dir[PATH_MAX];
+
+  snprintf (procfs_dir, sizeof (procfs_dir), "%s%s",
+           (nodestr != NULL) ? nodestr : "", "/proc");
 
 
-  dp = opendir (nto_procfs_path);
+  dp = opendir (procfs_dir);
   if (dp == NULL)
     {
       fprintf_unfiltered (gdb_stderr, "failed to opendir \"%s\" - %d (%s)",
   if (dp == NULL)
     {
       fprintf_unfiltered (gdb_stderr, "failed to opendir \"%s\" - %d (%s)",
-                         nto_procfs_path, errno, safe_strerror (errno));
+                         procfs_dir, errno, safe_strerror (errno));
       return;
     }
 
       return;
     }
 
+  cleanups = make_cleanup (do_closedir_cleanup, dp);
+
   /* Start scan at first pid.  */
   rewinddir (dp);
 
   do
     {
   /* Start scan at first pid.  */
   rewinddir (dp);
 
   do
     {
+      int fd;
+      struct cleanup *inner_cleanup;
+
       /* Get the right pid and procfs path for the pid.  */
       do
        {
          dirp = readdir (dp);
          if (dirp == NULL)
            {
       /* Get the right pid and procfs path for the pid.  */
       do
        {
          dirp = readdir (dp);
          if (dirp == NULL)
            {
-             closedir (dp);
+             do_cleanups (cleanups);
              return;
            }
              return;
            }
-         snprintf (buf, 511, "%s/%s/as", nto_procfs_path, dirp->d_name);
+         snprintf (buf, sizeof (buf), "%s%s/%s/as",
+                   (nodestr != NULL) ? nodestr : "",
+                   "/proc", dirp->d_name);
          pid = atoi (dirp->d_name);
        }
       while (pid == 0);
 
          pid = atoi (dirp->d_name);
        }
       while (pid == 0);
 
-      /* Open the procfs path. */
+      /* Open the procfs path.  */
       fd = open (buf, O_RDONLY);
       if (fd == -1)
        {
          fprintf_unfiltered (gdb_stderr, "failed to open %s - %d (%s)\n",
                              buf, errno, safe_strerror (errno));
       fd = open (buf, O_RDONLY);
       if (fd == -1)
        {
          fprintf_unfiltered (gdb_stderr, "failed to open %s - %d (%s)\n",
                              buf, errno, safe_strerror (errno));
-         closedir (dp);
-         return;
+         continue;
        }
        }
+      inner_cleanup = make_cleanup_close (fd);
 
       pidinfo = (procfs_info *) buf;
       if (devctl (fd, DCMD_PROC_INFO, pidinfo, sizeof (buf), 0) != EOK)
 
       pidinfo = (procfs_info *) buf;
       if (devctl (fd, DCMD_PROC_INFO, pidinfo, sizeof (buf), 0) != EOK)
@@ -334,22 +440,27 @@ procfs_pidlist (char *args, int from_tty)
       status = (procfs_status *) buf;
       for (status->tid = 1; status->tid <= num_threads; status->tid++)
        {
       status = (procfs_status *) buf;
       for (status->tid = 1; status->tid <= num_threads; status->tid++)
        {
-         if (devctl (fd, DCMD_PROC_TIDSTATUS, status, sizeof (buf), 0) != EOK
-             && status->tid != 0)
-           break;
-         if (status->tid != 0)
-           printf_filtered ("%s - %d/%d\n", name, pid, status->tid);
+         const int err
+           = devctl (fd, DCMD_PROC_TIDSTATUS, status, sizeof (buf), 0);
+         printf_filtered ("%s - %d", name, pid);
+         if (err == EOK && status->tid != 0)
+           printf_filtered ("/%d\n", status->tid);
+         else
+           {
+             printf_filtered ("\n");
+             break;
+           }
        }
        }
-      close (fd);
+
+      do_cleanups (inner_cleanup);
     }
   while (dirp != NULL);
 
     }
   while (dirp != NULL);
 
-  close (fd);
-  closedir (dp);
+  do_cleanups (cleanups);
   return;
 }
 
   return;
 }
 
-void
+static void
 procfs_meminfo (char *args, int from_tty)
 {
   procfs_mapinfo *mapinfos = NULL;
 procfs_meminfo (char *args, int from_tty)
 {
   procfs_mapinfo *mapinfos = NULL;
@@ -390,7 +501,7 @@ procfs_meminfo (char *args, int from_tty)
       return;
     }
 
       return;
     }
 
-  mapinfos = xmalloc (num * sizeof (procfs_mapinfo));
+  mapinfos = XNEWVEC (procfs_mapinfo, num);
 
   num_mapinfos = num;
   mapinfo_p = mapinfos;
 
   num_mapinfos = num;
   mapinfo_p = mapinfos;
@@ -405,7 +516,7 @@ procfs_meminfo (char *args, int from_tty)
       return;
     }
 
       return;
     }
 
-  num = min (num, num_mapinfos);
+  num = std::min (num, num_mapinfos);
 
   /* Run through the list of mapinfos, and store the data and text info
      so we can print it at the bottom of the loop.  */
 
   /* Run through the list of mapinfos, and store the data and text info
      so we can print it at the bottom of the loop.  */
@@ -478,14 +589,14 @@ procfs_meminfo (char *args, int from_tty)
                       printme.text.addr);
       printf_filtered ("\t\tflags=%08x\n", printme.text.flags);
       printf_filtered ("\t\tdebug=%08x\n", printme.text.debug_vaddr);
                       printme.text.addr);
       printf_filtered ("\t\tflags=%08x\n", printme.text.flags);
       printf_filtered ("\t\tdebug=%08x\n", printme.text.debug_vaddr);
-      printf_filtered ("\t\toffset=%016llx\n", printme.text.offset);
+      printf_filtered ("\t\toffset=%s\n", phex (printme.text.offset, 8));
       if (printme.data.size)
        {
          printf_filtered ("\tdata=%08x bytes @ 0x%08x\n", printme.data.size,
                           printme.data.addr);
          printf_filtered ("\t\tflags=%08x\n", printme.data.flags);
          printf_filtered ("\t\tdebug=%08x\n", printme.data.debug_vaddr);
       if (printme.data.size)
        {
          printf_filtered ("\tdata=%08x bytes @ 0x%08x\n", printme.data.size,
                           printme.data.addr);
          printf_filtered ("\t\tflags=%08x\n", printme.data.flags);
          printf_filtered ("\t\tdebug=%08x\n", printme.data.debug_vaddr);
-         printf_filtered ("\t\toffset=%016llx\n", printme.data.offset);
+         printf_filtered ("\t\toffset=%s\n", phex (printme.data.offset, 8));
        }
       printf_filtered ("\tdev=0x%x\n", printme.dev);
       printf_filtered ("\tino=0x%x\n", (unsigned int) printme.ino);
        }
       printf_filtered ("\tdev=0x%x\n", printme.dev);
       printf_filtered ("\tino=0x%x\n", (unsigned int) printme.ino);
@@ -498,29 +609,50 @@ procfs_meminfo (char *args, int from_tty)
 static void
 procfs_files_info (struct target_ops *ignore)
 {
 static void
 procfs_files_info (struct target_ops *ignore)
 {
+  struct inferior *inf = current_inferior ();
+
   printf_unfiltered ("\tUsing the running image of %s %s via %s.\n",
   printf_unfiltered ("\tUsing the running image of %s %s via %s.\n",
-                    attach_flag ? "attached" : "child",
-                    target_pid_to_str (inferior_ptid), nto_procfs_path);
+                    inf->attach_flag ? "attached" : "child",
+                    target_pid_to_str (inferior_ptid),
+                    (nodestr != NULL) ? nodestr : "local node");
 }
 
 }
 
-/* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
-static int
-procfs_can_run (void)
+/* Target to_pid_to_exec_file implementation.  */
+
+static char *
+procfs_pid_to_exec_file (struct target_ops *ops, const int pid)
 {
 {
-  return 1;
+  int proc_fd;
+  static char proc_path[PATH_MAX];
+  ssize_t rd;
+
+  /* Read exe file name.  */
+  snprintf (proc_path, sizeof (proc_path), "%s/proc/%d/exefile",
+           (nodestr != NULL) ? nodestr : "", pid);
+  proc_fd = open (proc_path, O_RDONLY);
+  if (proc_fd == -1)
+    return NULL;
+
+  rd = read (proc_fd, proc_path, sizeof (proc_path) - 1);
+  close (proc_fd);
+  if (rd <= 0)
+    {
+      proc_path[0] = '\0';
+      return NULL;
+    }
+  proc_path[rd] = '\0';
+  return proc_path;
 }
 
 /* Attach to process PID, then initialize for debugging it.  */
 static void
 }
 
 /* Attach to process PID, then initialize for debugging it.  */
 static void
-procfs_attach (char *args, int from_tty)
+procfs_attach (struct target_ops *ops, const char *args, int from_tty)
 {
   char *exec_file;
   int pid;
 {
   char *exec_file;
   int pid;
+  struct inferior *inf;
 
 
-  if (!args)
-    error_no_arg (_("process-id to attach"));
-
-  pid = atoi (args);
+  pid = parse_pid_to_attach (args);
 
   if (pid == getpid ())
     error (_("Attaching GDB to itself is not a good idea..."));
 
   if (pid == getpid ())
     error (_("Attaching GDB to itself is not a good idea..."));
@@ -539,14 +671,21 @@ procfs_attach (char *args, int from_tty)
       gdb_flush (gdb_stdout);
     }
   inferior_ptid = do_attach (pid_to_ptid (pid));
       gdb_flush (gdb_stdout);
     }
   inferior_ptid = do_attach (pid_to_ptid (pid));
-  push_target (&procfs_ops);
+  inf = current_inferior ();
+  inferior_appeared (inf, pid);
+  inf->attach_flag = 1;
+
+  if (!target_is_pushed (ops))
+    push_target (ops);
+
+  procfs_update_thread_list (ops);
 }
 
 static void
 }
 
 static void
-procfs_post_attach (pid_t pid)
+procfs_post_attach (struct target_ops *self, pid_t pid)
 {
   if (exec_bfd)
 {
   if (exec_bfd)
-    solib_create_inferior_hook ();
+    solib_create_inferior_hook (0);
 }
 
 static ptid_t
 }
 
 static ptid_t
@@ -556,7 +695,8 @@ do_attach (ptid_t ptid)
   struct sigevent event;
   char path[PATH_MAX];
 
   struct sigevent event;
   char path[PATH_MAX];
 
-  snprintf (path, PATH_MAX - 1, "%s/%d/as", nto_procfs_path, PIDGET (ptid));
+  snprintf (path, PATH_MAX - 1, "%s%s/%d/as",
+           (nodestr != NULL) ? nodestr : "", "/proc", ptid_get_pid (ptid));
   ctl_fd = open (path, O_RDWR);
   if (ctl_fd == -1)
     error (_("Couldn't open proc file %s, error %d (%s)"), path, errno,
   ctl_fd = open (path, O_RDWR);
   if (ctl_fd == -1)
     error (_("Couldn't open proc file %s, error %d (%s)"), path, errno,
@@ -574,48 +714,44 @@ do_attach (ptid_t ptid)
 
   if (devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0) == EOK
       && status.flags & _DEBUG_FLAG_STOPPED)
 
   if (devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0) == EOK
       && status.flags & _DEBUG_FLAG_STOPPED)
-    SignalKill (nto_node (), PIDGET (ptid), 0, SIGCONT, 0, 0);
-  attach_flag = 1;
+    SignalKill (nto_node (), ptid_get_pid (ptid), 0, SIGCONT, 0, 0);
   nto_init_solib_absolute_prefix ();
   nto_init_solib_absolute_prefix ();
-  return ptid;
+  return ptid_build (ptid_get_pid (ptid), 0, status.tid);
 }
 
 /* Ask the user what to do when an interrupt is received.  */
 static void
 interrupt_query (void)
 {
 }
 
 /* Ask the user what to do when an interrupt is received.  */
 static void
 interrupt_query (void)
 {
-  target_terminal_ours ();
-
-  if (query ("Interrupted while waiting for the program.\n\
-Give up (and stop debugging it)? "))
+  if (query (_("Interrupted while waiting for the program.\n\
+Give up (and stop debugging it)? ")))
     {
     {
-      target_mourn_inferior ();
-      deprecated_throw_reason (RETURN_QUIT);
+      target_mourn_inferior (inferior_ptid);
+      quit ();
     }
     }
-
-  target_terminal_inferior ();
 }
 
 /* The user typed ^C twice.  */
 static void
 }
 
 /* The user typed ^C twice.  */
 static void
-nto_interrupt_twice (int signo)
+nto_handle_sigint_twice (int signo)
 {
   signal (signo, ofunc);
   interrupt_query ();
 {
   signal (signo, ofunc);
   interrupt_query ();
-  signal (signo, nto_interrupt_twice);
+  signal (signo, nto_handle_sigint_twice);
 }
 
 static void
 }
 
 static void
-nto_interrupt (int signo)
+nto_handle_sigint (int signo)
 {
   /* If this doesn't work, try more severe steps.  */
 {
   /* If this doesn't work, try more severe steps.  */
-  signal (signo, nto_interrupt_twice);
+  signal (signo, nto_handle_sigint_twice);
 
 
-  target_stop ();
+  target_interrupt (inferior_ptid);
 }
 
 static ptid_t
 }
 
 static ptid_t
-procfs_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
+procfs_wait (struct target_ops *ops,
+            ptid_t ptid, struct target_waitstatus *ourstatus, int options)
 {
   sigset_t set;
   siginfo_t info;
 {
   sigset_t set;
   siginfo_t info;
@@ -627,7 +763,7 @@ procfs_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
   if (ptid_equal (inferior_ptid, null_ptid))
     {
       ourstatus->kind = TARGET_WAITKIND_STOPPED;
   if (ptid_equal (inferior_ptid, null_ptid))
     {
       ourstatus->kind = TARGET_WAITKIND_STOPPED;
-      ourstatus->value.sig = TARGET_SIGNAL_0;
+      ourstatus->value.sig = GDB_SIGNAL_0;
       exit_signo = 0;
       return null_ptid;
     }
       exit_signo = 0;
       return null_ptid;
     }
@@ -638,22 +774,25 @@ procfs_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
   devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
   while (!(status.flags & _DEBUG_FLAG_ISTOP))
     {
   devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
   while (!(status.flags & _DEBUG_FLAG_ISTOP))
     {
-      ofunc = (void (*)()) signal (SIGINT, nto_interrupt);
+      ofunc = signal (SIGINT, nto_handle_sigint);
       sigwaitinfo (&set, &info);
       signal (SIGINT, ofunc);
       devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
     }
 
       sigwaitinfo (&set, &info);
       signal (SIGINT, ofunc);
       devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
     }
 
+  nto_inferior_data (NULL)->stopped_flags = status.flags;
+  nto_inferior_data (NULL)->stopped_pc = status.ip;
+
   if (status.flags & _DEBUG_FLAG_SSTEP)
     {
       ourstatus->kind = TARGET_WAITKIND_STOPPED;
   if (status.flags & _DEBUG_FLAG_SSTEP)
     {
       ourstatus->kind = TARGET_WAITKIND_STOPPED;
-      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+      ourstatus->value.sig = GDB_SIGNAL_TRAP;
     }
   /* Was it a breakpoint?  */
   else if (status.flags & _DEBUG_FLAG_TRACE)
     {
       ourstatus->kind = TARGET_WAITKIND_STOPPED;
     }
   /* Was it a breakpoint?  */
   else if (status.flags & _DEBUG_FLAG_TRACE)
     {
       ourstatus->kind = TARGET_WAITKIND_STOPPED;
-      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+      ourstatus->value.sig = GDB_SIGNAL_TRAP;
     }
   else if (status.flags & _DEBUG_FLAG_ISTOP)
     {
     }
   else if (status.flags & _DEBUG_FLAG_ISTOP)
     {
@@ -662,7 +801,7 @@ procfs_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
        case _DEBUG_WHY_SIGNALLED:
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
          ourstatus->value.sig =
        case _DEBUG_WHY_SIGNALLED:
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
          ourstatus->value.sig =
-           target_signal_from_host (status.info.si_signo);
+           gdb_signal_from_host (status.info.si_signo);
          exit_signo = 0;
          break;
        case _DEBUG_WHY_FAULTED:
          exit_signo = 0;
          break;
        case _DEBUG_WHY_FAULTED:
@@ -675,7 +814,7 @@ procfs_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
          else
            {
              ourstatus->value.sig =
          else
            {
              ourstatus->value.sig =
-               target_signal_from_host (status.info.si_signo);
+               gdb_signal_from_host (status.info.si_signo);
              exit_signo = ourstatus->value.sig;
            }
          break;
              exit_signo = ourstatus->value.sig;
            }
          break;
@@ -684,7 +823,7 @@ procfs_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
          {
            int waitval = 0;
 
          {
            int waitval = 0;
 
-           waitpid (PIDGET (inferior_ptid), &waitval, WNOHANG);
+           waitpid (ptid_get_pid (inferior_ptid), &waitval, WNOHANG);
            if (exit_signo)
              {
                /* Abnormal death.  */
            if (exit_signo)
              {
                /* Abnormal death.  */
@@ -704,20 +843,21 @@ procfs_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
        case _DEBUG_WHY_REQUESTED:
          /* We are assuming a requested stop is due to a SIGINT.  */
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
        case _DEBUG_WHY_REQUESTED:
          /* We are assuming a requested stop is due to a SIGINT.  */
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
-         ourstatus->value.sig = TARGET_SIGNAL_INT;
+         ourstatus->value.sig = GDB_SIGNAL_INT;
          exit_signo = 0;
          break;
        }
     }
 
          exit_signo = 0;
          break;
        }
     }
 
-  return inferior_ptid;
+  return ptid_build (status.pid, 0, status.tid);
 }
 
 /* Read the current values of the inferior's registers, both the
    general register set and floating point registers (if supported)
    and update gdb's idea of their current values.  */
 static void
 }
 
 /* Read the current values of the inferior's registers, both the
    general register set and floating point registers (if supported)
    and update gdb's idea of their current values.  */
 static void
-procfs_fetch_registers (int regno)
+procfs_fetch_registers (struct target_ops *ops,
+                       struct regcache *regcache, int regno)
 {
   union
   {
 {
   union
   {
@@ -728,41 +868,88 @@ procfs_fetch_registers (int regno)
   reg;
   int regsize;
 
   reg;
   int regsize;
 
-  procfs_set_thread (inferior_ptid);
+  procfs_set_thread (regcache_get_ptid (regcache));
   if (devctl (ctl_fd, DCMD_PROC_GETGREG, &reg, sizeof (reg), &regsize) == EOK)
   if (devctl (ctl_fd, DCMD_PROC_GETGREG, &reg, sizeof (reg), &regsize) == EOK)
-    nto_supply_gregset ((char *) &reg.greg);
+    nto_supply_gregset (regcache, (char *) &reg.greg);
   if (devctl (ctl_fd, DCMD_PROC_GETFPREG, &reg, sizeof (reg), &regsize)
       == EOK)
   if (devctl (ctl_fd, DCMD_PROC_GETFPREG, &reg, sizeof (reg), &regsize)
       == EOK)
-    nto_supply_fpregset ((char *) &reg.fpreg);
+    nto_supply_fpregset (regcache, (char *) &reg.fpreg);
   if (devctl (ctl_fd, DCMD_PROC_GETALTREG, &reg, sizeof (reg), &regsize)
       == EOK)
   if (devctl (ctl_fd, DCMD_PROC_GETALTREG, &reg, sizeof (reg), &regsize)
       == EOK)
-    nto_supply_altregset ((char *) &reg.altreg);
+    nto_supply_altregset (regcache, (char *) &reg.altreg);
 }
 
 }
 
-/* Copy LEN bytes to/from inferior's memory starting at MEMADDR
-   from/to debugger memory starting at MYADDR.  Copy from inferior
-   if DOWRITE is zero or to inferior if DOWRITE is nonzero.
+/* Helper for procfs_xfer_partial that handles memory transfers.
+   Arguments are like target_xfer_partial.  */
 
 
-   Returns the length copied, which is either the LEN argument or
-   zero.  This xfer function does not do partial moves, since procfs_ops
-   doesn't allow memory operations to cross below us in the target stack
-   anyway.  */
-static int
-procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite,
-                   struct mem_attrib *attrib, struct target_ops *target)
+static enum target_xfer_status
+procfs_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
+                   ULONGEST memaddr, ULONGEST len, ULONGEST *xfered_len)
 {
 {
-  int nbytes = 0;
+  int nbytes;
+
+  if (lseek (ctl_fd, (off_t) memaddr, SEEK_SET) != (off_t) memaddr)
+    return TARGET_XFER_E_IO;
+
+  if (writebuf != NULL)
+    nbytes = write (ctl_fd, writebuf, len);
+  else
+    nbytes = read (ctl_fd, readbuf, len);
+  if (nbytes <= 0)
+    return TARGET_XFER_E_IO;
+  *xfered_len = nbytes;
+  return TARGET_XFER_OK;
+}
+
+/* Target to_xfer_partial implementation.  */
 
 
-  if (lseek (ctl_fd, (off_t) memaddr, SEEK_SET) == (off_t) memaddr)
+static enum target_xfer_status
+procfs_xfer_partial (struct target_ops *ops, enum target_object object,
+                    const char *annex, gdb_byte *readbuf,
+                    const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+                    ULONGEST *xfered_len)
+{
+  switch (object)
     {
     {
-      if (dowrite)
-       nbytes = write (ctl_fd, myaddr, len);
-      else
-       nbytes = read (ctl_fd, myaddr, len);
-      if (nbytes < 0)
-       nbytes = 0;
+    case TARGET_OBJECT_MEMORY:
+      return procfs_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
+    case TARGET_OBJECT_AUXV:
+      if (readbuf != NULL)
+       {
+         int err;
+         CORE_ADDR initial_stack;
+         debug_process_t procinfo;
+         /* For 32-bit architecture, size of auxv_t is 8 bytes.  */
+         const unsigned int sizeof_auxv_t = sizeof (auxv_t);
+         const unsigned int sizeof_tempbuf = 20 * sizeof_auxv_t;
+         int tempread;
+         gdb_byte *const tempbuf = alloca (sizeof_tempbuf);
+
+         if (tempbuf == NULL)
+           return TARGET_XFER_E_IO;
+
+         err = devctl (ctl_fd, DCMD_PROC_INFO, &procinfo,
+                       sizeof procinfo, 0);
+         if (err != EOK)
+           return TARGET_XFER_E_IO;
+
+         initial_stack = procinfo.initial_stack;
+
+         /* procfs is always 'self-hosted', no byte-order manipulation.  */
+         tempread = nto_read_auxv_from_initial_stack (initial_stack, tempbuf,
+                                                      sizeof_tempbuf,
+                                                      sizeof (auxv_t));
+         tempread = std::min (tempread, len) - offset;
+         memcpy (readbuf, tempbuf + offset, tempread);
+         *xfered_len = tempread;
+         return tempread ? TARGET_XFER_OK : TARGET_XFER_EOF;
+       }
+       /* Fallthru */
+    default:
+      return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+                                           readbuf, writebuf, offset, len,
+                                           xfered_len);
     }
     }
-  return (nbytes);
 }
 
 /* Take a program previously attached to and detaches it.
 }
 
 /* Take a program previously attached to and detaches it.
@@ -770,31 +957,27 @@ procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite,
    on signals, etc.  We'd better not have left any breakpoints
    in the program or it'll die when it hits one.  */
 static void
    on signals, etc.  We'd better not have left any breakpoints
    in the program or it'll die when it hits one.  */
 static void
-procfs_detach (char *args, int from_tty)
+procfs_detach (struct target_ops *ops, const char *args, int from_tty)
 {
   int siggnal = 0;
 {
   int siggnal = 0;
+  int pid;
+
+  target_announce_detach ();
 
 
-  if (from_tty)
-    {
-      char *exec_file = get_exec_file (0);
-      if (exec_file == 0)
-       exec_file = "";
-      printf_unfiltered ("Detaching from program: %s %s\n",
-                        exec_file, target_pid_to_str (inferior_ptid));
-      gdb_flush (gdb_stdout);
-    }
   if (args)
     siggnal = atoi (args);
 
   if (siggnal)
   if (args)
     siggnal = atoi (args);
 
   if (siggnal)
-    SignalKill (nto_node (), PIDGET (inferior_ptid), 0, siggnal, 0, 0);
+    SignalKill (nto_node (), ptid_get_pid (inferior_ptid), 0, siggnal, 0, 0);
 
   close (ctl_fd);
   ctl_fd = -1;
 
   close (ctl_fd);
   ctl_fd = -1;
-  init_thread_list ();
+
+  pid = ptid_get_pid (inferior_ptid);
   inferior_ptid = null_ptid;
   inferior_ptid = null_ptid;
-  attach_flag = 0;
-  unpush_target (&procfs_ops); /* Pop out of handling an inferior.  */
+  detach_inferior (pid);
+  init_thread_list ();
+  inf_child_maybe_unpush_target (ops);
 }
 
 static int
 }
 
 static int
@@ -812,34 +995,46 @@ procfs_breakpoint (CORE_ADDR addr, int type, int size)
 }
 
 static int
 }
 
 static int
-procfs_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
+procfs_insert_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
+                         struct bp_target_info *bp_tgt)
 {
 {
-  return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC, 0);
+  bp_tgt->placed_address = bp_tgt->reqstd_address;
+  return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, 0);
 }
 
 static int
 }
 
 static int
-procfs_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
+procfs_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
+                         struct bp_target_info *bp_tgt,
+                         enum remove_bp_reason reason)
 {
 {
-  return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC, -1);
+  return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, -1);
 }
 
 static int
 }
 
 static int
-procfs_insert_hw_breakpoint (CORE_ADDR addr, char *contents_cache)
+procfs_insert_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch,
+                            struct bp_target_info *bp_tgt)
 {
 {
-  return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, 0);
+  bp_tgt->placed_address = bp_tgt->reqstd_address;
+  return procfs_breakpoint (bp_tgt->placed_address,
+                           _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, 0);
 }
 
 static int
 }
 
 static int
-procfs_remove_hw_breakpoint (CORE_ADDR addr, char *contents_cache)
+procfs_remove_hw_breakpoint (struct target_ops *self,
+                            struct gdbarch *gdbarch,
+                            struct bp_target_info *bp_tgt)
 {
 {
-  return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, -1);
+  return procfs_breakpoint (bp_tgt->placed_address,
+                           _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, -1);
 }
 
 static void
 }
 
 static void
-procfs_resume (ptid_t ptid, int step, enum target_signal signo)
+procfs_resume (struct target_ops *ops,
+              ptid_t ptid, int step, enum gdb_signal signo)
 {
   int signal_to_pass;
   procfs_status status;
 {
   int signal_to_pass;
   procfs_status status;
+  sigset_t *run_fault = (sigset_t *) (void *) &run.fault;
 
   if (ptid_equal (inferior_ptid, null_ptid))
     return;
 
   if (ptid_equal (inferior_ptid, null_ptid))
     return;
@@ -851,37 +1046,35 @@ procfs_resume (ptid_t ptid, int step, enum target_signal signo)
   if (step)
     run.flags |= _DEBUG_RUN_STEP;
 
   if (step)
     run.flags |= _DEBUG_RUN_STEP;
 
-  sigemptyset ((sigset_t *) &run.fault);
-  sigaddset ((sigset_t *) &run.fault, FLTBPT);
-  sigaddset ((sigset_t *) &run.fault, FLTTRACE);
-  sigaddset ((sigset_t *) &run.fault, FLTILL);
-  sigaddset ((sigset_t *) &run.fault, FLTPRIV);
-  sigaddset ((sigset_t *) &run.fault, FLTBOUNDS);
-  sigaddset ((sigset_t *) &run.fault, FLTIOVF);
-  sigaddset ((sigset_t *) &run.fault, FLTIZDIV);
-  sigaddset ((sigset_t *) &run.fault, FLTFPE);
+  sigemptyset (run_fault);
+  sigaddset (run_fault, FLTBPT);
+  sigaddset (run_fault, FLTTRACE);
+  sigaddset (run_fault, FLTILL);
+  sigaddset (run_fault, FLTPRIV);
+  sigaddset (run_fault, FLTBOUNDS);
+  sigaddset (run_fault, FLTIOVF);
+  sigaddset (run_fault, FLTIZDIV);
+  sigaddset (run_fault, FLTFPE);
   /* Peter V will be changing this at some point.  */
   /* Peter V will be changing this at some point.  */
-  sigaddset ((sigset_t *) &run.fault, FLTPAGE);
+  sigaddset (run_fault, FLTPAGE);
 
   run.flags |= _DEBUG_RUN_ARM;
 
 
   run.flags |= _DEBUG_RUN_ARM;
 
-  sigemptyset (&run.trace);
-  notice_signals ();
-  signal_to_pass = target_signal_to_host (signo);
+  signal_to_pass = gdb_signal_to_host (signo);
 
   if (signal_to_pass)
     {
       devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
 
   if (signal_to_pass)
     {
       devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
-      signal_to_pass = target_signal_to_host (signo);
+      signal_to_pass = gdb_signal_to_host (signo);
       if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
        {
          if (signal_to_pass != status.info.si_signo)
            {
       if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
        {
          if (signal_to_pass != status.info.si_signo)
            {
-             SignalKill (nto_node (), PIDGET (inferior_ptid), 0,
+             SignalKill (nto_node (), ptid_get_pid (inferior_ptid), 0,
                          signal_to_pass, 0, 0);
              run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
            }
                          signal_to_pass, 0, 0);
              run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
            }
-         else                  /* Let it kill the program without telling us.  */
+         else          /* Let it kill the program without telling us.  */
            sigdelset (&run.trace, signal_to_pass);
        }
     }
            sigdelset (&run.trace, signal_to_pass);
        }
     }
@@ -891,24 +1084,22 @@ procfs_resume (ptid_t ptid, int step, enum target_signal signo)
   errno = devctl (ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
   if (errno != EOK)
     {
   errno = devctl (ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
   if (errno != EOK)
     {
-      perror ("run error!\n");
+      perror (_("run error!\n"));
       return;
     }
 }
 
 static void
       return;
     }
 }
 
 static void
-procfs_mourn_inferior (void)
+procfs_mourn_inferior (struct target_ops *ops)
 {
   if (!ptid_equal (inferior_ptid, null_ptid))
     {
 {
   if (!ptid_equal (inferior_ptid, null_ptid))
     {
-      SignalKill (nto_node (), PIDGET (inferior_ptid), 0, SIGKILL, 0, 0);
+      SignalKill (nto_node (), ptid_get_pid (inferior_ptid), 0, SIGKILL, 0, 0);
       close (ctl_fd);
     }
   inferior_ptid = null_ptid;
   init_thread_list ();
       close (ctl_fd);
     }
   inferior_ptid = null_ptid;
   init_thread_list ();
-  unpush_target (&procfs_ops);
-  generic_mourn_inferior ();
-  attach_flag = 0;
+  inf_child_mourn_inferior (ops);
 }
 
 /* This function breaks up an argument string into an argument
 }
 
 /* This function breaks up an argument string into an argument
@@ -972,8 +1163,9 @@ breakup_args (char *scratch, char **argv)
 }
 
 static void
 }
 
 static void
-procfs_create_inferior (char *exec_file, char *allargs, char **env,
-                       int from_tty)
+procfs_create_inferior (struct target_ops *ops, const char *exec_file,
+                       const std::string &allargs,
+                       char **env, int from_tty)
 {
   struct inheritance inherit;
   pid_t pid;
 {
   struct inheritance inherit;
   pid_t pid;
@@ -983,8 +1175,9 @@ procfs_create_inferior (char *exec_file, char *allargs, char **env,
   int fd, fds[3];
   sigset_t set;
   const char *inferior_io_terminal = get_inferior_io_terminal ();
   int fd, fds[3];
   sigset_t set;
   const char *inferior_io_terminal = get_inferior_io_terminal ();
+  struct inferior *inf;
 
 
-  argv = xmalloc (((strlen (allargs) + 1) / (unsigned) 2 + 2) *
+  argv = xmalloc ((allargs.size () / (unsigned) 2 + 2) *
                  sizeof (*argv));
   argv[0] = get_exec_file (1);
   if (!argv[0])
                  sizeof (*argv));
   argv[0] = get_exec_file (1);
   if (!argv[0])
@@ -995,8 +1188,8 @@ procfs_create_inferior (char *exec_file, char *allargs, char **env,
        return;
     }
 
        return;
     }
 
-  args = xstrdup (allargs);
-  breakup_args (args, exec_file ? &argv[1] : &argv[0]);
+  args = xstrdup (allargs.c_str ());
+  breakup_args (args, (exec_file != NULL) ? &argv[1] : &argv[0]);
 
   argv = nto_parse_redirection (argv, &in, &out, &err);
 
 
   argv = nto_parse_redirection (argv, &in, &out, &err);
 
@@ -1076,8 +1269,12 @@ procfs_create_inferior (char *exec_file, char *allargs, char **env,
     close (fds[2]);
 
   inferior_ptid = do_attach (pid_to_ptid (pid));
     close (fds[2]);
 
   inferior_ptid = do_attach (pid_to_ptid (pid));
+  procfs_update_thread_list (ops);
+
+  inf = current_inferior ();
+  inferior_appeared (inf, pid);
+  inf->attach_flag = 0;
 
 
-  attach_flag = 0;
   flags = _DEBUG_FLAG_KLC;     /* Kill-on-Last-Close flag.  */
   errn = devctl (ctl_fd, DCMD_PROC_SET_FLAG, &flags, sizeof (flags), 0);
   if (errn != EOK)
   flags = _DEBUG_FLAG_KLC;     /* Kill-on-Last-Close flag.  */
   errn = devctl (ctl_fd, DCMD_PROC_SET_FLAG, &flags, sizeof (flags), 0);
   if (errn != EOK)
@@ -1086,32 +1283,25 @@ procfs_create_inferior (char *exec_file, char *allargs, char **env,
       /* warning( "Failed to set Kill-on-Last-Close flag: errno = %d(%s)\n",
          errn, strerror(errn) ); */
     }
       /* warning( "Failed to set Kill-on-Last-Close flag: errno = %d(%s)\n",
          errn, strerror(errn) ); */
     }
-  push_target (&procfs_ops);
+  if (!target_is_pushed (ops))
+    push_target (ops);
   target_terminal_init ();
 
   if (exec_bfd != NULL
       || (symfile_objfile != NULL && symfile_objfile->obfd != NULL))
   target_terminal_init ();
 
   if (exec_bfd != NULL
       || (symfile_objfile != NULL && symfile_objfile->obfd != NULL))
-    solib_create_inferior_hook ();
-  stop_soon = 0;
+    solib_create_inferior_hook (0);
 }
 
 static void
 }
 
 static void
-procfs_stop (void)
+procfs_interrupt (struct target_ops *self, ptid_t ptid)
 {
   devctl (ctl_fd, DCMD_PROC_STOP, NULL, 0, 0);
 }
 
 static void
 {
   devctl (ctl_fd, DCMD_PROC_STOP, NULL, 0, 0);
 }
 
 static void
-procfs_kill_inferior (void)
-{
-  target_mourn_inferior ();
-}
-
-/* Store register REGNO, or all registers if REGNO == -1, from the contents
-   of REGISTERS.  */
-static void
-procfs_prepare_to_store (void)
+procfs_kill_inferior (struct target_ops *ops)
 {
 {
+  target_mourn_inferior (inferior_ptid);
 }
 
 /* Fill buf with regset and return devctl cmd to do the setting.  Return
 }
 
 /* Fill buf with regset and return devctl cmd to do the setting.  Return
@@ -1141,14 +1331,15 @@ get_regset (int regset, char *buf, int bufsize, int *regsize)
     default:
       return -1;
     }
     default:
       return -1;
     }
-  if (devctl (ctl_fd, dev_get, &buf, bufsize, regsize) != EOK)
+  if (devctl (ctl_fd, dev_get, buf, bufsize, regsize) != EOK)
     return -1;
 
   return dev_set;
 }
 
     return -1;
 
   return dev_set;
 }
 
-void
-procfs_store_registers (int regno)
+static void
+procfs_store_registers (struct target_ops *ops,
+                       struct regcache *regcache, int regno)
 {
   union
   {
 {
   union
   {
@@ -1160,10 +1351,11 @@ procfs_store_registers (int regno)
   unsigned off;
   int len, regset, regsize, dev_set, err;
   char *data;
   unsigned off;
   int len, regset, regsize, dev_set, err;
   char *data;
+  ptid_t ptid = regcache_get_ptid (regcache);
 
 
-  if (ptid_equal (inferior_ptid, null_ptid))
+  if (ptid_equal (ptid, null_ptid))
     return;
     return;
-  procfs_set_thread (inferior_ptid);
+  procfs_set_thread (ptid);
 
   if (regno == -1)
     {
 
   if (regno == -1)
     {
@@ -1174,7 +1366,7 @@ procfs_store_registers (int regno)
          if (dev_set == -1)
            continue;
 
          if (dev_set == -1)
            continue;
 
-         if (nto_regset_fill (regset, (char *) &reg) == -1)
+         if (nto_regset_fill (regcache, regset, (char *) &reg) == -1)
            continue;
 
          err = devctl (ctl_fd, dev_set, &reg, regsize, 0);
            continue;
 
          err = devctl (ctl_fd, dev_set, &reg, regsize, 0);
@@ -1194,12 +1386,13 @@ procfs_store_registers (int regno)
       if (dev_set == -1)
        return;
 
       if (dev_set == -1)
        return;
 
-      len = nto_register_area (regno, regset, &off);
+      len = nto_register_area (get_regcache_arch (regcache),
+                              regno, regset, &off);
 
       if (len < 1)
        return;
 
 
       if (len < 1)
        return;
 
-      regcache_raw_collect (current_regcache, regno, (char *) &reg + off);
+      regcache_raw_collect (regcache, regno, (char *) &reg + off);
 
       err = devctl (ctl_fd, dev_set, &reg, regsize, 0);
       if (err != EOK)
 
       err = devctl (ctl_fd, dev_set, &reg, regsize, 0);
       if (err != EOK)
@@ -1209,43 +1402,26 @@ procfs_store_registers (int regno)
     }
 }
 
     }
 }
 
+/* Set list of signals to be handled in the target.  */
+
 static void
 static void
-notice_signals (void)
+procfs_pass_signals (struct target_ops *self,
+                    int numsigs, unsigned char *pass_signals)
 {
   int signo;
 
 {
   int signo;
 
+  sigfillset (&run.trace);
+
   for (signo = 1; signo < NSIG; signo++)
     {
   for (signo = 1; signo < NSIG; signo++)
     {
-      if (signal_stop_state (target_signal_from_host (signo)) == 0
-         && signal_print_state (target_signal_from_host (signo)) == 0
-         && signal_pass_state (target_signal_from_host (signo)) == 1)
-       sigdelset (&run.trace, signo);
-      else
-       sigaddset (&run.trace, signo);
+      int target_signo = gdb_signal_from_host (signo);
+      if (target_signo < numsigs && pass_signals[target_signo])
+        sigdelset (&run.trace, signo);
     }
 }
 
     }
 }
 
-/* When the user changes the state of gdb's signal handling via the
-   "handle" command, this function gets called to see if any change
-   in the /proc interface is required.  It is also called internally
-   by other /proc interface functions to initialize the state of
-   the traced signal set.  */
-static void
-procfs_notice_signals (ptid_t ptid)
-{
-  sigemptyset (&run.trace);
-  notice_signals ();
-}
-
-static struct tidinfo *
-procfs_thread_info (pid_t pid, short tid)
-{
-/* NYI */
-  return NULL;
-}
-
-char *
-procfs_pid_to_str (ptid_t ptid)
+static char *
+procfs_pid_to_str (struct target_ops *ops, ptid_t ptid)
 {
   static char buf[1024];
   int pid, tid, n;
 {
   static char buf[1024];
   int pid, tid, n;
@@ -1265,66 +1441,106 @@ procfs_pid_to_str (ptid_t ptid)
   return buf;
 }
 
   return buf;
 }
 
+/* to_can_run implementation for "target procfs".  Note this really
+  means "can this target be the default run target", which there can
+  be only one, and we make it be "target native" like other ports.
+  "target procfs <node>" wouldn't make sense as default run target, as
+  it needs <node>.  */
+
+static int
+procfs_can_run (struct target_ops *self)
+{
+  return 0;
+}
+
+/* "target procfs".  */
+static struct target_ops nto_procfs_ops;
+
+/* "target native".  */
+static struct target_ops *nto_native_ops;
+
+/* to_open implementation for "target procfs".  */
+
 static void
 static void
-init_procfs_ops (void)
+procfs_open (const char *arg, int from_tty)
 {
 {
-  procfs_ops.to_shortname = "procfs";
-  procfs_ops.to_longname = "QNX Neutrino procfs child process";
-  procfs_ops.to_doc =
-    "QNX Neutrino procfs child process (started by the \"run\" command).\n\
-       target procfs <node>";
-  procfs_ops.to_open = procfs_open;
-  procfs_ops.to_attach = procfs_attach;
-  procfs_ops.to_post_attach = procfs_post_attach;
-  procfs_ops.to_detach = procfs_detach;
-  procfs_ops.to_resume = procfs_resume;
-  procfs_ops.to_wait = procfs_wait;
-  procfs_ops.to_fetch_registers = procfs_fetch_registers;
-  procfs_ops.to_store_registers = procfs_store_registers;
-  procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
-  procfs_ops.deprecated_xfer_memory = procfs_xfer_memory;
-  procfs_ops.to_files_info = procfs_files_info;
-  procfs_ops.to_insert_breakpoint = procfs_insert_breakpoint;
-  procfs_ops.to_remove_breakpoint = procfs_remove_breakpoint;
-  procfs_ops.to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
-  procfs_ops.to_insert_hw_breakpoint = procfs_insert_hw_breakpoint;
-  procfs_ops.to_remove_hw_breakpoint = procfs_remove_breakpoint;
-  procfs_ops.to_insert_watchpoint = procfs_insert_hw_watchpoint;
-  procfs_ops.to_remove_watchpoint = procfs_remove_hw_watchpoint;
-  procfs_ops.to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
-  procfs_ops.to_terminal_init = terminal_init_inferior;
-  procfs_ops.to_terminal_inferior = terminal_inferior;
-  procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
-  procfs_ops.to_terminal_ours = terminal_ours;
-  procfs_ops.to_terminal_info = child_terminal_info;
-  procfs_ops.to_kill = procfs_kill_inferior;
-  procfs_ops.to_create_inferior = procfs_create_inferior;
-  procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
-  procfs_ops.to_can_run = procfs_can_run;
-  procfs_ops.to_notice_signals = procfs_notice_signals;
-  procfs_ops.to_thread_alive = procfs_thread_alive;
-  procfs_ops.to_find_new_threads = procfs_find_new_threads;
-  procfs_ops.to_pid_to_str = procfs_pid_to_str;
-  procfs_ops.to_stop = procfs_stop;
-  procfs_ops.to_stratum = process_stratum;
-  procfs_ops.to_has_all_memory = 1;
-  procfs_ops.to_has_memory = 1;
-  procfs_ops.to_has_stack = 1;
-  procfs_ops.to_has_registers = 1;
-  procfs_ops.to_has_execution = 1;
-  procfs_ops.to_magic = OPS_MAGIC;
-  procfs_ops.to_have_continuable_watchpoint = 1;
+  procfs_open_1 (&nto_procfs_ops, arg, from_tty);
+}
+
+/* to_open implementation for "target native".  */
+
+static void
+procfs_native_open (const char *arg, int from_tty)
+{
+  procfs_open_1 (nto_native_ops, arg, from_tty);
+}
+
+/* Create the "native" and "procfs" targets.  */
+
+static void
+init_procfs_targets (void)
+{
+  struct target_ops *t = inf_child_target ();
+
+  /* Leave to_shortname as "native".  */
+  t->to_longname = "QNX Neutrino local process";
+  t->to_doc = "QNX Neutrino local process (started by the \"run\" command).";
+  t->to_open = procfs_native_open;
+  t->to_attach = procfs_attach;
+  t->to_post_attach = procfs_post_attach;
+  t->to_detach = procfs_detach;
+  t->to_resume = procfs_resume;
+  t->to_wait = procfs_wait;
+  t->to_fetch_registers = procfs_fetch_registers;
+  t->to_store_registers = procfs_store_registers;
+  t->to_xfer_partial = procfs_xfer_partial;
+  t->to_files_info = procfs_files_info;
+  t->to_insert_breakpoint = procfs_insert_breakpoint;
+  t->to_remove_breakpoint = procfs_remove_breakpoint;
+  t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
+  t->to_insert_hw_breakpoint = procfs_insert_hw_breakpoint;
+  t->to_remove_hw_breakpoint = procfs_remove_hw_breakpoint;
+  t->to_insert_watchpoint = procfs_insert_hw_watchpoint;
+  t->to_remove_watchpoint = procfs_remove_hw_watchpoint;
+  t->to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
+  t->to_kill = procfs_kill_inferior;
+  t->to_create_inferior = procfs_create_inferior;
+  t->to_mourn_inferior = procfs_mourn_inferior;
+  t->to_pass_signals = procfs_pass_signals;
+  t->to_thread_alive = procfs_thread_alive;
+  t->to_update_thread_list = procfs_update_thread_list;
+  t->to_pid_to_str = procfs_pid_to_str;
+  t->to_interrupt = procfs_interrupt;
+  t->to_have_continuable_watchpoint = 1;
+  t->to_extra_thread_info = nto_extra_thread_info;
+  t->to_pid_to_exec_file = procfs_pid_to_exec_file;
+
+  nto_native_ops = t;
+
+  /* Register "target native".  This is the default run target.  */
+  add_target (t);
+
+  /* Register "target procfs <node>".  */
+  nto_procfs_ops = *t;
+  nto_procfs_ops.to_shortname = "procfs";
+  nto_procfs_ops.to_can_run = procfs_can_run;
+  t->to_longname = "QNX Neutrino local or remote process";
+  t->to_doc = "QNX Neutrino process.  target procfs <node>";
+  t->to_open = procfs_open;
+
+  add_target (&nto_procfs_ops);
 }
 
 #define OSTYPE_NTO 1
 
 }
 
 #define OSTYPE_NTO 1
 
+extern initialize_file_ftype _initialize_procfs;
+
 void
 _initialize_procfs (void)
 {
   sigset_t set;
 
 void
 _initialize_procfs (void)
 {
   sigset_t set;
 
-  init_procfs_ops ();
-  add_target (&procfs_ops);
+  init_procfs_targets ();
 
   /* We use SIGUSR1 to gain control after we block waiting for a process.
      We use sigwaitevent to wait.  */
 
   /* We use SIGUSR1 to gain control after we block waiting for a process.
      We use sigwaitevent to wait.  */
@@ -1332,8 +1548,8 @@ _initialize_procfs (void)
   sigaddset (&set, SIGUSR1);
   sigprocmask (SIG_BLOCK, &set, NULL);
 
   sigaddset (&set, SIGUSR1);
   sigprocmask (SIG_BLOCK, &set, NULL);
 
-  /* Set up trace and fault sets, as gdb expects them.  */
-  sigemptyset (&run.trace);
+  /* Initially, make sure all signals are reported.  */
+  sigfillset (&run.trace);
 
   /* Stuff some information.  */
   nto_cpuinfo_flags = SYSPAGE_ENTRY (cpuinfo)->flags;
 
   /* Stuff some information.  */
   nto_cpuinfo_flags = SYSPAGE_ENTRY (cpuinfo)->flags;
@@ -1347,16 +1563,16 @@ _initialize_procfs (void)
 
 
 static int
 
 
 static int
-procfs_hw_watchpoint (int addr, int len, int type)
+procfs_hw_watchpoint (int addr, int len, enum target_hw_bp_type type)
 {
   procfs_break brk;
 
   switch (type)
     {
 {
   procfs_break brk;
 
   switch (type)
     {
-    case 1:                    /* Read.  */
+    case hw_read:
       brk.type = _DEBUG_BREAK_RD;
       break;
       brk.type = _DEBUG_BREAK_RD;
       break;
-    case 2:                    /* Read/Write.  */
+    case hw_access:
       brk.type = _DEBUG_BREAK_RW;
       break;
     default:                   /* Modify.  */
       brk.type = _DEBUG_BREAK_RW;
       break;
     default:                   /* Modify.  */
@@ -1370,32 +1586,56 @@ procfs_hw_watchpoint (int addr, int len, int type)
   errno = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0);
   if (errno != EOK)
     {
   errno = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0);
   if (errno != EOK)
     {
-      perror ("Failed to set hardware watchpoint");
+      perror (_("Failed to set hardware watchpoint"));
       return -1;
     }
   return 0;
 }
 
 static int
       return -1;
     }
   return 0;
 }
 
 static int
-procfs_can_use_hw_breakpoint (int type, int cnt, int othertype)
+procfs_can_use_hw_breakpoint (struct target_ops *self,
+                             enum bptype type,
+                             int cnt, int othertype)
 {
   return 1;
 }
 
 static int
 {
   return 1;
 }
 
 static int
-procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type)
+procfs_remove_hw_watchpoint (struct target_ops *self,
+                            CORE_ADDR addr, int len,
+                            enum target_hw_bp_type type,
+                            struct expression *cond)
 {
   return procfs_hw_watchpoint (addr, -1, type);
 }
 
 static int
 {
   return procfs_hw_watchpoint (addr, -1, type);
 }
 
 static int
-procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type)
+procfs_insert_hw_watchpoint (struct target_ops *self,
+                            CORE_ADDR addr, int len,
+                            enum target_hw_bp_type type,
+                            struct expression *cond)
 {
   return procfs_hw_watchpoint (addr, len, type);
 }
 
 static int
 {
   return procfs_hw_watchpoint (addr, len, type);
 }
 
 static int
-procfs_stopped_by_watchpoint (void)
+procfs_stopped_by_watchpoint (struct target_ops *ops)
 {
 {
-  return 0;
+  /* NOTE: nto_stopped_by_watchpoint will be called ONLY while we are
+     stopped due to a SIGTRAP.  This assumes gdb works in 'all-stop' mode;
+     future gdb versions will likely run in 'non-stop' mode in which case
+     we will have to store/examine statuses per thread in question.
+     Until then, this will work fine.  */
+
+  struct inferior *inf = current_inferior ();
+  struct nto_inferior_data *inf_data;
+
+  gdb_assert (inf != NULL);
+
+  inf_data = nto_inferior_data (inf);
+
+  return inf_data->stopped_flags
+        & (_DEBUG_FLAG_TRACE_RD
+           | _DEBUG_FLAG_TRACE_WR
+           | _DEBUG_FLAG_TRACE_MODIFY);
 }
 }
This page took 0.042293 seconds and 4 git commands to generate.