diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/bfd/elf.c src/bfd/elf.c
*** src.orig/bfd/elf.c	Thu Jan 23 06:51:32 2003
--- src/bfd/elf.c	Fri Jan 31 11:53:58 2003
*************** static bfd_boolean elfcore_grok_netbsd_p
*** 97,102 ****
--- 97,108 ----
    PARAMS ((bfd *, Elf_Internal_Note *));
  static bfd_boolean elfcore_grok_netbsd_note
    PARAMS ((bfd *, Elf_Internal_Note *));
+ static bfd_boolean elfcore_grok_nto_gregs
+   PARAMS ((bfd *, Elf_Internal_Note *, pid_t));
+ static bfd_boolean elfcore_grok_nto_status
+   PARAMS ((bfd *, Elf_Internal_Note *, pid_t *));
+ static bfd_boolean elfcore_grok_nto_note
+   PARAMS ((bfd *, Elf_Internal_Note *));
  
  /* Swap version information in and out.  The version information is
     currently size independent.  If that ever changes, this code will
*************** elfcore_read_notes (abfd, offset, size)
*** 7189,7194 ****
--- 7195,7205 ----
            if (! elfcore_grok_netbsd_note (abfd, &in))
              goto error;
          }
+       else if (strncmp (in.namedata, "QNX", 3) == 0)
+         {
+           if (! elfcore_grok_nto_note (abfd, &in))
+             goto error;
+         }
        else
          {
            if (! elfcore_grok_note (abfd, &in))
*************** _bfd_elf_section_offset (abfd, info, sec
*** 7391,7393 ****
--- 7402,7505 ----
        return offset;
      }
  }
+ 
+ static bfd_boolean
+ elfcore_grok_nto_status(abfd, note, tid)
+      bfd *abfd;
+      Elf_Internal_Note *note;
+      pid_t *tid;
+ {
+   void *ddata = note->descdata;
+   char buf[100];
+   char *name;
+   asection *sect;
+ 
+   /* nto_procfs_status 'pid' field is at offset 0 */
+   elf_tdata (abfd)->core_pid = bfd_get_32( abfd, (bfd_byte *)ddata);
+ 
+   /* nto_procfs_status 'tid' field is at offset 4 */
+   elf_tdata (abfd)->core_lwpid = bfd_get_32( abfd, (bfd_byte *)ddata + 4);
+ 
+   /* nto_procfs_status 'what' field is at offset 14 */
+   elf_tdata (abfd)->core_signal = bfd_get_16( abfd, (bfd_byte *)ddata + 14);
+ 
+   /* pass tid back */
+   *tid = elf_tdata (abfd)->core_lwpid;
+ 
+   /* Make a ".qnx_core_status/%d" section. */
+   sprintf (buf, ".qnx_core_status/%d", *tid);
+ 
+   name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+   if (name == NULL)
+     return FALSE;
+   strcpy (name, buf);
+ 
+   sect = bfd_make_section (abfd, name);
+   if (sect == NULL)
+     return FALSE;
+ 
+   sect->_raw_size = note->descsz;
+   sect->filepos = note->descpos;
+ 
+   sect->flags = SEC_HAS_CONTENTS;
+   sect->alignment_power = 2;
+ 
+   return (elfcore_maybe_make_sect (abfd, ".qnx_core_status", sect));
+ }
+ 
+ 
+ static bfd_boolean
+ elfcore_grok_nto_gregs(abfd, note, tid)
+      bfd *abfd;
+      Elf_Internal_Note *note;
+      pid_t tid;
+ {
+   char buf[100];
+   char *name;
+   asection *sect;
+ 
+   /* Make a ".reg/%d" section. */
+   sprintf (buf, ".reg/%d", tid);
+ 
+   name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+   if (name == NULL)
+     return FALSE;
+   strcpy (name, buf);
+ 
+   sect = bfd_make_section (abfd, name);
+   if (sect == NULL)
+     return FALSE;
+ 
+   sect->_raw_size = note->descsz;
+   sect->filepos = note->descpos;
+ 
+   sect->flags = SEC_HAS_CONTENTS;
+   sect->alignment_power = 2;
+ 
+   return elfcore_maybe_make_sect (abfd, ".reg", sect);
+ }
+ 
+ static bfd_boolean
+ elfcore_grok_nto_note (abfd, note)
+      bfd *abfd;
+      Elf_Internal_Note *note;
+ {
+ 	/* Every GREG section has a STATUS section before it.  Store the
+ 	 * tid from the previous call to pass down to the next gregs 
+ 	 * function. */
+   static pid_t tid = 1;
+   switch (note->type)
+     {
+     default:
+       return TRUE;
+     case 7: //QNT_CORE_INFO
+ 	return elfcore_make_note_pseudosection (abfd, ".qnx_core_info", note);
+     case 8: //QNT_CORE_STATUS
+ 	return elfcore_grok_nto_status (abfd, note, &tid);
+     case 9: //QNT_CORE_GREG
+ 	return elfcore_grok_nto_gregs (abfd, note, tid);
+     case 10: //QNT_CORE_FPREG
+ 	return elfcore_grok_prfpreg (abfd, note);
+     }
+     /* NOTREACHED */
+ }
Binary files src.orig/bfd/po/da.gmo and src/bfd/po/da.gmo differ
Binary files src.orig/bfd/po/es.gmo and src/bfd/po/es.gmo differ
Binary files src.orig/bfd/po/fr.gmo and src/bfd/po/fr.gmo differ
Binary files src.orig/bfd/po/ja.gmo and src/bfd/po/ja.gmo differ
Binary files src.orig/bfd/po/sv.gmo and src/bfd/po/sv.gmo differ
Binary files src.orig/bfd/po/tr.gmo and src/bfd/po/tr.gmo differ
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/config/mh-qnxnto src/config/mh-qnxnto
*** src.orig/config/mh-qnxnto	Wed Dec 31 19:00:00 1969
--- src/config/mh-qnxnto	Mon Jan 13 12:12:04 2003
***************
*** 0 ****
--- 1 ----
+ LIBCFLAGS += -DNEED_sys_siglist=1 -DNO_SYS_FILE_H
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/config.sub src/config.sub
*** src.orig/config.sub	Wed Jan  8 17:09:30 2003
--- src/config.sub	Mon Jan 13 16:22:24 2003
*************** case $basic_machine in
*** 727,732 ****
--- 727,740 ----
  	nsr-tandem)
  		basic_machine=nsr-tandem
  		;;
+ 	ntox86)
+ 		basic_machine=i386${os:--unknown}
+ 		os=-nto
+ 		;;
+ 	ntomulti)
+ 		basic_machine=i686${os:--unknown}
+ 		os=-cygwin32
+ 		;;	
  	op50n-* | op60c-*)
  		basic_machine=hppa1.1-oki
  		os=-proelf
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/configure.in src/configure.in
*** src.orig/configure.in	Mon Jan 27 14:47:23 2003
--- src/configure.in	Tue Jan 28 13:50:28 2003
*************** case "${host}" in
*** 1089,1094 ****
--- 1089,1097 ----
      tentative_cc="/usr/ccs/ATT/cc"
      host_makefile_frag="config/mh-ncr3000"
      ;;
+   i[3456]86-*-nto*)
+     host_makefile_frag="config/mh-qnxnto"
+     ;;
    i[[3456]]86-*-sco3.2v5*)
      ;;
    i[[3456]]86-*-sco*)
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/config/i386/i386nto.mt src/gdb/config/i386/i386nto.mt
*** src.orig/gdb/config/i386/i386nto.mt	Wed Dec 31 19:00:00 1969
--- src/gdb/config/i386/i386nto.mt	Tue Jan 21 14:19:26 2003
***************
*** 0 ****
--- 1,4 ----
+ # Target: Intel 386 running qnx6
+ TDEPFILES= i386-tdep.o i387-tdep.o corelow.o solib.o solib-svr4.o \
+ 	remote-nto.o remote-nto-i386.o
+ TM_FILE= tm-i386nto.h
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/config/i386/nm-nto.h src/gdb/config/i386/nm-nto.h
*** src.orig/gdb/config/i386/nm-nto.h	Wed Dec 31 19:00:00 1969
--- src/gdb/config/i386/nm-nto.h	Fri Jan 31 12:24:06 2003
***************
*** 0 ****
--- 1 ----
+ #define __QNXNTO_USE_PROCFS__
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/config/i386/nto.mh src/gdb/config/i386/nto.mh
*** src.orig/gdb/config/i386/nto.mh	Wed Dec 31 19:00:00 1969
--- src/gdb/config/i386/nto.mh	Mon Jan 27 17:06:58 2003
***************
*** 0 ****
--- 1,9 ----
+ # Host: Intel 386 running QNX
+ 
+ MH_CFLAGS=-DNEED_SYS_SELECT_H
+ 
+ XM_FILE= xm-nto.h
+ 
+ NAT_FILE= nm-nto.h
+ 
+ NATDEPFILES= nto-procfs.o ser-ntopty.o
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/config/i386/tm-i386nto.h src/gdb/config/i386/tm-i386nto.h
*** src.orig/gdb/config/i386/tm-i386nto.h	Wed Dec 31 19:00:00 1969
--- src/gdb/config/i386/tm-i386nto.h	Fri Jan 31 12:24:06 2003
***************
*** 0 ****
--- 1,114 ----
+ /*-
+ 	QNX Debug Protocol, i386
+  */
+ 
+ #ifndef TM_I386QNX_H
+ #define TM_I386QNX_H 1
+ 
+ #define HAVE_I387_REGS
+ 
+ /* Pick up most of what we need from the generic i386 target include file. */
+ 
+ #include "i386/tm-i386.h"
+ #include "tm-qnxnto.h"
+ 
+ #define __QNXTARGET__
+ #define QNX_TARGET_CPUTYPE CPUTYPE_X86
+ 
+ /* Used in solib.c */
+ #define EBX_REGNUM       3
+ 
+ #undef DECR_PC_AFTER_BREAK
+ #define DECR_PC_AFTER_BREAK 0	/* neutrino rewinds to look more normal */
+ 
+ /* Offsets (in target ints) into jmp_buf.  Not defined in any system header
+    file, so we have to step through setjmp/longjmp with a debugger and figure
+    them out.  Note that <setjmp> defines _JBLEN as 10, which is the default
+    if no specific machine is selected, even though we only use 6 slots. */
+ 
+ #define JB_ELEMENT_SIZE sizeof(int)	/* jmp_buf[_JBLEN] is array of ints */
+ 
+ #define JB_EBX	0
+ #define JB_ESI	1
+ #define JB_EDI	2
+ #define JB_EBP	3
+ #define JB_ESP	4
+ #define JB_EDX	5
+ 
+ #define JB_PC	JB_EDX		/* Setjmp()'s return PC saved in EDX */
+ 
+ /* Figure out where the longjmp will land.  Slurp the args out of the stack.
+    We expect the first arg to be a pointer to the jmp_buf structure from which
+    we extract the pc (JB_PC) that we will land at.  The pc is copied into ADDR.
+    This routine returns true on success */
+ #if 0
+ extern int i386_get_longjmp_target PARAMS ((CORE_ADDR *));
+ 
+ #define GET_LONGJMP_TARGET(ADDR) i386_get_longjmp_target(ADDR)
+ #endif
+ 
+ /* The following redefines make backtracing through sigtramp work.
+    They manufacture a fake sigtramp frame and obtain the saved pc in sigtramp
+    from the ucontext structure which is pushed by the kernel on the
+    user stack. Unfortunately there are three variants of sigtramp handlers.  */
+ 
+ #define I386V4_SIGTRAMP_SAVED_PC
+ #define IN_SIGTRAMP(pc, name) ((name)					\
+ 			       && (STREQ ("_sigreturn", name)		\
+ 				   || STREQ ("_sigacthandler", name)	\
+ 				   || STREQ ("sigvechandler", name)))
+ 
+ /* Saved Pc.  Get it from ucontext if within sigtramp.  */
+ 
+ #define sigtramp_saved_pc i386v4_sigtramp_saved_pc
+ extern CORE_ADDR i386v4_sigtramp_saved_pc PARAMS ((struct frame_info *));
+ 
+ /* Neutrino supports the 386 hardware debugging registers.  */
+ 
+ #define TARGET_HAS_HARDWARE_WATCHPOINTS
+ 
+ #define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1
+ 
+ /* After a watchpoint trap, the PC points to the instruction after
+    the one that caused the trap.  Therefore we don't need to step over it.
+    But we do need to reset the status register to avoid another trap.  */
+ #define HAVE_CONTINUABLE_WATCHPOINT
+ 
+ #define STOPPED_BY_WATCHPOINT(W)  \
+   qnx_stopped_by_watchpoint()
+ 
+ /* Use these macros for watchpoint insertion/removal.  */
+ 
+ #define target_insert_watchpoint(addr, len, type)  \
+   qnx_insert_hw_watchpoint ( addr, len, type)
+ 
+ #define target_remove_watchpoint(addr, len, type)  \
+   qnx_remove_hw_watchpoint ( addr, len, type)
+ 
+ /* Use these macros for watchpoint insertion/removal.  */
+ 
+ #define target_remove_hw_breakpoint(ADDR,SHADOW) \
+   qnx_remove_hw_breakpoint(ADDR,SHADOW)
+ 
+ #define target_insert_hw_breakpoint(ADDR,SHADOW) \
+   qnx_insert_hw_breakpoint(ADDR,SHADOW)
+ 
+ #define FIND_NEW_THREADS qnx_find_new_threads
+ void qnx_find_new_threads PARAMS ((void));
+ 
+ /* default processor for search path for libs */
+ #define SOLIB_PROCESSOR "x86"
+ 
+ /* Use target_specific function to define link map offsets.  */
+ extern struct link_map_offsets *i386_qnx_svr4_fetch_link_map_offsets (void);
+ #define SVR4_FETCH_LINK_MAP_OFFSETS() i386_qnx_svr4_fetch_link_map_offsets ()
+ 
+ #define HANDLE_SVR4_EXEC_EMULATORS 1
+ #include "solib.h"		/* Support for shared libraries. */
+ 
+ #define NO_PTRACE_H
+ 
+ /* Use .ntox86-gdbinit */
+ #define EXTRA_GDBINIT_FILENAME ".ntox86-gdbinit"
+ 
+ #endif /* ifndef TM_I386QNX_H */
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/config/i386/xm-nto.h src/gdb/config/i386/xm-nto.h
*** src.orig/gdb/config/i386/xm-nto.h	Wed Dec 31 19:00:00 1969
--- src/gdb/config/i386/xm-nto.h	Fri Jan 31 12:24:06 2003
***************
*** 0 ****
--- 1,46 ----
+ /* Host support for i386.
+    Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+    Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu), July 1988.
+ 
+ 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.  */
+ 
+ #define HOST_BYTE_ORDER LITTLE_ENDIAN
+ 
+ /* I'm running gdb 3.4 under 386/ix 2.0.2, which is a derivative of AT&T's
+ Sys V/386 3.2.
+ 
+ On some machines, gdb crashes when it's starting up while calling the
+ vendor's termio tgetent() routine.  It always works when run under
+ itself (actually, under 3.2, it's not an infinitely recursive bug.)
+ After some poking around, it appears that depending on the environment
+ size, or whether you're running YP, or the phase of the moon or something,
+ the stack is not always long-aligned when main() is called, and tgetent()
+ takes strong offense at that.  On some machines this bug never appears, but
+ on those where it does, it occurs quite reliably.  */
+ #define ALIGN_STACK_ON_STARTUP
+ 
+ /* define USG if you are using sys5 /usr/include's */
+ #define USG
+ 
+ #ifndef HAVE_TERMIOS_H
+ #define HAVE_TERMIO
+ #endif
+ 
+ /* This is the amount to subtract from u.u_ar0
+    to get the offset in the core file of the register values.  */
+ 
+ #define KERNEL_U_ADDR 0xe0000000
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/config/tm-qnxnto.h src/gdb/config/tm-qnxnto.h
*** src.orig/gdb/config/tm-qnxnto.h	Wed Dec 31 19:00:00 1969
--- src/gdb/config/tm-qnxnto.h	Fri Jan 31 12:24:06 2003
***************
*** 0 ****
--- 1,69 ----
+ /* Target machine sub-description for QNX Neutrino version 6.
+    This is included by other tm-*.h files to specify nto specific
+    stuff.  Copyright 2002 Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 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.  */
+ 
+ #define __QNXTARGET__
+ #include "tm-sysv4.h"
+ 
+ #define FIND_NEW_THREADS qnx_find_new_threads
+ void qnx_find_new_threads PARAMS ((void));
+ 
+ #define target_pid_to_str(PTID) \
+ 	qnx_pid_to_str(PTID)
+ extern char *qnx_pid_to_str PARAMS ((ptid_t ptid));
+ 
+ /* Setup the valid realtime signal range. */
+ #define REALTIME_LO 41
+ #define REALTIME_HI 56
+ 
+ /* Set up the undefined useable signals. */
+ #define RAW_SIGNAL_LO 32
+ #define RAW_SIGNAL_HI (REALTIME_LO - 1)
+ 
+ #define TARGET_SIGNAL_RAW_VALUES \
+ TARGET_SIGNAL_RAW0, \
+ TARGET_SIGNAL_RAW1, \
+ TARGET_SIGNAL_RAW2, \
+ TARGET_SIGNAL_RAW3, \
+ TARGET_SIGNAL_RAW4, \
+ TARGET_SIGNAL_RAW5, \
+ TARGET_SIGNAL_RAW6, \
+ TARGET_SIGNAL_RAW7, \
+ TARGET_SIGNAL_RAW8
+ 
+ #define TARGET_SIGNAL_RAW_TABLE \
+ {"SIGNAL32", "Signal 32"}, \
+ {"SIGNAL33", "Signal 33"}, \
+ {"SIGNAL34", "Signal 34"}, \
+ {"SIGNAL35", "Signal 35"}, \
+ {"SIGNAL36", "Signal 36"}, \
+ {"SIGNAL37", "Signal 37"}, \
+ {"SIGNAL38", "Signal 38"}, \
+ {"SIGNAL39", "Signal 39"}, \
+ {"SIGNAL40", "Signal 40"}
+ 
+ /* See solib-svr4.c
+  * This works around a problem with static binaries.  An internal breakpoint
+  * is set on _start but for whatever reason, gdb doesn't handle it properly
+  * and claims a SIGTRAP has been raised on the inferior.  If we move the
+  * shlib_event breakpoint ahead to main (this already happened by default
+  * on sh for some reason), then it works.  FIXME: we need to discover why
+  * gdb isn't handling breakpoints properly at the early stages of execution. */
+ #define SOLIB_BKPT_NAME "main"
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/configure.host src/gdb/configure.host
*** src.orig/gdb/configure.host	Sat Feb  1 07:28:00 2003
--- src/gdb/configure.host	Mon Feb  3 14:15:16 2003
*************** i[3456]86-*-msdosdjgpp*) gdb_host=go32 ;
*** 64,69 ****
--- 64,70 ----
  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* | x86-*-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 ;;
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/configure.tgt src/gdb/configure.tgt
*** src.orig/gdb/configure.tgt	Fri Jan 31 11:32:44 2003
--- src/gdb/configure.tgt	Mon Feb  3 14:15:16 2003
*************** i[3456]86-*-netbsd*)	gdb_target=nbsd ;;
*** 90,95 ****
--- 90,96 ----
  i[3456]86-*-openbsd*)	gdb_target=obsd ;;
  i[3456]86-*-go32*)	gdb_target=i386aout ;;
  i[3456]86-*-msdosdjgpp*) gdb_target=go32 ;;
