This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Patch] Native QNX Neutrino support


"Kris Warkentin" <kewarken@qnx.com> writes:

Kris, sorry for not looking at this at an earlier moment.  Anyway,
here are a few comments:

> For your consideration, I present nto-procfs.c and assorted config files
> required to build a native debugger on QNX Neutrino.
> 
> cheers,
> 
> Kris
> 
> ChangeLog:
> 
>  * nto-procfs.c: New file.  Native procfs support for QNX Neutrino.
>  * config/i386/nto.mt: New file.
>  * config/i386/nm-nto.h: New file.
>  * configure.host: Add i[3456]86-*-nto*.
> 
> Index: configure.host
> ===================================================================
> RCS file: /cvs/src/src/gdb/configure.host,v
> retrieving revision 1.51
> diff -u -r1.51 configure.host
> --- configure.host      9 Apr 2003 16:19:51 -0000       1.51
> +++ configure.host      29 May 2003 19:49:51 -0000
> @@ -63,6 +63,7 @@
>  i[3456]86-*-linux*)    gdb_host=linux ;;
>  i[3456]86-*-lynxos*)   gdb_host=i386lynx ;;
>  i[3456]86-*-gnu*)      gdb_host=i386gnu ;;
> +i[3456]86-*-nto*)      gdb_host=nto ;;
>  i[3456]86-*-openbsd*)  gdb_host=obsd ;;
>  i[3456]86-*-sco3.2v5*) gdb_host=i386sco5 ;;
>  i[3456]86-*-sco3.2v4*) gdb_host=i386sco4 ;;

OK!

> ====================================
> nto.mt
> ====================================
> # Host: Intel 386 running QNX.
> 
> NAT_FILE= nm-nto.h
> 
> NATDEPFILES= nto-procfs.o

What?  This file should be named nto.mh.  You'll probably want to set
XM_FILE here too.  The ChangeLog entry for this should be fixed too.

> ====================================
> nm-nto.h
> ====================================
> #ifndef _NM_NTO_H
> #define _NM_NTO_H
> 
> /* This file needed to build a native debugger.  */
> 
> #endif

Too bad this is needed, but that's not your fault.  OK.

> 
> ====================================
> nto-procfs.c
> ====================================
> /* Machine independent support for QNX Neutrino /proc (process file system)
>    for GDB.  Written by Colin Burgess at QNX Software Systems Limited.
> 
>    Copyright 2003 Free Software Foundation, Inc.
> 
>    Contributed by QNX Software Systems Ltd.
> 
>    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 2 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, write to the Free Software
>    Foundation, Inc., 59 Temple Place - Suite 330,
>    Boston, MA 02111-1307, USA.  */
> 
> 
> #include "defs.h"
> 
> #include <fcntl.h>
> #include <spawn.h>
> #include <sys/debug.h>
> #include <sys/procfs.h>
> #include <sys/neutrino.h>
> #include <sys/syspage.h>
> #include <dirent.h>
> #include <sys/netmgr.h>
> 
> #include "gdb_string.h"
> #include "gdbcore.h"
> #include "inferior.h"
> #include "target.h"
> #include "objfiles.h"
> #include "gdbthread.h"
> #include "nto-tdep.h"
> #include "command.h"
> #include "regcache.h"
> 
> #define NULL_PID  0
> #define _DEBUG_FLAG_TRACE
> (_DEBUG_FLAG_TRACE_EXEC|_DEBUG_FLAG_TRACE_RD|_DEBUG_FLAG_TRACE_WR|_DEBUG_FLA
> G_TRACE_MODIFY)

That line is too long.  There are more lines that are too long.  They
should be at most 72-chars, or at least less than 80-chars.  Please fix.

> static struct target_ops procfs_ops;
> 
> int ctl_fd;
> 
> static void (*ofunc) ();
> 
> 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 int procfs_can_use_hw_breakpoint (int, int, int);
> 
> static int procfs_insert_hw_breakpoint (CORE_ADDR, char *);
> 
> static int procfs_remove_hw_breakpoint (CORE_ADDR addr, char *);
> 
> static int procfs_insert_hw_watchpoint
> (CORE_ADDR addr, int len, int type);
> 
> static int procfs_remove_hw_watchpoint
> (CORE_ADDR addr, int len, int type);
> 
> static int procfs_stopped_by_watchpoint (void);
> 
> /* These two globals are only ever set in procfs_open(), 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.  */
> static char nto_procfs_path[PATH_MAX] = { "/proc" };
> static unsigned nto_procfs_node = ND_LOCAL_NODE;
> 
> /* This is a simple wrapper for the netmgr_strtond() function.  It is
>    only called from the QNX_NODE macro declared below.  The reason for
>    the macro and function are because QNX node descriptors are transient,
>    so we have to re-acquire them every time.  */
> static unsigned
> procfs_nto_node (unsigned node)
> {
>   if (node == -1)
>     {
>       error ("Lost the QNX node.  Debug session probably over.");
>     }
>   return (node);
> }

The braces here are redundant.  Oh, and in error messages I suppose
there only needs to be one space after the full stop.