+ i[3456]86-*-nto*)	gdb_target=i386nto;;
  i[3456]86-*-lynxos*)	gdb_target=i386lynx ;;
  i[3456]86-*-solaris*)	gdb_target=i386sol2 ;;
  i[3456]86-*-sysv4.2*)	gdb_target=i386v42mp ;;
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/nto-procfs.c src/gdb/nto-procfs.c
*** src.orig/gdb/nto-procfs.c	Wed Dec 31 19:00:00 1969
--- src/gdb/nto-procfs.c	Mon Feb  3 11:36:20 2003
***************
*** 0 ****
--- 1,1450 ----
+ /* Machine independent support for QNX Neutrino /proc (process file system) for GDB.
+    Copyright 1991, 1992-99, 2000 Free Software Foundation, Inc.
+    Written by Colin Burgess at QNX Software Systems Limited.  
+ 
+ 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 <errno.h>
+ #include <string.h>
+ #include <fcntl.h>
+ #include <spawn.h>
+ #include <sys/debug.h>
+ #include <sys/procfs.h>
+ #include <sys/neutrino.h>
+ #include <sys/types.h>
+ #include <sys/syspage.h>
+ #include <time.h>
+ #include <unistd.h>
+ #include <dirent.h>
+ #include <sys/netmgr.h>
+ 
+ #include "defs.h"
+ #include "gdb_string.h"
+ #include "gdbcore.h"
+ #include "frame.h"
+ #include "inferior.h"
+ #include "bfd.h"
+ #include "symfile.h"
+ #include "target.h"
+ #include "gdb_wait.h"
+ #include "gdbcmd.h"
+ #include "objfiles.h"
+ #include "gdb-stabs.h"
+ #include "gdbthread.h"
+ #include "nto-share/dsmsgs.h"
+ #include "dcache.h"
+ #include "gdb_stat.h"
+ #include "command.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)
+ 
+ static struct target_ops procfs_ops;
+ int ctl_fd;
+ static void (*ofunc) ();
+ static procfs_run run;
+ 
+ static void procfs_open PARAMS ((char *, int));
+ static int procfs_can_run PARAMS ((void));
+ static ptid_t procfs_wait PARAMS ((ptid_t, struct target_waitstatus *));
+ static int procfs_xfer_memory
+ PARAMS ((CORE_ADDR, char *, int, int, struct mem_attrib * attrib,
+ 	 struct target_ops *));
+ static void procfs_fetch_registers PARAMS ((int));
+ static void notice_signals (void);
+ 
+ static void init_procfs_ops PARAMS ((void));
+ static ptid_t do_attach PARAMS ((ptid_t ptid));
+ 
+ extern char **qnx_parse_redirection
+ PARAMS ((char *start_argv[], char **in, char **out, char **err));
+ extern short int qnx_swap16 PARAMS ((int val));
+ extern void qnx_init_solib_search_path ();
+ extern unsigned qnx_cpu_register_area
+ PARAMS ((unsigned first_regno, unsigned last_regno, unsigned char *subcmd,
+ 	 unsigned *off, unsigned *len));
+ extern int qnx_cpu_register_store
+ PARAMS ((int endian, unsigned first_regno, unsigned last_regno, void *data));
+ 
+ /* 
+    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_qnx_node (unsigned node)
+ {
+   if (node == -1)
+     {
+       error ("Lost the QNX node.  Debug session probably over.");
+       /* NOTREACHED */
+     }
+   return (node);
+ }
+ 
+ /* 
+    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_qnx_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/gp".  If arg is not a valid QNX node, we will default to local. 
+ */
+ static void
+ procfs_open (arg, from_tty)
+      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;
+ 	}
+       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");
+       /* NOTREACHED */
+     }
+ 
+   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.");
+       /* NOTREACHED */
+     }
+   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.");
+ 	  /* NOTREACHED */
+ 	}
+       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.");
+ 	      /* NOTREACHED */
+ 	    }
+ 	  else
+ 	    {
+ 	      if (sysinfo->type != QNX_TARGET_CPUTYPE)
+ 		{
+ 		  close (fd);
+ 		  error ("Invalid target CPU.");
+ 		  /* NOTREACHED */
+ 		}
+ 	    }
+ 	}
+     }
+   close (fd);
+   printf_filtered ("Debugging using %s\n", nto_procfs_path);
+ 
+ }
+ 
+ static void
+ procfs_set_thread (ptid)
+      ptid_t ptid;
+ {
+   pid_t tid;
+ 
+   tid = ptid_get_tid (inferior_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, qnx_swap16 (status.tid));
+       if (!in_thread_list (ptid))
+ 	add_thread (ptid);
+     }
+   return;
+ }
+ 
+ void
+ procfs_pidlist (char *args, int from_tty)
+ {
+   static DIR *dp = NULL;
+   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)
+ 	    {
+ 	      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;
+ 
+ 
+   // 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)
+     {
+       printf ("failed devctl mapinfos - %d (%s)\n", err, strerror (err));
+       xfree (mapinfos);
+       return;
+     }
+ 
+   num = min (num, num_mapinfos);
+ 
+   //
+   // Run through the list of mapinfo's, 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)
+ 	    {
+ 	      map.info.vaddr = mapinfo_p2->vaddr;
+ 	      if ((err =
+ 		   devctl (ctl_fd, DCMD_PROC_MAPDEBUG, &map, sizeof (map),
+ 			   0)) != EOK)
+ 		continue;
+ 
+ 	      if (strcmp (map.info.path, printme.name))
+ 		{
+ 		  continue;
+ 		}
+ 
+ 	      /*
+ 	       * 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 (ignore)
+      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 (args, from_tty)
+      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 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));
+       /* NOTREACHED */
+     }
+   if (devctl (ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0) != EOK)
+     {
+       error ("Couldn't stop process");
+       /* NOTREACHED */
+     }
+ 
+   // 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;
+   qnx_init_solib_search_path ();
+   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
+ qnx_interrupt_twice (signo)
+      int signo;
+ {
+   signal (signo, ofunc);
+   interrupt_query ();
+   signal (signo, qnx_interrupt_twice);
+ }
+ 
+ static void
+ qnx_interrupt (int signo)
+ {
+   /* If this doesn't work, try more severe steps.  */
+   signal (signo, qnx_interrupt_twice);
+ 
+   target_stop ();
+ }
+ 
+ static ptid_t
+ procfs_wait (ptid, ourstatus)
+      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, qnx_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);	//status.what;
+ 	      }
+ 	    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;
+ }
+ 
+ /*
+ 
+ LOCAL FUNCTION
+ 
+ 	procfs_fetch_registers -- fetch current registers from inferior
+ 
+ SYNOPSIS
+ 
+ 	void procfs_fetch_registers (int regno)
+ 
+ DESCRIPTION
+ 
+ 	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.
+ 
+ */
+ 
+ extern void nto_supply_gregset (procfs_greg * gregsetp);
+ extern void nto_supply_fpregset (procfs_fpreg * fpregsetp);
+ 
+ static void
+ procfs_fetch_registers (regno)
+      int regno;
+ {
+   union
+   {
+     procfs_greg greg;
+     procfs_fpreg fpreg;
+   }
+   reg;
+   int regsize;
+ 
+   procfs_set_thread (inferior_ptid);
+   if (devctl (ctl_fd, DCMD_PROC_GETGREG, &reg, sizeof (reg), &regsize) == EOK)
+     {
+       nto_supply_gregset (&reg.greg);
+     }
+   if (devctl (ctl_fd, DCMD_PROC_GETFPREG, &reg, sizeof (reg), &regsize) ==
+       EOK)
+     {
+       nto_supply_fpregset (&reg.fpreg);
+     }
+ }
+ 
+ /*
+ 
+ LOCAL FUNCTION
+ 
+ 	procfs_xfer_memory -- copy data to or from inferior memory space
+ 
+ SYNOPSIS
+ 
+ 	int procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
+ 		int dowrite, struct target_ops target)
+ 
+ DESCRIPTION
+ 
+ 	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.
+ 
+ NOTES
+ 
+ 	The /proc interface makes this an almost trivial task.
+  */
+ 
+ static int
+ procfs_xfer_memory (memaddr, myaddr, len, dowrite, attrib, target)
+      CORE_ADDR memaddr;
+      char *myaddr;
+      int len;
+      int dowrite;
+      struct mem_attrib *attrib;	/* ignored */
+      struct target_ops *target;	/* ignored */
+ {
+   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.  For this
+    to work, it may be necessary for the process to have been
+    previously attached.  It *might* work if the program was
+    started via the normal ptrace (PTRACE_TRACEME).  */
+ 
+ static void
+ procfs_detach (args, from_tty)
+      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
+ nto_breakpoint (addr, type, size)
+      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 (addr, contents_cache)
+      CORE_ADDR addr;
+      char *contents_cache;
+ {
+   return nto_breakpoint (addr, _DEBUG_BREAK_EXEC, 0);
+ }
+ 
+ static int
+ procfs_remove_breakpoint (addr, contents_cache)
+      CORE_ADDR addr;
+      char *contents_cache;
+ {
+   return nto_breakpoint (addr, _DEBUG_BREAK_EXEC, -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 (scratch, argv)
+      char *scratch;
+      char **argv;
+ {
+   char *pp, *cp = scratch;
+   char quoting = 0;
+ 
+   for (;;)
+     {
+ 
+       /* 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;
+ 
+ }
+ 
+ static void
+ procfs_create_inferior (exec_file, allargs, env)
+      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 = qnx_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 ();
+ 
+   /* NYI: add the symbol info somewhere? */
+ #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 ()
+ {
+ }
+ 
+ void
+ procfs_store_registers (regno)
+      int regno;
+ {
+   union
+   {
+     procfs_greg greg;
+     procfs_fpreg fpreg;
+   }
+   reg;
+   unsigned first;
+   unsigned last;
+   unsigned end;
+   unsigned off;
+   unsigned len;
+   unsigned char subcmd;
+   char *data;
+ 
+   if (ptid_equal (inferior_ptid, null_ptid))
+     return;
+   procfs_set_thread (inferior_ptid);
+ 
+   if (regno == -1)
+     {
+       first = 0;
+       last = NUM_REGS - 1;
+     }
+   else
+     {
+       first = regno;
+       last = regno;
+     }
+   while (first <= last)
+     {
+       end = qnx_cpu_register_area (first, last, &subcmd, &off, &len);
+       switch (subcmd)
+ 	{
+ 	case DSMSG_REG_GENERAL:
+ 	  if (devctl
+ 	      (ctl_fd, DCMD_PROC_GETGREG, &reg.greg, sizeof (reg.greg),
+ 	       0) != EOK)
+ 	    {
+ 	      printf ("error fetching general registers\n");
+ 	      break;
+ 	    }
+ 	  data = (char *) &reg.greg + off;
+ 	  if (qnx_cpu_register_store (0, first, end, data))
+ 	    {
+ 	      devctl (ctl_fd, DCMD_PROC_SETGREG, &reg.greg,
+ 		      sizeof (reg.greg), 0);
+ 	    }
+ 	  break;
+ 	case DSMSG_REG_FLOAT:
+ 	  if (devctl
+ 	      (ctl_fd, DCMD_PROC_GETFPREG, &reg.fpreg,
+ 	       sizeof (reg.fpreg), 0) != EOK)
+ 	    {
+ 	      /* Do not print a warning.  Not all inferiors 
+ 	         have fpregs.  */
+ 	      break;
+ 	    }
+ 	  data = (char *) &reg.fpreg + off;
+ 	  if (qnx_cpu_register_store (0, first, end, data))
+ 	    {
+ 	      devctl (ctl_fd, DCMD_PROC_SETFPREG, &reg.fpreg,
+ 		      sizeof (reg.fpreg), 0);
+ 	    }
+ 	  break;
+ 	case DSMSG_REG_SYSTEM:
+ 	  break;
+ 	default:
+ 	  break;
+ 	}
+       first = end + 1;
+     }
+ }
+ 
+ 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)
+ 	{
+ 	  sigdelset (&run.trace, signo);
+ 	}
+       else
+ 	{
+ 	  sigaddset (&run.trace, signo);
+ 	}
+     }
+ }
+ 
+ /*
+ 
+ GLOBAL FUNCTION
+ 
+ 	procfs_notice_signals
+ 
+ SYNOPSIS
+ 
+ 	static void procfs_notice_signals (int pid);
+ 
+ DESCRIPTION
+ 
+ 	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.
+ 
+ 	One thing it does is that signals for which the state is "nostop",
+ 	"noprint", and "pass", have their trace bits reset in the pr_trace
+ 	field, so that they are no longer traced.  This allows them to be
+ 	delivered directly to the inferior without the debugger ever being
+ 	involved.
+  */
+ 
+ static void
+ procfs_notice_signals (pid)
+      int pid;
+ {
+   sigemptyset (&run.trace);
+   notice_signals ();
+ }
+ 
+ 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_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_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 = qnx_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;
+ }
+ 
+ extern int qnx_ostype;
+ 
+ void
+ _initialize_procfs ()
+ {
+   sigset_t set;
+   extern struct dscpuinfo qnx_cpuinfo;
+   extern int qnx_cpuinfo_valid;
+ 
+   init_procfs_ops ();
+   add_target (&procfs_ops);
+   qnx_ostype = OSTYPE_NTO;
+ 
+   //
+   // 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 */
+   qnx_cpuinfo.cpuflags = SYSPAGE_ENTRY (cpuinfo)->flags;
+   qnx_cpuinfo_valid = 1;
+ }
+ 
+ 
+ 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;
+ }
+ 
+ CORE_ADDR
+ procfs_getbase (void)
+ {
+   procfs_info procinfo;
+ 
+   if (devctl (ctl_fd, DCMD_PROC_INFO, &procinfo, sizeof procinfo, 0) != EOK)
+     return (CORE_ADDR) NULL;
+   return procinfo.base_address;
+ }
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/nto-share/debug.h src/gdb/nto-share/debug.h
*** src.orig/gdb/nto-share/debug.h	Wed Dec 31 19:00:00 1969
--- src/gdb/nto-share/debug.h	Fri Jan 31 12:28:10 2003
***************
*** 0 ****
--- 1,429 ----
+ #ifndef __DEBUG_H_INCLUDED
+ #define __DEBUG_H_INCLUDED
+ 
+ #include <time.h>
+ #include <sys/time.h>
+ #include <sys/types.h>
+ 
+ #define QNX_NOTE_NAME	"QNX"
+ 
+ enum Elf_qnx_note_types
+ {
+   QNT_NULL = 0,
+   QNT_DEBUG_FULLPATH,
+   QNT_DEBUG_RELOC,
+   QNT_STACK,
+   QNT_GENERATOR,
+   QNT_DEFAULT_LIB,
+   QNT_CORE_SYSINFO,
+   QNT_CORE_INFO,
+   QNT_CORE_STATUS,
+   QNT_CORE_GREG,
+   QNT_CORE_FPREG,
+   QNT_NUM
+ };
+ 
+ typedef struct
+ {
+   long bits[2];
+ } nto_sigset_t;
+ 
+ union nto_sigval
+ {
+   int sival_int;
+   void *sival_ptr;
+ };
+ 
+ typedef struct nto_siginfo
+ {
+   int si_signo;
+   int si_code;			/* if SI_NOINFO, only si_signo is valid */
+   void (*si_handler) ();
+   union
+   {
+     int _pad[6];
+     struct
+     {
+       pid_t _pid;
+       union
+       {
+ 	struct
+ 	{
+ 	  union nto_sigval _value;
+ 	  uid_t _uid;
+ 	} _kill;		/* si_code <= 0 SI_FROMUSER */
+ 	struct
+ 	{
+ 	  int _status;		/* CLD_EXITED status, else signo */
+ 	  clock_t _utime;
+ 	  clock_t _stime;
+ 	} _chld;		/* si_signo=SIGCHLD si_code=CLD_* */
+       } _pdata;
+     } _proc;
+     struct
+     {
+       int _fltno;
+       void *_addr;
+       void *_fltip;
+     } _fault;			/* si_signo=SIGSEGV,ILL,FPE,TRAP,BUS */
+   } _data;
+ } nto_siginfo_t;
+ 
+ typedef struct arm_cpu_registers
+ {
+   unsigned gpr[16];
+   unsigned spsr;
+ } ARM_CPU_REGISTERS;
+ 
+ typedef struct arm_fpu_registers
+ {
+   /*
+    * There is no architecturally defined FPU
+    */
+   unsigned __dummy;
+ } ARM_FPU_REGISTERS;
+ 
+ typedef struct arm_alt_registers
+ {
+   union
+   {
+     struct xscale_cp0
+     {
+       unsigned acc0_lo;
+       unsigned acc0_hi;
+     } xscale;
+   } un;
+ } ARM_ALT_REGISTERS;
+ 
+ typedef union
+ {
+   unsigned long long u64;
+   double f;
+ } mipsfloat;
+ 
+ typedef struct mips_cpu_registers
+ {
+   unsigned regs[74];
+   unsigned long long regs_alignment;
+ } MIPS_CPU_REGISTERS;
+ 
+ typedef struct mips_fpu_registers
+ {
+   mipsfloat fpr[32];
+   unsigned fpcr31;
+ } MIPS_FPU_REGISTERS;
+ 
+ typedef struct mips_alt_registers
+ {
+   union
+   {
+     struct mips_tx79
+     {
+       unsigned long long gpr_hi[32];
+       unsigned long long lo1;
+       unsigned long long hi1;
+       unsigned sa;
+     } tx79;
+   } un;
+ } MIPS_ALT_REGISTERS;
+ 
+ #ifdef __BIGREGS__
+ typedef unsigned long long ppcint;
+ #else
+ typedef unsigned ppcint;
+ #endif
+ 
+ typedef union
+ {
+   unsigned long long u64;
+   double f;
+ } ppcfloat;
+ 
+ typedef union
+ {
+   unsigned long long u64[2];
+   unsigned u32[4];
+   unsigned char u8[16];
+   float f32[4];
+ } ppcvmx;
+ 
+ typedef struct ppc_cpu_registers
+ {
+   ppcint gpr[32];
+   ppcint ctr;
+   ppcint lr;
+   ppcint msr;
+   ppcint iar;
+   unsigned cr;
+   unsigned xer;
+   unsigned ear;			/* not present on all chips */
+   unsigned mq;			/* only on the 601 */
+   unsigned vrsave;		/* on Altivec CPU's, SPR256 */
+ } PPC_CPU_REGISTERS;
+ 
+ typedef struct ppc_fpu_registers
+ {
+   ppcfloat fpr[32];
+   unsigned fpscr;
+   unsigned fpscr_val;
+   /* load/store of fpscr is done through fprs, the real value is in [32,63] of a fpr.
+      fpscr is the address for lfd, stfd. fpscr_val is the real value of fpscr */
+ } PPC_FPU_REGISTERS;
+ 
+ typedef struct ppc_vmx_registers
+ {
+   ppcvmx vmxr[32];
+   ppcvmx vscr;
+ } PPC_VMX_REGISTERS;
+ 
+ typedef struct ppc_alt_registers
+ {
+   PPC_VMX_REGISTERS vmx;
+ } PPC_ALT_REGISTERS;
+ 
+ typedef unsigned shint;
+ 
+ typedef unsigned shfloat;
+ 
+ typedef struct sh_cpu_registers
+ {
+   shint gr[16];
+   shint sr;
+   shint pc;
+ /*	shint		dbr; */
+   shint gbr;
+   shint mach;
+   shint macl;
+   shint pr;
+ } SH_CPU_REGISTERS;
+ 
+ typedef struct sh_fpu_registers
+ {
+   shfloat fpr_bank0[16];
+   shfloat fpr_bank1[16];
+   unsigned fpul;
+   unsigned fpscr;
+ } SH_FPU_REGISTERS;
+ 
+ typedef struct sh_alt_registers
+ {
+   /*
+    * There are no architecturally defined alt regs
+    */
+   unsigned __dummy;
+ } SH_ALT_REGISTERS;
+ 
+ typedef struct x86_cpu_registers
+ {
+ #ifdef __SEGMENTS__
+   unsigned gs, fs;
+   unsigned es, ds;
+ #endif
+   unsigned edi, esi, ebp, exx, ebx, edx, ecx, eax;
+   unsigned eip, cs, efl;
+   unsigned esp, ss;
+ } X86_CPU_REGISTERS;
+ 
+ typedef struct fsave_area
+ {
+   unsigned fpu_control_word;
+   unsigned fpu_status_word;
+   unsigned fpu_tag_word;
+   unsigned fpu_ip;
+   unsigned fpu_cs;
+   unsigned fpu_op;
+   unsigned fpu_ds;
+   unsigned char st_regs[80];	/* each register is 10 bytes! */
+ } X86_FSAVE_REGISTERS;
+ 
+ typedef struct fxsave_area
+ {
+   unsigned short fpu_control_word;
+   unsigned short fpu_status_word;
+   unsigned short fpu_tag_word;
+   unsigned short fpu_operand;
+   unsigned fpu_ip;
+   unsigned fpu_cs;
+   unsigned fpu_op;
+   unsigned fpu_ds;
+   unsigned mxcsr;
+   unsigned reserved;
+   unsigned char st_regs[128];
+   unsigned char xmm_regs[128];
+   unsigned char reserved2[224];
+ } X86_FXSAVE_REGISTERS;
+ 
+ typedef union x86_fpu_registers
+ {
+   X86_FSAVE_REGISTERS fsave_area;
+   X86_FXSAVE_REGISTERS fxsave_area;
+   unsigned char data[512];	/* Needs to be this big for the emulator. */
+ } X86_FPU_REGISTERS;
+ 
+ #ifdef __QNX__
+ __BEGIN_DECLS
+ #include <_pack64.h>
+ #endif
+ #define _DEBUG_FLAG_STOPPED			0x00000001	/* Thread is not running */
+ #define DEBUG_FLAG_ISTOP			0x00000002	/* Stopped at point of interest */
+ #define _DEBUG_FLAG_IPINVAL			0x00000010	/* IP is not valid */
+ #define _DEBUG_FLAG_ISSYS			0x00000020	/* System process */
+ #define _DEBUG_FLAG_SSTEP			0x00000040	/* Stopped because of single step */
+ #define _DEBUG_FLAG_CURTID			0x00000080	/* Thread is current thread */
+ #define DEBUG_FLAG_TRACE_EXEC		0x00000100	/* Stopped because of breakpoint */
+ #define _DEBUG_FLAG_TRACE_RD		0x00000200	/* Stopped because of read access */
+ #define _DEBUG_FLAG_TRACE_WR		0x00000400	/* Stopped because of write access */
+ #define _DEBUG_FLAG_TRACE_MODIFY	0x00000800	/* Stopped because of modified memory */
+ #define _DEBUG_FLAG_RLC				0x00010000	/* Run-on-Last-Close flag is set */
+ #define _DEBUG_FLAG_KLC				0x00020000	/* Kill-on-Last-Close flag is set */
+ #define _DEBUG_FLAG_FORK			0x00040000	/* Child inherits flags (Stop on fork/spawn) */
+ #define _DEBUG_FLAG_MASK			0x000f0000	/* Flags that can be changed */
+   enum
+ {
+   _DEBUG_WHY_REQUESTED,
+   _DEBUG_WHY_SIGNALLED,
+   _DEBUG_WHY_FAULTED,
+   _DEBUG_WHY_JOBCONTROL,
+   _DEBUG_WHY_TERMINATED,
+   _DEBUG_WHY_CHILD,
+   _DEBUG_WHY_EXEC
+ };
+ 
+ #define _DEBUG_RUN_CLRSIG			0x00000001	/* Clear pending signal */
+ #define _DEBUG_RUN_CLRFLT			0x00000002	/* Clear pending fault */
+ #define DEBUG_RUN_TRACE			0x00000004	/* Trace mask flags interesting signals */
+ #define DEBUG_RUN_HOLD				0x00000008	/* Hold mask flags interesting signals */
+ #define DEBUG_RUN_FAULT			0x00000010	/* Fault mask flags interesting faults */
+ #define _DEBUG_RUN_VADDR			0x00000020	/* Change ip before running */
+ #define _DEBUG_RUN_STEP				0x00000040	/* Single step only one thread */
+ #define _DEBUG_RUN_STEP_ALL			0x00000080	/* Single step one thread, other threads run */
+ #define _DEBUG_RUN_CURTID			0x00000100	/* Change current thread (target thread) */
+ #define DEBUG_RUN_ARM				0x00000200	/* Deliver event at point of interest */
+ 
+ typedef struct _debug_process_info
+ {
+   pid_t pid;
+   pid_t parent;
+   unsigned flags;
+   unsigned umask;
+   pid_t child;
+   pid_t sibling;
+   pid_t pgrp;
+   pid_t sid;
+   int base_address;
+   int initial_stack;
+   uid_t uid;
+   gid_t gid;
+   uid_t euid;
+   gid_t egid;
+   uid_t suid;
+   gid_t sgid;
+   nto_sigset_t sig_ignore;
+   nto_sigset_t sig_queue;
+   nto_sigset_t sig_pending;
+   unsigned num_chancons;
+   unsigned num_fdcons;
+   unsigned num_threads;
+   unsigned num_timers;
+   unsigned long long reserved[20];
+ } nto_procfs_info;
+ 
+ typedef struct _debug_thread_info
+ {
+   pid_t pid;
+   unsigned tid;
+   unsigned flags;
+   unsigned short why;
+   unsigned short what;
+   int ip;
+   int sp;
+   int stkbase;
+   int tls;
+   unsigned stksize;
+   unsigned tid_flags;
+   unsigned char priority;
+   unsigned char real_priority;
+   unsigned char policy;
+   unsigned char state;
+   short syscall;
+   unsigned short last_cpu;
+   unsigned timeout;
+   int last_chid;
+   nto_sigset_t sig_blocked;
+   nto_sigset_t sig_pending;
+   nto_siginfo_t info;
+   unsigned reserved1;
+   union
+   {
+     struct
+     {
+       unsigned tid;
+     } join;
+     struct
+     {
+       int id;
+       int sync;
+     } sync;
+     struct
+     {
+       unsigned nid;
+       pid_t pid;
+       int coid;
+       int chid;
+       int scoid;
+     } connect;
+     struct
+     {
+       int chid;
+     } channel;
+     struct
+     {
+       pid_t pid;
+       int vaddr;
+       unsigned flags;
+     } waitpage;
+     struct
+     {
+       unsigned size;
+     } stack;
+     unsigned long long filler[4];
+   } blocked;
+   unsigned long long reserved2[8];
+ } nto_procfs_status;
+ 
+ typedef union _debug_gregs
+ {
+   ARM_CPU_REGISTERS arm;
+   MIPS_CPU_REGISTERS mips;
+   PPC_CPU_REGISTERS ppc;
+   SH_CPU_REGISTERS sh;
+   X86_CPU_REGISTERS x86;
+   unsigned long long padding[1024];
+ } nto_gregset_t;
+ 
+ typedef union _debug_fpregs
+ {
+ /*	ARM_FPU_REGISTERS	arm;	*/
+   MIPS_FPU_REGISTERS mips;
+   PPC_FPU_REGISTERS ppc;
+   SH_FPU_REGISTERS sh;
+   X86_FPU_REGISTERS x86;
+   unsigned long long padding[1024];
+ } nto_fpregset_t;
+ 
+ typedef union _debug_altregs
+ {
+   ARM_ALT_REGISTERS arm;
+   MIPS_ALT_REGISTERS mips;
+   PPC_ALT_REGISTERS ppc;
+ /*	SH_ALT_REGISTERS	sh;	*/
+ /*	X86_ALT_REGISTERS	x86;	*/
+   unsigned long long padding[1024];
+ } debug_altreg_t;
+ 
+ #ifdef __QNX__
+ #include <_packpop.h>
+ 
+ __END_DECLS
+ #endif
+ #endif
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/nto-share/dsmsgs.h src/gdb/nto-share/dsmsgs.h
*** src.orig/gdb/nto-share/dsmsgs.h	Wed Dec 31 19:00:00 1969
--- src/gdb/nto-share/dsmsgs.h	Fri Jan 31 12:28:10 2003
***************
*** 0 ****
--- 1,819 ----
+ #ifndef __DSMSGS_H__
+ #define __DSMSGS_H__
+ 
+ //
+ // These are the protocol versioning numbers
+ // Update them with changes that introduce potential 
+ // compatibility issues
+ //
+ #define PDEBUG_PROTOVER_MAJOR				0x00000000
+ #define PDEBUG_PROTOVER_MINOR				0x00000003
+ 
+ #include <stddef.h>
+ 
+ //
+ // These are pdebug specific errors, sent sometimes with the errno after
+ // an action failed.  Simply provides additional info on the reason for the 
+ // error.  Sent in the DSrMsg_err_t.hdr.subcmd byte.
+ //
+ 
+ #define PDEBUG_ENOERR		0	/* No error                                                                     */
+ #define PDEBUG_ENOPTY		1	/* No Pseudo Terminals found                            */
+ #define PDEBUG_ETHREAD		2	/* Thread Create error                                          */
+ #define PDEBUG_ECONINV		3	/* Invalid Console number                                       */
+ #define PDEBUG_ESPAWN		4	/* Spawn error                                                          */
+ #define PDEBUG_EPROCFS		5	/* NTO Proc File System error                           */
+ #define PDEBUG_EPROCSTOP	6	/* NTO Process Stop error                                       */
+ #define PDEBUG_EQPSINFO		7	/* QNX4 PSINFO error                                            */
+ #define PDEBUG_EQMEMMODEL	8	/* QNX4 - Flat Memory Model only supported      */
+ #define PDEBUG_EQPROXY		9	/* QNX4 Proxy error                                                     */
+ #define PDEBUG_EQDBG		10	/* QNX4 qnx_debug_* error                                       */
+ 
+ // 
+ //  There is room for pdebugerrnos up to sizeof(unsigned char)
+ //
+ 
+ 
+ // We are moving away from the channel commands - only the RESET
+ // and NAK are required.  The DEBUG and TEXT channels are now part
+ // of the DShdr and TShdr structs, 4th byte.  GP June 1 1999.
+ // They are still supported, but not required.
+ //
+ // A packet containg a single byte is a set channel command. 
+ //     IE:  7e xx chksum 7e
+ // 
+ // After a set channel all following packets are in the format
+ // for the specified channel. Currently three channels are defined.
+ // The raw channel has no structure. The other channels are all framed.
+ // The contents of each channel is defined by structures below. 
+ //
+ // 0 - Reset channel. Used when either end starts.
+ //
+ // 1 - Debug channel with the structure which follows below.
+ //     Uses DS (Debug Services) prefix.
+ //
+ // 2 - Text channel with the structure which follows below.
+ //     Uses TS (Text Services) prefix.
+ //
+ // 0xff - Negative acknowledgment of a packet transmission.
+ //
+ 
+ 
+ #define SET_CHANNEL_RESET				0
+ #define SET_CHANNEL_DEBUG				1
+ #define SET_CHANNEL_TEXT				2
+ #define SET_CHANNEL_NAK					0xff
+ 
+ 
+ ///////////////////////////////////////////////////////////////////////////////
+ // Debug channel Messages:   DS - Debug services
+ //
+ 
+ //
+ // Defines and structures for the debug channel.
+ //
+ #define DS_DATA_MAX_SIZE				1024
+ #define DS_DATA_RCV_SIZE(msg, total)	((total) - (sizeof(*(msg)) - DS_DATA_MAX_SIZE))
+ #define DS_MSG_OKSTATUS_FLAG			0x20000000
+ #define DS_MSG_OKDATA_FLAG				0x40000000
+ #define DS_MSG_NO_RESPONSE				0x80000000
+ 
+ #define QNXNTO_NSIG			57	// from signals.h NSIG
+ 
+ //
+ // Common message header. It must be 32 or 64 bit aligned.
+ // The top bit of cmd is 1 for BIG endian data format.
+ //
+ #define DSHDR_MSG_BIG_ENDIAN	0x80
+ struct DShdr
+ {
+   unsigned char cmd;
+   unsigned char subcmd;
+   unsigned char mid;
+   unsigned char channel;
+ };
+ 
+ //
+ // Command types
+ //
+ enum
+ {
+   DStMsg_connect,		//  0  0x0
+   DStMsg_disconnect,		//  1  0x1
+   DStMsg_select,		//  2  0x2
+   DStMsg_mapinfo,		//  3  0x3
+   DStMsg_load,			//  4  0x4
+   DStMsg_attach,		//  5  0x5
+   DStMsg_detach,		//  6  0x6
+   DStMsg_kill,			//  7  0x7
+   DStMsg_stop,			//  8  0x8
+   DStMsg_memrd,			//  9  0x9
+   DStMsg_memwr,			// 10  0xA
+   DStMsg_regrd,			// 11  0xB
+   DStMsg_regwr,			// 12  0xC
+   DStMsg_run,			// 13  0xD
+   DStMsg_brk,			// 14  0xE
+   DStMsg_fileopen,		// 15  0xF
+   DStMsg_filerd,		// 16  0x10
+   DStMsg_filewr,		// 17  0x11
+   DStMsg_fileclose,		// 18  0x12
+   DStMsg_pidlist,		// 19  0x13
+   DStMsg_cwd,			// 20  0x14
+   DStMsg_env,			// 21  0x15
+   DStMsg_base_address,		// 22  0x16
+   DStMsg_protover,		// 23  0x17
+   DStMsg_handlesig,		// 24  0x18
+   DStMsg_cpuinfo,		// 25  0x19
+   // Room for new codes here
+   DSrMsg_err = 32,		// 32  0x20
+   DSrMsg_ok,			// 33  0x21
+   DSrMsg_okstatus,		// 34  0x22
+   DSrMsg_okdata,		// 35  0x23
+   // Room for new codes here
+   DShMsg_notify = 64		// 64  0x40
+ };
+ 
+ 
+ //
+ // Subcommand types
+ //
+ enum
+ {
+   DSMSG_LOAD_DEBUG,
+   DSMSG_LOAD_RUN,
+   DSMSG_LOAD_RUN_PERSIST,
+   DSMSG_LOAD_INHERIT_ENV = 0x80
+ };
+ 
+ enum
+ {
+   DSMSG_ENV_CLEARARGV,
+   DSMSG_ENV_ADDARG,
+   DSMSG_ENV_CLEARENV,
+   DSMSG_ENV_SETENV,
+   DSMSG_ENV_SETENV_MORE
+ };
+ 
+ enum
+ {
+   DSMSG_STOP_PID,
+   DSMSG_STOP_PIDS
+ };
+ 
+ enum
+ {
+   DSMSG_SELECT_SET,
+   DSMSG_SELECT_QUERY
+ };
+ 
+ enum
+ {
+   DSMSG_KILL_PIDTID,
+   DSMSG_KILL_PID,
+   DSMSG_KILL_PIDS
+ };
+ 
+ enum
+ {
+   DSMSG_MEM_VIRTUAL,
+   DSMSG_MEM_PHYSICAL,
+   DSMSG_MEM_IO,
+   DSMSG_MEM_BASEREL
+ };
+ 
+ enum
+ {
+   DSMSG_REG_GENERAL,
+   DSMSG_REG_FLOAT,
+   DSMSG_REG_SYSTEM,
+   DSMSG_REG_ALT
+ };
+ 
+ enum
+ {
+   DSMSG_RUN,
+   DSMSG_RUN_COUNT,
+   DSMSG_RUN_RANGE,
+ };
+ 
+ enum
+ {
+   DSMSG_PIDLIST_BEGIN,
+   DSMSG_PIDLIST_NEXT,
+   DSMSG_PIDLIST_SPECIFIC,
+   DSMSG_PIDLIST_SPECIFIC_TID,	// *_TID - send starting tid for the request,
+ };				// and the response will have total to be sent
+ 
+ enum
+ {
+   DSMSG_CWD_QUERY,
+   DSMSG_CWD_SET,
+ };
+ 
+ enum
+ {
+   DSMSG_MAPINFO_BEGIN = 0x01,
+   DSMSG_MAPINFO_NEXT = 0x02,
+   DSMSG_MAPINFO_SPECIFIC = 0x04,
+   DSMSG_MAPINFO_ELF = 0x80,
+ };
+ 
+ enum
+ {
+   DSMSG_PROTOVER_MINOR = 0x000000FF,	// bit field (status & DSMSG_PROTOVER_MAJOR)
+   DSMSG_PROTOVER_MAJOR = 0x0000FF00,	// bit field (status & DSMSG_PROTOVER_MINOR)
+ };
+ 
+ enum
+ {
+   DSMSG_BRK_EXEC = 0x0001,	// execution breakpoint
+   DSMSG_BRK_RD = 0x0002,	// read access (fail if not supported)
+   DSMSG_BRK_WR = 0x0004,	// write access (fail if not supported)
+   DSMSG_BRK_RW = 0x0006,	// read or write access (fail if not supported)
+   DSMSG_BRK_MODIFY = 0x0008,	// memory modified
+   DSMSG_BRK_RDM = 0x000a,	// read access if suported otherwise modified
+   DSMSG_BRK_WRM = 0x000c,	// write access if suported otherwise modified
+   DSMSG_BRK_RWM = 0x000e,	// read or write access if suported otherwise modified
+   DSMSG_BRK_HW = 0x0010,	// only use hardware debugging (i.e. no singlestep)
+ };
+ 
+ enum
+ {
+   DSMSG_NOTIFY_PIDLOAD,		/*  0 */
+   DSMSG_NOTIFY_TIDLOAD,		/*  1 */
+   DSMSG_NOTIFY_DLLLOAD,		/*  2 */
+   DSMSG_NOTIFY_PIDUNLOAD,	/*  3 */
+   DSMSG_NOTIFY_TIDUNLOAD,	/*  4 */
+   DSMSG_NOTIFY_DLLUNLOAD,	/*  5 */
+   DSMSG_NOTIFY_BRK,		/*  6 */
+   DSMSG_NOTIFY_STEP,		/*  7 */
+   DSMSG_NOTIFY_SIGEV,		/*  8 */
+   DSMSG_NOTIFY_STOPPED		/*  9 */
+ };
+ 
+ 
+ 
+ //
+ // Messages sent to the target. DStMsg_* (t - for target messages)
+ //
+ 
+ 
+ //
+ // Connect to the agent running on the target
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned char major;
+   unsigned char minor;
+   unsigned char spare[2];
+ } DStMsg_connect_t;
+ 
+ 
+ //
+ // Disconnect from the agent running on the target
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+ } DStMsg_disconnect_t;
+ 
+ 
+ //
+ // Select a pid, tid for subsequent messages or query their validity
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   int pid;
+   int tid;
+ } DStMsg_select_t;
+ 
+ 
+ //
+ // Return information on what is at the specified virtual address.
+ // If nothing is there we return info on the next thing in the address.
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   int pid;
+   int addr;
+ } DStMsg_mapinfo_t;
+ 
+ 
+ //
+ // Load a new process into memory for a filesystem
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   int argc;
+   int envc;
+   char cmdline[DS_DATA_MAX_SIZE];
+ } DStMsg_load_t;
+ 
+ 
+ //
+ // Attach to an already running process
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   int pid;
+ } DStMsg_attach_t;
+ 
+ 
+ //
+ // Detach from a running process which was attached to or loaded
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   int pid;
+ } DStMsg_detach_t;
+ 
+ 
+ //
+ // Set a signal on a process
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   int signo;
+ } DStMsg_kill_t;
+ 
+ 
+ //
+ // Stop one or more processes/threads
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+ } DStMsg_stop_t;
+ 
+ 
+ //
+ // Memory read request
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned spare0;
+   unsigned long long addr;
+   unsigned short size;
+ } DStMsg_memrd_t;
+ 
+ 
+ //
+ // Memory write request
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned spare0;
+   unsigned long long addr;
+   unsigned char data[DS_DATA_MAX_SIZE];
+ } DStMsg_memwr_t;
+ 
+ 
+ //
+ // Register read request
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned short offset;
+   unsigned short size;
+ } DStMsg_regrd_t;
+ 
+ 
+ //
+ // Register write request
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned short offset;
+   unsigned char data[DS_DATA_MAX_SIZE];
+ } DStMsg_regwr_t;
+ 
+ 
+ //
+ // Run
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   union
+   {
+     unsigned count;
+     unsigned addr[2];
+   } step;
+ } DStMsg_run_t;
+ 
+ 
+ //
+ // Break
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned addr;
+   unsigned size;
+ } DStMsg_brk_t;
+ 
+ 
+ //
+ // Open a file on the target
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   int mode;
+   int perms;
+   char pathname[DS_DATA_MAX_SIZE];
+ } DStMsg_fileopen_t;
+ 
+ 
+ //
+ // Read a file on the target
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned short size;
+ } DStMsg_filerd_t;
+ 
+ 
+ //
+ // Write a file on the target
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned char data[DS_DATA_MAX_SIZE];
+ } DStMsg_filewr_t;
+ 
+ 
+ //
+ // Close a file on the target
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   int mtime;
+ } DStMsg_fileclose_t;
+ 
+ 
+ //
+ // Get pids and process names in the system
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   int pid;			// Only valid for type subtype SPECIFIC
+   int tid;			// tid to start reading from
+ } DStMsg_pidlist_t;
+ 
+ 
+ // Set current working directory of process
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned char path[DS_DATA_MAX_SIZE];
+ } DStMsg_cwd_t;
+ 
+ 
+ //
+ // clear, set, get environment for new process
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   char data[DS_DATA_MAX_SIZE];
+ } DStMsg_env_t;
+ 
+ 
+ //
+ // Get the base address of a process
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+ } DStMsg_baseaddr_t;
+ 
+ 
+ //
+ // Send pdebug protocol version info, get the same in response_ok_status
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned char major;
+   unsigned char minor;
+ } DStMsg_protover_t;
+ 
+ 
+ //
+ // Handle signal message.
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned char signals[QNXNTO_NSIG];
+   unsigned sig_to_pass;
+ } DStMsg_handlesig_t;
+ 
+ 
+ //
+ // Get some cpu info
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned spare;
+ } DStMsg_cpuinfo_t;
+ 
+ 
+ //
+ // Messages sent to the host. DStMsg_* (h - for host messages)
+ //
+ 
+ 
+ //
+ // Notify host that something happened it needs to know about
+ //
+ #define NOTIFY_HDR_SIZE				offsetof(DShMsg_notify_t, un)
+ #define NOTIFY_MEMBER_SIZE(member)	sizeof(member)
+ 
+ // Keep this consistant with neutrino syspage.h
+ enum
+ {
+   CPUTYPE_X86,
+   CPUTYPE_PPC,
+   CPUTYPE_MIPS,
+   CPUTYPE_SPARE,
+   CPUTYPE_ARM,
+   CPUTYPE_SH
+ };
+ 
+ enum
+ {
+   OSTYPE_QNX4,
+   OSTYPE_NTO
+ };
+ 
+ typedef struct aaa
+ {
+   struct DShdr hdr;
+   int pid;
+   int tid;
+   union
+   {
+     struct
+     {
+       unsigned codeoff;
+       unsigned dataoff;
+       unsigned short ostype;
+       unsigned short cputype;
+       unsigned cpuid;		// CPU dependant value
+       char name[DS_DATA_MAX_SIZE];
+     } pidload;
+     struct
+     {
+       int status;
+     } pidunload;
+     struct
+     {
+       int status;
+       unsigned char faulted;
+       unsigned char reserved[3];
+     } pidunload_v3;
+     struct
+     {
+       unsigned ip;
+       unsigned dp;
+       unsigned flags;		// defined in <sys/debug.h>
+     } brk;
+     struct
+     {
+       unsigned ip;
+       unsigned lastip;
+     } step;
+     struct
+     {
+       int signo;
+       int code;
+       int value;
+     } sigev;
+   } un;
+ } DShMsg_notify_t;
+ 
+ 
+ 
+ //
+ // Responses to a message. DSrMsg_* (r - for response messages)
+ //
+ 
+ //
+ // Error response packet
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   int err;
+ } DSrMsg_err_t;
+ 
+ //
+ // Simple OK response. 
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+ } DSrMsg_ok_t;
+ 
+ 
+ //
+ // Simple OK response with a result. Used where limited data needs
+ // to be returned. For example, if the number of bytes which were
+ // successfully written was less than requested on any write cmd the
+ // status will be the number actually written.
+ // The 'subcmd' will always be zero.
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   int status;
+ } DSrMsg_okstatus_t;
+ 
+ 
+ //
+ // The following structures overlay data[..] on a DSrMsg_okdata_t
+ //
+ 
+ struct dslinkmap
+ {
+   unsigned addr;
+   unsigned size;
+   unsigned flags;
+   unsigned debug_vaddr;
+   unsigned long long offset;
+ };
+ 
+ struct dsmapinfo
+ {
+   struct dsmapinfo *next;
+   unsigned spare0;
+   unsigned long long ino;
+   unsigned dev;
+   unsigned spare1;
+   struct dslinkmap text;
+   struct dslinkmap data;
+   char name[256];
+ };
+ 
+ struct dspidlist
+ {
+   int pid;
+   int num_tids;			// num of threads this pid has
+   int spare[6];
+   struct tidinfo
+   {
+     short tid;
+     unsigned char state;
+     unsigned char flags;
+   } tids[1];			// Variable length terminated by tid==0
+   char name[1];			// Variable length terminated by \0
+ };
+ 
+ struct dscpuinfo
+ {
+   unsigned cpuflags;
+   unsigned spare1;
+   unsigned spare2;
+   unsigned spare3;
+ };
+ 
+ //
+ // Long OK response with 0..DS_DATA_MAX_SIZE data.
+ // The 'subcmd' will always be zero.
+ //
+ typedef struct
+ {
+   struct DShdr hdr;
+   unsigned char data[DS_DATA_MAX_SIZE];
+ } DSrMsg_okdata_t;
+ 
+ 
+ //
+ // A union of all possible messages and responses.
+ //
+ typedef union
+ {
+   struct DShdr hdr;
+   DStMsg_connect_t connect;
+   DStMsg_disconnect_t disconnect;
+   DStMsg_select_t select;
+   DStMsg_load_t load;
+   DStMsg_attach_t attach;
+   DStMsg_detach_t detach;
+   DStMsg_kill_t kill;
+   DStMsg_stop_t stop;
+   DStMsg_memrd_t memrd;
+   DStMsg_memwr_t memwr;
+   DStMsg_regrd_t regrd;
+   DStMsg_regwr_t regwr;
+   DStMsg_run_t run;
+   DStMsg_brk_t brk;
+   DStMsg_fileopen_t fileopen;
+   DStMsg_filerd_t filerd;
+   DStMsg_filewr_t filewr;
+   DStMsg_fileclose_t fileclose;
+   DStMsg_pidlist_t pidlist;
+   DStMsg_mapinfo_t mapinfo;
+   DStMsg_cwd_t cwd;
+   DStMsg_env_t env;
+   DStMsg_baseaddr_t baseaddr;
+   DStMsg_protover_t protover;
+   DStMsg_handlesig_t handlesig;
+   DStMsg_cpuinfo_t cpuinfo;
+   DShMsg_notify_t notify;
+   DSrMsg_err_t err;
+   DSrMsg_ok_t ok;
+   DSrMsg_okstatus_t okstatus;
+   DSrMsg_okdata_t okdata;
+ } DSMsg_union_t;
+ 
+ 
+ 
+ 
+ 
+ ///////////////////////////////////////////////////////////////////////////////
+ // Text channel Messages:   TS - Text services
+ //
+ 
+ #define TS_TEXT_MAX_SIZE	100
+ 
+ //
+ // Command types
+ //
+ enum
+ {
+   TSMsg_text,			/*  0 */
+   TSMsg_done,			/*  1 */
+   TSMsg_start,			/*  2 */
+   TSMsg_stop,			/*  3 */
+   TSMsg_ack,			/*  4 */
+ };
+ 
+ 
+ struct TShdr
+ {
+   unsigned char cmd;
+   unsigned char console;
+   unsigned char spare1;
+   unsigned char channel;
+ };
+ 
+ 
+ //
+ // Deliver text. This message can be sent by either side.
+ // The debugger displays it in a window. The agent gives it to a pty
+ // which a program may be listening on.
+ //
+ 
+ typedef struct
+ {
+   struct TShdr hdr;
+   char text[TS_TEXT_MAX_SIZE];
+ } TSMsg_text_t;
+ 
+ 
+ //
+ // There is no longer a program connected to this console.
+ //
+ typedef struct
+ {
+   struct TShdr hdr;
+ } TSMsg_done_t;
+ 
+ 
+ //
+ // TextStart or TextStop flow controlÿ
+ //
+ typedef struct
+ {
+   struct TShdr hdr;
+ } TSMsg_flowctl_t;
+ 
+ 
+ //
+ // Ack a flowctl message
+ //
+ typedef struct
+ {
+   struct TShdr hdr;
+ } TSMsg_ack_t;
+ 
+ #endif
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/remote-nto-i386.c src/gdb/remote-nto-i386.c
*** src.orig/gdb/remote-nto-i386.c	Wed Dec 31 19:00:00 1969
--- src/gdb/remote-nto-i386.c	Fri Jan 31 12:24:06 2003
***************
*** 0 ****
--- 1,393 ----
+ /* Remote target communications for serial-line targets in custom GDB protocol
+    Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+    Contributed by QNX Software Systems Limited.
+ 
+ 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.  */
+ 
+ /* This file was derived from remote.c. It implements the MIPS specific
+    portion of the Neutrino remote debug proctocol (see remote-nto.c for
+    the CPU independent portion). */
+ 
+ #include "defs.h"
+ #include "gdb_string.h"
+ #include <fcntl.h>
+ #include "frame.h"
+ #include "inferior.h"
+ #include "bfd.h"
+ #include "symfile.h"
+ #include "target.h"
+ #include "gdb_wait.h"
+ #include "gdbcmd.h"
+ #include "objfiles.h"
+ #include "gdb-stabs.h"
+ #include "gdbthread.h"
+ #include "nto-share/dsmsgs.h"
+ #include "regcache.h"
+ #include "solib-svr4.h"
+ #include "dcache.h"
+ 
+ #ifdef USG
+ #include <sys/types.h>
+ #endif
+ 
+ #include <signal.h>
+ #include "serial.h"
+ 
+ #include "nto-share/debug.h"
+ 
+ /* Prototypes for i387_supply_fsave etc.  */
+ #include "i387-tdep.h"
+ 
+ #ifndef FPC_REGNUM
+ #define FPC_REGNUM (FP0_REGNUM + 8)
+ #endif
+ 
+ #define NUM_GPREGS 13
+ static int gdb_to_nto[NUM_GPREGS] =
+   { 7, 6, 5, 4, 11, 2, 1, 0, 8, 10, 9, 12, -1 };
+ 
+ #define GDB_TO_OS(x)	((x >= 0 && x < NUM_GPREGS) ? gdb_to_nto[x] : -1)
+ 
+ #ifndef X86_CPU_FXSR
+ #define X86_CPU_FXSR (1L << 12)
+ #endif
+ 
+ extern struct dscpuinfo qnx_cpuinfo;
+ extern int qnx_cpuinfo_valid;
+ extern int qnx_ostype, qnx_cputype;
+ /*
+ 	Given a register return an id that represents the Neutrino regset it came from
+ 	if reg == -1 update all regsets
+ 	$MJC
+  */
+ 
+ enum QNX_REGS
+ {
+   QNX_REGS_GP = 0,
+   QNX_REGS_FP = 1,
+   QNX_REGS_END = 2
+ };
+ unsigned
+ qnx_get_regset_id (int regno)
+ {
+   unsigned regset;
+   if (regno == -1)
+     {				/* return size so we can enumerate */
+       regset = 2;
+     }
+   else if (regno < FP0_REGNUM)
+     {
+       regset = 0;
+     }
+   else if (regno < FPC_REGNUM)
+     {
+       regset = 1;
+     }
+   else
+     {
+       regset = -1;		/* error */
+     }
+   return regset;
+ }
+ 
+ /* Tell GDB about the regset contained in the 'data' buffer  */
+ static void
+ gp_regset_fetch (char *data)
+ {
+   unsigned first_regno;
+   for (first_regno = 0; first_regno < FP0_REGNUM; first_regno++)
+     {
+       int regno = GDB_TO_OS (first_regno);
+       int const minusone = -1;
+ 
+       if (data == NULL || regno == -1)
+ 	{
+ 	  supply_register (first_regno, (char *) &minusone);
+ 	}
+       else
+ 	{
+ 	  supply_register (first_regno, &data[regno * 4]);
+ 	}
+     }
+ }
+ 
+ // get 8087 data
+ static void
+ fp_regset_fetch (char *data)
+ {
+   if (qnx_cpuinfo_valid && qnx_cpuinfo.cpuflags | X86_CPU_FXSR)
+     i387_supply_fxsave (data);
+   else
+     i387_supply_fsave (data);
+ }
+ 
+ void
+ qnx_cpu_regset_fetch (int endian, int regset, void *data)
+ {
+   endian = endian;		/* x86, don't care about endian */
+ 
+   switch (regset)
+     {
+     case QNX_REGS_GP:		/* QNX has different ordering of GP regs GDB */
+       gp_regset_fetch ((char *) data);
+       break;
+     case QNX_REGS_FP:
+       fp_regset_fetch ((char *) data);
+       break;
+     }
+ }
+ 
+ /* get regset characteristics */
+ unsigned
+ qnx_get_regset_area (unsigned regset, char *subcmd)
+ {
+   unsigned length = 0;
+   switch (regset)
+     {
+     case QNX_REGS_GP:
+       *subcmd = DSMSG_REG_GENERAL;
+       length = NUM_GPREGS * sizeof (unsigned);
+       break;
+     case QNX_REGS_FP:
+       *subcmd = DSMSG_REG_FLOAT;
+       /* FIXME: should we calculate based on fxsave/fsave? */
+       length = 512;
+       break;
+     default:
+       length = 0;
+     }
+   return length;
+ }
+ 
+ /*-
+ 	Given the first and last register number, figure out the size/len
+ 	of the Neutrino register save area to ask for/tell about. Also set
+ 	the register set that's being dealt with in *subcmd. Watch out for
+ 	the range crossing a register set boundry.
+  */
+ 
+ unsigned
+ qnx_cpu_register_area (first_regno, last_regno, subcmd, off, len)
+      unsigned first_regno;
+      unsigned last_regno;
+      unsigned char *subcmd;
+      unsigned *off;
+      unsigned *len;
+ {
+   int regno = -1;
+ 
+   if (first_regno < FP0_REGNUM)
+     {
+       if (last_regno >= FP0_REGNUM)
+ 	last_regno = FP0_REGNUM - 1;
+       *subcmd = DSMSG_REG_GENERAL;
+       regno = GDB_TO_OS (first_regno);
+       *off = regno * sizeof (unsigned);
+       if (regno == -1)
+ 	*len = 0;
+       else
+ 	*len = (last_regno - first_regno + 1) * sizeof (unsigned);
+     }
+   else if (first_regno == FP_REGNUM)
+     {
+       /* Frame Pointer Psuedo-register */
+       *off = SP_REGNUM * sizeof (unsigned);
+       *len = sizeof (unsigned);
+       return FP_REGNUM;
+     }
+   else if (first_regno >= FP0_REGNUM && first_regno < FPC_REGNUM)
+     {
+       unsigned off_adjust, regsize;
+ 
+       if (qnx_cpuinfo_valid && qnx_cpuinfo.cpuflags | X86_CPU_FXSR)
+ 	{
+ 	  off_adjust = 32;
+ 	  regsize = 16;
+ 	}
+       else
+ 	{
+ 	  off_adjust = 28;
+ 	  regsize = 10;
+ 	}
+ 
+       if (last_regno >= FPC_REGNUM)
+ 	last_regno = FPC_REGNUM - 1;
+       *subcmd = DSMSG_REG_FLOAT;
+       *off = (first_regno - FP0_REGNUM) * regsize + off_adjust;
+       *len = (last_regno - first_regno + 1) * 10;
+       /* Why 10?  GDB only stores 10 bytes per FP register so if we're
+        * sending a register back to the target, we only want pdebug to write
+        * 10 bytes so as not to clobber the reserved 6 bytes in the fxsave
+        * structure.  The astute reader will note that this will fail if we
+        * try to send a range of fpregs rather than 1 at a time but, as far
+        * as I know, there is no way to send more than one fpreg at a time
+        * anyway.  If this turns out to be wrong, we may need to put more code
+        * in pdebug to deal with this - perhaps by masking off part of the
+        * register when it writes it in.*/
+     }
+   else
+     {
+       *len = 0;
+       return last_regno;
+     }
+   return last_regno;
+ }
+ 
+ /* Tell GDB about the registers contained in the 'data' buffer  */
+ 
+ void
+ qnx_cpu_register_fetch (endian, first_regno, last_regno, data)
+      int endian;
+      unsigned first_regno;
+      unsigned last_regno;
+      void *data;
+ {
+   fprintf_unfiltered (gdb_stderr, "warning: qnx_cpu_register_fetch called \
+ 			in remote-qnx-i386.c.  This shouldn't happen\n");
+   /* If remote-qnx-i386.c calls qnx_supply_register in remote-qnx.c,
+    * then remote-qnx.c calls qnx_cpu_register_fetch.  Since this never
+    * happens, this function is left unimplemented. */
+ }
+ 
+ /* Build the Neutrino register set info into the 'data' buffer */
+ 
+ int
+ qnx_cpu_register_store (endian, first_regno, last_regno, data)
+      int endian;
+      unsigned first_regno;
+      unsigned last_regno;
+      void *data;
+ {
+   /* Mostly (always?) you're only storing one at a time */
+   if (first_regno == last_regno)
+     {
+       regcache_collect (first_regno, data);
+       return 1;
+     }
+   /* Floating point is the same for gdb and target */
+   if (first_regno >= FP0_REGNUM)
+     {
+       for (; first_regno <= last_regno; first_regno++)
+ 	{
+ 	  regcache_collect (first_regno, data);
+ 	  (char *) data += REGISTER_RAW_SIZE (first_regno);
+ 	}
+       return 1;
+     }
+   /* GP registers are mapped differently for NTO than GDB */
+   for (; first_regno <= last_regno; first_regno++)
+     {
+       int regnum = GDB_TO_OS (first_regno);
+       if (regnum == -1)
+ 	continue;
+       regcache_collect (first_regno,
+ 			(char *) data + sizeof (unsigned) * regnum);
+     }
+   return 1;
+ }
+ 
+ /* nto_supply_* are used by nto_procfs.c and qnx_core-regset.c */
+ void
+ nto_supply_gregset (gregsetp)
+      nto_gregset_t *gregsetp;
+ {
+   register int regi, i = 0;
+   register unsigned *regp = (unsigned *) gregsetp;
+ 
+   for (regi = 0; regi < (NUM_REGS - FP0_REGNUM); regi++)
+     {
+       i = GDB_TO_OS (regi);
+       supply_register (regi, (char *) &regp[i]);
+     }
+ }
+ 
+ void
+ nto_supply_fpregset (fpregsetp)
+      nto_fpregset_t *fpregsetp;
+ {
+   if (qnx_cpuinfo_valid && qnx_cpuinfo.cpuflags | X86_CPU_FXSR)
+     i387_supply_fxsave ((char *) fpregsetp);
+   else
+     i387_supply_fsave ((char *) fpregsetp);
+ }
+ 
+ extern void qnx_read_ioport_8 PARAMS ((char *, int));
+ extern void qnx_read_ioport_16 PARAMS ((char *, int));
+ extern void qnx_read_ioport_32 PARAMS ((char *, int));
+ extern void qnx_write_ioport_8 PARAMS ((char *, int));
+ extern void qnx_write_ioport_16 PARAMS ((char *, int));
+ extern void qnx_write_ioport_32 PARAMS ((char *, int));
+ 
+ void
+ _initialize_nto_i386 ()
+ {
+ #define IO_PORT_HACKS
+ #ifdef IO_PORT_HACKS
+   add_com ("in8", class_maintenance, qnx_read_ioport_8,
+ 	   "read a 8 bit value from an ioport");
+   add_com ("in16", class_maintenance, qnx_read_ioport_16,
+ 	   "read a 16 bit value from an ioport");
+   add_com ("in32", class_maintenance, qnx_read_ioport_32,
+ 	   "read a 32 bit value from an ioport");
+   add_com ("out8", class_maintenance, qnx_write_ioport_8,
+ 	   "write a 8 bit value to an ioport");
+   add_com ("out16", class_maintenance, qnx_write_ioport_16,
+ 	   "write a 16 bit value to an ioport");
+   add_com ("out32", class_maintenance, qnx_write_ioport_32,
+ 	   "write a 32 bit value to an ioport");
+ #endif
+ }
+ 
+ /* Fetch (and possibly build) an appropriate link_map_offsets
+    structure for native x86 targets using the struct offsets
+    defined in link.h (but without actual reference to that file).
+ 
+    This makes it possible to access x86 shared libraries from a GDB
+    that was not built on an x86 host (for cross debugging).  */
+ 
+ struct link_map_offsets *
+ i386_qnx_svr4_fetch_link_map_offsets (void)
+ {
+   static struct link_map_offsets lmo;
+   static struct link_map_offsets *lmp = NULL;
+ 
+   if (lmp == NULL)
+     {
+       lmp = &lmo;
+ 
+       lmo.r_debug_size = 8;	/* The actual size is 20 bytes, but
+ 				   this is all we need.  */
+       lmo.r_map_offset = 4;
+       lmo.r_map_size = 4;
+ 
+       lmo.link_map_size = 20;	/* The actual size is 552 bytes, but
+ 				   this is all we need.  */
+       lmo.l_addr_offset = 0;
+       lmo.l_addr_size = 4;
+ 
+       lmo.l_name_offset = 4;
+       lmo.l_name_size = 4;
+ 
+       lmo.l_next_offset = 12;
+       lmo.l_next_size = 4;
+ 
+       lmo.l_prev_offset = 16;
+       lmo.l_prev_size = 4;
+     }
+ 
+   return lmp;
+ }
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/remote-nto.c src/gdb/remote-nto.c
*** src.orig/gdb/remote-nto.c	Wed Dec 31 19:00:00 1969
--- src/gdb/remote-nto.c	Mon Feb  3 12:50:30 2003
***************
*** 0 ****
--- 1,3679 ----
+ /* Remote target communications for serial-line targets in Neutrino Pdebug protocol
+    Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+    Contributed by QNX Software Systems Limited.
+ 
+ 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.  */
+ 
+ /* This file was derived from remote.c. It communicates with a
+    box talking the QNX Software Systems Limited's Neutrino remote debug
+    protocol. See dsmsgs.h for details. */
+ 
+ #include "defs.h"
+ #include "gdb_string.h"
+ #include "gdbcore.h"
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #include "frame.h"
+ #include "inferior.h"
+ #include "bfd.h"
+ #include "symfile.h"
+ #include "target.h"
+ #include "gdb_wait.h"
+ #include "gdbcmd.h"
+ #include "objfiles.h"
+ #include "gdb-stabs.h"
+ #include "gdbthread.h"
+ #include "nto-share/dsmsgs.h"
+ #include "dcache.h"
+ #include "cli/cli-decode.h"
+ #include "completer.h"
+ #include "solist.h"
+ #include "solib-svr4.h"
+ #include "top.h"
+ #include "regcache.h"
+ 
+ #ifdef USG
+ #include <sys/types.h>
+ #endif
+ 
+ #include "nto-share/debug.h"
+ 
+ #include <sys/stat.h>
+ #include <signal.h>
+ #include "serial.h"
+ #include <termios.h>
+ 
+ #ifdef __CYGWIN__
+ #include <sys/cygwin.h>
+ #endif
+ 
+ #ifndef EOK
+ #define EOK 0
+ #endif
+ 
+ #define QNX_READ_MODE	0x0
+ #define QNX_WRITE_MODE	0x301
+ #define QNX_WRITE_PERMS	0x1ff
+ 
+ #if defined(_WIN32) || defined(__CYGWIN__)
+ #define HOST_READ_MODE  O_RDONLY|O_BINARY
+ #define HOST_WRITE_MODE  O_WRONLY|O_CREAT|O_TRUNC|O_BINARY
+ #else
+ #define HOST_READ_MODE  O_RDONLY
+ #define HOST_WRITE_MODE  O_WRONLY|O_CREAT|O_TRUNC
+ #endif
+ 
+ /* Prototypes in the appropriate remote-nto<CPU>.c file */
+ 
+ int (*target_created_hook) (pid_t);
+ CORE_ADDR qnx_getbase (void);
+ extern unsigned qnx_get_regset_id (int regno);
+ extern void qnx_cpu_regset_fetch (int endian, int regset, void *data);
+ extern unsigned qnx_get_regset_area (unsigned regset, char *subcmd);
+ extern unsigned qnx_cpu_register_area
+ PARAMS ((unsigned first_regno, unsigned last_regno, unsigned char *subcmd,
+ 	 unsigned *off, unsigned *len));
+ extern void qnx_cpu_register_fetch
+ PARAMS ((int endian, unsigned first_regno, unsigned last_regno, void *data));
+ extern int qnx_cpu_register_store
+ PARAMS ((int endian, unsigned first_regno, unsigned last_regno, void *data));
+ 
+ /* Prototypes for local functions */
+ 
+ static void init_qnx_ops PARAMS ((void));
+ static int putpkt PARAMS ((unsigned));
+ static int readchar PARAMS ((int timeout));
+ static int getpkt PARAMS ((int forever));
+ static unsigned qnx_send PARAMS ((unsigned, int));
+ static int qnx_write_bytes
+ PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+ static int qnx_read_bytes PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+ static void qnx_files_info PARAMS ((struct target_ops * ignore));
+ static void qnx_parse_notify PARAMS ((struct target_waitstatus * status));
+ static int qnx_xfer_memory
+ PARAMS ((CORE_ADDR memaddr, char *myaddr, int len, int should_write,
+ 	 struct mem_attrib * attrib, struct target_ops * target));
+ static int qnx_incoming_text PARAMS ((int len));
+ void qnx_outgoing_text (char *buf, int nbytes);
+ void qnx_fetch_registers PARAMS ((int regno));
+ static void qnx_prepare_to_store PARAMS ((void));
+ static void qnx_store_registers PARAMS ((int regno));
+ static void qnx_resume
+ PARAMS ((ptid_t ptid, int step, enum target_signal sig));
+ static int qnx_start_remote PARAMS ((char *dummy));
+ static void qnx_open PARAMS ((char *name, int from_tty));
+ static void qnx_close PARAMS ((int quitting));
+ static void qnx_mourn PARAMS ((void));
+ static ptid_t qnx_wait
+ PARAMS ((ptid_t ptid, struct target_waitstatus * status));
+ static void qnx_kill PARAMS ((void));
+ static void qnx_detach PARAMS ((char *args, int from_tty));
+ static void qnx_interrupt PARAMS ((int signo));
+ static void qnx_interrupt_twice PARAMS ((int signo));
+ static void interrupt_query PARAMS ((void));
+ static void qnx_upload PARAMS ((char *args, int from_tty));
+ static void qnx_download PARAMS ((char *args, int from_tty));
+ static void qnx_add_commands PARAMS ((void));
+ static void qnx_remove_commands PARAMS ((void));
+ static int qnx_fileopen PARAMS ((char *fname, int mode, int perms));
+ static void qnx_fileclose PARAMS ((int));
+ static int qnx_fileread PARAMS ((char *buf, int size));
+ static int qnx_filewrite PARAMS ((char *buf, int size));
+ char *qnx_pid_to_str (ptid_t ptid);
+ char **qnx_parse_redirection
+ PARAMS ((char *start_argv[], char **in, char **out, char **err));
+ enum target_signal target_signal_from_qnx PARAMS ((int sig));
+ enum target_signal target_signal_to_qnx PARAMS ((int sig));
+ static struct target_ops qnx_ops;
+ 
+ /* This was 5 seconds, which is a long time to sit and wait.
+    Unless this is going though some terminal server or multiplexer or
+    other form of hairy serial connection, I would think 2 seconds would
+    be plenty.  */
+ 
+ /*-
+    2 seconds is way too short considering commands load across the
+    network
+  */
+ static int qnx_timeout = 10;
+ static int qnx_inherit_env = 1;
+ int qnx_target_has_stack_frame = 0;
+ static char *qnx_remote_cwd = NULL;
+ 
+ /* Descriptor for I/O to remote machine.  Initialize it to NULL so that
+    qnx_open knows that we don't have a file open when the program
+    starts.  */
+ struct serial *qnx_desc = NULL;
+ int qnx_ostype = -1, qnx_cputype = -1;
+ unsigned qnx_cpuid = 0;
+ 
+ /* Filled in cpu info structure and flag to indicate its validity. 
+  * This is initialized in procfs_attach or qnx_start_remote depending on
+  * our host/target.  It would only be invalid if we were talking to an
+  * older pdebug which didn't support the cpuinfo message. */
+ struct dscpuinfo qnx_cpuinfo;
+ int qnx_cpuinfo_valid;
+ 
+ struct qnx_process
+ {
+   int pid;
+   int tid;
+ };
+ 
+ static struct qnx_process curr_proc;
+ 
+ static int host_endian;
+ static unsigned channelrd = SET_CHANNEL_DEBUG;	// Set in getpkt()
+ static unsigned channelwr = SET_CHANNEL_DEBUG;	// Set in putpkt()
+ 
+ /* Maintenance debugging flag */
+ int nto_internal_debugging;
+ 
+ /* 
+  * These store the version of the protocol used by the pdebug we connect to
+  */
+ static int TargetQNXProtoverMajor = 0;	// Set in qnx_start_remote()
+ static int TargetQNXProtoverMinor = 0;	// Set in qnx_start_remote()
+ 
+ /*
+  * These define the version of the protocol implemented here.
+  */
+ #define HOST_QNX_PROTOVER_MAJOR	0
+ #define HOST_QNX_PROTOVER_MINOR	3
+ 
+ static union
+ {
+   unsigned char buf[DS_DATA_MAX_SIZE];
+   DSMsg_union_t pkt;
+ } tran, recv;
+ 
+ #define SWAP64( val ) ( \
+ 				(((val) >> 56) & 0x00000000000000ff) \
+ 			|	(((val) >> 40) & 0x000000000000ff00) \
+ 			|	(((val) >> 24) & 0x0000000000ff0000) \
+ 			|	(((val) >> 8)  & 0x00000000ff000000) \
+ 			|	(((val) << 8)  & 0x000000ff00000000) \
+ 			|	(((val) << 24) & 0x0000ff0000000000) \
+ 			|	(((val) << 40) & 0x00ff000000000000) \
+ 			|	(((val) << 56) & 0xff00000000000000) )
+ 
+ #define SWAP32( val ) ( (((val) >> 24) & 0x000000ff)	\
+ 			  | (((val) >> 8)  & 0x0000ff00)\
+ 			  | (((val) << 8)  & 0x00ff0000)\
+ 			  | (((val) << 24) & 0xff000000) )
+ 
+ #define SWAP16( val ) ( (((val) >> 8) & 0xff) | (((val) << 8) & 0xff00) )
+ 
+ 
+ short int
+ qnx_swap16 (int val)
+ {
+   return (host_endian != TARGET_BYTE_ORDER ? SWAP16 (val) : val);
+ }
+ 
+ 
+ long int
+ qnx_swap32 (long int val)
+ {
+   return (host_endian != TARGET_BYTE_ORDER ? SWAP32 (val) : val);
+ }
+ 
+ long long int
+ qnx_swap64 (long long int val)
+ {
+   return (host_endian != TARGET_BYTE_ORDER ? SWAP64 (val) : val);
+ }
+ 
+ /* Stuff for dealing with the packets which are part of this protocol. */
+ 
+ #define MAX_TRAN_TRIES 3
+ #define MAX_RECV_TRIES 3
+ 
+ #define FRAME_CHAR	0x7e
+ #define ESC_CHAR	0x7d
+ 
+ static unsigned char nak_packet[] =
+   { FRAME_CHAR, SET_CHANNEL_NAK, 0, FRAME_CHAR };
+ static unsigned char ch_reset_packet[] =
+   { FRAME_CHAR, SET_CHANNEL_RESET, 0xff, FRAME_CHAR };
+ static unsigned char ch_debug_packet[] =
+   { FRAME_CHAR, SET_CHANNEL_DEBUG, 0xfe, FRAME_CHAR };
+ static unsigned char ch_text_packet[] =
+   { FRAME_CHAR, SET_CHANNEL_TEXT, 0xfd, FRAME_CHAR };
+ 
+ #define SEND_NAK         serial_write(qnx_desc,nak_packet,sizeof(nak_packet))
+ #define SEND_CH_RESET    serial_write(qnx_desc,ch_reset_packet,sizeof(ch_reset_packet))
+ #define SEND_CH_DEBUG    serial_write(qnx_desc,ch_debug_packet,sizeof(ch_debug_packet))
+ #define SEND_CH_TEXT     serial_write(qnx_desc,ch_text_packet,sizeof(ch_text_packet))
+ 
+ /* Send a packet to the remote machine.  Also sets channelwr and informs
+    target if channelwr has changed.  */
+ 
+ static int
+ putpkt (unsigned len)
+ {
+   int i;
+   unsigned char csum = 0;
+   unsigned char buf2[DS_DATA_MAX_SIZE * 2];
+   unsigned char *p;
+ 
+   /* Copy the packet into buffer BUF2, encapsulating it
+      and giving it a checksum.  */
+ 
+   p = buf2;
+   *p++ = FRAME_CHAR;
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("putpkt() - cmd %d, subcmd %d, mid %d\n",
+ 			 tran.pkt.hdr.cmd, tran.pkt.hdr.subcmd,
+ 			 tran.pkt.hdr.mid);
+     }
+ 
+   if (remote_debug)
+     printf_unfiltered ("Sending packet (len %d): ", len);
+ 
+   for (i = 0; i < len; i++)
+     {
+       unsigned char c = tran.buf[i];
+ 
+       if (remote_debug)
+ 	printf_unfiltered ("%2.2x", c);
+       csum += c;
+ 
+       switch (c)
+ 	{
+ 	case FRAME_CHAR:
+ 	case ESC_CHAR:
+ 	  if (remote_debug)
+ 	    printf_unfiltered ("[escape]");
+ 	  *p++ = ESC_CHAR;
+ 	  c ^= 0x20;
+ 	  break;
+ 	}
+       *p++ = c;
+     }
+ 
+   csum ^= 0xff;
+ 
+   if (remote_debug)
+     {
+       printf_unfiltered ("%2.2x\n", csum);
+       gdb_flush (gdb_stdout);
+     }
+   switch (csum)
+     {
+     case FRAME_CHAR:
+     case ESC_CHAR:
+       *p++ = ESC_CHAR;
+       csum ^= 0x20;
+       break;
+     }
+   *p++ = csum;
+   *p++ = FRAME_CHAR;
+ 
+   /*      
+    * GP added - June 17, 1999.  There used to be only 'channel'.  now channelwr
+    * and channelrd keep track of the state better.  
+    * If channelwr is not in the right state, notify target and set channelwr  
+    */
+ 
+   if (channelwr != tran.pkt.hdr.channel)
+     {
+       switch (tran.pkt.hdr.channel)
+ 	{
+ 	case SET_CHANNEL_TEXT:
+ 	  SEND_CH_TEXT;
+ 	  break;
+ 	case SET_CHANNEL_DEBUG:
+ 	  SEND_CH_DEBUG;
+ 	  break;
+ 	}
+       channelwr = tran.pkt.hdr.channel;
+     }
+ 
+   if (serial_write (qnx_desc, buf2, p - buf2))
+     perror_with_name ("putpkt: write failed");
+ 
+   return len;
+ }
+ 
+ /* Read a single character from the remote end, masking it down to 8 bits. */
+ 
+ static int
+ readchar (int timeout)
+ {
+   int ch;
+ 
+   ch = serial_readchar (qnx_desc, timeout);
+ 
+   switch (ch)
+     {
+     case SERIAL_EOF:
+       error ("Remote connection closed");
+     case SERIAL_ERROR:
+       perror_with_name ("Remote communication error");
+     case SERIAL_TIMEOUT:
+       return ch;
+     default:
+       return ch & 0xff;
+     }
+ }
+ 
+ /* Come here after finding the start of the frame.  Collect the rest into BUF,
+    verifying the checksum, length, and handling run-length compression.
+    Returns 0 on any error, 1 on success.  */
+ 
+ static int
+ read_frame ()
+ {
+   unsigned char csum;
+   unsigned char *bp;
+   unsigned char modifier = 0;
+   int c;
+ 
+   if (remote_debug)
+     printf_filtered ("Receiving data: ");
+ 
+   csum = 0;
+   bp = recv.buf;
+ 
+   memset (bp, -1, sizeof recv.buf);
+   for (;;)
+     {
+       c = readchar (qnx_timeout);
+ 
+       switch (c)
+ 	{
+ 	case SERIAL_TIMEOUT:
+ 	  puts_filtered ("Timeout in mid-packet, retrying\n");
+ 	  return -1;
+ 	case ESC_CHAR:
+ 	  modifier = 0x20;
+ 	  continue;
+ 	case FRAME_CHAR:
+ 	  if (bp == recv.buf)
+ 	    continue;		/* Ignore multiple start frames */
+ 	  if (csum != 0xff)	/* Checksum error */
+ 	    return -1;
+ 	  return bp - recv.buf - 1;
+ 	default:
+ 	  c ^= modifier;
+ 	  if (remote_debug)
+ 	    printf_filtered ("%2.2x", c);
+ 	  csum += c;
+ 	  *bp++ = c;
+ 	  break;
+ 	}
+       modifier = 0;
+     }
+ }
+ 
+ /* Read a packet from the remote machine, with error checking,
+    and store it in recv.buf.  
+    If FOREVER, wait forever rather than timing out; this is used
+    while the target is executing user code.  */
+ 
+ static int
+ getpkt (int forever)
+ {
+   int c;
+   int tries;
+   int timeout;
+   unsigned len;
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("getpkt(%d)\n", forever);
+     }
+ 
+   if (forever)
+     {
+ #ifdef MAINTENANCE_CMDS
+       timeout = watchdog > 0 ? watchdog : -1;
+ #else
+       timeout = -1;
+ #endif
+     }
+   else
+     {
+       timeout = qnx_timeout;
+     }
+ 
+   for (tries = 0; tries < MAX_RECV_TRIES; tries++)
+     {
+       /* This can loop forever if the remote side sends us characters
+          continuously, but if it pauses, we'll get a zero from readchar
+          because of timeout.  Then we'll count that as a retry.  */
+ 
+       /* Note that we will only wait forever prior to the start of a packet.
+          After that, we expect characters to arrive at a brisk pace.  They
+          should show up within qnx_timeout intervals.  */
+ 
+       do
+ 	{
+ 	  c = readchar (timeout);
+ 
+ 	  if (c == SERIAL_TIMEOUT)
+ 	    {
+ #ifdef MAINTENANCE_CMDS
+ 	      if (forever)	/* Watchdog went off.  Kill the target. */
+ 		{
+ 		  target_mourn_inferior ();
+ 		  error ("Watchdog has expired.  Target detached.");
+ 		}
+ #endif
+ 	      puts_filtered ("Timed out.\n");
+ 	      return -1;
+ 	    }
+ 	}
+       while (c != FRAME_CHAR);
+ 
+       /* We've found the start of a packet, now collect the data.  */
+ 
+       len = read_frame ();
+ 
+       if (remote_debug)
+ 	printf_filtered ("\n");
+ 
+       if (len >= sizeof (struct DShdr))
+ 	{
+ 	  if (recv.pkt.hdr.channel)	// if hdr.channel is not 0, then hdr.channel is supported
+ 	    channelrd = recv.pkt.hdr.channel;
+ 
+ 	  if (nto_internal_debugging == 2)
+ 	    {
+ 	      printf_unfiltered ("getpkt() - len %d, channelrd %d,", len,
+ 				 channelrd);
+ 	      switch (channelrd)
+ 		{
+ 		case SET_CHANNEL_DEBUG:
+ 		  printf_unfiltered (" cmd = %d, subcmd = %d, mid = %d\n",
+ 				     recv.pkt.hdr.cmd, recv.pkt.hdr.subcmd,
+ 				     recv.pkt.hdr.mid);
+ 		  break;
+ 		case SET_CHANNEL_TEXT:
+ 		  printf_unfiltered (" text message\n");
+ 		  break;
+ 		case SET_CHANNEL_RESET:
+ 		  printf_unfiltered (" set_channel_reset\n");
+ 		  break;
+ 		default:
+ 		  printf_unfiltered (" unknown channel!\n");
+ 		  break;
+ 		}
+ 	    }
+ 	  return len;
+ 	}
+       if (len >= 1)
+ 	{
+ 	  /* Packet too small to be part of the debug protocol,
+ 	     must be a transport level command */
+ 	  if (recv.buf[0] == SET_CHANNEL_NAK)
+ 	    {
+ 	      /* Our last transmission didn't make it - send it again. */
+ 	      channelrd = SET_CHANNEL_NAK;
+ 	      return -1;
+ 	    }
+ 	  if (recv.buf[0] <= SET_CHANNEL_TEXT)
+ 	    channelrd = recv.buf[0];
+ 
+ 	  if (nto_internal_debugging == 2)
+ 	    {
+ 	      printf_unfiltered ("set channelrd to %d\n", channelrd);
+ 	    }
+ 	  --tries;		/* doesn't count as a retry */
+ 	  continue;
+ 	}
+       SEND_NAK;
+     }
+ 
+   /* We have tried hard enough, and just can't receive the packet.  Give up. */
+   printf_unfiltered ("Ignoring packet error, continuing...");
+   return 0;
+ }
+ 
+ void
+ qnx_send_init (unsigned cmd, unsigned subcmd, unsigned chan)
+ {
+   static unsigned char mid;
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("    qnx_send_init(cmd %d, subcmd %d)\n", cmd,
+ 			 subcmd);
+     }
+ 
+   if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+     cmd |= DSHDR_MSG_BIG_ENDIAN;
+ 
+   tran.pkt.hdr.cmd = cmd;	//TShdr.cmd
+   tran.pkt.hdr.subcmd = subcmd;	//TShdr.console
+   tran.pkt.hdr.mid = ((chan == SET_CHANNEL_DEBUG) ? mid++ : 0);	//TShdr.spare1
+   tran.pkt.hdr.channel = chan;	//TShdr.channel
+ }
+ 
+ 
+ /* Send text to remote debug daemon - Pdebug */
+ void
+ qnx_outgoing_text (char *buf, int nbytes)
+ {
+   TSMsg_text_t *msg;
+ 
+   msg = (TSMsg_text_t *) & tran;
+ 
+   msg->hdr.cmd = TSMsg_text;
+   msg->hdr.console = 0;
+   msg->hdr.spare1 = 0;
+   msg->hdr.channel = SET_CHANNEL_TEXT;
+ 
+   memcpy (msg->text, buf, nbytes);
+ 
+   putpkt (nbytes + offsetof (TSMsg_text_t, text));
+ }
+ 
+ 
+ /* Display some text that came back across the text channel */
+ 
+ static int
+ qnx_incoming_text (int len)
+ {
+   int textlen;
+   TSMsg_text_t *text;
+   char fmt[20];
+   char buf[TS_TEXT_MAX_SIZE];
+ 
+   text = (void *) &recv.buf[0];
+   textlen = len - offsetof (TSMsg_text_t, text);
+ 
+   switch (text->hdr.cmd)
+     {
+     case TSMsg_text:
+       sprintf (fmt, "%%%d.%ds", textlen, textlen);
+       sprintf (buf, fmt, text->text);
+       ui_file_write (gdb_stdtarg, buf, textlen);
+       return 0;
+     default:
+       return -1;
+     }
+ }
+ 
+ /* Send the command in tran.buf to the remote machine,
+    and read the reply into recv.buf. */
+ 
+ static unsigned
+ qnx_send (unsigned len, int report_errors)
+ {
+   int rlen;
+   unsigned tries;
+ 
+   if (qnx_desc == NULL)
+     {
+       errno = ENOTCONN;
+       return 0;
+     }
+ 
+   for (tries = 0;; tries++)
+     {
+       if (tries >= MAX_TRAN_TRIES)
+ 	{
+ 	  unsigned char err = DSrMsg_err;
+ 
+ 	  printf_unfiltered ("Remote exhausted %d retries.\n", tries);
+ 	  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ 	    err |= DSHDR_MSG_BIG_ENDIAN;
+ 	  recv.pkt.hdr.cmd = err;
+ 	  recv.pkt.err.err = qnx_swap32 (EIO);
+ 	  rlen = sizeof (recv.pkt.err);
+ 	  break;
+ 	}
+       putpkt (len);
+       for (;;)
+ 	{
+ 	  rlen = getpkt (0);
+ 	  if ((channelrd != SET_CHANNEL_TEXT) || (rlen == -1))
+ 	    break;
+ 	  qnx_incoming_text (rlen);
+ 	}
+       if (rlen == -1)		// getpkt returns -1 if MsgNAK received.
+ 	{
+ 	  printf_unfiltered ("MsgNak received - resending\n");
+ 	  continue;
+ 	}
+       if ((rlen >= 0) && (recv.pkt.hdr.mid == tran.pkt.hdr.mid))
+ 	break;
+ 
+       if (nto_internal_debugging == 2)
+ 	{
+ 	  printf_unfiltered ("mid mismatch!\n");
+ 	}
+     }
+   /*
+    * getpkt() sets channelrd to indicate where the message came from.
+    * now we switch on the channel (/type of message) and then deal
+    * with it.
+    */
+   switch (channelrd)
+     {
+     case SET_CHANNEL_DEBUG:
+       if (((recv.pkt.hdr.cmd & DSHDR_MSG_BIG_ENDIAN) != 0))
+ 	{
+ 	  sprintf (tran.buf, "set endian big");
+ 	  if (TARGET_BYTE_ORDER != BFD_ENDIAN_BIG)
+ 	    execute_command (tran.buf, 0);
+ 	}
+       else
+ 	{
+ 	  sprintf (tran.buf, "set endian little");
+ 	  if (TARGET_BYTE_ORDER != BFD_ENDIAN_LITTLE)
+ 	    execute_command (tran.buf, 0);
+ 	}
+       recv.pkt.hdr.cmd &= ~DSHDR_MSG_BIG_ENDIAN;
+       if (recv.pkt.hdr.cmd == DSrMsg_err)
+ 	{
+ 	  errno = qnx_swap32 (recv.pkt.err.err);
+ 	  if (report_errors)
+ 	    {
+ 	      switch (recv.pkt.hdr.subcmd)
+ 		{
+ 		case PDEBUG_ENOERR:
+ 		  break;
+ 		case PDEBUG_ENOPTY:
+ 		  perror_with_name ("Remote (no ptys available)");
+ 		  break;
+ 		case PDEBUG_ETHREAD:
+ 		  perror_with_name ("Remote (thread start error)");
+ 		  break;
+ 		case PDEBUG_ECONINV:
+ 		  perror_with_name ("Remote (invalid console number)");
+ 		  break;
+ 		case PDEBUG_ESPAWN:
+ 		  perror_with_name ("Remote (spawn error)");
+ 		  break;
+ 		case PDEBUG_EPROCFS:
+ 		  perror_with_name ("Remote (procfs [/proc] error)");
+ 		  break;
+ 		case PDEBUG_EPROCSTOP:
+ 		  perror_with_name ("Remote (devctl PROC_STOP error)");
+ 		  break;
+ 		case PDEBUG_EQPSINFO:
+ 		  perror_with_name ("Remote (psinfo error)");
+ 		  break;
+ 		case PDEBUG_EQMEMMODEL:
+ 		  perror_with_name
+ 		    ("Remote (invalid memory model [not flat] )");
+ 		  break;
+ 		case PDEBUG_EQPROXY:
+ 		  perror_with_name ("Remote (proxy error)");
+ 		  break;
+ 		case PDEBUG_EQDBG:
+ 		  perror_with_name ("Remote (__qnx_debug_* error)");
+ 		  break;
+ 		default:
+ 		  perror_with_name ("Remote");
+ 		}
+ 	    }
+ 	}
+       break;
+     case SET_CHANNEL_TEXT:
+     case SET_CHANNEL_RESET:	/* no-ops */
+       break;
+     }
+   return rlen;
+ }
+ 
+ /* FIXME: should we be ignoring th? */
+ static void
+ set_thread (int th)
+ {
+   int new_pid;
+   int new_tid;
+ 
+   new_pid = ptid_get_pid (inferior_ptid);
+   new_tid = ptid_get_tid (inferior_ptid);
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered
+ 	("set_thread(th %d) -- th is unused (using pid %d, tid %d)\n", th,
+ 	 new_pid, new_tid);
+     }
+ 
+   if (new_pid != curr_proc.pid || new_tid != curr_proc.tid)
+     {
+       curr_proc.pid = new_pid;
+       curr_proc.tid = new_tid;
+       qnx_send_init (DStMsg_select, DSMSG_SELECT_SET, SET_CHANNEL_DEBUG);
+       tran.pkt.select.pid = qnx_swap32 (new_pid);
+       tran.pkt.select.tid = qnx_swap32 (new_tid);
+       qnx_send (sizeof (tran.pkt.select), 1);
+     }
+ }
+ 
+ 
+ /*  Return nonzero if the thread TH is still alive on the remote system.  */
+ 
+ static int
+ qnx_thread_alive (ptid_t th)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_thread_alive -- pid %d, tid %ld\n",
+ 			 ptid_get_pid (th), ptid_get_tid (th));
+     }
+ 
+   qnx_send_init (DStMsg_select, DSMSG_SELECT_QUERY, SET_CHANNEL_DEBUG);
+   tran.pkt.select.pid = qnx_swap32 (ptid_get_pid (th));
+   tran.pkt.select.tid = qnx_swap32 (ptid_get_tid (th));
+   qnx_send (sizeof (tran.pkt.select), 0);
+   return recv.pkt.hdr.cmd != DSrMsg_err;
+ }
+ 
+ /* Clean up connection to a remote debugger.  */
+ 
+ /* ARGSUSED */
+ static int
+ qnx_close_1 (char *dummy)
+ {
+   qnx_send_init (DStMsg_disconnect, 0, SET_CHANNEL_DEBUG);
+   qnx_send (sizeof (tran.pkt.disconnect), 0);
+   serial_close (qnx_desc);
+ 
+   return 0;
+ }
+ 
+ /* ARGSUSED */
+ static void
+ qnx_close (int quitting)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_close(quitting %d)\n", quitting);
+     }
+ 
+   if (qnx_desc)
+     {
+       catch_errors ((catch_errors_ftype *) qnx_close_1, NULL, "",
+ 		    RETURN_MASK_ALL);
+       qnx_desc = NULL;
+       qnx_remove_commands ();
+     }
+ }
+ 
+ /* Stub for catch_errors.  */
+ 
+ extern void qnx_init_solib_search_path ();
+ 
+ static int
+ qnx_start_remote (char *dummy)
+ {
+   int orig_target_endian;
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered
+ 	("qnx_start_remote, recv.pkt.hdr.cmd %d, (dummy %s)\n",
+ 	 recv.pkt.hdr.cmd, dummy);
+     }
+ 
+   immediate_quit = 1;		/* Allow user to interrupt it */
+   for (;;)
+     {
+       orig_target_endian = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
+ 
+       /* reset remote pdebug */
+       SEND_CH_RESET;
+ 
+       /*
+        * This is the first significant backward incompatible change made to
+        * pdebug.  We used to handle a notifyhost/ctl-c race condition by dropping
+        * the out of order debug message in pdebug.  Now we handle the message.
+        * The new pdebug will know this by checking against the minor version,
+        * which is now being set to 1, as opposed to 0.  We then have to query
+        * the remote agent for their protover, so we can behave accordingly.
+        */
+ 
+       qnx_send_init (DStMsg_connect, 0, SET_CHANNEL_DEBUG);
+ 
+       tran.pkt.connect.major = HOST_QNX_PROTOVER_MAJOR;
+       tran.pkt.connect.minor = HOST_QNX_PROTOVER_MINOR;
+ 
+       qnx_send (sizeof (tran.pkt.connect), 0);
+ 
+       if (recv.pkt.hdr.cmd != DSrMsg_err)
+ 	break;
+       if (orig_target_endian == (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG))
+ 	break;
+       /* Send packet again, with opposite endianness */
+     }
+   if (recv.pkt.hdr.cmd == DSrMsg_err)
+     {
+       error ("Connection failed: %ld.", qnx_swap32 (recv.pkt.err.err));
+     }
+   /* NYI: need to size transmit/receive buffers to allowed size in connect response */
+   immediate_quit = 0;
+ 
+ #ifdef TARGET_BYTE_ORDER_SELECTABLE
+   printf_unfiltered ("Remote target is %s-endian\n",
+ 		     (TARGET_BYTE_ORDER ==
+ 		      BFD_ENDIAN_BIG) ? "big" : "little");
+ /*	if ( t_endian )
+ 		TARGET_BYTE_ORDER = BFD_ENDIAN_BIG;
+ 	else
+ 		TARGET_BYTE_ORDER = BFD_ENDIAN_LITTLE; */
+   target_byte_order_auto = 1;
+ #endif
+   qnx_init_solib_search_path ();
+ 
+   /*
+    * Try to query pdebug for their version of the protocol
+    */
+ 
+   qnx_send_init (DStMsg_protover, 0, SET_CHANNEL_DEBUG);
+   tran.pkt.protover.major = HOST_QNX_PROTOVER_MAJOR;
+   tran.pkt.protover.minor = HOST_QNX_PROTOVER_MINOR;
+   qnx_send (sizeof (tran.pkt.protover), 0);
+   if ((recv.pkt.hdr.cmd == DSrMsg_err) && (qnx_swap32 (recv.pkt.err.err) == EINVAL))	// old pdebug protocol version 0.0
+     {
+       TargetQNXProtoverMajor = 0;
+       TargetQNXProtoverMinor = 0;
+     }
+   else if (recv.pkt.hdr.cmd == DSrMsg_okstatus)
+     {
+       TargetQNXProtoverMajor = qnx_swap32 (recv.pkt.okstatus.status);
+       TargetQNXProtoverMinor = qnx_swap32 (recv.pkt.okstatus.status);
+       TargetQNXProtoverMajor =
+ 	(TargetQNXProtoverMajor >> 8) & DSMSG_PROTOVER_MAJOR;
+       TargetQNXProtoverMinor = TargetQNXProtoverMinor & DSMSG_PROTOVER_MINOR;
+     }
+   else
+     {
+       error ("Connection failed (Protocol Version Query): %ld.",
+ 	     qnx_swap32 (recv.pkt.err.err));
+     }
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("Pdebug protover %d.%d, GDB protover %d.%d\n",
+ 			 TargetQNXProtoverMajor, TargetQNXProtoverMinor,
+ 			 HOST_QNX_PROTOVER_MAJOR, HOST_QNX_PROTOVER_MINOR);
+     }
+ 
+   target_has_execution = 0;
+   target_has_stack = 0;
+   qnx_target_has_stack_frame = 0;
+   start_remote ();		/* Initialize gdb process mechanisms */
+ 
+   qnx_send_init (DStMsg_cpuinfo, 0, SET_CHANNEL_DEBUG);
+   qnx_send (sizeof (tran.pkt.cpuinfo), 1);
+   if (recv.pkt.hdr.cmd == DSrMsg_err)
+     {
+       qnx_cpuinfo_valid = 0;
+     }
+   else
+     {
+       memcpy (&qnx_cpuinfo, recv.pkt.okdata.data, sizeof (struct dscpuinfo));
+       qnx_cpuinfo.cpuflags = qnx_swap32 (qnx_cpuinfo.cpuflags);
+       qnx_cpuinfo_valid = 1;
+     }
+ 
+   return 1;
+ }
+ 
+ /* Open a connection to a remote debugger.
+    NAME is the filename used for communication.  */
+ 
+ static void
+ qnx_semi_init (void)
+ {
+   qnx_send_init (DStMsg_disconnect, 0, SET_CHANNEL_DEBUG);
+   qnx_send (sizeof (tran.pkt.disconnect), 0);
+ 
+   curr_proc.pid = 0;
+   curr_proc.tid = 0;
+ 
+   /* Without this, some commands which require an active target (such as kill)
+      won't work.  This variable serves (at least) double duty as both the pid
+      of the target process (if it has such), and as a flag indicating that a
+      target is active.  These functions should be split out into seperate
+      variables, especially since GDB will someday have a notion of debugging
+      several processes.  */
+ 
+   inferior_ptid = null_ptid;
+   init_thread_list ();
+ 
+   if (!catch_errors ((catch_errors_ftype *) qnx_start_remote, (char *) 0,
+ 		     "Couldn't establish connection to remote target\n",
+ 		     RETURN_MASK_ALL))
+     {
+       flush_cached_frames ();
+       pop_target ();
+       if (nto_internal_debugging == 3)
+ 	{
+ 	  printf_unfiltered ("qnx_semi_init() - pop_target\n");
+ 	}
+     }
+ }
+ 
+ static void
+ qnx_open (char *name, int from_tty)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_open(name '%s', from_tty %d)\n", name,
+ 			 from_tty);
+     }
+ 
+   if (name == 0)
+     error
+       ("To open a remote debug connection, you need to specify what serial\ndevice is attached to the remote system (e.g. /dev/ttya).");
+ 
+   immediate_quit = 1;		/* Allow user to interrupt it */
+ 
+   target_preopen (from_tty);
+   unpush_target (&qnx_ops);
+ 
+   if (nto_internal_debugging == 3)
+     {
+       printf_unfiltered ("qnx_open() - unpush_target\n");
+     }
+ 
+   qnx_desc = serial_open (name);
+ 
+   if (!qnx_desc)
+     {
+       immediate_quit = 0;
+       perror_with_name (name);
+     }
+ 
+   if (baud_rate != -1)
+     {
+       if (serial_setbaudrate (qnx_desc, baud_rate))
+ 	{
+ 	  immediate_quit = 0;
+ 	  serial_close (qnx_desc);
+ 	  perror_with_name (name);
+ 	}
+     }
+ 
+   serial_raw (qnx_desc);
+ 
+   /* If there is something sitting in the buffer we might take it as a
+      response to a command, which would be bad.  */
+   serial_flush_input (qnx_desc);
+ 
+   if (from_tty)
+     {
+       puts_filtered ("Remote debugging using ");
+       puts_filtered (name);
+       puts_filtered ("\n");
+     }
+   push_target (&qnx_ops);	/* Switch to using remote target now */
+   qnx_add_commands ();
+   if (nto_internal_debugging == 3)
+     {
+       printf_unfiltered ("qnx_open() - push_target\n");
+     }
+ 
+   curr_proc.pid = 0;
+   curr_proc.tid = 0;
+ 
+   /* Without this, some commands which require an active target (such as kill)
+      won't work.  This variable serves (at least) double duty as both the pid
+      of the target process (if it has such), and as a flag indicating that a
+      target is active.  These functions should be split out into seperate
+      variables, especially since GDB will someday have a notion of debugging
+      several processes.  */
+ 
+   inferior_ptid = null_ptid;
+   init_thread_list ();
+ 
+   /* Start the remote connection; if error (0), discard this target.
+      In particular, if the user quits, be sure to discard it
+      (we'd be in an inconsistent state otherwise).  */
+ 
+   if (!catch_errors ((catch_errors_ftype *) qnx_start_remote, (char *) 0,
+ 		     "Couldn't establish connection to remote target\n",
+ 		     RETURN_MASK_ALL))
+     {
+       immediate_quit = 0;
+       pop_target ();
+ 
+       if (nto_internal_debugging == 1)
+ 	{
+ 	  printf_unfiltered ("qnx_open() - pop_target\n");
+ 	}
+     }
+   immediate_quit = 0;
+ }
+ 
+ /* Attaches to a process on the target side.  Arguments are as passed
+    to the `attach' command by the user.  This routine can be called
+    when the target is not on the target-stack, if the target_can_run
+    routine returns 1; in that case, it must push itself onto the stack.  
+    Upon exit, the target should be ready for normal operations, and
+    should be ready to deliver the status of the process immediately 
+    (without waiting) to an upcoming target_wait call.  */
+ 
+ static void
+ qnx_attach (char *args, int from_tty)
+ {
+   ptid_t ptid;
+ 
+   if (!ptid_equal (inferior_ptid, null_ptid))
+     qnx_semi_init ();
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_attach(args '%s', from_tty %d)\n",
+ 			 args ? args : "(null)", from_tty);
+     }
+ 
+   if (!args)
+     error_no_arg ("process-id to attach");
+ 
+   ptid = pid_to_ptid (atoi (args));
+ 
+   if (from_tty)
+     {
+       printf_unfiltered ("Attaching to %s\n", target_pid_to_str (ptid));
+       gdb_flush (gdb_stdout);
+     }
+ 
+   qnx_send_init (DStMsg_attach, 0, SET_CHANNEL_DEBUG);
+   tran.pkt.attach.pid = qnx_swap32 (PIDGET (ptid));
+   qnx_send (sizeof (tran.pkt.attach), 1);
+ 
+   /* NYI: add symbol information for process */
+   /*
+    * Turn the PIDLOAD into a STOPPED notification so that when gdb
+    * calls qnx_wait, we won't cycle around.
+    */
+   recv.pkt.hdr.cmd = DShMsg_notify;
+   recv.pkt.hdr.subcmd = DSMSG_NOTIFY_STOPPED;
+ 
+   /* hack this in here, since we will bypass the notify */
+   qnx_ostype = qnx_swap16 (recv.pkt.notify.un.pidload.ostype);
+   qnx_cputype = qnx_swap16 (recv.pkt.notify.un.pidload.cputype);
+   qnx_cpuid = qnx_swap32 (recv.pkt.notify.un.pidload.cpuid);
+ #ifdef QNX_SET_PROCESSOR_TYPE
+   QNX_SET_PROCESSOR_TYPE (qnx_cpuid);	// for mips
+ #endif
+   inferior_ptid = ptid;
+   target_has_execution = 1;
+   target_has_stack = 1;
+   target_has_registers = 1;
+   qnx_target_has_stack_frame = 1;
+   if (target_created_hook)
+     target_created_hook (curr_proc.pid);
+   attach_flag = 1;
+ }
+ 
+ /* This takes a program previously attached to and detaches it.  After
+    this is done, GDB can be used to debug some other program.  We
+    better not have left any breakpoints in the target program or it'll
+    die when it hits one.  */
+ 
+ static void
+ qnx_detach (char *args, int from_tty)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_detach(args '%s', from_tty %d)\n",
+ 			 args ? args : "(null)", from_tty);
+     }
+   if (from_tty)
+     {
+       char *exec_file = get_exec_file (0);
+       if (exec_file == 0)
+ 	exec_file = "";
+ 
+       printf_unfiltered ("Detaching from program: %s %d\n", exec_file,
+ 			 PIDGET (inferior_ptid));
+       gdb_flush (gdb_stdout);
+     }
+   if (args)
+     {
+       int sig = target_signal_to_qnx (atoi (args));
+ 
+       qnx_send_init (DStMsg_kill, 0, SET_CHANNEL_DEBUG);
+       tran.pkt.kill.signo = qnx_swap32 (sig);
+       qnx_send (sizeof (tran.pkt.kill), 1);
+     }
+ 
+   qnx_send_init (DStMsg_detach, 0, SET_CHANNEL_DEBUG);
+   tran.pkt.detach.pid = qnx_swap32 (PIDGET (inferior_ptid));
+   qnx_send (sizeof (tran.pkt.detach), 1);
+   inferior_ptid = null_ptid;
+   init_thread_list ();
+   target_has_execution = 0;
+   target_has_stack = 0;
+   target_has_registers = 0;
+   qnx_target_has_stack_frame = 0;
+ 
+   attach_flag = 0;
+ }
+ 
+ 
+ /* Tell the remote machine to resume.  */
+ 
+ static void
+ qnx_resume (ptid_t ptid, int step, enum target_signal sig)
+ {
+   int signo;
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_resume(pid %d, step %d, sig %d)\n",
+ 			 PIDGET (ptid), step, target_signal_to_qnx (sig));
+     }
+ 
+   if (ptid_equal (inferior_ptid, null_ptid))
+     return;
+ 
+   set_thread (ptid_equal (ptid, minus_one_ptid) ? ptid_get_tid (inferior_ptid)
+ 	      : ptid_get_tid (ptid));
+ 
+   // The HandleSig stuff is part of the new protover 0.1, but has not
+   // been implemented in all pdebugs that reflect that version.  If
+   // the HandleSig comes back with an error, then revert to protover 0.0
+   // behaviour, regardless of actual protover.
+   // The handlesig msg sends the signal to pass, and a char array
+   // 'signals', which is the list of signals to notice.
+ 
+   qnx_send_init (DStMsg_handlesig, 0, SET_CHANNEL_DEBUG);
+   tran.pkt.handlesig.sig_to_pass = qnx_swap32 (target_signal_to_qnx (sig));
+   for (signo = 0; signo < QNXNTO_NSIG; signo++)
+     {
+       if (signal_stop_state (target_signal_from_qnx (signo)) == 0 &&
+ 	  signal_print_state (target_signal_from_qnx (signo)) == 0 &&
+ 	  signal_pass_state (target_signal_from_qnx (signo)) == 1)
+ 	{
+ 	  tran.pkt.handlesig.signals[signo] = 0;
+ 	}
+       else
+ 	{
+ 	  tran.pkt.handlesig.signals[signo] = 1;
+ 	}
+     }
+   qnx_send (sizeof (tran.pkt.handlesig), 0);
+   if (recv.pkt.hdr.cmd == DSrMsg_err)
+     if (sig != TARGET_SIGNAL_0)
+       {
+ 	qnx_send_init (DStMsg_kill, 0, SET_CHANNEL_DEBUG);
+ 	tran.pkt.kill.signo = qnx_swap32 (target_signal_to_qnx (sig));
+ 	qnx_send (sizeof (tran.pkt.kill), 1);
+       }
+ 
+   qnx_send_init (DStMsg_run, step ? DSMSG_RUN_COUNT : DSMSG_RUN,
+ 		 SET_CHANNEL_DEBUG);
+   tran.pkt.run.step.count = qnx_swap32 (1);
+   qnx_send (sizeof (tran.pkt.run), 1);
+ }
+ 
+ static void (*ofunc) ();
+ static void (*ofunc_alrm) ();
+ 
+ //
+ // Yucky but necessary globals used to track state in qnx_wait() as a result of 
+ // things done in qnx_interrupt(), qnx_interrupt_twice(), and qnx_interrupt_retry();
+ //
+ static sig_atomic_t SignalCount = 0;	// used to track ctl-c retransmits
+ static sig_atomic_t InterruptedTwice = 0;	// Set in qnx_interrupt_twice()
+ static sig_atomic_t WaitingForStopResponse = 0;	// Set in qnx_interrupt(), cleared in qnx_wait()
+ 
+ #define QNX_TIMER_TIMEOUT 5
+ #define QNX_CTL_C_RETRIES 3
+ 
+ static void
+ qnx_interrupt_retry (signo)
+ {
+   SignalCount++;
+   if (SignalCount >= QNX_CTL_C_RETRIES)	// retry QNX_CTL_C_RETRIES times after original tranmission
+     {
+       printf_unfiltered
+ 	("CTL-C transmit - 3 retries exhausted.  Ending debug session.\n");
+       WaitingForStopResponse = 0;
+       SignalCount = 0;
+       target_mourn_inferior ();
+       throw_exception (RETURN_QUIT);
+     }
+   else
+     {
+       qnx_interrupt (SIGINT);
+     }
+ }
+ 
+ 
+ /* Ask the user what to do when an interrupt is received.  */
+ 
+ static void
+ interrupt_query ()
+ {
+   alarm (0);
+   signal (SIGINT, ofunc);
+   signal (SIGALRM, ofunc_alrm);
+   target_terminal_ours ();
+   InterruptedTwice = 0;
+ 
+   if (query
+       ("Interrupted while waiting for the program.\n Give up (and stop debugging it)? "))
+     {
+       SignalCount = 0;
+       target_mourn_inferior ();
+       throw_exception (RETURN_QUIT);
+     }
+   target_terminal_inferior ();
+   signal (SIGALRM, qnx_interrupt_retry);
+   signal (SIGINT, qnx_interrupt_twice);
+   alarm (QNX_TIMER_TIMEOUT);
+ }
+ 
+ 
+ /* The user typed ^C twice.  */
+ static void
+ qnx_interrupt_twice (signo)
+      int signo;
+ {
+   InterruptedTwice = 1;
+ }
+ 
+ /* Send ^C to target to halt it.  Target will respond, and send us a
+    packet.  */
+ 
+ //
+ // GP - Dec 21, 2000.  If the target sends a NotifyHost at the same time as
+ // GDB sends a DStMsg_stop, then we would get into problems as both ends
+ // would be waiting for a response, and not the sent messages.  Now, we put
+ // the pkt and set the global flag 'WaitingForStopResponse', and return.
+ // This then goes back to the the main loop in qnx_wait() below where we
+ // now check against the debug message received, and handle both.
+ // All retries of the DStMsg_stop are handled via SIGALRM and alarm(timeout);
+ //
+ 
+ static void
+ qnx_interrupt (int signo)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_interrupt(signo %d)\n", signo);
+     }
+ 
+   /* If this doesn't work, try more severe steps.  */
+   signal (signo, qnx_interrupt_twice);
+   signal (SIGALRM, qnx_interrupt_retry);
+ 
+   WaitingForStopResponse = 1;
+ 
+   qnx_send_init (DStMsg_stop, DSMSG_STOP_PIDS, SET_CHANNEL_DEBUG);
+   putpkt (sizeof (tran.pkt.stop));
+ 
+   // Set timeout
+   alarm (QNX_TIMER_TIMEOUT);
+ }
+ 
+ /* Wait until the remote machine stops, then return,
+    storing status in STATUS just as `wait' would.
+    Returns "pid". */
+ 
+ static ptid_t
+ qnx_wait (ptid_t ptid, struct target_waitstatus *status)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_wait pid %d, inferior pid %d\n",
+ 			 ptid_get_pid (ptid), ptid_get_pid (inferior_ptid));
+     }
+ 
+   status->kind = TARGET_WAITKIND_STOPPED;
+   status->value.sig = TARGET_SIGNAL_0;
+ 
+   if (ptid_equal (inferior_ptid, null_ptid))
+     return null_ptid;
+ 
+   if (recv.pkt.hdr.cmd != DShMsg_notify)
+     {
+       int len;
+       char waiting_for_notify;
+ 
+       waiting_for_notify = 1;
+       SignalCount = 0;
+       InterruptedTwice = 0;
+ 
+       ofunc = (void (*)()) signal (SIGINT, qnx_interrupt);
+       ofunc_alrm = (void (*)()) signal (SIGALRM, qnx_interrupt_retry);
+       for (;;)
+ 	{
+ 	  len = getpkt (1);
+ 	  if (len < 0)		// error - probably received MSG_NAK
+ 	    {
+ 	      if (WaitingForStopResponse)
+ 		{
+ 		  // we do not want to get SIGALRM while calling it's handler
+ 		  // the timer is reset in the handler
+ 		  alarm (0);
+ 		  qnx_interrupt_retry (SIGALRM);
+ 		  continue;
+ 		}
+ 	      else
+ 		{
+ 		  // turn off the alarm, and reset the signals, and return
+ 		  alarm (0);
+ 		  signal (SIGINT, ofunc);
+ 		  signal (SIGALRM, ofunc_alrm);
+ 		  return null_ptid;
+ 		}
+ 	    }
+ 	  if (channelrd == SET_CHANNEL_TEXT)
+ 	    qnx_incoming_text (len);
+ 	  else			// DEBUG CHANNEL
+ 	    {
+ 	      recv.pkt.hdr.cmd &= ~DSHDR_MSG_BIG_ENDIAN;
+ 	      // If we have sent the DStMsg_stop due to a ^C, we expect
+ 	      // to get the response, so check and clear the flag
+ 	      // also turn off the alarm - no need to retry, we did not lose the packet.
+ 	      if ((WaitingForStopResponse) && (recv.pkt.hdr.cmd == DSrMsg_ok))
+ 		{
+ 		  WaitingForStopResponse = 0;
+ 		  status->value.sig = TARGET_SIGNAL_INT;
+ 		  alarm (0);
+ 		  if (!waiting_for_notify)
+ 		    break;
+ 		}
+ 	      else		// else we get the Notify we are waiting for
+ 	      if (recv.pkt.hdr.cmd == DShMsg_notify)
+ 		{
+ 		  waiting_for_notify = 0;
+ 		  // Send an OK packet to acknowledge the notify.
+ 		  tran.pkt.hdr.cmd = DSrMsg_ok;
+ 		  if ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG))
+ 		    tran.pkt.hdr.cmd |= DSHDR_MSG_BIG_ENDIAN;
+ 		  tran.pkt.hdr.channel = SET_CHANNEL_DEBUG;
+ 		  tran.pkt.hdr.mid = recv.pkt.hdr.mid;
+ 		  SEND_CH_DEBUG;
+ 		  putpkt (sizeof (tran.pkt.ok));
+ 		  // Handle old pdebug protocol behavior, where out of order msgs get dropped
+ 		  // version 0.0 does this, so we must resend after a notify.
+ 		  if ((TargetQNXProtoverMajor == 0)
+ 		      && (TargetQNXProtoverMinor == 0))
+ 		    {
+ 		      if (WaitingForStopResponse)
+ 			{
+ 			  alarm (0);
+ 			  // change the command to something other than notify
+ 			  // so we don't loop in here again - leave the rest of
+ 			  // the packet alone for qnx_parse_notify() below!!!
+ 			  recv.pkt.hdr.cmd = DSrMsg_ok;
+ 			  qnx_interrupt (SIGINT);
+ 			}
+ 		    }
+ 		  qnx_parse_notify (status);
+ 
+ 		  if (!WaitingForStopResponse)
+ 		    break;
+ 		}
+ 	    }
+ 	}
+       alarm (0);
+ 
+       //
+       // Hitting Ctl-C sends a stop request, a second ctl-c means quit, 
+       // so query here, after handling the results of the first ctl-c
+       // We know we were interrupted twice because the yucky global flag
+       // 'InterruptedTwice' is set in the handler, and cleared in interrupt_query()
+       //
+       if (InterruptedTwice)
+ 	interrupt_query ();
+ 
+       signal (SIGINT, ofunc);
+       signal (SIGALRM, ofunc_alrm);
+     }
+ 
+   recv.pkt.hdr.cmd = DSrMsg_ok;	/* to make us wait the next time */
+   return inferior_ptid;
+ }
+ 
+ static void
+ qnx_parse_notify (struct target_waitstatus *status)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_parse_notify(status) - subcmd %d\n",
+ 			 recv.pkt.hdr.subcmd);
+     }
+   curr_proc.pid = qnx_swap32 (recv.pkt.notify.pid);
+   curr_proc.tid = qnx_swap32 (recv.pkt.notify.tid);
+   if (curr_proc.tid == 0)
+     curr_proc.tid = 1;
+ 
+   // This was added for arm.  See arm_init_extra_frame_info()
+   // in arm-tdep.c.  arm_scan_prologue() causes a memory_error()
+   // if there is not a valid stack frame, and when the inferior
+   // is loaded, but has not started executing, the stack frame
+   // is invalid.  The default is to assume a stack frame, and
+   // this is set to 0 if we have a DSMSG_NOTIFY_PIDLOAD
+   // GP July 5, 2001.
+ 
+   qnx_target_has_stack_frame = 1;
+ 
+   switch (recv.pkt.hdr.subcmd)
+     {
+     case DSMSG_NOTIFY_PIDUNLOAD:
+       /*
+        * Added a new struct pidunload_v3 to the notify.un.  This includes a 
+        * faulted flag so we can tell if the status value is a signo or an 
+        * exit value.  See dsmsgs.h, protoverminor bumped to 3. GP Oct 31 2002.
+        */
+       if ((TargetQNXProtoverMajor == 0) && (TargetQNXProtoverMinor >= 3))
+ 	{
+ 	  if (recv.pkt.notify.un.pidunload_v3.faulted)
+ 	    {
+ 	      status->value.integer =
+ 		target_signal_from_qnx (qnx_swap32
+ 					(recv.pkt.notify.un.pidunload_v3.
+ 					 status));
+ 	      if (status->value.integer)
+ 		status->kind = TARGET_WAITKIND_SIGNALLED;	//abnormal death
+ 	      else
+ 		status->kind = TARGET_WAITKIND_EXITED;	//normal death
+ 	    }
+ 	  else
+ 	    {
+ 	      status->value.integer =
+ 		qnx_swap32 (recv.pkt.notify.un.pidunload_v3.status);
+ 	      status->kind = TARGET_WAITKIND_EXITED;	//normal death, possibly with exit value
+ 	    }
+ 	}
+       else
+ 	{
+ 	  status->value.integer =
+ 	    target_signal_from_qnx (qnx_swap32
+ 				    (recv.pkt.notify.un.pidunload.status));
+ 	  if (status->value.integer)
+ 	    status->kind = TARGET_WAITKIND_SIGNALLED;	//abnormal death
+ 	  else
+ 	    status->kind = TARGET_WAITKIND_EXITED;	//normal death
+ 	}
+       target_has_execution = 0;
+       target_has_stack = 0;
+       target_has_registers = 0;
+       qnx_target_has_stack_frame = 0;
+       break;
+     case DSMSG_NOTIFY_BRK:
+     case DSMSG_NOTIFY_STEP:
+       /* NYI: could update the CPU's IP register here. */
+       status->kind = TARGET_WAITKIND_STOPPED;
+       status->value.sig = TARGET_SIGNAL_TRAP;
+       break;
+     case DSMSG_NOTIFY_SIGEV:
+       status->kind = TARGET_WAITKIND_STOPPED;
+       status->value.sig =
+ 	target_signal_from_qnx (qnx_swap32 (recv.pkt.notify.un.sigev.signo));
+       break;
+     case DSMSG_NOTIFY_PIDLOAD:
+       qnx_ostype = qnx_swap16 (recv.pkt.notify.un.pidload.ostype);
+       qnx_cputype = qnx_swap16 (recv.pkt.notify.un.pidload.cputype);
+       qnx_cpuid = qnx_swap32 (recv.pkt.notify.un.pidload.cpuid);
+ #ifdef QNX_SET_PROCESSOR_TYPE
+       QNX_SET_PROCESSOR_TYPE (qnx_cpuid);	// for mips
+ #endif
+       target_has_execution = 1;
+       target_has_stack = 1;
+       target_has_registers = 1;
+       qnx_target_has_stack_frame = 0;
+       if (target_created_hook)
+ 	target_created_hook (curr_proc.pid);
+       status->kind = TARGET_WAITKIND_LOADED;
+       break;
+     case DSMSG_NOTIFY_DLLLOAD:
+     case DSMSG_NOTIFY_TIDLOAD:
+     case DSMSG_NOTIFY_TIDUNLOAD:
+     case DSMSG_NOTIFY_DLLUNLOAD:
+       status->kind = TARGET_WAITKIND_SPURIOUS;
+       break;
+     case DSMSG_NOTIFY_STOPPED:
+       status->kind = TARGET_WAITKIND_STOPPED;
+       break;
+     default:
+       warning ("Unexpected notify type %d", recv.pkt.hdr.subcmd);
+       break;
+     }
+   inferior_ptid = ptid_build (curr_proc.pid, 0, curr_proc.tid);
+ }
+ 
+ /* Read register REGNO, or all registers if REGNO == -1, from the contents
+    of REGISTERS.  */
+ void
+ qnx_fetch_registers (int regno)
+ {
+   unsigned first;
+   unsigned last;
+   int len;
+   int minusone = -1;
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_fetch_registers(regno %d)\n", regno);
+     }
+ 
+   if (ptid_equal (inferior_ptid, null_ptid))
+     return;
+ 
+   set_thread (ptid_get_tid (inferior_ptid));
+ 
+   if (regno == -1)
+     {				/* get all regsets */
+       first = 0;
+       last = qnx_get_regset_id (-1);
+     }
+   else
+     {				/* get regset regno is in */
+       first = qnx_get_regset_id (regno);
+       last = first + 1;
+       if (first == -1)
+ 	{			/* don't support reg */
+ 	  supply_register (regno, (char *) &minusone);
+ 	  return;
+ 	}
+     }
+   for (; first < last; ++first)
+     {
+       qnx_send_init (DStMsg_regrd, 0, SET_CHANNEL_DEBUG);
+       len = qnx_get_regset_area (first, &tran.pkt.hdr.subcmd);
+       if (len > 0)
+ 	{
+ 	  void *data;
+ #ifdef TM_I386QNX_H
+ /* FIXME: these ifdefs should be taken out once we move to the new proc which
+  * has a long enough structure to hold floating point registers */
+ 	  int rlen;
+ #endif
+ 
+ 	  tran.pkt.regrd.offset = qnx_swap16 (0);	/* Always get whole set */
+ 	  tran.pkt.regrd.size = qnx_swap16 (len);
+ #ifdef TM_I386QNX_H
+ 	  rlen = qnx_send (sizeof (tran.pkt.regrd), 0);
+ #else
+ 	  qnx_send (sizeof (tran.pkt.regrd), 0);
+ #endif
+ 	  if (recv.pkt.hdr.cmd != DSrMsg_err)
+ 	    {
+ 	      data = recv.pkt.okdata.data;
+ 	    }
+ 	  else
+ 	    {
+ 	      data = NULL;
+ 	      return;
+ 	    }
+ #ifdef TM_I386QNX_H
+ 	  if (first == 1 && rlen <= 128)
+ 	    return;		//trying to get fpregs from an old proc
+ 
+ #endif
+ 	  qnx_cpu_regset_fetch ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG), first,
+ 				data);
+ 	}
+     }
+ }
+ 
+ /* Prepare to store registers.  Don't have to do anything. */
+ 
+ static void
+ qnx_prepare_to_store ()
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_prepare_to_store()\n");
+     }
+ }
+ 
+ 
+ /* Store register REGNO, or all registers if REGNO == -1, from the contents
+    of REGISTERS.  */
+ 
+ void
+ qnx_store_registers (int regno)
+ {
+   unsigned first;
+   unsigned last;
+   unsigned end;
+   unsigned off;
+   unsigned len;
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_store_registers(regno %d)\n", regno);
+     }
+ 
+   if (ptid_equal (inferior_ptid, null_ptid))
+     return;
+ 
+   set_thread (ptid_get_tid (inferior_ptid));
+ 
+   if (regno == -1)
+     {
+       first = 0;
+       last = NUM_REGS - 1;
+     }
+   else
+     {
+       first = regno;
+       last = regno;
+     }
+ 
+   while (first <= last)
+     {
+       qnx_send_init (DStMsg_regwr, 0, SET_CHANNEL_DEBUG);
+       end = qnx_cpu_register_area (first, last,
+ 				   &tran.pkt.hdr.subcmd, &off, &len);
+       if (len > 0)
+ 	{
+ 	  tran.pkt.regwr.offset = qnx_swap16 (off);
+ 	  if (qnx_cpu_register_store
+ 	      ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG), first, end,
+ 	       tran.pkt.regwr.data))
+ 	    qnx_send (offsetof (DStMsg_regwr_t, data) + len, 1);
+ 	}
+       first = end + 1;
+     }
+ }
+ 
+ /* 
+    Use of the data cache *used* to be disabled because it loses for looking at
+    and changing hardware I/O ports and the like.  Accepting `volatile'
+    would perhaps be one way to fix it.  Another idea would be to use the
+    executable file for the text segment (for all SEC_CODE sections?
+    For all SEC_READONLY sections?).  This has problems if you want to
+    actually see what the memory contains (e.g. self-modifying code,
+    clobbered memory, user downloaded the wrong thing).  
+ 
+    Because it speeds so much up, it's now enabled, if you're playing
+    with registers you turn it off (set remotecache 0)
+ */
+ 
+ 
+ /* Write memory data directly to the remote machine.
+    This does not inform the data cache; the data cache uses this.
+    MEMADDR is the address in the remote memory space.
+    MYADDR is the address of the buffer in our space.
+    LEN is the number of bytes.
+ 
+    Returns number of bytes transferred, or 0 for error.  */
+ 
+ static int
+ qnx_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
+ {
+   long long addr;
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_write_bytes(to %lx, from %p, len %d)\n",
+ 			 memaddr, myaddr, len);
+     }
+ 
+   /* NYI: need to handle requests bigger than largest allowed packet */
+   qnx_send_init (DStMsg_memwr, 0, SET_CHANNEL_DEBUG);
+   addr = memaddr;
+   tran.pkt.memwr.addr = qnx_swap64 (addr);
+   memcpy (tran.pkt.memwr.data, myaddr, len);
+   qnx_send (offsetof (DStMsg_memwr_t, data) + len, 0);
+ 
+   switch (recv.pkt.hdr.cmd)
+     {
+     case DSrMsg_ok:
+       return len;
+     case DSrMsg_okstatus:
+       return qnx_swap32 (recv.pkt.okstatus.status);
+     }
+   return 0;
+ }
+ 
+ /* Read memory data directly from the remote machine.
+    This does not use the data cache; the data cache uses this.
+    MEMADDR is the address in the remote memory space.
+    MYADDR is the address of the buffer in our space.
+    LEN is the number of bytes.
+ 
+    Returns number of bytes transferred, or 0 for error.  */
+ 
+ static int
+ qnx_read_bytes (CORE_ADDR memaddr, char *myaddr, int len)
+ {
+   int rcv_len, tot_len, ask_len;
+   long long addr;
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_read_bytes(from %lx, to %p, len %d)\n", memaddr,
+ 			 myaddr, len);
+     }
+ 
+   tot_len = rcv_len = ask_len = 0;
+ 
+   /* GP, Jan 27,2000 - need to handle requests bigger than largest allowed packet */
+   do
+     {
+       qnx_send_init (DStMsg_memrd, 0, SET_CHANNEL_DEBUG);
+       addr = memaddr + tot_len;
+       tran.pkt.memrd.addr = qnx_swap64 (addr);
+       ask_len =
+ 	((len - tot_len) >
+ 	 DS_DATA_MAX_SIZE) ? DS_DATA_MAX_SIZE : (len - tot_len);
+       tran.pkt.memrd.size = qnx_swap16 (ask_len);
+       rcv_len = qnx_send (sizeof (tran.pkt.memrd), 0) - sizeof (recv.pkt.hdr);
+       if (rcv_len <= 0)
+ 	break;
+       if (recv.pkt.hdr.cmd == DSrMsg_okdata)
+ 	{
+ 	  memcpy (myaddr + tot_len, recv.pkt.okdata.data, rcv_len);
+ 	  tot_len += rcv_len;
+ 	}
+       else
+ 	break;
+     }
+   while (tot_len != len);
+ 
+   return (tot_len);
+ }
+ 
+ /* Read or write LEN bytes from inferior memory at MEMADDR, transferring
+    to or from debugger address MYADDR.  Write to inferior if SHOULD_WRITE is
+    nonzero.  Returns length of data written or read; 0 for error.  */
+ 
+ /* ARGSUSED */
+ static int
+ qnx_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int should_write,
+ 		 struct mem_attrib *attrib, struct target_ops *ignore)
+ {
+   int res;
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered
+ 	("qnx_xfer_memory(memaddr %lx, myaddr %p, len %d, should_write %d, target %p)\n",
+ 	 memaddr, myaddr, len, should_write, ignore);
+     }
+   if (ptid_equal (inferior_ptid, null_ptid))
+     {
+       /* pretend to read if no inferior but fail on write */
+       if (should_write)
+ 	return 0;
+       memset (myaddr, 0, len);
+       return len;
+     }
+   if (should_write)
+     res = qnx_write_bytes (memaddr, myaddr, len);
+   else
+     res = qnx_read_bytes (memaddr, myaddr, len);
+   return res;
+ }
+ 
+ 
+ static void
+ qnx_files_info (struct target_ops *ignore)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_files_info(ignore %p)\n", ignore);
+     }
+   puts_filtered ("Debugging a target over a serial line.\n");
+ }
+ 
+ 
+ static int
+ qnx_kill_1 (char *dummy)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_kill_1(dummy %p)\n", dummy);
+     }
+ 
+   if (!ptid_equal (inferior_ptid, null_ptid))
+     {
+       qnx_send_init (DStMsg_kill, DSMSG_KILL_PID, SET_CHANNEL_DEBUG);
+       tran.pkt.kill.signo = qnx_swap32 (9);	/* SIGKILL */
+       qnx_send (sizeof (tran.pkt.kill), 0);
+     }
+   return 0;
+ }
+ 
+ static void
+ qnx_kill ()
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_kill()\n");
+     }
+ 
+   /* Use catch_errors so the user can quit from gdb even when we aren't on
+      speaking terms with the remote system.  */
+   if (catch_errors
+       ((catch_errors_ftype *) qnx_kill_1, (char *) 0, "", RETURN_MASK_ERROR))
+     target_mourn_inferior ();
+ }
+ 
+ static void
+ qnx_mourn ()
+ {
+   extern int show_breakpoint_hit_counts;
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_mourn()\n");
+     }
+ 
+   init_thread_list ();
+ 
+   attach_flag = 0;
+   breakpoint_init_inferior (inf_exited);
+   registers_changed ();
+ 
+ #ifdef CLEAR_DEFERRED_STORES
+   /* Delete any pending stores to the inferior... */
+   CLEAR_DEFERRED_STORES;
+ #endif
+ 
+   inferior_ptid = null_ptid;
+ 
+   reopen_exec_file ();
+   reinit_frame_cache ();
+ 
+   /* It is confusing to the user for ignore counts to stick around
+      from previous runs of the inferior.  So clear them.  */
+   /* However, it is more confusing for the ignore counts to disappear when
+      using hit counts.  So don't clear them if we're counting hits.  */
+ 
+   if (!show_breakpoint_hit_counts)
+     breakpoint_clear_ignore_counts ();
+ 
+ }
+ 
+ int
+ qnx_fd_raw (int fd)
+ {
+   struct termios termios_p;
+ 
+   if (tcgetattr (fd, &termios_p))
+     return (-1);
+ 
+   termios_p.c_cc[VMIN] = 1;
+   termios_p.c_cc[VTIME] = 0;
+   termios_p.c_lflag &= ~(ECHO | ICANON | ISIG | ECHOE | ECHOK | ECHONL);
+   termios_p.c_oflag &= ~(OPOST);
+   return (tcsetattr (fd, TCSADRAIN, &termios_p));
+ }
+ 
+ static void
+ qnx_create (char *exec_file, char *args, char **env)
+ {
+   unsigned argc;
+   unsigned envc;
+   char **start_argv;
+   char **argv;
+   char *p;
+   int fd;
+   struct target_waitstatus status;
+   char *in, *out, *err;
+   int len = 0;
+   int totlen = 0;
+ 
+   if (qnx_desc == NULL)
+     qnx_open ("pty", 0);
+ 
+   if (!ptid_equal (inferior_ptid, null_ptid))
+     qnx_semi_init ();
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_create(exec_file '%s', args '%s', environ)\n",
+ 			 exec_file ? exec_file : "(null)",
+ 			 args ? args : "(null)");
+     }
+ 
+   qnx_send_init (DStMsg_env, DSMSG_ENV_CLEARENV, SET_CHANNEL_DEBUG);
+   qnx_send (sizeof (DStMsg_env_t), 1);
+ 
+   if (!qnx_inherit_env)
+     {
+       for (envc = 0; *env; env++, envc++)
+ 	{
+ 	  len = strlen (*env);
+ 	  totlen = 0;
+ 	  if (TargetQNXProtoverMinor >= 2)	/* HOST_QNX_PROTOVER_MINOR == 2 */
+ 	    {
+ 	      if (len > DS_DATA_MAX_SIZE)
+ 		{
+ 		  while (len > DS_DATA_MAX_SIZE)
+ 		    {
+ 		      qnx_send_init (DStMsg_env, DSMSG_ENV_SETENV_MORE,
+ 				     SET_CHANNEL_DEBUG);
+ 		      memcpy (tran.pkt.env.data, *env + totlen,
+ 			      DS_DATA_MAX_SIZE);
+ 		      qnx_send (offsetof (DStMsg_env_t, data) +
+ 				DS_DATA_MAX_SIZE, 1);
+ 		      len -= DS_DATA_MAX_SIZE;
+ 		      totlen += DS_DATA_MAX_SIZE;
+ 		    }
+ 		}
+ 	    }
+ 	  else if (len > DS_DATA_MAX_SIZE)
+ 	    {
+ 	      printf_unfiltered
+ 		("** Skipping env var \"%.40s .....\" <cont>\n", *env);
+ 	      printf_unfiltered
+ 		("** Protovers under 0.2 do not handle env vars longer than %d\n",
+ 		 DS_DATA_MAX_SIZE);
+ 	      continue;
+ 	    }
+ 	  qnx_send_init (DStMsg_env, DSMSG_ENV_SETENV, SET_CHANNEL_DEBUG);
+ 	  strcpy (tran.pkt.env.data, *env + totlen);
+ 	  qnx_send (offsetof (DStMsg_env_t, data) +
+ 		    strlen (tran.pkt.env.data) + 1, 1);
+ 	}
+     }
+ 
+   if (qnx_remote_cwd != NULL)
+     {
+       qnx_send_init (DStMsg_cwd, DSMSG_CWD_SET, SET_CHANNEL_DEBUG);
+       strcpy (tran.pkt.cwd.path, qnx_remote_cwd);
+       qnx_send (offsetof (DStMsg_cwd_t, path) + strlen (tran.pkt.cwd.path) +
+ 		1, 1);
+     }
+ 
+   qnx_send_init (DStMsg_env, DSMSG_ENV_CLEARARGV, SET_CHANNEL_DEBUG);
+   qnx_send (sizeof (DStMsg_env_t), 1);
+ 
+   start_argv = buildargv (args);
+   if (start_argv == NULL)
+     nomem (0);
+   start_argv = qnx_parse_redirection (start_argv, &in, &out, &err);
+ //      printf("stdin=%s, stdout=%s, stderr=%s\n", in, out, err );
+ 
+   if (in[0])
+     {
+       if ((fd = open (in, O_RDONLY)) == -1)
+ 	perror (in);
+       else
+ 	qnx_fd_raw (fd);
+     }
+ 
+   if (out[0])
+     {
+       if ((fd = open (out, O_WRONLY)) == -1)
+ 	perror (out);
+       else
+ 	qnx_fd_raw (fd);
+     }
+ 
+   if (err[0])
+     {
+       if ((fd = open (err, O_WRONLY)) == -1)
+ 	perror (err);
+       else
+ 	qnx_fd_raw (fd);
+     }
+ 
+   in = "";
+   out = "";
+   err = "";
+   argc = 0;
+   if (exec_file != NULL)
+     {
+       qnx_send_init (DStMsg_env, DSMSG_ENV_ADDARG, SET_CHANNEL_DEBUG);
+       strcpy (tran.pkt.env.data, exec_file);
+       /* send it twice - first as cmd, second as argv[0] */
+       qnx_send (offsetof (DStMsg_env_t, data) + strlen (tran.pkt.env.data) +
+ 		1, 1);
+       qnx_send_init (DStMsg_env, DSMSG_ENV_ADDARG, SET_CHANNEL_DEBUG);
+       strcpy (tran.pkt.env.data, exec_file);
+       qnx_send (offsetof (DStMsg_env_t, data) + strlen (tran.pkt.env.data) +
+ 		1, 1);
+     }
+   else if (*start_argv == NULL)
+     {
+       error ("No executable specified.");
+       freeargv (start_argv);
+       return;
+     }
+   else
+     {
+       exec_file = *start_argv;
+       qnx_send_init (DStMsg_env, DSMSG_ENV_ADDARG, SET_CHANNEL_DEBUG);
+       strcpy (tran.pkt.env.data, *start_argv);
+       qnx_send (offsetof (DStMsg_env_t, data) + strlen (tran.pkt.env.data) +
+ 		1, 1);
+     }
+ 
+   for (argv = start_argv; *argv && **argv; argv++, argc++)
+     {
+       qnx_send_init (DStMsg_env, DSMSG_ENV_ADDARG, SET_CHANNEL_DEBUG);
+       strcpy (tran.pkt.env.data, *argv);
+       qnx_send (offsetof (DStMsg_env_t, data) + strlen (tran.pkt.env.data) +
+ 		1, 1);
+     }
+   freeargv (start_argv);
+ 
+   /* NYI: msg too big for buffer */
+   if (qnx_inherit_env)
+     qnx_send_init (DStMsg_load, DSMSG_LOAD_DEBUG | DSMSG_LOAD_INHERIT_ENV,
+ 		   SET_CHANNEL_DEBUG);
+   else
+     qnx_send_init (DStMsg_load, DSMSG_LOAD_DEBUG, SET_CHANNEL_DEBUG);
+ 
+   p = tran.pkt.load.cmdline;
+ 
+   tran.pkt.load.envc = 0;
+   tran.pkt.load.argc = 0;
+ 
+   strcpy (p, exec_file);
+   p += strlen (p);
+   *p++ = '\0';			/* load_file */
+ 
+   strcpy (p, in);
+   p += strlen (p);
+   *p++ = '\0';			/* stdin */
+ 
+   strcpy (p, out);
+   p += strlen (p);
+   *p++ = '\0';			/* stdout */
+ 
+   strcpy (p, err);
+   p += strlen (p);
+   *p++ = '\0';			/* stderr */
+ 
+   qnx_send (offsetof (DStMsg_load_t, cmdline) + p - tran.pkt.load.cmdline + 1,
+ 	    1);
+   /* comes back as an DSrMsg_okdata, but it's really a DShMsg_notify */
+   if (recv.pkt.hdr.cmd == DSrMsg_okdata)
+     {
+       qnx_parse_notify (&status);
+       add_thread (inferior_ptid);
+     }
+   /* NYI: add the symbol info somewhere? */
+ #ifdef SOLIB_CREATE_INFERIOR_HOOK
+   if (exec_bfd)
+     SOLIB_CREATE_INFERIOR_HOOK (pid);
+ #endif
+   attach_flag = 0;
+ }
+ 
+ static int
+ qnx_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered
+ 	("qnx_insert_breakpoint(addr %lx, contents_cache %p)\n", addr,
+ 	 contents_cache);
+     }
+ 
+   qnx_send_init (DStMsg_brk, DSMSG_BRK_EXEC, SET_CHANNEL_DEBUG);
+   tran.pkt.brk.addr = qnx_swap32 (addr);
+   tran.pkt.brk.size = 0;
+   qnx_send (sizeof (tran.pkt.brk), 0);
+   return recv.pkt.hdr.cmd == DSrMsg_err;
+ }
+ 
+ static int
+ qnx_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered
+ 	("qnx_remove_breakpoint(addr %lx, contents_cache %p)\n", addr,
+ 	 contents_cache);
+     }
+ 
+   /* This got changed to send DSMSG_BRK_EXEC with a size of -1 
+    * qnx_send_init(DStMsg_brk, DSMSG_BRK_REMOVE, SET_CHANNEL_DEBUG); 
+    */
+   qnx_send_init (DStMsg_brk, DSMSG_BRK_EXEC, SET_CHANNEL_DEBUG);
+   tran.pkt.brk.addr = qnx_swap32 (addr);
+   tran.pkt.brk.size = qnx_swap32 (-1);
+   qnx_send (sizeof (tran.pkt.brk), 0);
+   return recv.pkt.hdr.cmd == DSrMsg_err;
+ }
+ 
+ #ifdef __CYGWIN__
+ void
+ slashify (char *buf)
+ {
+   int i = 0;
+   while (buf[i])
+     {
+       /* Not sure why we would want to leave an escaped '\', but seems 
+          safer.  */
+       if (buf[i] == '\\')
+ 	{
+ 	  if (buf[i + 1] == '\\')
+ 	    i++;
+ 	  else
+ 	    buf[i] = '/';
+ 	}
+       i++;
+     }
+ }
+ #endif
+ 
+ static void
+ qnx_upload (char *args, int fromtty)
+ {
+ #ifdef __CYGWIN__
+   char cygbuf[PATH_MAX];
+ #endif
+   int fd;
+   int len;
+   char buf[DS_DATA_MAX_SIZE];
+   char *from, *to;
+   char **argv;
+ 
+   if (args == 0)
+     {
+       printf_unfiltered ("You must specify a filename to send.\n");
+       return;
+     }
+ 
+ #ifdef __CYGWIN__
+   /*
+    * We need to convert back slashes to forward slashes for DOS
+    * style paths, else buildargv will remove them.
+    */
+   slashify (args);
+ #endif
+   argv = buildargv (args);
+ 
+   if (argv == NULL)
+     nomem (0);
+ 
+ #ifdef __CYGWIN__
+   cygwin_conv_to_posix_path (argv[0], cygbuf);
+   from = cygbuf;
+ #else
+   from = argv[0];
+ #endif
+   to = argv[1] ? argv[1] : from;
+ 
+   if ((fd = open (from, HOST_READ_MODE)) == -1)
+     {
+       printf_unfiltered ("Unable to open '%s': %s\n", from, strerror (errno));
+       return;
+     }
+ 
+   if (qnx_fileopen (to, QNX_WRITE_MODE, QNX_WRITE_PERMS) == -1)
+     {
+       printf_unfiltered ("Remote was unable to open '%s': %s\n", to,
+ 			 strerror (errno));
+       close (fd);
+       return;
+     }
+ 
+   while ((len = read (fd, buf, sizeof buf)) > 0)
+     {
+       if (qnx_filewrite (buf, len) == -1)
+ 	{
+ 	  printf_unfiltered ("Remote was unable to complete write: %s\n",
+ 			     strerror (errno));
+ 	  close (fd);
+ 	  return;
+ 	}
+     }
+   if (len == -1)
+     printf_unfiltered ("Local read failed: %s\n", strerror (errno));
+   qnx_fileclose (fd);
+   close (fd);
+ }
+ 
+ static void
+ qnx_download (char *args, int fromtty)
+ {
+ #ifdef __CYGWIN__
+   char cygbuf[PATH_MAX];
+ #endif
+   int fd;
+   int len;
+   char buf[DS_DATA_MAX_SIZE];
+   char *from, *to;
+   char **argv;
+ 
+   if (args == 0)
+     {
+       printf_unfiltered ("You must specify a filename to get.\n");
+       return;
+     }
+ 
+ #ifdef __CYGWIN__
+   /*
+    * We need to convert back slashes to forward slashes for DOS
+    * style paths, else buildargv will remove them.
+    */
+   slashify (args);
+ #endif
+ 
+   argv = buildargv (args);
+   if (argv == NULL)
+     nomem (0);
+ 
+   from = argv[0];
+ #ifdef __CYGWIN__
+   if (argv[1])
+     {
+       cygwin_conv_to_posix_path (argv[1], cygbuf);
+       to = cygbuf;
+     }
+   else
+     to = from;
+ #else
+   to = argv[1] ? argv[1] : from;
+ #endif
+ 
+   if ((fd = open (to, HOST_WRITE_MODE, 0666)) == -1)
+     {
+       printf_unfiltered ("Unable to open '%s': %s\n", to, strerror (errno));
+       return;
+     }
+ 
+   if (qnx_fileopen (from, QNX_READ_MODE, 0) == -1)
+     {
+       printf_unfiltered ("Remote was unable to open '%s': %s\n", from,
+ 			 strerror (errno));
+       close (fd);
+       return;
+     }
+ 
+   while ((len = qnx_fileread (buf, sizeof buf)) > 0)
+     {
+       if (write (fd, buf, len) == -1)
+ 	{
+ 	  printf_unfiltered ("Local write failed: %s\n", strerror (errno));
+ 	  close (fd);
+ 	  return;
+ 	}
+     }
+ 
+   if (len == -1)
+     printf_unfiltered ("Remote read failed: %s\n", strerror (errno));
+   qnx_fileclose (fd);
+   close (fd);
+ }
+ 
+ static void
+ qnx_add_commands ()
+ {
+   struct cmd_list_element *c;
+ 
+   c =
+     add_com ("upload", class_obscure, qnx_upload,
+ 	     "Send a file to the target (upload {local} [{remote}])");
+   c->completer = filename_completer;
+   add_com ("download", class_obscure, qnx_download,
+ 	   "Get a file from the target (download {remote} [{local}])");
+ }
+ 
+ static void
+ qnx_remove_commands ()
+ {
+   extern struct cmd_list_element *cmdlist;
+ 
+   delete_cmd ("upload", &cmdlist);
+   delete_cmd ("download", &cmdlist);
+ }
+ 
+ static int qnx_remote_fd = -1;
+ 
+ static int
+ qnx_fileopen (char *fname, int mode, int perms)
+ {
+   if (qnx_remote_fd != -1)
+     {
+       printf_unfiltered
+ 	("Remote file currently open, it must be closed before you can open another.\n");
+       errno = EAGAIN;
+       return -1;
+     }
+ 
+   qnx_send_init (DStMsg_fileopen, 0, SET_CHANNEL_DEBUG);
+   strcpy (tran.pkt.fileopen.pathname, fname);
+   tran.pkt.fileopen.mode = qnx_swap32 (mode);
+   tran.pkt.fileopen.perms = qnx_swap32 (perms);
+   qnx_send (sizeof tran.pkt.fileopen, 0);
+ 
+   if (recv.pkt.hdr.cmd == DSrMsg_err)
+     {
+       errno = qnx_swap32 (recv.pkt.err.err);
+       return -1;
+     }
+   return qnx_remote_fd = 0;
+ }
+ 
+ static void
+ qnx_fileclose (int fd)
+ {
+   if (qnx_remote_fd == -1)
+     return;
+ 
+   qnx_send_init (DStMsg_fileclose, 0, SET_CHANNEL_DEBUG);
+   tran.pkt.fileclose.mtime = 0;
+   qnx_send (sizeof tran.pkt.fileclose, 1);
+   qnx_remote_fd = -1;
+ }
+ 
+ static int
+ qnx_fileread (char *buf, int size)
+ {
+   int len;
+ 
+   qnx_send_init (DStMsg_filerd, 0, SET_CHANNEL_DEBUG);
+   tran.pkt.filerd.size = qnx_swap16 (size);
+   len = qnx_send (sizeof tran.pkt.filerd, 0);
+ 
+   if (recv.pkt.hdr.cmd == DSrMsg_err)
+     {
+       errno = recv.pkt.err.err;
+       return -1;
+     }
+ 
+   len -= sizeof recv.pkt.okdata.hdr;
+   memcpy (buf, recv.pkt.okdata.data, len);
+   return len;
+ }
+ 
+ static int
+ qnx_filewrite (char *buf, int size)
+ {
+   int len, siz;
+ 
+   for (siz = size; siz > 0; siz -= len, buf += len)
+     {
+       len =
+ 	siz < sizeof tran.pkt.filewr.data ? siz : sizeof tran.pkt.filewr.data;
+       qnx_send_init (DStMsg_filewr, 0, SET_CHANNEL_DEBUG);
+       memcpy (tran.pkt.filewr.data, buf, len);
+       qnx_send (sizeof (tran.pkt.filewr.hdr) + len, 0);
+ 
+       if (recv.pkt.hdr.cmd == DSrMsg_err)
+ 	{
+ 	  errno = recv.pkt.err.err;
+ 	  return size - siz;
+ 	}
+     }
+   return size;
+ }
+ 
+ static int
+ qnx_can_run (void)
+ {
+   return 0;
+ }
+ 
+ static void
+ init_qnx_ops ()
+ {
+   qnx_ops.to_shortname = "qnx";
+   qnx_ops.to_longname =
+     "Remote serial target using the QNX Debugging Protocol";
+   qnx_ops.to_doc =
+     "Debug a remote machine using the QNX Debugging Protocol.\n\
+ Specify the device it is connected to (e.g. /dev/ser1, <rmt_host>:<port>)\n\
+ or `pty' to launch `pdebug' for debugging.";
+   qnx_ops.to_open = qnx_open;
+   qnx_ops.to_close = qnx_close;
+   qnx_ops.to_attach = qnx_attach;
+   qnx_ops.to_detach = qnx_detach;
+   qnx_ops.to_resume = qnx_resume;
+   qnx_ops.to_wait = qnx_wait;
+   qnx_ops.to_fetch_registers = qnx_fetch_registers;
+   qnx_ops.to_store_registers = qnx_store_registers;
+   qnx_ops.to_prepare_to_store = qnx_prepare_to_store;
+   qnx_ops.to_xfer_memory = qnx_xfer_memory;
+   qnx_ops.to_files_info = qnx_files_info;
+   qnx_ops.to_insert_breakpoint = qnx_insert_breakpoint;
+   qnx_ops.to_remove_breakpoint = qnx_remove_breakpoint;
+   qnx_ops.to_kill = qnx_kill;
+   qnx_ops.to_load = generic_load;
+   qnx_ops.to_create_inferior = qnx_create;
+   qnx_ops.to_mourn_inferior = qnx_mourn;
+   qnx_ops.to_can_run = qnx_can_run;
+   qnx_ops.to_thread_alive = qnx_thread_alive;
+   qnx_ops.to_find_new_threads = qnx_find_new_threads;
+   qnx_ops.to_stop = 0;
+   // qnx_ops.to_query = qnx_query;
+   qnx_ops.to_stratum = process_stratum;
+   qnx_ops.to_has_all_memory = 1;
+   qnx_ops.to_has_memory = 1;
+   qnx_ops.to_has_stack = 0;	// 1;
+   qnx_ops.to_has_registers = 1;
+   qnx_ops.to_has_execution = 0;
+   qnx_ops.to_pid_to_str = qnx_pid_to_str;
+   // qnx_ops.to_has_thread_control = tc_schedlock; /* can lock scheduler */
+   qnx_ops.to_magic = OPS_MAGIC;
+ }
+ 
+ 
+ void
+ qnx_find_new_threads (void)
+ {
+   pid_t pid, start_tid, total_tid;
+   ptid_t ptid;
+   struct dspidlist *pidlist = (void *) recv.pkt.okdata.data;
+   struct tidinfo *tip;
+   char subcmd;
+ 
+   pid = ptid_get_pid (inferior_ptid);
+   start_tid = 1;
+   total_tid = 1;
+   subcmd = DSMSG_PIDLIST_SPECIFIC_TID;
+ 
+   do
+     {
+       tran.pkt.pidlist.tid = qnx_swap32 (start_tid);
+       qnx_send_init (DStMsg_pidlist, subcmd, SET_CHANNEL_DEBUG);
+       tran.pkt.pidlist.pid = qnx_swap32 (pid);
+       qnx_send (sizeof (tran.pkt.pidlist), 0);
+ 
+       if (recv.pkt.hdr.cmd == DSrMsg_err)
+ 	{
+ 	  if (subcmd == DSMSG_PIDLIST_SPECIFIC_TID)
+ 	    {
+ 	      subcmd = DSMSG_PIDLIST_SPECIFIC;
+ 	      start_tid = 0;
+ 	      tran.pkt.pidlist.tid = qnx_swap32 (start_tid);
+ 	      qnx_send_init (DStMsg_pidlist, subcmd, SET_CHANNEL_DEBUG);
+ 	      tran.pkt.pidlist.pid = qnx_swap32 (pid);
+ 	      qnx_send (sizeof (tran.pkt.pidlist), 1);	//no need to check error, as '1' means no return on error
+ 	    }
+ 	  else
+ 	    {
+ 	      errno = recv.pkt.err.err;
+ 	      return;
+ 	    }
+ 	}
+       if (nto_internal_debugging == 1)
+ 	{
+ 	  printf_unfiltered ("pid = %ld\n", qnx_swap32 (pidlist->pid));
+ 	  printf_unfiltered ("start tid = %ld, total tid = %ld\n",
+ 			     qnx_swap32 (start_tid),
+ 			     qnx_swap32 (pidlist->num_tids));
+ 	  printf_unfiltered ("name = %s\n", pidlist->name);
+ 	}
+ 
+       for (tip =
+ 	   (void *) &pidlist->name[(strlen (pidlist->name) + 1 + 3) & ~3];
+ 	   tip->tid != 0; tip++)
+ 	{
+ 	  total_tid++;
+ 	  ptid = ptid_build (pid, 0, qnx_swap16 (tip->tid));
+ 	  if (nto_internal_debugging == 1)
+ 	    {
+ 	      printf_unfiltered ("%s - %d/%d\n", pidlist->name, pid,
+ 				 qnx_swap16 (tip->tid));
+ 	    }
+ 	  if (!in_thread_list (ptid))
+ 	    add_thread (ptid);
+ 	}
+       start_tid = total_tid + 1;
+       if (nto_internal_debugging == 1)
+ 	{
+ 	  printf_unfiltered ("total_tids = %x, pidlist->num_tids = %lx\n",
+ 			     total_tid, qnx_swap32 (pidlist->num_tids));
+ 	}
+     }
+   while ((total_tid < qnx_swap32 (pidlist->num_tids))
+ 	 && (subcmd == DSMSG_PIDLIST_SPECIFIC_TID));
+ 
+   return;
+ }
+ 
+ 
+ void
+ qnx_pidlist (char *args, int from_tty)
+ {
+   struct dspidlist *pidlist = (void *) recv.pkt.okdata.data;
+   struct tidinfo *tip;
+   char specific_tid_supported = 0;
+   pid_t pid, start_tid, total_tid;
+   char subcmd;
+ 
+ #if defined(__QNXNTO__) && defined(__QNXNTO_USE_PROCFS__)
+   extern void procfs_pidlist (char *args, int from_tty);
+   if (qnx_desc == NULL)
+     return procfs_pidlist (args, from_tty);
+ #endif
+   start_tid = 1;
+   total_tid = 0;
+   pid = 1;
+   subcmd = DSMSG_PIDLIST_BEGIN;
+ 
+   //
+   // Send a DSMSG_PIDLIST_SPECIFIC_TID to see if it is supported
+   // 
+   qnx_send_init (DStMsg_pidlist, DSMSG_PIDLIST_SPECIFIC_TID,
+ 		 SET_CHANNEL_DEBUG);
+   tran.pkt.pidlist.pid = qnx_swap32 (pid);
+   tran.pkt.pidlist.tid = qnx_swap32 (start_tid);
+   qnx_send (sizeof (tran.pkt.pidlist), 0);
+ 
+   if (recv.pkt.hdr.cmd == DSrMsg_err)
+     specific_tid_supported = 0;
+   else
+     specific_tid_supported = 1;
+ 
+   while (1)
+     {
+       qnx_send_init (DStMsg_pidlist, subcmd, SET_CHANNEL_DEBUG);
+       tran.pkt.pidlist.pid = qnx_swap32 (pid);
+       tran.pkt.pidlist.tid = qnx_swap32 (start_tid);
+       qnx_send (sizeof (tran.pkt.pidlist), 0);
+       if (recv.pkt.hdr.cmd == DSrMsg_err)
+ 	{
+ 	  errno = qnx_swap32 (recv.pkt.err.err);
+ 	  return;
+ 	}
+       if (recv.pkt.hdr.cmd != DSrMsg_okdata)
+ 	{
+ 	  errno = EOK;
+ 	  return;
+ 	}
+ 
+       for (tip =
+ 	   (void *) &pidlist->name[(strlen (pidlist->name) + 1 + 3) & ~3];
+ 	   tip->tid != 0; tip++)
+ 	{
+ 	  printf_filtered ("%s - %ld/%d\n", pidlist->name,
+ 			   qnx_swap32 (pidlist->pid), qnx_swap16 (tip->tid));
+ 	  total_tid++;
+ 	}
+       pid = qnx_swap32 (pidlist->pid);
+       if (specific_tid_supported)
+ 	{
+ 	  if (total_tid < qnx_swap32 (pidlist->num_tids))
+ 	    {
+ 	      subcmd = DSMSG_PIDLIST_SPECIFIC_TID;
+ 	      start_tid = total_tid + 1;
+ 	      continue;
+ 	    }
+ 	}
+       start_tid = 1;
+       total_tid = 0;
+       subcmd = DSMSG_PIDLIST_NEXT;
+     }
+   return;
+ }
+ 
+ struct dsmapinfo *
+ qnx_mapinfo (unsigned addr, int first, int elfonly)
+ {
+   //struct dsmapinfo      *map = (void *)recv.pkt.okdata.data;
+   struct dsmapinfo map;
+   static struct dsmapinfo dmap;
+   DStMsg_mapinfo_t *mapinfo = (DStMsg_mapinfo_t *) & tran.pkt;
+   char subcmd;
+ 
+   if (core_bfd != NULL)
+     {				/* have to implement corefile mapinfo */
+       errno = EOK;
+       return NULL;
+     }
+ 
+   subcmd = addr ? DSMSG_MAPINFO_SPECIFIC :
+     first ? DSMSG_MAPINFO_BEGIN : DSMSG_MAPINFO_NEXT;
+   if (elfonly)
+     subcmd |= DSMSG_MAPINFO_ELF;
+ 
+   qnx_send_init (DStMsg_mapinfo, subcmd, SET_CHANNEL_DEBUG);
+   mapinfo->addr = qnx_swap32 (addr);
+   qnx_send (sizeof (*mapinfo), 0);
+   if (recv.pkt.hdr.cmd == DSrMsg_err)
+     {
+       errno = qnx_swap32 (recv.pkt.err.err);
+       return NULL;
+     }
+   if (recv.pkt.hdr.cmd != DSrMsg_okdata)
+     {
+       errno = EOK;
+       return NULL;
+     }
+ 
+   memset (&dmap, 0, sizeof (dmap));
+   memcpy (&map, &recv.pkt.okdata.data[0], sizeof (map));
+   dmap.ino = qnx_swap64 (map.ino);
+   dmap.dev = qnx_swap32 (map.dev);
+ 
+   dmap.text.addr = qnx_swap32 (map.text.addr);
+   dmap.text.size = qnx_swap32 (map.text.size);
+   dmap.text.flags = qnx_swap32 (map.text.flags);
+   dmap.text.debug_vaddr = qnx_swap32 (map.text.debug_vaddr);
+   dmap.text.offset = qnx_swap64 (map.text.offset);
+ 
+   dmap.data.addr = qnx_swap32 (map.data.addr);
+   dmap.data.size = qnx_swap32 (map.data.size);
+   dmap.data.flags = qnx_swap32 (map.data.flags);
+   dmap.data.debug_vaddr = qnx_swap32 (map.data.debug_vaddr);
+   dmap.data.offset = qnx_swap64 (map.data.offset);
+ 
+   strcpy (dmap.name, map.name);
+ 
+   return &dmap;
+ }
+ 
+ void
+ qnx_meminfo (char *args, int from_tty)
+ {
+   struct dsmapinfo *dmp;
+   int first = 1;
+ 
+ #if defined(__QNXNTO__) && defined(__QNXNTO_USE_PROCFS__)
+   extern void procfs_meminfo (char *args, int from_tty);
+   if (qnx_desc == NULL)
+     return procfs_meminfo (args, from_tty);
+ #endif
+ 
+   while ((dmp = qnx_mapinfo (0, first, 0)) != NULL)
+     {
+       first = 0;
+       printf_filtered ("%s\n", dmp->name);
+       printf_filtered ("\ttext=%08x bytes @ 0x%08x\n", dmp->text.size,
+ 		       dmp->text.addr);
+       printf_filtered ("\t\tflags=%08x\n", dmp->text.flags);
+       printf_filtered ("\t\tdebug=%08x\n", dmp->text.debug_vaddr);
+       printf_filtered ("\t\toffset=%016llx\n", dmp->text.offset);
+       if (dmp->data.size)
+ 	{
+ 	  printf_filtered ("\tdata=%08x bytes @ 0x%08x\n", dmp->data.size,
+ 			   dmp->data.addr);
+ 	  printf_filtered ("\t\tflags=%08x\n", dmp->data.flags);
+ 	  printf_filtered ("\t\tdebug=%08x\n", dmp->data.debug_vaddr);
+ 	  printf_filtered ("\t\toffset=%016llx\n", dmp->data.offset);
+ 	}
+       printf_filtered ("\tdev=0x%x\n", dmp->dev);
+       printf_filtered ("\tino=0x%llx\n", dmp->ino);
+     }
+ }
+ 
+ /*
+ 
+    GLOBAL FUNCTION
+ 
+    fetch_core_registers -- fetch current registers from core file
+ 
+    SYNOPSIS
+ 
+    void fetch_core_registers (char *core_reg_sect,
+    unsigned core_reg_size,
+    int which, CORE_ADDR reg_addr)
+ 
+    DESCRIPTION
+ 
+    Read the values of either the general register set (WHICH equals 0)
+    or the floating point register set (WHICH equals 2) from the core
+    file data (pointed to by CORE_REG_SECT), and update gdb's idea of
+    their current values.  The CORE_REG_SIZE parameter is ignored.
+ 
+    NOTES
+ 
+    Use the indicated sizes to validate the gregset and fpregset
+    structures.
+  */
+ 
+ extern void nto_supply_gregset PARAMS ((nto_gregset_t *));
+ extern void nto_supply_fpregset PARAMS ((nto_fpregset_t *));
+ void qnx_init_solib_search_path ();
+ 
+ static void
+ fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+      char *core_reg_sect;
+      unsigned core_reg_size;
+      int which;
+      CORE_ADDR reg_addr;	/* Unused in this version */
+ {
+   nto_gregset_t gregset;
+   nto_fpregset_t fpregset;
+ 
+   qnx_init_solib_search_path ();
+ 
+   if (which == 0)
+     {
+       memcpy ((char *) &gregset, core_reg_sect,
+ 	      min (core_reg_size, sizeof (gregset)));
+       nto_supply_gregset (&gregset);
+     }
+   else if (which == 2)
+     {
+       memcpy ((char *) &fpregset, core_reg_sect,
+ 	      min (core_reg_size, sizeof (fpregset)));
+       nto_supply_fpregset (&fpregset);
+     }
+ }
+ 
+ /* struct lm_info, LM_ADDR and qnx_truncate_ptr are copied from
+    solib-svr4.c to support qnx_relocate_section_addresses which is different
+    from the svr4 version. */
+ 
+ struct lm_info
+ {
+   /* Pointer to copy of link map from inferior.  The type is char *
+      rather than void *, so that we may use byte offsets to find the
+      various fields without the need for a cast.  */
+   char *lm;
+ };
+ 
+ static CORE_ADDR
+ LM_ADDR (struct so_list *so)
+ {
+   struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
+ 
+   return (CORE_ADDR) extract_signed_integer (so->lm_info->lm +
+ 					     lmo->l_addr_offset,
+ 					     lmo->l_addr_size);
+ }
+ 
+ static CORE_ADDR
+ qnx_truncate_ptr (CORE_ADDR addr)
+ {
+   if (TARGET_PTR_BIT == sizeof (CORE_ADDR) * 8)
+     /* We don't need to truncate anything, and the bit twiddling below
+        will fail due to overflow problems.  */
+     return addr;
+   else
+     return addr & (((CORE_ADDR) 1 << TARGET_PTR_BIT) - 1);
+ }
+ 
+ #include "elf-bfd.h"
+ Elf_Internal_Phdr *
+ find_load_phdr (bfd *abfd)
+ {
+   Elf_Internal_Phdr *phdr;
+   unsigned int i;
+ 
+   if (!elf_tdata (abfd))
+     return NULL;
+ 
+   phdr = elf_tdata (abfd)->phdr;
+   for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
+     {
+       if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
+ 	return phdr;
+     }
+   return NULL;
+ }
+ 
+ static void
+ qnx_relocate_section_addresses (struct so_list *so, struct section_table *sec)
+ {
+   /* On some platforms, (ie. QNXnto, NetBSD) LM_ADDR is the assigned
+      address, not the offset.
+      The addresses are formed as follows:
+      LM_ADDR is the target address where the shared library file
+      is mapped, so the actual section start address is LM_ADDR plus
+      the section offset within the shared library file.  The end
+      address is that plus the section length.  Note that we pay no
+      attention to the section start address as recorded in the
+      library header.
+    */
+   Elf_Internal_Phdr *phdr = find_load_phdr (sec->bfd);
+   unsigned vaddr = phdr ? phdr->p_vaddr : 0;
+ 
+   sec->addr = qnx_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
+   sec->endaddr = qnx_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
+ }
+ 
+ /* Register that we are able to handle ELF file formats using standard
+    procfs "regset" structures.  */
+ 
+ static struct core_fns regset_core_fns = {
+   bfd_target_elf_flavour,	/* core_flavour */
+   default_check_format,		/* check_format */
+   default_core_sniffer,		/* core_sniffer */
+   fetch_core_registers,		/* core_read_registers */
+   NULL				/* next */
+ };
+ 
+ void
+ _initialize_nto ()
+ {
+   int endian = 1;
+ #ifdef EXTRA_GDBINIT_FILENAME
+   char *homedir, *homeinit, *extra_gdbinit;
+   struct stat statbuf;
+ #endif
+ 
+   if (*(char *) &endian != 1)
+     host_endian = BFD_ENDIAN_BIG;
+   else
+     host_endian = BFD_ENDIAN_LITTLE;
+ 
+ #ifdef __QNXNTO__
+   munlockall ();
+ #endif
+ 
+   init_qnx_ops ();
+   add_target (&qnx_ops);
+   add_show_from_set (add_set_cmd ("qnxtimeout", no_class,
+ 				  var_integer, (char *) &qnx_timeout,
+ 				  "Set timeout value for remote read.\n",
+ 				  &setlist), &showlist);
+ 
+   add_show_from_set (add_set_cmd ("qnxinheritenv", no_class,
+ 				  var_boolean, (char *) &qnx_inherit_env,
+ 				  "Set where remote process inherits env from pdebug, or has it set by gdb\n",
+ 				  &setlist), &showlist);
+ 
+   add_show_from_set (add_set_cmd ("qnxremotecwd", class_support, var_string,
+ 				  (char *) &qnx_remote_cwd,
+ 				  "Set the working directory for the remote process",
+ 				  &setlist), &showlist);
+ 
+   add_show_from_set (add_set_cmd ("nto-debug", class_maintenance, var_zinteger, (char *) &nto_internal_debugging, "Set QNX NTO internal debugging.\n\
+ When non-zero, nto specific debug info is\n\
+ displayed. Different information is displayed\n\
+ for different positive values.", &setdebuglist),
+ 		     &showdebuglist);
+   add_info ("pidlist", qnx_pidlist, "pidlist");
+   add_info ("meminfo", qnx_meminfo, "memory information");
+ 
+   //
+   // We use SIG45 for pulses, or something, so nostop, noprint
+   // and pass them.
+   //
+   signal_stop_update (target_signal_from_name ("SIG45"), 0);
+   signal_print_update (target_signal_from_name ("SIG45"), 0);
+   signal_pass_update (target_signal_from_name ("SIG45"), 1);
+ 
+ #if defined(SIGSELECT)
+   /* by default we don't want to stop on these two, but we do want to pass */
+   signal_stop_update (SIGSELECT, 0);
+   signal_print_update (SIGSELECT, 0);
+   signal_pass_update (SIGSELECT, 1);
+ #endif
+ 
+ #if defined(SIGPHOTON)
+   signal_stop_update (SIGPHOTON, 0);
+   signal_print_update (SIGPHOTON, 0);
+   signal_pass_update (SIGPHOTON, 1);
+ #endif
+ 
+   /* register core file support */
+   add_core_fns (&regset_core_fns);
+ 
+   /* Our loader handles solib relocations slightly differently than svr4 */
+   current_target_so_ops->relocate_section_addresses =
+     qnx_relocate_section_addresses;
+ 
+ #ifdef EXTRA_GDBINIT_FILENAME
+   homedir = getenv ("HOME");
+   extra_gdbinit = EXTRA_GDBINIT_FILENAME;
+ 
+   if (homedir && !inhibit_gdbinit)
+     {
+       homeinit = (char *) alloca (strlen (homedir) +
+ 				  strlen (extra_gdbinit) + 10);
+       sprintf (homeinit, "%s/%s", homedir, extra_gdbinit);
+       if (stat (homeinit, &statbuf) == 0)
+ 	catch_command_errors (source_command, homeinit, 0, RETURN_MASK_ALL);
+     }
+ #endif
+ }
+ 
+ int
+ qnx_insert_hw_breakpoint (CORE_ADDR addr, char *contents_cache)
+ {
+   if (qnx_desc == NULL)
+     return -1;
+ 
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered
+ 	("qnx_insert_hw_breakpoint(addr %lx, contents_cache %p)\n", addr,
+ 	 contents_cache);
+     }
+ 
+   qnx_send_init (DStMsg_brk, DSMSG_BRK_EXEC | DSMSG_BRK_HW,
+ 		 SET_CHANNEL_DEBUG);
+   tran.pkt.brk.addr = qnx_swap32 (addr);
+   qnx_send (sizeof (tran.pkt.brk), 0);
+   return recv.pkt.hdr.cmd == DSrMsg_err;
+ }
+ 
+ int
+ qnx_remove_hw_breakpoint (CORE_ADDR addr, char *contents_cache)
+ {
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered
+ 	("qnx_remove_hw_breakpoint(addr %lx, contents_cache %p)\n", addr,
+ 	 contents_cache);
+     }
+ 
+   return qnx_remove_breakpoint (addr, contents_cache);
+ }
+ 
+ int
+ qnx_stopped_by_watchpoint (void)
+ {
+   return 0;
+ }
+ 
+ 
+ int
+ qnx_hw_watchpoint (addr, len, type)
+ {
+   unsigned subcmd;
+ 
+ #if defined(__QNXNTO__) && defined(__QNXNTO_USE_PROCFS__)
+   extern int procfs_hw_watchpoint (int, int, int);
+ 
+   if (qnx_desc == NULL)
+     {
+       return procfs_hw_watchpoint (addr, type, len);
+     }
+ #endif
+   if (nto_internal_debugging == 1)
+     {
+       printf_unfiltered ("qnx_hw_watchpoint(addr %x, len %x, type %x)\n",
+ 			 addr, len, type);
+     }
+ 
+   switch (type)
+     {
+     case 1:			/* Read */
+       subcmd = DSMSG_BRK_RD;
+       break;
+     case 2:			/* Read/Write */
+       subcmd = DSMSG_BRK_WR;
+       break;
+     default:			/* Modify */
+       subcmd = DSMSG_BRK_MODIFY;
+     }
+   subcmd |= DSMSG_BRK_HW;
+ 
+   qnx_send_init (DStMsg_brk, subcmd, SET_CHANNEL_DEBUG);
+   tran.pkt.brk.addr = qnx_swap32 (addr);
+   tran.pkt.brk.size = qnx_swap32 (len);
+   qnx_send (sizeof (tran.pkt.brk), 0);
+   return recv.pkt.hdr.cmd == DSrMsg_err ? -1 : 0;
+ }
+ 
+ int
+ qnx_remove_hw_watchpoint (addr, len, type)
+ {
+   return qnx_hw_watchpoint (addr, -1, type);
+ }
+ 
+ int
+ qnx_insert_hw_watchpoint (addr, len, type)
+ {
+   return qnx_hw_watchpoint (addr, len, type);
+ }
+ 
+ char **
+ qnx_parse_redirection (char *pargv[], char **pin, char **pout, char **perr)
+ {
+   char **argv;
+   char *in, *out, *err, *p;
+   int argc, i, n;
+ 
+   for (n = 0; pargv[n]; n++);
+   if (n == 0)
+     return NULL;
+   in = "";
+   out = "";
+   err = "";
+ 
+   argv = xcalloc (n + 1, sizeof argv[0]);
+   argc = n;
+   for (i = 0, n = 0; n < argc; n++)
+     {
+       p = pargv[n];
+       if (*p == '>')
+ 	{
+ 	  p++;
+ 	  if (*p)
+ 	    out = p;
+ 	  else
+ 	    out = pargv[++n];
+ 	}
+       else if (*p == '<')
+ 	{
+ 	  p++;
+ 	  if (*p)
+ 	    in = p;
+ 	  else
+ 	    in = pargv[++n];
+ 	}
+       else if (*p++ == '2' && *p++ == '>')
+ 	{
+ 	  if (*p == '&' && *(p + 1) == '1')
+ 	    err = out;
+ 	  else if (*p)
+ 	    err = p;
+ 	  else
+ 	    err = pargv[++n];
+ 	}
+       else
+ 	argv[i++] = pargv[n];
+     }
+   *pin = in;
+   *pout = out;
+   *perr = err;
+   return argv;
+ }
+ 
+ struct tidinfo *
+ qnx_thread_info (pid_t pid, short tid)
+ {
+   struct dspidlist *pidlist = (void *) recv.pkt.okdata.data;
+   struct tidinfo *tip;
+ 
+   tran.pkt.pidlist.tid = tid;
+   qnx_send_init (DStMsg_pidlist, DSMSG_PIDLIST_SPECIFIC_TID,
+ 		 SET_CHANNEL_DEBUG);
+   tran.pkt.pidlist.pid = qnx_swap32 (pid);
+   qnx_send (sizeof (tran.pkt.pidlist), 0);
+ 
+   if (recv.pkt.hdr.cmd == DSrMsg_err)
+     {
+       qnx_send_init (DStMsg_pidlist, DSMSG_PIDLIST_SPECIFIC,
+ 		     SET_CHANNEL_DEBUG);
+       tran.pkt.pidlist.pid = qnx_swap32 (pid);
+       qnx_send (sizeof (tran.pkt.pidlist), 1);
+       if (recv.pkt.hdr.cmd == DSrMsg_err)
+ 	{
+ 	  errno = recv.pkt.err.err;
+ 	  return NULL;
+ 	}
+     }
+ 
+   for (tip = (void *) &pidlist->name[(strlen (pidlist->name) + 1 + 3) & ~3];
+        tip->tid != 0; tip++)
+     {
+       if (tid == qnx_swap16 (tip->tid))
+ 	return tip;
+     }
+ 
+   return NULL;
+ }
+ 
+ char *
+ qnx_pid_to_str (ptid_t ptid)
+ {
+   static char buf[1024];
+   int pid, tid, n;
+   struct tidinfo *tip;
+ 
+   pid = ptid_get_pid (ptid);	// returns pid if listed, else returns ptid
+   tid = ptid_get_tid (ptid);	// returns tid if listed, else 0
+ 
+   n = sprintf (buf, "process %d", pid);
+ 
+   tip = qnx_thread_info (pid, tid);
+   if (tip != NULL)
+     sprintf (&buf[n], " (state = 0x%02x)", tip->state);
+ 
+   return buf;
+ }
+ 
+ void
+ qnx_supply_register (unsigned first, unsigned last, char *regp)
+ {
+   unsigned end, off, len;
+   unsigned char notused;
+ 
+   while (first <= last)
+     {
+       end = qnx_cpu_register_area (first, last, &notused, &off, &len);
+       if (len > 0)
+ 	qnx_cpu_register_fetch ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG), first,
+ 				end, regp + off);
+       else
+ 	qnx_cpu_register_fetch ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG), first,
+ 				end, NULL);
+       first = end + 1;
+     }
+ }
+ 
+ CORE_ADDR
+ qnx_getbase (void)
+ {
+   unsigned long long base_address;
+ #if defined(__QNXNTO__) && defined(__QNXNTO_USE_PROCFS__)
+   extern int procfs_getbase (void);
+ 
+   if (qnx_desc == NULL)
+     {
+       return procfs_getbase ();
+     }
+ #endif
+ 
+   qnx_send_init (DStMsg_base_address, 0, SET_CHANNEL_DEBUG);
+   qnx_send (sizeof (tran.pkt.baseaddr), 0);
+ 
+   if (recv.pkt.hdr.cmd == DSrMsg_err)
+     {
+       errno = recv.pkt.err.err;
+       return -1;
+     }
+   memcpy (&base_address, &recv.pkt.okdata.data[0], sizeof (base_address));
+   if (base_address == 0)
+     return (CORE_ADDR) -1;
+   return (CORE_ADDR) qnx_swap64 (base_address);
+ }
+ 
+ #define IO_PORT_HACKS
+ #ifdef IO_PORT_HACKS
+ static int
+ qnx_read_ioport (long long addr, short len, void *dst)
+ {
+   qnx_send_init (DStMsg_memrd, DSMSG_MEM_IO, SET_CHANNEL_DEBUG);
+   tran.pkt.memrd.addr = qnx_swap64 (addr);
+   tran.pkt.memrd.size = qnx_swap16 (len);
+   len = qnx_send (sizeof (tran.pkt.memrd), 0) - sizeof (recv.pkt.hdr);
+ 
+   if (recv.pkt.hdr.cmd == DSrMsg_okdata)
+     {
+       memcpy (dst, recv.pkt.okdata.data, len);
+       return 0;
+     }
+   errno = recv.pkt.err.err;
+   printf ("error reading ioport %#llx: %s\n", addr, strerror (errno));
+   return -1;
+ }
+ 
+ void
+ qnx_read_ioport_8 (char *args, int from_tty)
+ {
+   unsigned char data;
+   long long addr;
+ 
+   addr = strtol (args, NULL, 0);
+   if (qnx_read_ioport (addr, 1, (void *) &data) == 0)
+     {
+       printf ("ioport @ %#llx: ", addr);
+       printf ("0x%02x\n", (int) data);
+     }
+ }
+ 
+ void
+ qnx_read_ioport_16 (char *args, int from_tty)
+ {
+   unsigned short data;
+   long long addr;
+ 
+   addr = strtol (args, NULL, 0);
+   if (qnx_read_ioport (addr, 2, (void *) &data) == 0)
+     {
+       printf ("ioport @ %#llx: ", addr);
+       printf ("0x%04x\n", (int) data);
+     }
+ }
+ 
+ void
+ qnx_read_ioport_32 (char *args, int from_tty)
+ {
+   unsigned int data;
+   long long addr;
+ 
+   addr = strtol (args, NULL, 0);
+   if (qnx_read_ioport (addr, 4, (void *) &data) == 0)
+     {
+       printf ("ioport @ %#llx: ", addr);
+       printf ("0x%08x\n", (int) data);
+     }
+ }
+ 
+ static int
+ qnx_write_ioport (long long addr, short len, void *src)
+ {
+   int i;
+ 
+   qnx_send_init (DStMsg_memwr, DSMSG_MEM_IO, SET_CHANNEL_DEBUG);
+   tran.pkt.memwr.addr = qnx_swap64 (addr);
+   printf ("iowrite to %#llx: ", addr);
+   memcpy (tran.pkt.memwr.data, src, len);
+ 
+   for (i = 0; i < len; i++)
+     printf ("%02x ", tran.pkt.memwr.data[i]);
+   printf ("\n");
+ 
+   qnx_send (offsetof (DStMsg_memwr_t, data) + len, 0);
+ 
+   if (recv.pkt.hdr.cmd != DSrMsg_err)
+     {
+       return 0;
+     }
+   errno = recv.pkt.err.err;
+   printf_filtered ("error writing to ioport %#llx: %s\n", addr,
+ 		   strerror (errno));
+   return -1;
+ }
+ 
+ void
+ qnx_write_ioport_8 (char *args, int from_tty)
+ {
+   unsigned char data = 0;
+   long long addr = 0;
+   char *p;
+ 
+   p = strtok (args, " ,\t");
+   if (p != NULL)
+     addr = strtol (p, NULL, 0);
+   p = strtok (NULL, " ,\t");
+   if (p != NULL)
+     data = (unsigned char) strtol (p, NULL, 0);
+   qnx_write_ioport (addr, 1, (void *) &data);
+ }
+ 
+ void
+ qnx_write_ioport_16 (char *args, int from_tty)
+ {
+   unsigned char data = 0;
+   long long addr = 0;
+   char *p;
+ 
+   p = strtok (args, " ,\t");
+   if (p != NULL)
+     addr = strtol (p, NULL, 0);
+   p = strtok (NULL, " ,\t");
+   if (p != NULL)
+     data = (unsigned char) strtol (p, NULL, 0);
+   qnx_write_ioport (addr, 1, (void *) &data);
+ }
+ 
+ void
+ qnx_write_ioport_32 (char *args, int from_tty)
+ {
+   unsigned char data = 0;
+   long long addr = 0;
+   char *p;
+ 
+   p = strtok (args, " ,\t");
+   if (p != NULL)
+     addr = strtol (p, NULL, 0);
+   p = strtok (NULL, " ,\t");
+   if (p != NULL)
+     data = (unsigned char) strtol (p, NULL, 0);
+   qnx_write_ioport (addr, 1, (void *) &data);
+ }
+ #endif
+ 
+ #ifndef __QNXNTO__
+ 
+ #define QNXSIGHUP      1	/* hangup */
+ #define QNXSIGINT      2	/* interrupt */
+ #define QNXSIGQUIT     3	/* quit */
+ #define QNXSIGILL      4	/* illegal instruction (not reset when caught) */
+ #define QNXSIGTRAP     5	/* trace trap (not reset when caught) */
+ #define QNXSIGIOT      6	/* IOT instruction */
+ #define QNXSIGABRT     6	/* used by abort */
+ #define QNXSIGEMT      7	/* EMT instruction */
+ #define QNXSIGDEADLK   7	/* Mutex deadlock */
+ #define QNXSIGFPE      8	/* floating point exception */
+ #define QNXSIGKILL     9	/* kill (cannot be caught or ignored) */
+ #define QNXSIGBUS      10	/* bus error */
+ #define QNXSIGSEGV     11	/* segmentation violation */
+ #define QNXSIGSYS      12	/* bad argument to system call */
+ #define QNXSIGPIPE     13	/* write on pipe with no reader */
+ #define QNXSIGALRM     14	/* real-time alarm clock */
+ #define QNXSIGTERM     15	/* software termination signal from kill */
+ #define QNXSIGUSR1     16	/* user defined signal 1 */
+ #define QNXSIGUSR2     17	/* user defined signal 2 */
+ #define QNXSIGCHLD     18	/* death of child */
+ #define QNXSIGPWR      19	/* power-fail restart */
+ #define QNXSIGWINCH    20	/* window change */
+ #define QNXSIGURG      21	/* urgent condition on I/O channel */
+ #define QNXSIGPOLL     22	/* System V name for QNXSIGIO */
+ #define QNXSIGIO       QNXSIGPOLL
+ #define QNXSIGSTOP     23	/* sendable stop signal not from tty */
+ #define QNXSIGTSTP     24	/* stop signal from tty */
+ #define QNXSIGCONT     25	/* continue a stopped process */
+ #define QNXSIGTTIN     26	/* attempted background tty read */
+ #define QNXSIGTTOU     27	/* attempted background tty write */
+ #define QNXSIGVTALRM   28	/* virtual timer expired */
+ #define QNXSIGPROF     29	/* profileing timer expired */
+ #define QNXSIGXCPU     30	/* exceded cpu limit */
+ #define QNXSIGXFSZ     31	/* exceded file size limit */
+ 
+ #endif
+ 
+ /* Convert qnx signal to gdb signal.  */
+ enum target_signal
+ target_signal_from_qnx (sig)
+      int sig;
+ {
+ #ifndef __QNXNTO__
+   switch (sig)
+     {
+     case 0:
+       return 0;
+       break;
+     case QNXSIGHUP:
+       return TARGET_SIGNAL_HUP;
+       break;
+     case QNXSIGINT:
+       return TARGET_SIGNAL_INT;
+       break;
+     case QNXSIGQUIT:
+       return TARGET_SIGNAL_QUIT;
+       break;
+     case QNXSIGILL:
+       return TARGET_SIGNAL_ILL;
+       break;
+     case QNXSIGTRAP:
+       return TARGET_SIGNAL_TRAP;
+       break;
+     case QNXSIGABRT:
+       return TARGET_SIGNAL_ABRT;
+       break;
+     case QNXSIGEMT:
+       return TARGET_SIGNAL_EMT;
+       break;
+     case QNXSIGFPE:
+       return TARGET_SIGNAL_FPE;
+       break;
+     case QNXSIGKILL:
+       return TARGET_SIGNAL_KILL;
+       break;
+     case QNXSIGBUS:
+       return TARGET_SIGNAL_BUS;
+       break;
+     case QNXSIGSEGV:
+       return TARGET_SIGNAL_SEGV;
+       break;
+     case QNXSIGSYS:
+       return TARGET_SIGNAL_SYS;
+       break;
+     case QNXSIGPIPE:
+       return TARGET_SIGNAL_PIPE;
+       break;
+     case QNXSIGALRM:
+       return TARGET_SIGNAL_ALRM;
+       break;
+     case QNXSIGTERM:
+       return TARGET_SIGNAL_TERM;
+       break;
+     case QNXSIGUSR1:
+       return TARGET_SIGNAL_USR1;
+       break;
+     case QNXSIGUSR2:
+       return TARGET_SIGNAL_USR2;
+       break;
+     case QNXSIGCHLD:
+       return TARGET_SIGNAL_CHLD;
+       break;
+     case QNXSIGPWR:
+       return TARGET_SIGNAL_PWR;
+       break;
+     case QNXSIGWINCH:
+       return TARGET_SIGNAL_WINCH;
+       break;
+     case QNXSIGURG:
+       return TARGET_SIGNAL_URG;
+       break;
+     case QNXSIGPOLL:
+       return TARGET_SIGNAL_POLL;
+       break;
+ //      case QNXSIGIO: return TARGET_SIGNAL_IO; break;
+     case QNXSIGSTOP:
+       return TARGET_SIGNAL_STOP;
+       break;
+     case QNXSIGTSTP:
+       return TARGET_SIGNAL_TSTP;
+       break;
+     case QNXSIGCONT:
+       return TARGET_SIGNAL_CONT;
+       break;
+     case QNXSIGTTIN:
+       return TARGET_SIGNAL_TTIN;
+       break;
+     case QNXSIGTTOU:
+       return TARGET_SIGNAL_TTOU;
+       break;
+     case QNXSIGVTALRM:
+       return TARGET_SIGNAL_VTALRM;
+       break;
+     case QNXSIGPROF:
+       return TARGET_SIGNAL_PROF;
+       break;
+     case QNXSIGXCPU:
+       return TARGET_SIGNAL_XCPU;
+       break;
+     case QNXSIGXFSZ:
+       return TARGET_SIGNAL_XFSZ;
+       break;
+     default:
+       break;
+     }
+ #endif /* __QNXNTO__ */
+   return target_signal_from_host (sig);
+ }
+ 
+ 
+ /* Convert gdb signal to qnx signal.  */
+ enum target_signal
+ target_signal_to_qnx (sig)
+      int sig;
+ {
+ #ifndef __QNXNTO__
+   switch (sig)
+     {
+     case 0:
+       return 0;
+       break;
+     case TARGET_SIGNAL_HUP:
+       return QNXSIGHUP;
+       break;
+     case TARGET_SIGNAL_INT:
+       return QNXSIGINT;
+       break;
+     case TARGET_SIGNAL_QUIT:
+       return QNXSIGQUIT;
+       break;
+     case TARGET_SIGNAL_ILL:
+       return QNXSIGILL;
+       break;
+     case TARGET_SIGNAL_TRAP:
+       return QNXSIGTRAP;
+       break;
+     case TARGET_SIGNAL_ABRT:
+       return QNXSIGABRT;
+       break;
+     case TARGET_SIGNAL_EMT:
+       return QNXSIGEMT;
+       break;
+     case TARGET_SIGNAL_FPE:
+       return QNXSIGFPE;
+       break;
+     case TARGET_SIGNAL_KILL:
+       return QNXSIGKILL;
+       break;
+     case TARGET_SIGNAL_BUS:
+       return QNXSIGBUS;
+       break;
+     case TARGET_SIGNAL_SEGV:
+       return QNXSIGSEGV;
+       break;
+     case TARGET_SIGNAL_SYS:
+       return QNXSIGSYS;
+       break;
+     case TARGET_SIGNAL_PIPE:
+       return QNXSIGPIPE;
+       break;
+     case TARGET_SIGNAL_ALRM:
+       return QNXSIGALRM;
+       break;
+     case TARGET_SIGNAL_TERM:
+       return QNXSIGTERM;
+       break;
+     case TARGET_SIGNAL_USR1:
+       return QNXSIGUSR1;
+       break;
+     case TARGET_SIGNAL_USR2:
+       return QNXSIGUSR2;
+       break;
+     case TARGET_SIGNAL_CHLD:
+       return QNXSIGCHLD;
+       break;
+     case TARGET_SIGNAL_PWR:
+       return QNXSIGPWR;
+       break;
+     case TARGET_SIGNAL_WINCH:
+       return QNXSIGWINCH;
+       break;
+     case TARGET_SIGNAL_URG:
+       return QNXSIGURG;
+       break;
+     case TARGET_SIGNAL_IO:
+       return QNXSIGIO;
+       break;
+     case TARGET_SIGNAL_POLL:
+       return QNXSIGPOLL;
+       break;
+     case TARGET_SIGNAL_STOP:
+       return QNXSIGSTOP;
+       break;
+     case TARGET_SIGNAL_TSTP:
+       return QNXSIGTSTP;
+       break;
+     case TARGET_SIGNAL_CONT:
+       return QNXSIGCONT;
+       break;
+     case TARGET_SIGNAL_TTIN:
+       return QNXSIGTTIN;
+       break;
+     case TARGET_SIGNAL_TTOU:
+       return QNXSIGTTOU;
+       break;
+     case TARGET_SIGNAL_VTALRM:
+       return QNXSIGVTALRM;
+       break;
+     case TARGET_SIGNAL_PROF:
+       return QNXSIGPROF;
+       break;
+     case TARGET_SIGNAL_XCPU:
+       return QNXSIGXCPU;
+       break;
+     case TARGET_SIGNAL_XFSZ:
+       return QNXSIGXFSZ;
+       break;
+     default:
+       break;
+     }
+ #endif /* __QNXNTO__ */
+   return target_signal_to_host (sig);
+ }
+ 
+ #ifdef __CYGWIN__
+ char default_qnx_target[] = "C:\\QNXsdk\\target\\qnx6";
+ #elif defined(__QNX__) && !defined(__QNXNTO__)
+ char default_qnx_target[] = "/usr/nto";
+ #elif defined(__sun__) || defined(linux)
+ char default_qnx_target[] = "/opt/QNXsdk/target/qnx6";
+ #else
+ char default_qnx_target[] = "";
+ #endif
+ 
+ char *
+ qnx_target (void)
+ {
+   char *p = getenv ("QNX_TARGET");
+ 
+ #ifdef __CYGWIN__
+   static char buf[PATH_MAX];
+   if (p)
+     cygwin_conv_to_posix_path (p, buf);
+   else
+     cygwin_conv_to_posix_path (default_qnx_target, buf);
+   return buf;
+ #else
+   return p ? p : default_qnx_target;
+ #endif
+ }
+ 
+ int
+ proc_iterate_over_mappings (int (*func) (int, CORE_ADDR))
+ {
+   struct dsmapinfo *lm;
+   char *tmp_pathname;
+   int fd;
+ 
+   lm = qnx_mapinfo (0, 1, 1);
+   while (lm != NULL)
+     {
+       if ((fd = solib_open (lm->name, &tmp_pathname)) != -1)
+ 	{
+ 	  func (fd, lm->text.addr);
+ 	  if (tmp_pathname)
+ 	    xfree (tmp_pathname);
+ 	}
+       lm = qnx_mapinfo (0, 0, 1);
+     }
+   return 0;
+ }
+ 
+ void
+ qnx_init_solib_search_path (void)
+ {
+   char tmp[_POSIX_PATH_MAX * 2];
+   char *nto_root;
+   char *solib_search_path, *cmd_name = "solib-search-path";
+   struct cmd_list_element *c;
+ 
+   c = lookup_cmd (&cmd_name, setlist, "", 1, 1);
+ 
+   if (!c || !c->var)
+     return;
+ 
+   solib_search_path = *((char **) c->var);
+ 
+   if (solib_search_path != NULL)
+     return;
+   nto_root = qnx_target ();
+ 
+ #ifdef TARGET_BYTE_ORDER_SELECTABLE
+ #if defined(SOLIB_PROCESSOR_BE) && defined(SOLIB_PROCESSOR_LE)
+   sprintf (tmp, "set solib-absolute-prefix %s/%s",
+ 	   nto_root,
+ 	   (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) ?
+ 	   SOLIB_PROCESSOR_BE : SOLIB_PROCESSOR_LE);
+   execute_command (tmp, 0);
+   sprintf (tmp,
+ 	   "set solib-search-path %s/%s/lib:%s/%s/usr/lib:%s/%s/usr/photon/lib:%s/%s/usr/photon/dll:%s/%s/lib/dll",
+ 	   nto_root,
+ 	   (TARGET_BYTE_ORDER ==
+ 	    BFD_ENDIAN_BIG) ? SOLIB_PROCESSOR_BE : SOLIB_PROCESSOR_LE,
+ 	   nto_root,
+ 	   (TARGET_BYTE_ORDER ==
+ 	    BFD_ENDIAN_BIG) ? SOLIB_PROCESSOR_BE : SOLIB_PROCESSOR_LE,
+ 	   nto_root,
+ 	   (TARGET_BYTE_ORDER ==
+ 	    BFD_ENDIAN_BIG) ? SOLIB_PROCESSOR_BE : SOLIB_PROCESSOR_LE,
+ 	   nto_root,
+ 	   (TARGET_BYTE_ORDER ==
+ 	    BFD_ENDIAN_BIG) ? SOLIB_PROCESSOR_BE : SOLIB_PROCESSOR_LE,
+ 	   nto_root,
+ 	   (TARGET_BYTE_ORDER ==
+ 	    BFD_ENDIAN_BIG) ? SOLIB_PROCESSOR_BE : SOLIB_PROCESSOR_LE);
+   execute_command (tmp, 0);
+ #endif
+ #else
+ #if defined(SOLIB_PROCESSOR)
+   sprintf (tmp, "set solib-absolute-prefix %s/%s", nto_root, SOLIB_PROCESSOR);
+   execute_command (tmp, 0);
+   sprintf (tmp,
+ 	   "set solib-search-path %s/%s/lib:%s/%s/usr/lib:%s/%s/usr/photon/lib:%s/%s/usr/photon/dll:%s/%s/lib/dll",
+ 	   nto_root, SOLIB_PROCESSOR, nto_root, SOLIB_PROCESSOR, nto_root,
+ 	   SOLIB_PROCESSOR, nto_root, SOLIB_PROCESSOR, nto_root,
+ 	   SOLIB_PROCESSOR);
+   execute_command (tmp, 0);
+ #endif
+ #endif
+ }
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/ser-ntopty.c src/gdb/ser-ntopty.c
*** src.orig/gdb/ser-ntopty.c	Wed Dec 31 19:00:00 1969
--- src/gdb/ser-ntopty.c	Mon Feb  3 13:43:00 2003
***************
*** 0 ****
--- 1,803 ----
+ #undef GKM_DEBUG
+ 
+ #include <string.h>
+ #include "defs.h"
+ #include "serial.h"
+ #include "command.h"
+ #include "gdbcmd.h"
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <signal.h>
+ #include "terminal.h"
+ #ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+ #endif
+ #ifdef __QNXTARGET__
+ #include "nto-share/dsmsgs.h"	/* This is for TS_TEXT_MAX_SIZE  */
+ #define re_comp ignore_re_comp	// Use the one in defs.h...
+ #include <unix.h>
+ #undef re_comp
+ #endif
+ 
+ #ifndef PATH_MAX
+ #define PATH_MAX 255
+ #endif
+ 
+ #include <sys/time.h>
+ 
+ #ifdef HAVE_TERMIOS
+ 
+ struct ntopty_ttystate
+ {
+   struct termios termios;
+ };
+ #endif /* termios */
+ 
+ #ifdef HAVE_TERMIO
+ 
+ /* It is believed that all systems which have added job control to SVR3
+    (e.g. sco) have also added termios.  Even if not, trying to figure out
+    all the variations (TIOCGPGRP vs. TCGETPGRP, etc.) would be pretty
+    bewildering.  So we don't attempt it.  */
+ 
+ struct ntopty_ttystate
+ {
+   struct termio termio;
+ };
+ #endif /* termio */
+ 
+ #ifdef HAVE_SGTTY
+ /* Needed for the code which uses select().  We would include <sys/select.h>
+    too if it existed on all systems.  */
+ #include <sys/time.h>
+ 
+ struct ntopty_ttystate
+ {
+   struct sgttyb sgttyb;
+   struct tchars tc;
+   struct ltchars ltc;
+   /* Line discipline flags.  */
+   int lmode;
+ };
+ #endif /* sgtty */
+ 
+ static int ntopty_open PARAMS ((struct serial * scb, const char *name));
+ static void ntopty_raw PARAMS ((struct serial * scb));
+ static int wait_for PARAMS ((struct serial * scb, int timeout));
+ static int ntopty_readchar PARAMS ((struct serial * scb, int timeout));
+ static int ntopty_setbaudrate PARAMS ((struct serial * scb, int rate));
+ static int ntopty_write
+ PARAMS ((struct serial * scb, const char *str, int len));
+ /* FIXME: static void ntopty_restore PARAMS ((struct serial *scb)); */
+ static void ntopty_close PARAMS ((struct serial * scb));
+ static int get_tty_state
+ PARAMS ((struct serial * scb, struct ntopty_ttystate * state));
+ static int set_tty_state
+ PARAMS ((struct serial * scb, struct ntopty_ttystate * state));
+ static serial_ttystate ntopty_get_tty_state PARAMS ((struct serial * scb));
+ static int ntopty_set_tty_state
+ PARAMS ((struct serial * scb, serial_ttystate state));
+ extern void qnx_outgoing_text (char *buf, int nbytes);
+ 
+ static char *ntoserver = NULL;
+ static char *ntoserverdev = NULL;
+ static pid_t ntopid = -1;
+ static int nto_ptydelay = 1;
+ 
+ 
+ /* 
+  * Open up a pty/tty pair for IPC with the ntoserver (pdebug). 
+  * We open both master and slave, fork, close the slave
+  * in the child and dup2 stdin/out/err to the master.  We close 
+  * the master in the parent, leaving the slave tty fd in the scb.  
+  * This means pdebug has to use stdio, NOT the tty device, so we 
+  * launch it now with "pdebug -", meaning "use stdio" as opposed
+  * to "pdebug /dev/ptyNM".
+  */
+ 
+ static int
+ ntopty_open (scb, name)
+      struct serial *scb;
+      const char *name;
+ {
+   char pty[PATH_MAX];
+   char *p;
+   int master;
+ 
+   if (openpty (&master, &scb->fd, &pty[0], 0, 0) == -1)
+     {
+       printf_unfiltered ("openpty() failed: %s\n", strerror (errno));
+       return -1;
+     }
+ 
+   p = strstr (pty, "tty");
+   *p = 'p';
+   printf_unfiltered ("Launching on pty %s\n", pty);
+ 
+   ntopid = fork ();
+ 
+   if (ntopid == -1)
+     {
+       printf_unfiltered ("fork() failed: %s\n", strerror (errno));
+       return -1;
+     }
+ 
+   else if (ntopid == 0)
+     {				/* child */
+       sigset_t set;
+ 
+       sigemptyset (&set);
+       sigaddset (&set, SIGUSR1);
+       sigprocmask (SIG_UNBLOCK, &set, NULL);
+ 
+       setsid ();
+ 
+       close (scb->fd);		/* all done with slave in child */
+ 
+       /* master becomes stdin/stdout/stderr of child */
+       if (dup2 (master, STDIN_FILENO) != STDIN_FILENO)
+ 	{
+ 	  printf_unfiltered ("dup2 of stdin failed.\n");
+ 	  close (master);
+ 	  exit (0);
+ 	}
+       if (dup2 (master, STDOUT_FILENO) != STDOUT_FILENO)
+ 	{
+ 	  printf_unfiltered ("dup2 of stdout failed.\n");
+ 	  close (master);
+ 	  exit (0);
+ 	}
+       if (dup2 (master, STDERR_FILENO) != STDERR_FILENO)
+ 	{
+ 	  printf_unfiltered ("dup2 of stderr failed.\n");
+ 	  close (master);
+ 	  exit (0);
+ 	}
+ 
+       /* Launch the ntoserver, which in this case has to be "pdebug -". */
+       execlp (ntoserver, ntoserver, ntoserverdev, 0);
+ 
+       printf_unfiltered ("execlp(%s) failed: %s\n", ntoserver,
+ 			 strerror (errno));
+       close (master);
+       exit (1);
+     }
+   close (master);
+   printf_unfiltered ("Debug server launched.\n");
+   sleep (nto_ptydelay);		// wait for a while for the server, pdebug.
+   return 0;
+ }
+ 
+ static int
+ get_tty_state (scb, state)
+      struct serial *scb;
+      struct ntopty_ttystate *state;
+ {
+ #ifdef HAVE_TERMIOS
+   extern int errno;
+ 
+   if (tcgetattr (scb->fd, &state->termios) < 0)
+     return -1;
+ 
+   return 0;
+ #endif
+ 
+ #ifdef HAVE_TERMIO
+   if (ioctl (scb->fd, TCGETA, &state->termio) < 0)
+     return -1;
+   return 0;
+ #endif
+ 
+ #ifdef HAVE_SGTTY
+   if (ioctl (scb->fd, TIOCGETP, &state->sgttyb) < 0)
+     return -1;
+   if (ioctl (scb->fd, TIOCGETC, &state->tc) < 0)
+     return -1;
+   if (ioctl (scb->fd, TIOCGLTC, &state->ltc) < 0)
+     return -1;
+   if (ioctl (scb->fd, TIOCLGET, &state->lmode) < 0)
+     return -1;
+ 
+   return 0;
+ #endif
+ }
+ 
+ static int
+ set_tty_state (scb, state)
+      struct serial *scb;
+      struct ntopty_ttystate *state;
+ {
+ #ifdef HAVE_TERMIOS
+   if (tcsetattr (scb->fd, TCSANOW, &state->termios) < 0)
+     return -1;
+ 
+   return 0;
+ #endif
+ 
+ #ifdef HAVE_TERMIO
+   if (ioctl (scb->fd, TCSETA, &state->termio) < 0)
+     return -1;
+   return 0;
+ #endif
+ 
+ #ifdef HAVE_SGTTY
+   if (ioctl (scb->fd, TIOCSETN, &state->sgttyb) < 0)
+     return -1;
+   if (ioctl (scb->fd, TIOCSETC, &state->tc) < 0)
+     return -1;
+   if (ioctl (scb->fd, TIOCSLTC, &state->ltc) < 0)
+     return -1;
+   if (ioctl (scb->fd, TIOCLSET, &state->lmode) < 0)
+     return -1;
+ 
+   return 0;
+ #endif
+ }
+ 
+ static serial_ttystate
+ ntopty_get_tty_state (scb)
+      struct serial *scb;
+ {
+   struct ntopty_ttystate *state;
+ 
+   state = (struct ntopty_ttystate *) xmalloc (sizeof *state);
+ 
+   if (get_tty_state (scb, state))
+     return NULL;
+ 
+   return (serial_ttystate) state;
+ }
+ 
+ static int
+ ntopty_set_tty_state (scb, ttystate)
+      struct serial *scb;
+      serial_ttystate ttystate;
+ {
+   struct ntopty_ttystate *state;
+ 
+   state = (struct ntopty_ttystate *) ttystate;
+ 
+   return set_tty_state (scb, state);
+ }
+ 
+ static int
+ ntopty_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+      struct serial *scb;
+      serial_ttystate new_ttystate;
+      serial_ttystate old_ttystate;
+ {
+   struct ntopty_ttystate new_state;
+ #ifdef HAVE_SGTTY
+   struct ntopty_ttystate *state = (struct ntopty_ttystate *) old_ttystate;
+ #endif
+ 
+   new_state = *(struct ntopty_ttystate *) new_ttystate;
+ 
+   /* Don't change in or out of raw mode; we don't want to flush input.
+      termio and termios have no such restriction; for them flushing input
+      is separate from setting the attributes.  */
+ 
+ #ifdef HAVE_SGTTY
+   if (state->sgttyb.sg_flags & RAW)
+     new_state.sgttyb.sg_flags |= RAW;
+   else
+     new_state.sgttyb.sg_flags &= ~RAW;
+ 
+   /* I'm not sure whether this is necessary; the manpage just mentions
+      RAW not CBREAK.  */
+   if (state->sgttyb.sg_flags & CBREAK)
+     new_state.sgttyb.sg_flags |= CBREAK;
+   else
+     new_state.sgttyb.sg_flags &= ~CBREAK;
+ #endif
+ 
+   return set_tty_state (scb, &new_state);
+ }
+ 
+ static void
+ ntopty_print_tty_state (scb, ttystate)
+      struct serial *scb;
+      serial_ttystate ttystate;
+ {
+   struct ntopty_ttystate *state = (struct ntopty_ttystate *) ttystate;
+   int i;
+ 
+ #ifdef HAVE_TERMIOS
+   printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
+ 		   (unsigned int) state->termios.c_iflag,
+ 		   (unsigned int) state->termios.c_oflag);
+   printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x\n",
+ 		   (unsigned int) state->termios.c_cflag,
+ 		   (unsigned int) state->termios.c_lflag);
+ #if 0
+   /* This not in POSIX, and is not really documented by those systems
+      which have it (at least not Sun).  */
+   printf_filtered ("c_line = 0x%x.\n", state->termios.c_line);
+ #endif
+   printf_filtered ("c_cc: ");
+   for (i = 0; i < NCCS; i += 1)
+     printf_filtered ("0x%x ", state->termios.c_cc[i]);
+   printf_filtered ("\n");
+ #endif
+ 
+ #ifdef HAVE_TERMIO
+   printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
+ 		   state->termio.c_iflag, state->termio.c_oflag);
+   printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
+ 		   state->termio.c_cflag, state->termio.c_lflag,
+ 		   state->termio.c_line);
+   printf_filtered ("c_cc: ");
+   for (i = 0; i < NCC; i += 1)
+     printf_filtered ("0x%x ", state->termio.c_cc[i]);
+   printf_filtered ("\n");
+ #endif
+ 
+ #ifdef HAVE_SGTTY
+   printf_filtered ("sgttyb.sg_flags = 0x%x.\n", state->sgttyb.sg_flags);
+ 
+   printf_filtered ("tchars: ");
+   for (i = 0; i < (int) sizeof (struct tchars); i++)
+     printf_filtered ("0x%x ", ((unsigned char *) &state->tc)[i]);
+   printf_filtered ("\n");
+ 
+   printf_filtered ("ltchars: ");
+   for (i = 0; i < (int) sizeof (struct ltchars); i++)
+     printf_filtered ("0x%x ", ((unsigned char *) &state->ltc)[i]);
+   printf_filtered ("\n");
+ 
+   printf_filtered ("lmode:  0x%x\n", state->lmode);
+ #endif
+ }
+ 
+ static int
+ ntopty_flush_output (scb)
+      struct serial *scb;
+ {
+ #ifdef HAVE_TERMIOS
+   return tcflush (scb->fd, TCOFLUSH);
+ #endif
+ 
+ #ifdef HAVE_TERMIO
+   return ioctl (scb->fd, TCFLSH, 1);
+ #endif
+ 
+ #ifdef HAVE_SGTTY
+   /* This flushes both input and output, but we can't do better.  */
+   return ioctl (scb->fd, TIOCFLUSH, 0);
+ #endif
+ }
+ 
+ static int
+ ntopty_flush_input (scb)
+      struct serial *scb;
+ {
+   scb->bufcnt = 0;
+   scb->bufp = scb->buf;
+ 
+ #ifdef HAVE_TERMIOS
+   return tcflush (scb->fd, TCIFLUSH);
+ #endif
+ 
+ #ifdef HAVE_TERMIO
+   return ioctl (scb->fd, TCFLSH, 0);
+ #endif
+ 
+ #ifdef HAVE_SGTTY
+   /* This flushes both input and output, but we can't do better.  */
+   return ioctl (scb->fd, TIOCFLUSH, 0);
+ #endif
+ }
+ 
+ static int
+ ntopty_send_break (scb)
+      struct serial *scb;
+ {
+ #ifdef HAVE_TERMIOS
+   return tcsendbreak (scb->fd, 0);
+ #endif
+ 
+ #ifdef HAVE_TERMIO
+   return ioctl (scb->fd, TCSBRK, 0);
+ #endif
+ 
+ #ifdef HAVE_SGTTY
+   {
+     int status;
+     struct timeval timeout;
+ 
+     status = ioctl (scb->fd, TIOCSBRK, 0);
+ 
+     /* Can't use usleep; it doesn't exist in BSD 4.2.  */
+     /* Note that if this select() is interrupted by a signal it will not wait
+        the full length of time.  I think that is OK.  */
+     timeout.tv_sec = 0;
+     timeout.tv_usec = 250000;
+     select (0, 0, 0, 0, &timeout);
+     status = ioctl (scb->fd, TIOCCBRK, 0);
+     return status;
+   }
+ #endif
+ }
+ 
+ static void
+ ntopty_raw (scb)
+      struct serial *scb;
+ {
+   struct ntopty_ttystate state;
+ 
+   if (get_tty_state (scb, &state))
+     fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n",
+ 			safe_strerror (errno));
+ 
+ #ifdef HAVE_TERMIOS
+   state.termios.c_iflag = 0;
+   state.termios.c_oflag = 0;
+   state.termios.c_lflag = 0;
+   state.termios.c_cflag &= ~(CSIZE | PARENB);
+   state.termios.c_cflag |= CLOCAL | CS8;
+   state.termios.c_cc[VMIN] = 0;
+   state.termios.c_cc[VTIME] = 0;
+ #endif
+ 
+ #ifdef HAVE_TERMIO
+   state.termio.c_iflag = 0;
+   state.termio.c_oflag = 0;
+   state.termio.c_lflag = 0;
+   state.termio.c_cflag &= ~(CSIZE | PARENB);
+   state.termio.c_cflag |= CLOCAL | CS8;
+   state.termio.c_cc[VMIN] = 0;
+   state.termio.c_cc[VTIME] = 0;
+ #endif
+ 
+ #ifdef HAVE_SGTTY
+   state.sgttyb.sg_flags |= RAW | ANYP;
+   state.sgttyb.sg_flags &= ~(CBREAK | ECHO);
+ #endif
+ 
+   scb->current_timeout = 0;
+ 
+   if (set_tty_state (scb, &state))
+     fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n",
+ 			safe_strerror (errno));
+ }
+ 
+ /* Wait for input on scb, with timeout seconds.  Returns 0 on success,
+    otherwise SERIAL_TIMEOUT or SERIAL_ERROR.
+ 
+    For termio{s}, we actually just setup VTIME if necessary, and let the
+    timeout occur in the read() in ntopty_read().
+  */
+ 
+ static int
+ wait_for (scb, timeout)
+      struct serial *scb;
+      int timeout;
+ {
+   scb->timeout_remaining = 0;
+ 
+ // We want to use the select so we can easily handle stdinput with the select
+ #if defined(HAVE_SGTTY) || defined(__QNXTARGET__)
+   {
+     struct timeval tv;
+     fd_set readfds;
+ 
+     tv.tv_sec = timeout;
+     tv.tv_usec = 0;
+ 
+ 
+     while (1)
+       {
+ 	int numfds;
+ 
+ 	FD_ZERO (&readfds);
+ 	FD_SET (scb->fd, &readfds);
+ 	if (timeout < 0)
+ 	  FD_SET (STDIN_FILENO, &readfds);
+ 
+ 	if (timeout >= 0)
+ 	  numfds = select (scb->fd + 1, &readfds, 0, 0, &tv);
+ 	else
+ 	  numfds = select (scb->fd + 1, &readfds, 0, 0, 0);
+ 
+ 	if (numfds <= 0)
+ 	  {
+ 	    if (numfds == 0)
+ 	      return SERIAL_TIMEOUT;
+ 	    else if (errno == EINTR)
+ 	      continue;
+ 	    else
+ 	      return SERIAL_ERROR;	/* Got an error from select or poll */
+ 	  }
+ 	if ((timeout < 0) && (FD_ISSET (STDIN_FILENO, &readfds)))
+ 	  {
+ 	    int i;
+ 	    char buf[TS_TEXT_MAX_SIZE];
+ 	    i = read (STDIN_FILENO, buf, TS_TEXT_MAX_SIZE);
+ 	    qnx_outgoing_text (buf, i);
+ 	  }
+ 	else
+ 	  return 0;
+       }
+   }
+ #else /* end of HAVE_SGTTY  || __QNXTARGET__ */
+ 
+ #if defined HAVE_TERMIO || defined HAVE_TERMIOS
+   if (timeout == scb->current_timeout)
+     return 0;
+ 
+   scb->current_timeout = timeout;
+ 
+   {
+     struct ntopty_ttystate state;
+ 
+     if (get_tty_state (scb, &state))
+       fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n",
+ 			  safe_strerror (errno));
+ 
+ #ifdef HAVE_TERMIOS
+     if (timeout < 0)
+       {
+ 	/* No timeout.  */
+ 	state.termios.c_cc[VTIME] = 0;
+ 	state.termios.c_cc[VMIN] = 1;
+       }
+     else
+       {
+ 	state.termios.c_cc[VMIN] = 0;
+ 	state.termios.c_cc[VTIME] = timeout * 10;
+ 	if (state.termios.c_cc[VTIME] != timeout * 10)
+ 	  {
+ 
+ 	    /* If c_cc is an 8-bit signed character, we can't go 
+ 	       bigger than this.  If it is always unsigned, we could use
+ 	       25.  */
+ 
+ 	    scb->current_timeout = 12;
+ 	    state.termios.c_cc[VTIME] = scb->current_timeout * 10;
+ 	    scb->timeout_remaining = timeout - scb->current_timeout;
+ 	  }
+       }
+ #endif
+ 
+ #ifdef HAVE_TERMIO
+     if (timeout < 0)
+       {
+ 	/* No timeout.  */
+ 	state.termio.c_cc[VTIME] = 0;
+ 	state.termio.c_cc[VMIN] = 1;
+       }
+     else
+       {
+ 	state.termio.c_cc[VMIN] = 0;
+ 	state.termio.c_cc[VTIME] = timeout * 10;
+ 	if (state.termio.c_cc[VTIME] != timeout * 10)
+ 	  {
+ 	    /* If c_cc is an 8-bit signed character, we can't go 
+ 	       bigger than this.  If it is always unsigned, we could use
+ 	       25.  */
+ 
+ 	    scb->current_timeout = 12;
+ 	    state.termio.c_cc[VTIME] = scb->current_timeout * 10;
+ 	    scb->timeout_remaining = timeout - scb->current_timeout;
+ 	  }
+       }
+ #endif
+ 
+     if (set_tty_state (scb, &state))
+       fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n",
+ 			  safe_strerror (errno));
+ 
+     return 0;
+   }
+ #endif /* HAVE_TERMIO || HAVE_TERMIOS */
+ #endif
+ }
+ 
+ /* Read a character with user-specified timeout.  TIMEOUT is number of seconds
+    to wait, or -1 to wait forever.  Use timeout of 0 to effect a poll.  Returns
+    char if successful.  Returns SERIAL_TIMEOUT if timeout expired, EOF if line
+    dropped dead, or SERIAL_ERROR for any other error (see errno in that case).  */
+ 
+ static int
+ ntopty_readchar (scb, timeout)
+      struct serial *scb;
+      int timeout;
+ {
+   int status;
+ 
+   if (scb->bufcnt-- > 0)
+     return *scb->bufp++;
+ 
+   while (1)
+     {
+       status = wait_for (scb, timeout);
+ 
+       if (status < 0)
+ 	return status;
+ 
+       scb->bufcnt = read (scb->fd, scb->buf, BUFSIZ);
+ 
+       if (scb->bufcnt <= 0)
+ 	{
+ 	  if (scb->bufcnt == 0)
+ 	    {
+ 	      /* Zero characters means timeout (it could also be EOF, but
+ 	         we don't (yet at least) distinguish).  */
+ 	      if (scb->timeout_remaining > 0)
+ 		{
+ 		  timeout = scb->timeout_remaining;
+ 		  continue;
+ 		}
+ 	      else
+ 		return SERIAL_TIMEOUT;
+ 	    }
+ 	  else if (errno == EINTR)
+ 	    continue;
+ 	  else
+ 	    return SERIAL_ERROR;	/* Got an error from read */
+ 	}
+ 
+       scb->bufcnt--;
+       scb->bufp = scb->buf;
+       return *scb->bufp++;
+     }
+ }
+ 
+ static int
+ ntopty_setbaudrate (scb, rate)
+      struct serial *scb;
+      int rate;
+ {
+   struct ntopty_ttystate state;
+ 
+   if (get_tty_state (scb, &state))
+     return -1;
+ 
+ #ifdef HAVE_TERMIOS
+   cfsetospeed (&state.termios, rate);
+   cfsetispeed (&state.termios, rate);
+ #endif
+ 
+ #ifdef HAVE_TERMIO
+ #ifndef CIBAUD
+ #define CIBAUD CBAUD
+ #endif
+ 
+   state.termio.c_cflag &= ~(CBAUD | CIBAUD);
+   state.termio.c_cflag |= rate;
+ #endif
+ 
+ #ifdef HAVE_SGTTY
+   state.sgttyb.sg_ispeed = rate;
+   state.sgttyb.sg_ospeed = rate;
+ #endif
+ 
+   return set_tty_state (scb, &state);
+ }
+ 
+ static int
+ ntopty_setstopbits (scb, num)
+      struct serial *scb;
+      int num;
+ {
+   struct ntopty_ttystate state;
+   int newbit;
+ 
+   if (get_tty_state (scb, &state))
+     return -1;
+ 
+   switch (num)
+     {
+     case SERIAL_1_STOPBITS:
+       newbit = 0;
+       break;
+     case SERIAL_1_AND_A_HALF_STOPBITS:
+     case SERIAL_2_STOPBITS:
+       newbit = 1;
+       break;
+     default:
+       return 1;
+     }
+ 
+ #ifdef HAVE_TERMIOS
+   if (!newbit)
+     state.termios.c_cflag &= ~CSTOPB;
+   else
+     state.termios.c_cflag |= CSTOPB;	/* two bits */
+ #endif
+ 
+ #ifdef HAVE_TERMIO
+   if (!newbit)
+     state.termio.c_cflag &= ~CSTOPB;
+   else
+     state.termio.c_cflag |= CSTOPB;	/* two bits */
+ #endif
+ 
+ #ifdef HAVE_SGTTY
+   return 0;			/* sgtty doesn't support this */
+ #endif
+ 
+   return set_tty_state (scb, &state);
+ }
+ 
+ static int
+ ntopty_write (scb, str, len)
+      struct serial *scb;
+      const char *str;
+      int len;
+ {
+   int cc;
+ 
+   while (len > 0)
+     {
+       cc = write (scb->fd, str, len);
+ 
+       if (cc < 0)
+ 	return 1;
+       len -= cc;
+       str += cc;
+     }
+   return 0;
+ }
+ 
+ static void
+ ntopty_close (scb)
+      struct serial *scb;
+ {
+   if (scb->fd < 0)
+     return;
+ 
+   kill (ntopid, SIGTERM);
+   close (scb->fd);
+   scb->fd = -1;
+ }
+ 
+ static int
+ ntopty_nop_drain_output (struct serial *scb)
+ {
+   return 0;
+ }
+ 
+ static void
+ ntopty_nop_async (struct serial *scb, int async_p)
+ {
+   return;
+ }
+ 
+ void
+ _initialize_ser_ntopty ()
+ {
+   struct serial_ops *ops = xmalloc (sizeof (struct serial_ops));
+   memset (ops, sizeof (struct serial_ops), 0);
+   ops->name = "pty";
+   ops->next = 0;
+   ops->open = ntopty_open;
+   ops->close = ntopty_close;
+   ops->readchar = ntopty_readchar;
+   ops->write = ntopty_write;
+   ops->flush_output = ntopty_flush_output;
+   ops->flush_input = ntopty_flush_input;
+   ops->send_break = ntopty_send_break;
+   ops->go_raw = ntopty_raw;
+   ops->get_tty_state = ntopty_get_tty_state;
+   ops->set_tty_state = ntopty_set_tty_state;
+   ops->print_tty_state = ntopty_print_tty_state;
+   ops->noflush_set_tty_state = ntopty_noflush_set_tty_state;
+   ops->setbaudrate = ntopty_setbaudrate;
+   ops->setstopbits = ntopty_setstopbits;
+   ops->drain_output = ntopty_nop_drain_output;
+   ops->async = ntopty_nop_async;
+   serial_add_interface (ops);
+ 
+   ntoserver = strdup ("pdebug");
+   ntoserverdev = strdup ("-");
+   add_show_from_set (add_set_cmd ("ntoserver", no_class,
+ 				  var_filename, (char *) &ntoserver,
+ 				  "Set QNX debug protocol server.\n",
+ 				  &setlist), &showlist);
+   add_show_from_set (add_set_cmd
+ 		     ("ntoptydelay", no_class, var_integer,
+ 		      (char *) &nto_ptydelay,
+ 		      "Set delay before attempting to talk to pdebug.\n",
+ 		      &setlist), &showlist);
+ }
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -x configure src.orig/readline/Makefile.in src/readline/Makefile.in
*** src.orig/readline/Makefile.in	Sun Dec  8 17:31:37 2002
--- src/readline/Makefile.in	Wed Jan 22 14:17:46 2003
*************** GCC_LINT_CFLAGS = $(XCCFLAGS) $(GCC_LINT
*** 86,91 ****
--- 86,98 ----
  LIBRARY_NAME = libreadline.a
  STATIC_LIBS = libreadline.a libhistory.a
  
+ HAVE_WCWIDTH = @HAVE_WCWIDTH@
+ 
+ ifeq ($(HAVE_WCWIDTH), no)
+ WCWIDTH_SRC = $(srcdir)/support/wcwidth.c
+ WCWIDTH_OBJ = wcwidth.o
+ endif
+ 
  # The C code source files for this library.
  CSOURCES = $(srcdir)/readline.c $(srcdir)/funmap.c $(srcdir)/keymaps.c \
  	   $(srcdir)/vi_mode.c $(srcdir)/parens.c $(srcdir)/rltty.c \
*************** CSOURCES = $(srcdir)/readline.c $(srcdir
*** 98,104 ****
  	   $(srcdir)/histfile.c $(srcdir)/nls.c $(srcdir)/search.c \
  	   $(srcdir)/shell.c $(srcdir)/savestring.c $(srcdir)/tilde.c \
  	   $(srcdir)/text.c $(srcdir)/misc.c $(srcdir)/compat.c \
! 	   $(srcdir)/mbutil.c
  
  # The header files for this library.
  HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h histlib.h \
--- 105,111 ----
  	   $(srcdir)/histfile.c $(srcdir)/nls.c $(srcdir)/search.c \
  	   $(srcdir)/shell.c $(srcdir)/savestring.c $(srcdir)/tilde.c \
  	   $(srcdir)/text.c $(srcdir)/misc.c $(srcdir)/compat.c \
! 	   $(srcdir)/mbutil.c $(WCWIDTH_SRC)
  
  # The header files for this library.
  HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h histlib.h \
*************** TILDEOBJ = tilde.o
*** 111,117 ****
  OBJECTS = readline.o vi_mode.o funmap.o keymaps.o parens.o search.o \
  	  rltty.o complete.o bind.o isearch.o display.o signals.o \
  	  util.o kill.o undo.o macro.o input.o callback.o terminal.o \
! 	  text.o nls.o misc.o compat.o xmalloc.o $(HISTOBJ) $(TILDEOBJ)
  
  # The texinfo files which document this library.
  DOCSOURCE = doc/rlman.texinfo doc/rltech.texinfo doc/rluser.texinfo
--- 118,125 ----
  OBJECTS = readline.o vi_mode.o funmap.o keymaps.o parens.o search.o \
  	  rltty.o complete.o bind.o isearch.o display.o signals.o \
  	  util.o kill.o undo.o macro.o input.o callback.o terminal.o \
! 	  text.o nls.o misc.o compat.o xmalloc.o $(HISTOBJ) $(TILDEOBJ) \
! 	  $(WCWIDTH_OBJ)
  
  # The texinfo files which document this library.
  DOCSOURCE = doc/rlman.texinfo doc/rltech.texinfo doc/rluser.texinfo
*************** libhistory.a: $(HISTOBJ) xmalloc.o
*** 147,152 ****
--- 155,166 ----
  	$(AR) $(ARFLAGS) $@ $(HISTOBJ) xmalloc.o
  	-test -n "$(RANLIB)" && $(RANLIB) $@
  
+ ifeq ($(HAVE_WCWIDTH), no)
+ $(WCWIDTH_OBJ): $(WCWIDTH_SRC)
+ 	$(RM) $@
+ 	$(CC) $(CCFLAGS) -c $(WCWIDTH_SRC)
+ endif
+ 
  # Since tilde.c is shared between readline and bash, make sure we compile
  # it with the right flags when it's built as part of readline
  tilde.o:	tilde.c
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -x configure src.orig/readline/aclocal.m4 src/readline/aclocal.m4
*** src.orig/readline/aclocal.m4	Sun Dec  8 17:31:37 2002
--- src/readline/aclocal.m4	Wed Jan 22 14:14:26 2003
*************** AC_CHECK_HEADERS(wchar.h)
*** 1653,1659 ****
  AC_CHECK_HEADERS(langinfo.h)
  
  AC_CHECK_FUNC(mbsrtowcs, AC_DEFINE(HAVE_MBSRTOWCS))
! AC_CHECK_FUNC(wcwidth, AC_DEFINE(HAVE_WCWIDTH))
  
  AC_CACHE_CHECK([for mbstate_t], bash_cv_have_mbstate_t,
  [AC_TRY_RUN([
--- 1653,1659 ----
  AC_CHECK_HEADERS(langinfo.h)
  
  AC_CHECK_FUNC(mbsrtowcs, AC_DEFINE(HAVE_MBSRTOWCS))
! AC_CHECK_FUNC(wcwidth, AC_DEFINE(HAVE_WCWIDTH), AC_SUBST(HAVE_WCWIDTH,no))
  
  AC_CACHE_CHECK([for mbstate_t], bash_cv_have_mbstate_t,
  [AC_TRY_RUN([
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -x configure src.orig/readline/shlib/Makefile.in src/readline/shlib/Makefile.in
*** src.orig/readline/shlib/Makefile.in	Sun Dec  8 17:31:38 2002
--- src/readline/shlib/Makefile.in	Wed Jan 22 14:18:46 2003
*************** SHARED_READLINE = libreadline.$(SHLIB_LI
*** 103,108 ****
--- 103,115 ----
  SHARED_HISTORY = libhistory.$(SHLIB_LIBVERSION)
  SHARED_LIBS = $(SHARED_READLINE) $(SHARED_HISTORY)
  
+ HAVE_WCWIDTH = @HAVE_WCWIDTH@
+ 
+ ifeq ($(HAVE_WCWIDTH), no)
+ WCWIDTH_SRC = $(srcdir)/support/wcwidth.c
+ WCWIDTH_OBJ = wcwidth.so
+ endif
+ 
  # The C code source files for this library.
  CSOURCES = $(topdir)/readline.c $(topdir)/funmap.c $(topdir)/keymaps.c \
  	   $(topdir)/vi_mode.c $(topdir)/parens.c $(topdir)/rltty.c \
*************** CSOURCES = $(topdir)/readline.c $(topdir
*** 115,121 ****
  	   $(topdir)/histfile.c $(topdir)/nls.c $(topdir)/search.c \
  	   $(topdir)/shell.c $(topdir)/savestring.c $(topdir)/tilde.c \
  	   $(topdir)/text.c $(topdir)/misc.c $(topdir)/compat.c \
! 	   $(topdir)/mbutil.c
  
  # The header files for this library.
  HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h histlib.h \
--- 122,128 ----
  	   $(topdir)/histfile.c $(topdir)/nls.c $(topdir)/search.c \
  	   $(topdir)/shell.c $(topdir)/savestring.c $(topdir)/tilde.c \
  	   $(topdir)/text.c $(topdir)/misc.c $(topdir)/compat.c \
! 	   $(topdir)/mbutil.c $(WCWIDTH_SRC)
  
  # The header files for this library.
  HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h histlib.h \
*************** SHARED_OBJ = readline.so vi_mode.so funm
*** 129,135 ****
  	  rltty.so complete.so bind.so isearch.so display.so signals.so \
  	  util.so kill.so undo.so macro.so input.so callback.so terminal.so \
  	  text.so nls.so misc.so xmalloc.so $(SHARED_HISTOBJ) $(SHARED_TILDEOBJ) \
! 	  compat.so
  
  ##########################################################################
  
--- 136,142 ----
  	  rltty.so complete.so bind.so isearch.so display.so signals.so \
  	  util.so kill.so undo.so macro.so input.so callback.so terminal.so \
  	  text.so nls.so misc.so xmalloc.so $(SHARED_HISTOBJ) $(SHARED_TILDEOBJ) \
! 	  compat.so $(WCWIDTH_OBJ)
  
  ##########################################################################
  
*************** $(SHARED_HISTORY):	$(SHARED_HISTOBJ) xma
*** 153,158 ****
--- 160,172 ----
  	$(RM) $@
  	$(SHOBJ_LD) ${SHOBJ_LDFLAGS} ${SHLIB_XLDFLAGS} -o $@ $(SHARED_HISTOBJ) xmalloc.so $(SHLIB_LIBS)
  
+ ifeq ($(HAVE_WCWIDTH), no)
+ $(WCWIDTH_OBJ): $(WCWIDTH_SRC)
+ 	$(RM) $@
+ 	$(SHOBJ_CC) -c $(CCFLAGS) $(SHOBJ_FLAGS) -o wcwidth.o $(WCWIDTH_SRC)
+ 	$(MV) wcwidth.o $@
+ endif
+ 
  # Since tilde.c is shared between readline and bash, make sure we compile 
  # it with the right flags when it's built as part of readline
  tilde.so:        tilde.c