> /* This define returns the current QNX Node, or -1 on error.  It calls the
> above
>    function which is a simple wrapper for the error() call.  */
> #define QNX_NODE (ND_NODE_CMP(nto_procfs_node, ND_LOCAL_NODE) == 0 ?
> ND_LOCAL_NODE : \
>                    procfs_nto_node(netmgr_strtond(nto_procfs_path, 0)))
>
> /* 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.  */
> static void
> procfs_open (char *arg, int from_tty)
> {
>   char *nodestr;
>   char *endstr;
>   char buffer[50];
>   int fd, total_size;
>   procfs_sysinfo *sysinfo;
> 
>   /* Set the default node used for spawning to this one,
>      and only override it if there is a valid arg.  */
> 
>   nto_procfs_node = ND_LOCAL_NODE;
>   nodestr = arg ? strdup (arg) : arg;
> 
>   init_thread_list ();
> 
>   if (nodestr)
>     {
>       nto_procfs_node = netmgr_strtond (nodestr, &endstr);
>       if (nto_procfs_node == -1)
>  {
>    if (errno == ENOTSUP)
>      printf_filtered ("QNX Net Manager not found.\n");
>    printf_filtered ("Invalid QNX node %s: error %d (%s).\n", nodestr,
>       errno, strerror (errno));
>    xfree (nodestr);
>    nodestr = NULL;
>    nto_procfs_node = ND_LOCAL_NODE;
>  }

The indentation is all wrong here.  Hmm, the attached file is all-right here.  Looks like you need to use a decent MUA ;-).

>       else if (*endstr)
>  {
>    if (*(endstr - 1) == '/')
>      *(endstr - 1) = 0;
>    else
>      *endstr = 0;
>  }
>     }
>   sprintf (nto_procfs_path, "%s%s", nodestr ? nodestr : "", "/proc");
>   if (nodestr)
>     xfree (nodestr);
> 
>   fd = open (nto_procfs_path, O_RDONLY);
>   if (fd == -1)
>     {
>       printf_filtered ("Error opening %s : %d (%s)\n", nto_procfs_path,
> errno,
>          strerror (errno));
>       error ("Invalid procfs arg");
>     }
> 
>   sysinfo = (void *) buffer;
>   if (devctl (fd, DCMD_PROC_SYSINFO, sysinfo, sizeof buffer, 0) != EOK)
>     {
>       printf_filtered ("Error getting size: %d (%s)\n", errno,
>          strerror (errno));
>       close (fd);
>       error ("Devctl failed.");
>     }
>   else
>     {
>       total_size = sysinfo->total_size;
>       if (!(sysinfo = alloca (total_size)))
>  {
>    printf_filtered ("Memory error: %d (%s)\n", errno,
>       strerror (errno));
>    close (fd);
>    error ("alloca failed.");
>  }
>       else
>  {
>    if (devctl (fd, DCMD_PROC_SYSINFO, sysinfo, total_size, 0) != EOK)
>      {
>        printf_filtered ("Error getting sysinfo: %d (%s)\n", errno,
>           strerror (errno));
>        close (fd);
>        error ("Devctl failed.");
>      }
>    else
>      {
>        if (sysinfo->type !=
> nto_map_arch_to_cputype(TARGET_ARCHITECTURE->arch_name))
>   {
>     close (fd);
>     error ("Invalid target CPU.");
>   }
>      }
>  }
>     }
>   close (fd);
>   printf_filtered ("Debugging using %s\n", nto_procfs_path);
> 
> }

Please remove the whitespace before the closing brace.

> 
> static void
> procfs_set_thread (ptid_t ptid)
> {
>   pid_t tid;
> 
>   tid = ptid_get_tid (ptid);
>   devctl (ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0);
> }
> 
> /*  Return nonzero if the thread TH is still alive.  */
> static int
> procfs_thread_alive (ptid_t ptid)
> {
>   pid_t tid;
> 
>   tid = ptid_get_tid (ptid);
>   if (devctl (ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0) == EOK)
>     return 1;
>   return 0;
> }
> 
> 
> void
> procfs_find_new_threads (void)
> {
>   procfs_status status;
>   pid_t pid;
>   ptid_t ptid;
> 
>   if (ctl_fd == -1)
>     return;
> 
>   pid = ptid_get_pid (inferior_ptid);
> 
>   for (status.tid = 1;; ++status.tid)
>     {
>       if (devctl (ctl_fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0)
> !=
>    EOK && status.tid != 0)
>  {
>    break;
>  }
>       ptid = ptid_build (pid, 0, status.tid);
>       if (!in_thread_list (ptid))
>  add_thread (ptid);
>     }
>   return;
> }
> 
> void
> procfs_pidlist (char *args, int from_tty)
> {
>   static DIR *dp = NULL;

Why is this static?

>   struct dirent *dirp = NULL;
>   int fd = -1;
>   char buf[512];
>   procfs_info *pidinfo = NULL;
>   procfs_debuginfo *info = NULL;
>   procfs_status *status = NULL;
>   pid_t num_threads = 0;
>   pid_t pid;
>   char name[512];
> 
>   dp = opendir (nto_procfs_path);
>   if (dp == NULL)
>     {
>       printf ("failed to opendir \"%s\" - %d (%s)", nto_procfs_path, errno,
>        strerror (errno));
>       return;
>     }
> 
>   /* Start scan at first pid.  */
>   rewinddir (dp);
> 
>   do
>     {
>       /* Get the right pid and procfs path for the pid.  */
>       do
>  {
>    if ((dirp = readdir (dp)) == NULL)

Please don't use assignments in if-statements.  There are more places
where this is done.  Please fix them all.

>      {
>        closedir (dp);
>        return;
>      }
>    strcat (strcat
>     (strcat (strcpy (buf, nto_procfs_path), "/"), dirp->d_name),
>     "/as");
>  }
>       while ((pid = atoi (dirp->d_name)) == 0);
> 
>       /* Open the procfs path. */
>       if ((fd = open (buf, O_RDONLY)) == -1)
>  {
>    printf ("failed to open %s - %d (%s)\n", buf, errno,
>     strerror (errno));
>    closedir (dp);
>    return;
>  }
> 
>       pidinfo = (procfs_info *) buf;
>       if (devctl (fd, DCMD_PROC_INFO, pidinfo, sizeof (buf), 0) != EOK)
>  {
>    printf ("devctl DCMD_PROC_INFO failed - %d (%s)\n", errno,
>     strerror (errno));
>    break;
>  }
>       num_threads = pidinfo->num_threads;
> 
>       info = (procfs_debuginfo *) buf;
>       if (devctl (fd, DCMD_PROC_MAPDEBUG_BASE, info, sizeof (buf), 0) !=
> EOK)
>  strcpy (name, "unavailable");
>       else
>  strcpy (name, info->path);
> 
>       /* Collect state info on all the threads.  */
>       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);
>  }
>       close (fd);
>     }
>   while (dirp != NULL);
> 
>   close (fd);
>   closedir (dp);
>   return;
> }
> 
> 
> void
> procfs_meminfo (char *args, int from_tty)
> {
>   procfs_mapinfo *mapinfos = NULL;
>   static int num_mapinfos = 0;
>   procfs_mapinfo *mapinfo_p, *mapinfo_p2;
>   int flags = ~0, err, num, i, j;
> 
>   struct
>   {
>     procfs_debuginfo info;
>     char buff[_POSIX_PATH_MAX];
>   } map;
> 
>   struct info
>   {
>     unsigned addr;
>     unsigned size;
>     unsigned flags;
>     unsigned debug_vaddr;
>     unsigned long long offset;
>   };
> 
>   struct printinfo
>   {
>     unsigned long long ino;
>     unsigned dev;
>     struct info text;
>     struct info data;
>     char name[256];
>   } printme;
> 
>
 
A single line of whitespace is enough here.

>   /* Get the number of map entrys.  */
>   if ((err = devctl (ctl_fd, DCMD_PROC_MAPINFO, NULL, 0, &num)) != EOK)
>     {
>       printf ("failed devctl num mapinfos - %d (%s)\n", err, strerror
> (err));
>       return;
>     }
> 
>   mapinfos = xmalloc (num * sizeof (procfs_mapinfo));
> 
>   num_mapinfos = num;
>   mapinfo_p = mapinfos;
> 
>   /* Fill the map entrys.  */
>   if ((err =
>        devctl (ctl_fd, DCMD_PROC_MAPINFO, mapinfo_p,
>         num * sizeof (procfs_mapinfo), &num)) != EOK)

Please remove the line-break after the `=' here.

>     {
>       printf ("failed devctl mapinfos - %d (%s)\n", err, strerror (err));
>       xfree (mapinfos);
>       return;
>     }
> 
>   num = 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.  */
>   for (mapinfo_p = mapinfos, i = 0; i < num; i++, mapinfo_p++)
>     {
>       if (!(mapinfo_p->flags & flags))
>  mapinfo_p->ino = 0;
> 
>       if (mapinfo_p->ino == 0) /* Already visited.  */
>  continue;
> 
>       map.info.vaddr = mapinfo_p->vaddr;
> 
>       if ((err =
>     devctl (ctl_fd, DCMD_PROC_MAPDEBUG, &map, sizeof (map), 0)) != EOK)
>  continue;
> 
>       memset (&printme, 0, sizeof printme);
>       printme.dev = mapinfo_p->dev;
>       printme.ino = mapinfo_p->ino;
>       printme.text.addr = mapinfo_p->vaddr;
>       printme.text.size = mapinfo_p->size;
>       printme.text.flags = mapinfo_p->flags;
>       printme.text.offset = mapinfo_p->offset;
>       printme.text.debug_vaddr = map.info.vaddr;
>       strcpy (printme.name, map.info.path);
> 
>       /* Check for matching data.  */
>       for (mapinfo_p2 = mapinfos, j = 0; j < num; j++, mapinfo_p2++)
>  {
>    if (mapinfo_p2->vaddr != mapinfo_p->vaddr &&
>        mapinfo_p2->ino == mapinfo_p->ino
>        && mapinfo_p2->dev == mapinfo_p->dev)
>      {

The && at the end of the first line of the if-statement should be on
the next line.

>        map.info.vaddr = mapinfo_p2->vaddr;
>        if ((err =
>      devctl (ctl_fd, DCMD_PROC_MAPDEBUG, &map, sizeof (map),
>       0)) != EOK)
>   continue;

Again, please remove the line-break after the `='.

> 
>        if (strcmp (map.info.path, printme.name))
>   {
>     continue;
>   }

Redundant braces.

>        /* Lower debug_vaddr is always text, if nessessary, swap.  */
>        if ((int) map.info.vaddr < (int) printme.text.debug_vaddr)
>   {
>     memcpy (&(printme.data), &(printme.text),
>      sizeof (printme.data));
>     printme.text.addr = mapinfo_p2->vaddr;
>     printme.text.size = mapinfo_p2->size;
>     printme.text.flags = mapinfo_p2->flags;
>     printme.text.offset = mapinfo_p2->offset;
>     printme.text.debug_vaddr = map.info.vaddr;
>   }
>        else
>   {
>     printme.data.addr = mapinfo_p2->vaddr;
>     printme.data.size = mapinfo_p2->size;
>     printme.data.flags = mapinfo_p2->flags;
>     printme.data.offset = mapinfo_p2->offset;
>     printme.data.debug_vaddr = map.info.vaddr;
>   }
>        mapinfo_p2->ino = 0;
>      }
>  }
>       mapinfo_p->ino = 0;
> 
>       printf_filtered ("%s\n", printme.name);
>       printf_filtered ("\ttext=%08x bytes @ 0x%08x\n", printme.text.size,
>          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);
>       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 ("\tdev=0x%x\n", printme.dev);
>       printf_filtered ("\tino=0x%x\n", (unsigned int) printme.ino);
>     }
>   xfree (mapinfos);
>   return;
> }
> 
> /* Print status information about what we're accessing.  */
> 
> static void
> procfs_files_info (struct target_ops *ignore)
> {
>   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);
> }
> 
> /* Mark our target-struct as eligible for stray "run" and "attach" commands.
> */
> static int
> procfs_can_run ()
> {
>   return 1;
> }
> 
> /* Attach to process PID, then initialize for debugging it.  */
> static void
> procfs_attach (char *args, int from_tty)
> {
>   char *exec_file;
>   int pid;
> 
>   if (!args)
>     error_no_arg ("process-id to attach");
> 
>   pid = atoi (args);
> 
>   if (pid == getpid ())
>     error ("Attaching GDB to itself is not a good idea...");
> 
>   if (from_tty)
>     {
>       exec_file = (char *) get_exec_file (0);
> 
>       if (exec_file)
>  printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
>       target_pid_to_str (pid_to_ptid (pid)));
>       else
>  printf_unfiltered ("Attaching to %s\n",
>       target_pid_to_str (pid_to_ptid (pid)));
> 
>       gdb_flush (gdb_stdout);
>     }
>   inferior_ptid = do_attach (pid_to_ptid (pid));
>   push_target (&procfs_ops);
> }
> 
> static void
> procfs_post_attach (pid_t pid)
> {
> #ifdef SOLIB_CREATE_INFERIOR_HOOK
>   if (exec_bfd)
>     SOLIB_CREATE_INFERIOR_HOOK (pid);
> #endif
> }
> 
> static ptid_t
> do_attach (ptid_t ptid)
> {
>   procfs_status status;
>   struct sigevent event;
>   char path[100];
> 
>   sprintf (path, "%s/%d/as", nto_procfs_path, PIDGET (ptid));
>   ctl_fd = open (path, O_RDWR);
>   if (ctl_fd == -1)
>     {
>       error ("Couldn't open proc file %s, error %d (%s)", path, errno,
>       strerror (errno));
>     }
>   if (devctl (ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0) != EOK)
>     {
>       error ("Couldn't stop process");
>     }
> 
>   /* Define a sigevent for process stopped notification.  */
>   event.sigev_notify = SIGEV_SIGNAL_THREAD;
>   event.sigev_signo = SIGUSR1;
>   event.sigev_code = 0;
>   event.sigev_value.sival_ptr = NULL;
>   event.sigev_priority = -1;
>   devctl (ctl_fd, DCMD_PROC_EVENT, &event, sizeof (event), 0);
> 
>   if (devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0) == EOK)
>     {
>       if (status.flags & _DEBUG_FLAG_STOPPED)
>  {
>    SignalKill (QNX_NODE, PIDGET (ptid), 0, SIGCONT, 0, 0);
>  }
>     }
>   attach_flag = 1;
>   nto_init_solib_absolute_prefix ();
>   return ptid;
> }
> 
> /* Ask the user what to do when an interrupt is received.  */
> static void
> interrupt_query ()
> {
>   target_terminal_ours ();
> 
>   if (query ("Interrupted while waiting for the program.\n\
> Give up (and stop debugging it)? "))
>     {
>       target_mourn_inferior ();
>       throw_exception (RETURN_QUIT);
>     }
> 
>   target_terminal_inferior ();
> }
> 
> /* The user typed ^C twice.  */
> static void
> nto_interrupt_twice (int signo)
> {
>   signal (signo, ofunc);
>   interrupt_query ();
>   signal (signo, nto_interrupt_twice);
> }
> 
> static void
> nto_interrupt (int signo)
> {
>   /* If this doesn't work, try more severe steps.  */
>   signal (signo, nto_interrupt_twice);
> 
>   target_stop ();
> }
> 
> static ptid_t
> procfs_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
> {
>   sigset_t set;
>   siginfo_t info;
>   procfs_status status;
>   static int exit_signo = 0; /* Used to track signals that cause
> termination.  */
> 
>   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
> 
>   if (ptid_equal (inferior_ptid, null_ptid))
>     {
>       ourstatus->kind = TARGET_WAITKIND_STOPPED;
>       ourstatus->value.sig = TARGET_SIGNAL_0;
>       exit_signo = 0;
>       return null_ptid;
>     }
> 
>   sigemptyset (&set);
>   sigaddset (&set, SIGUSR1);
> 
>   devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
>   while (!(status.flags & _DEBUG_FLAG_ISTOP))
>     {
>       ofunc = (void (*)()) signal (SIGINT, nto_interrupt);
>       sigwaitinfo (&set, &info);
>       signal (SIGINT, ofunc);
>       devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
>     }
> 
>   if (status.flags & _DEBUG_FLAG_SSTEP)
>     {
>       ourstatus->kind = TARGET_WAITKIND_STOPPED;
>       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
>     }
>   /* Was it a breakpoint?  */
>   else if (status.flags & _DEBUG_FLAG_TRACE)
>     {
>       ourstatus->kind = TARGET_WAITKIND_STOPPED;
>       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
>     }
>   else if (status.flags & _DEBUG_FLAG_ISTOP)
>     {
>       switch (status.why)
>  {
>  case _DEBUG_WHY_SIGNALLED:
>    ourstatus->kind = TARGET_WAITKIND_STOPPED;
>    ourstatus->value.sig =
>      target_signal_from_host (status.info.si_signo);
>    exit_signo = 0;
>    break;
>  case _DEBUG_WHY_FAULTED:
>    ourstatus->kind = TARGET_WAITKIND_STOPPED;
>    if (status.info.si_signo == SIGTRAP)
>      {
>        ourstatus->value.sig = 0;
>        exit_signo = 0;
>      }
>    else
>      {
>        ourstatus->value.sig =
>   target_signal_from_host (status.info.si_signo);
>        exit_signo = ourstatus->value.sig;
>      }
>    break;
> 
>  case _DEBUG_WHY_TERMINATED:
>    {
>      int waitval = 0;
> 
>      waitpid (PIDGET (inferior_ptid), &waitval, WNOHANG);
>      if (exit_signo)
>        {
>   ourstatus->kind = TARGET_WAITKIND_SIGNALLED; /* Abnormal death.  */
>   ourstatus->value.sig = exit_signo;
>        }
>      else
>        {
>   ourstatus->kind = TARGET_WAITKIND_EXITED; /* Normal death.  */
>   ourstatus->value.integer = WEXITSTATUS (waitval);
>        }
>      exit_signo = 0;
>      break;
>    }
> 
>  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;
>    exit_signo = 0;
>    break;
>  }
>     }
> 
>   return inferior_ptid;
> }
> 
> /* 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)
> {
>   union
>   {
>     procfs_greg greg;
>     procfs_fpreg fpreg;
>     procfs_altreg altreg;
>   }
>   reg;
>   int regsize;
> 
>   procfs_set_thread (inferior_ptid);
>   if (devctl (ctl_fd, DCMD_PROC_GETGREG, &reg, sizeof (reg), &regsize) ==
> EOK)
>     {
>       nto_supply_gregset ((char *)&reg.greg);
>     }
>   if (devctl (ctl_fd, DCMD_PROC_GETFPREG, &reg, sizeof (reg), &regsize) ==
>       EOK)
>     {
>       nto_supply_fpregset ((char *)&reg.fpreg);
>     }
>   if (devctl (ctl_fd, DCMD_PROC_GETALTREG, &reg, sizeof (reg), &regsize) ==
>       EOK)
>     {
>       nto_supply_altregset ((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.
> 
>    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)
> {
>   int nbytes = 0;
> 
>   if (lseek (ctl_fd, (off_t) memaddr, SEEK_SET) == (off_t) memaddr)
>     {
>       if (dowrite)
>  {
>    nbytes = write (ctl_fd, myaddr, len);
>  }
>       else
>  {
>    nbytes = read (ctl_fd, myaddr, len);
>  }
>       if (nbytes < 0)
>  {
>    nbytes = 0;
>  }
>     }
>   return (nbytes);
> }
> 
> /* Take a program previously attached to and detaches it.
>    The program resumes execution and will no longer stop
>    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)
> {
>   int siggnal = 0;
> 
>   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)
>     SignalKill (QNX_NODE, PIDGET (inferior_ptid), 0, siggnal, 0, 0);
> 
>   close (ctl_fd);
>   ctl_fd = -1;
>   init_thread_list ();
>   inferior_ptid = null_ptid;
>   attach_flag = 0;
>   unpush_target (&procfs_ops); /* Pop out of handling an inferior.  */
> }
> 
> static int
> procfs_breakpoint (CORE_ADDR addr, int type, int size)
> {
>   procfs_break brk;
> 
>   brk.type = type;
>   brk.addr = addr;
>   brk.size = size;
>   if ((errno = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0)) !=
>       EOK)
>     {
>       return 1;
>     }
>   return 0;
> }
> 
> static int
> procfs_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
> {
>   return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC, 0);
> }
> 
> static int
> procfs_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
> {
>   return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC, -1);
> }
> 
> static int
> procfs_insert_hw_breakpoint (CORE_ADDR addr, char *contents_cache)
> {
>   return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, 0);
> }
> 
> static int
> procfs_remove_hw_breakpoint (CORE_ADDR addr, char *contents_cache)
> {
>   return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, -1);
> }
> 
> static void
> procfs_resume (ptid_t ptid, int step, enum target_signal signo)
> {
>   int signal_to_pass;
>   procfs_status status;
> 
>   if (ptid_equal (inferior_ptid, null_ptid))
>     return;
> 
>   procfs_set_thread (ptid_equal (ptid, minus_one_ptid) ? inferior_ptid :
>        ptid);
> 
>   run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
>   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);
>   /* Peter V will be changing this at some point.  */
>   sigaddset ((sigset_t *) & run.fault, FLTPAGE);
> 
>   run.flags |= _DEBUG_RUN_ARM;
> 
>   sigemptyset (&run.trace);
>   notice_signals ();
>   signal_to_pass = target_signal_to_host (signo);
> 
>   if (signal_to_pass)
>     {
>       devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
>       signal_to_pass = target_signal_to_host (signo);
>       if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
>  {
>    if (signal_to_pass != status.info.si_signo)
>      {
>        SignalKill (QNX_NODE, PIDGET (inferior_ptid), 0, signal_to_pass,
>      0, 0);
>        run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
>      }
>    else
>      {
>        /* Let it kill the program without telling us.  */
>        sigdelset (&run.trace, signal_to_pass);
>      }
>  }
>     }
>   else
>     {
>       run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
>     }
>   if ((errno = devctl (ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0)) !=
> EOK)
>     {
>       perror ("run error!\n");
>       return;
>     }
> }
> 
> static void
> procfs_mourn_inferior ()
> {
>   if (!ptid_equal (inferior_ptid, null_ptid))
>     {
>       SignalKill (QNX_NODE, PIDGET (inferior_ptid), 0, SIGKILL, 0, 0);
>       close (ctl_fd);
>     }
>   inferior_ptid = null_ptid;
>   init_thread_list ();
>   unpush_target (&procfs_ops);
>   generic_mourn_inferior ();
>   attach_flag = 0;
> }
> 
> /* This function breaks up an argument string into an argument
>    vector suitable for passing to execvp().
>    E.g., on "run a b c d" this routine would get as input
>    the string "a b c d", and as output it would fill in argv with
>    the four arguments "a", "b", "c", "d".  The only additional
>    functionality is simple quoting.  The gdb command:
>    run a "b c d" f
>    will fill in argv with the three args "a", "b c d", "e".  */
> static void
> breakup_args (char *scratch, char **argv)
> {
>   char *pp, *cp = scratch;
>   char quoting = 0;
> 
>   for (;;)
>     {
> 

Please remove the whitespace here...

>       /* Scan past leading separators.  */
>       quoting = 0;
>       while (*cp == ' ' || *cp == '\t' || *cp == '\n')
>  {
>    cp++;
>  }
> 
>       /* Break if at end of string.  */
>       if (*cp == '\0')
>  break;
> 
>       /* Take an arg.  */
>       if (*cp == '"')
>  {
>    cp++;
>    quoting = strchr (cp, '"') ? 1 : 0;
>  }
> 
>       *argv++ = cp;
> 
>       /* Scan for next arg separator.  */
>       pp = cp;
>       if (quoting)
>  cp = strchr (pp, '"');
>       if ((cp == NULL) || (!quoting))
>  cp = strchr (pp, ' ');
>       if (cp == NULL)
>  cp = strchr (pp, '\t');
>       if (cp == NULL)
>  cp = strchr (pp, '\n');
> 
>       /* No separators => end of string => break.  */
>       if (cp == NULL)
>  {
>    pp = cp;
>    break;
>  }
> 
>       /* Replace the separator with a terminator.  */
>       *cp++ = '\0';
>     }
> 
>   /* Execv requires a null-terminated arg vector.  */
>   *argv = NULL;
> 
> }

... and here.

> 
> static void
> procfs_create_inferior (char *exec_file, char *allargs, char **env)
> {
>   struct inheritance inherit;
>   pid_t pid;
>   int flags, errn;
>   char **argv, *args;
>   char *in = "", *out = "", *err = "";
>   int fd, fds[3];
>   sigset_t set;
> 
>   argv =
>     (char **) xmalloc (((strlen (allargs) + 1) / (unsigned) 2 + 2) *
>          sizeof (*argv));
>   argv[0] = get_exec_file (1);
>   if (!argv[0])
>     {
>       if (exec_file)
>  argv[0] = exec_file;
>       else
>  return;
>     }
> 
>   args = strdup (allargs);
>   breakup_args (args, exec_file ? &argv[1] : &argv[0]);
> 
>   argv = nto_parse_redirection (argv, &in, &out, &err);
> 
>   fds[0] = STDIN_FILENO;
>   fds[1] = STDOUT_FILENO;
>   fds[2] = STDERR_FILENO;
> 
>   /* If the user specified I/O via gdb's --tty= arg, use it, but only
>      if the i/o is not also being specified via redirection.  */
>   if (inferior_io_terminal)
>     {
>       if (!in[0])
>  in = inferior_io_terminal;
>       if (!out[0])
>  out = inferior_io_terminal;
>       if (!err[0])
>  err = inferior_io_terminal;
>     }
> 
>   if (in[0])
>     {
>       if ((fd = open (in, O_RDONLY)) == -1)
>  {
>    perror (in);
>  }
>       else
>  fds[0] = fd;
>     }
>   if (out[0])
>     {
>       if ((fd = open (out, O_WRONLY)) == -1)
>  {
>    perror (out);
>  }
>       else
>  fds[1] = fd;
>     }
>   if (err[0])
>     {
>       if ((fd = open (err, O_WRONLY)) == -1)
>  {
>    perror (err);
>  }
>       else
>  fds[2] = fd;
>     }
> 
>   /* Clear any pending SIGUSR1's but keep the behavior the same.  */
>   signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
> 
>   sigemptyset (&set);
>   sigaddset (&set, SIGUSR1);
>   sigprocmask (SIG_UNBLOCK, &set, NULL);
> 
>   memset (&inherit, 0, sizeof (inherit));
> 
>   if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) != 0)
>     {
>       inherit.nd = QNX_NODE;
>       inherit.flags |= SPAWN_SETND;
>       inherit.flags &= ~SPAWN_EXEC;
>     }
>   inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
>   inherit.pgroup = SPAWN_NEWPGROUP;
>   pid =
>     spawnp (argv[0], 3, fds, &inherit, argv,
>      ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0 ? env : 0);
>   xfree (args);
> 
>   sigprocmask (SIG_BLOCK, &set, NULL);
> 
>   if (pid == -1)
>     error ("Error spawning %s: %d (%s)", argv[0], errno, strerror (errno));
> 
>   if (fds[0] != STDIN_FILENO)
>     close (fds[0]);
>   if (fds[1] != STDOUT_FILENO)
>     close (fds[1]);
>   if (fds[2] != STDERR_FILENO)
>     close (fds[2]);
> 
>   inferior_ptid = do_attach (pid_to_ptid (pid));
> 
>   attach_flag = 0;
>   flags = _DEBUG_FLAG_KLC; /* Kill-on-Last-Close flag.  */
>   if ((errn =
>        devctl (ctl_fd, DCMD_PROC_SET_FLAG, &flags, sizeof (flags), 0)) !=
> EOK)
>     {
>       /* warning( "Failed to set Kill-on-Last-Close flag: errno = %d(%s)\n",
> errn, strerror(errn) ); */
>     }
>   push_target (&procfs_ops);
>   target_terminal_init ();
> 
> #ifdef SOLIB_CREATE_INFERIOR_HOOK
>   if (exec_bfd != NULL
>       || (symfile_objfile != NULL && symfile_objfile->obfd != NULL))
>     SOLIB_CREATE_INFERIOR_HOOK (pid);
> #endif
> }
> 
> static void
> procfs_stop ()
> {
>   devctl (ctl_fd, DCMD_PROC_STOP, NULL, 0, 0);
> }
> 
> static void
> procfs_kill_inferior ()
> {
>   target_mourn_inferior ();
> }
> 
> /* Store register REGNO, or all registers if REGNO == -1, from the contents
>    of REGISTERS.  */
> 
> static void
> procfs_prepare_to_store ()
> {
> }
> 
> /* Fill buf with regset and return devctl cmd to do the setting.  Return
>    -1 if we fail to get the regset.  Store size of regset in regsize.  */
> static int
> get_regset(int regset, char *buf, int bufsize, int *regsize)
> {
>   int dev_get, dev_set;
>         switch(regset){
>         case NTO_REG_GENERAL:
>           dev_get = DCMD_PROC_GETGREG;
>           dev_set = DCMD_PROC_SETGREG;
>           break;
> 
>         case NTO_REG_FLOAT:
>           dev_get = DCMD_PROC_GETFPREG;
>           dev_set = DCMD_PROC_SETFPREG;
>           break;
> 
>         case NTO_REG_ALT:
>           dev_get = DCMD_PROC_GETALTREG;
>           dev_set = DCMD_PROC_SETALTREG;
>           break;
> 
>         case NTO_REG_SYSTEM:
>         default:
>           return -1;
>         }
>         if(devctl(ctl_fd, dev_get, &buf, bufsize, regsize) != EOK)
>           return -1;
> 
>         return dev_set;
> }
> 
> void
> procfs_store_registers (int regno)
> {
>   union
>   {
>     procfs_greg greg;
>     procfs_fpreg fpreg;
>     procfs_altreg altreg;
>   }
>   reg;
>   unsigned off;
>   int len, regset, regsize, dev_set, err;
>   char *data;
> 
>   if (ptid_equal (inferior_ptid, null_ptid))
>     return;
>   procfs_set_thread (inferior_ptid);
> 
>   if (regno == -1) {
>       for(regset = NTO_REG_GENERAL; regset < NTO_REG_END ; regset++){
>         if((dev_set = get_regset(regset, (char *)&reg, sizeof(reg),
> &regsize)) == -1)
>           continue;
> 
>         if(nto_regset_fill(regset, (char *)&reg) == -1)
>           continue;
> 
>         if((err = devctl(ctl_fd, dev_set, &reg, regsize, 0)) != EOK)
>           fprintf_unfiltered(gdb_stderr, "Warning unable to write regset %d:
> %s\n", regno, strerror(err));
>       }
>     }
>   else{
>     if((regset = nto_regset_id(regno)) == -1)
>       return;
> 
>     if((dev_set = get_regset(regset, (char *)&reg, sizeof(reg), &regsize))
> == -1)
>       return;
> 
>     len = nto_register_area(regno, regset, &off);
> 
>     if(len < 1)
>       return;
> 
>     regcache_collect(regno, (char *)&reg + off);
> 
>     if((err = devctl(ctl_fd, dev_set, &reg, regsize, 0)) != EOK)
>       fprintf_unfiltered(gdb_stderr, "Warning unable to write regset %d:
> %s\n", regno, strerror(err));
>   }
> }
> 
> static void
> notice_signals (void)
> {
>   int 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)

The &&'s should be moved to the next line.

>  {
>    sigdelset (&run.trace, signo);
>  }
>       else
>  {
>    sigaddset (&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 buf[1024];
>   int pid, tid, n;
>   struct tidinfo *tip;
> 
>   pid = ptid_get_pid (ptid);
>   tid = ptid_get_tid (ptid);
> 
>   n = sprintf (buf, "process %d", pid);
> 
> #if 0 /* NYI */
>   tip = procfs_thread_info (pid, tid);
>   if (tip != NULL)
>     sprintf (&buf[n], " (state = 0x%02x)", tip->state);
> #endif
> 
>   return buf;
> }
> 
> static void
> init_procfs_ops ()
> {
>   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.to_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;
> }
> 
> #define OSTYPE_NTO 1
> 
> void
> _initialize_procfs ()
> {
>   sigset_t set;
> 
>   init_procfs_ops ();
>   add_target (&procfs_ops);
> 
>   /* We use SIGUSR1 to gain control after we block waiting for a process.
>      We use sigwaitevent to wait.  */
>   sigemptyset (&set);
>   sigaddset (&set, SIGUSR1);
>   sigprocmask (SIG_BLOCK, &set, NULL);
> 
>   /* Set up trace and fault sets, as gdb expects them.  */
>   sigemptyset (&run.trace);
>   notice_signals ();
> 
>   /* Stuff some information.  */
>   nto_cpuinfo_flags = SYSPAGE_ENTRY (cpuinfo)->flags;
>   nto_cpuinfo_valid = 1;
> 
>   add_info ("pidlist", procfs_pidlist, "pidlist");
>   add_info ("meminfo", procfs_meminfo, "memory information");
> }
> 
> 
> static int
> procfs_hw_watchpoint (int addr, int len, int type)
> {
>   procfs_break brk;
>   int err;
> 
>   switch (type)
>     {
>     case 1:   /* Read.  */
>       brk.type = _DEBUG_BREAK_RD;
>       break;
>     case 2:   /* Read/Write.  */
>       brk.type = _DEBUG_BREAK_RW;
>       break;
>     default:   /* Modify.  */
> /*     brk.type = _DEBUG_BREAK_RWM; This should work, shouldn't it? I get
> EINVAL */
>       brk.type = _DEBUG_BREAK_RW;
>     }
>   brk.type |= _DEBUG_BREAK_HW; /* Always ask for HW.  */
>   brk.addr = addr;
>   brk.size = len;
> 
>   if ((err = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0)) !=
> EOK)
>     {
>       errno = err;
>       perror ("Failed to set hardware watchpoint");
>       return -1;
>     }
>   return 0;
> }
> 
> static int
> procfs_can_use_hw_breakpoint (int type, int cnt, int othertype)
> {
>   return 1;
> }
> 
> static int
> procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type)
> {
>   return procfs_hw_watchpoint (addr, -1, type);
> }
> 
> static int
> procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type)
> {
>   return procfs_hw_watchpoint (addr, len, type);
> }
> 
> static int
> procfs_stopped_by_watchpoint (void)
> {
>   return 0;
> }

Mark


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]