Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* patch to add QNX NTO i386 support
@ 2003-02-03 20:19 Kris Warkentin
  2003-02-04  7:23 ` Eli Zaretskii
                   ` (2 more replies)
  0 siblings, 3 replies; 64+ messages in thread
From: Kris Warkentin @ 2003-02-03 20:19 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 2117 bytes --]

I am submitting, on behalf of my employer QNX Software Systems Ltd., a patch
against the current HEAD branch of gdb (as of Feb.3/2003 - see attachment).
We already have copywrite assignment paperwork on file with the FSF.

Now that I've said what the lawyer told me to say ;-), the readline patch
deserves some explanation.  I didn't get any response from the readline or
bash mailing lists about the fact that if the test for wcwidth fails, no
action is taken.  Oddly, this test fails on other targets (ie Cygwin) but
there is no problem since wcwidth seems to resolve anyway.  Self hosted
Neutrino is actually missing it however so we had to conditionally compile
it in.  Hence the changes to Makefile.in.  I would have changed Makefile.am
but it doesn't seem to be in your sources.

Please let me know if the patch and these ChangeLog entries are
satisfactory.

cheers,

Kris

Top Level ChangeLog entry:

2003-03-02    Kris Warkentin    kewarken@qnx.com

    * config/mh-qnxnto: New file
    * config.sub: Add nto i386 and multi-arch support
    * configure.in: add host_makefile_frag

bfd/ChangeLog entry:

2003-03-02    Kris Warkentin    kewarken@qnx.com

    * elf.c: Add qnx corefile support

gdb/ChangeLog entry:

2003-03-02    Kris Warkentin    kewarken@qnx.com

    * config/i386/i386nto.mt: New file
    * config/i386/nm-nto.h: New file
    * config/i386/nto.mh: New file
    * config/i386/tm-i386nto.h: New file
    * config/i386/xm-nto.h: New file
    * config/tm-qnxnto.h: New file
    * configure.host: add gdb_host=nto
    * configure.tgt: add gdb_target=i386nto
    * nto-procfs.c: New file
    * nto-share/debug.h: New file
    * nto-share/dsmsgs.h: New file
    * remote-nto-i386.c: New file
    * remote-nto.c: New file
    * ser-ntopty.c: New file

readline/ChangeLog entry:

2003-03-02    Kris Warkentin    kewarken@qnx.com

    * Makefile.in: Check HAVE_WCWIDTH variable for conditionally compiling
                          support/wcwidth.c
    * shlib/Makefile.in: Likewise
    * aclocal.m4: If we don't have wcwidth, define HAVE_WCWIDTH=no for
Makefile
                          generation

[-- Attachment #2: qnxnto.diff --]
[-- Type: application/octet-stream, Size: 233635 bytes --]

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

^ permalink raw reply	[flat|nested] 64+ messages in thread
* Re: patch to add HAVE_CONTINUABLE_BREAKPOINT to target_ops
@ 2003-02-12 19:42 Kris Warkentin
  2003-02-14 18:49 ` Kris Warkentin
  0 siblings, 1 reply; 64+ messages in thread
From: Kris Warkentin @ 2003-02-12 19:42 UTC (permalink / raw)
  To: Kris Warkentin, Andrew Cagney; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 3413 bytes --]

Here's take 2 on the patch.  I had a slight error in the definition of
HAVE_CONTINUABLE_WATCHPOINT in the first one.  I was worried about
initialization (since infrun.c wanted the default to be zero) but since
target_ops structures are always declared as global data, it will be fine.

cheers,

Kris

----- Original Message -----
From: "Kris Warkentin" <kewarken@qnx.com>
To: "Andrew Cagney" <ac131313@redhat.com>
Cc: "Mark Kettenis" <kettenis@chello.nl>; <gdb-patches@sources.redhat.com>
Sent: Tuesday, February 11, 2003 1:41 PM
Subject: patch to add HAVE_CONTINUABLE_BREAKPOINT to target_ops


> Probably easier if I just give a diff for you to comment on.
>
> Changelog Entry:
>
> 2003-02-11    Kris Warkentin    kewarken@qnx.com
>
>     * target.h: Add to_have_continuable_watchpoint to struct target_ops.
>                     Initialize HAVE_CONTINUABLE_WATCHPOINT.
>     * target.c: update_current_target(): Add
to_have_continuable_watchpoint.
>     * infrun.c: remove initialization of HAVE_CONTINUABLE_WATCHPOINT.
>     * config/i386/nm-i386.h: Change HAVE_CONTINUABLE_WATCHPOINT defines to
> 1.
>     * config/i386/nm-i386sco5.h: ditto
>     * config/i386/nm-i386sol2.h: ditto
>     * config/s390/nm-linux.h: ditto
>     * config/sparc/nm-sun4sol2.h: ditto
>
> cheers,
>
> Kris
>
> ----- Original Message -----
> From: "Kris Warkentin" <kewarken@qnx.com>
> To: "Andrew Cagney" <ac131313@redhat.com>
> Cc: "Mark Kettenis" <kettenis@chello.nl>; <gdb-patches@sources.redhat.com>
> Sent: Tuesday, February 11, 2003 1:11 PM
> Subject: Re: patch to add QNX NTO i386 support
>
>
> > Hi Andrew,
> >
> > Sorry it took so long to reply - I took a couple days to do a port of a
> > vxworks lib for a BSP we're working on.
> >
> > Question: can I make any assumption about the initialization of the
> > target_ops vector?  It looks like infrun.c wants
> HAVE_CONTINUABLE_BREAKPOINT
> > to default to zero but I didn't see anywhere int target.[ch] that ops
were
> > being initialized.
> >
> > cheers,
> >
> > Kris
> >
> > > > /* 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
> > > >
> > > >>
> > > >> Hmm, this poses an interesting problem.  The other i386 targets
have
> > > >> this in their nm.h file, since they consider hardware watchpoints
as
> a
> > > >> native-only feature.  However, this isn't necessarily right since
we
> > > >> might support hardware breakpoints via the remote protocol.  If you
> > > >> can live with the native-only approach, please move this to your
nm.h
> > > >> file.  Otherwise we might need to multi-arch this definition.
> > > >
> > > >
> > > > Okay, file that under TODO along with the solib stuff.  We have
> hardware
> > > > breakpoints on all our remote targets that support them.
> > >
> > > Just FYI, this needs to be added to the target vector (target.h) and
not
> > > the architecture vector.
> > >
> > > For examples, see STOPPED_BY_WATCHPOINT et.al.  A bit of manipulation
of
> > > the existing nm-*.h files will be needed - have them define the value
as
> > 1.
> > >
> > > Can you please submit a separate patch that does just this.
> > >
> > > Andrew
> > >
> > >
> > >
> >
> >
>

[-- Attachment #2: contin2.diff --]
[-- Type: application/octet-stream, Size: 5708 bytes --]

Index: config/i386/nm-i386.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/nm-i386.h,v
retrieving revision 1.3
diff -u -r1.3 nm-i386.h
--- config/i386/nm-i386.h	4 Jul 2002 12:32:29 -0000	1.3
+++ config/i386/nm-i386.h	12 Feb 2003 19:38:15 -0000
@@ -93,7 +93,7 @@
    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 HAVE_CONTINUABLE_WATCHPOINT 1
 
 #define STOPPED_BY_WATCHPOINT(W)       (i386_stopped_data_address () != 0)
 
Index: config/i386/nm-i386sco5.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/nm-i386sco5.h,v
retrieving revision 1.3
diff -u -r1.3 nm-i386sco5.h
--- config/i386/nm-i386sco5.h	18 Aug 2002 22:23:32 -0000	1.3
+++ config/i386/nm-i386sco5.h	12 Feb 2003 19:38:15 -0000
@@ -63,7 +63,7 @@
 /* After a watchpoint trap, the PC points to the instruction which
    caused the trap.  But we can continue over it without disabling the
    trap.  */
-#define HAVE_CONTINUABLE_WATCHPOINT
+#define HAVE_CONTINUABLE_WATCHPOINT 1
 #define HAVE_STEPPABLE_WATCHPOINT
 
 #define STOPPED_BY_WATCHPOINT(W)  \
Index: config/i386/nm-i386sol2.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/nm-i386sol2.h,v
retrieving revision 1.7
diff -u -r1.7 nm-i386sol2.h
--- config/i386/nm-i386sol2.h	5 Jun 2002 19:18:19 -0000	1.7
+++ config/i386/nm-i386sol2.h	12 Feb 2003 19:38:15 -0000
@@ -32,7 +32,7 @@
 /* When a hardware watchpoint fires off the PC will be left at the
    instruction following the one which caused the watchpoint.  
    It will *NOT* be necessary for GDB to step over the watchpoint. */
-#define HAVE_CONTINUABLE_WATCHPOINT
+#define HAVE_CONTINUABLE_WATCHPOINT 1
 
 /* Solaris x86 2.6 and 2.7 targets have a kernel bug when stepping
    over an instruction that causes a page fault without triggering
Index: config/s390/nm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/s390/nm-linux.h,v
retrieving revision 1.5
diff -u -r1.5 nm-linux.h
--- config/s390/nm-linux.h	24 Feb 2002 22:56:06 -0000	1.5
+++ config/s390/nm-linux.h	12 Feb 2003 19:38:15 -0000
@@ -51,7 +51,7 @@
 /* WATCHPOINT SPECIFIC STUFF */
 
 #define TARGET_HAS_HARDWARE_WATCHPOINTS
-#define HAVE_CONTINUABLE_WATCHPOINT
+#define HAVE_CONTINUABLE_WATCHPOINT 1
 #define target_insert_watchpoint(addr, len, type)  \
   s390_insert_watchpoint (PIDGET (inferior_ptid), addr, len, type)
 
Index: config/sparc/nm-sun4sol2.h
===================================================================
RCS file: /cvs/src/src/gdb/config/sparc/nm-sun4sol2.h,v
retrieving revision 1.9
diff -u -r1.9 nm-sun4sol2.h
--- config/sparc/nm-sun4sol2.h	14 Nov 2002 00:25:05 -0000	1.9
+++ config/sparc/nm-sun4sol2.h	12 Feb 2003 19:38:15 -0000
@@ -51,7 +51,7 @@
 /* When a hardware watchpoint fires off the PC will be left at the
    instruction following the one which caused the watchpoint.  
    It will *NOT* be necessary for GDB to step over the watchpoint. */
-#define HAVE_CONTINUABLE_WATCHPOINT
+#define HAVE_CONTINUABLE_WATCHPOINT 1
 
 extern int procfs_stopped_by_watchpoint (ptid_t);
 #define STOPPED_BY_WATCHPOINT(W) \
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.96
diff -u -r1.96 infrun.c
--- infrun.c	31 Jan 2003 15:22:57 -0000	1.96
+++ infrun.c	12 Feb 2003 19:38:16 -0000
@@ -226,13 +226,6 @@
 #define HAVE_STEPPABLE_WATCHPOINT 1
 #endif
 
-#ifndef HAVE_CONTINUABLE_WATCHPOINT
-#define HAVE_CONTINUABLE_WATCHPOINT 0
-#else
-#undef  HAVE_CONTINUABLE_WATCHPOINT
-#define HAVE_CONTINUABLE_WATCHPOINT 1
-#endif
-
 #ifndef CANNOT_STEP_HW_WATCHPOINTS
 #define CANNOT_STEP_HW_WATCHPOINTS 0
 #else
Index: target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.49
diff -u -r1.49 target.c
--- target.c	19 Jan 2003 04:06:46 -0000	1.49
+++ target.c	12 Feb 2003 19:38:17 -0000
@@ -573,6 +573,7 @@
       INHERIT (to_remove_watchpoint, t);
       INHERIT (to_stopped_data_address, t);
       INHERIT (to_stopped_by_watchpoint, t);
+      INHERIT (to_have_continuable_watchpoint, t);
       INHERIT (to_region_size_ok_for_hw_watchpoint, t);
       INHERIT (to_terminal_init, t);
       INHERIT (to_terminal_inferior, t);
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.35
diff -u -r1.35 target.h
--- target.h	19 Jan 2003 04:06:46 -0000	1.35
+++ target.h	12 Feb 2003 19:38:17 -0000
@@ -256,6 +256,7 @@
     int (*to_remove_watchpoint) (CORE_ADDR, int, int);
     int (*to_insert_watchpoint) (CORE_ADDR, int, int);
     int (*to_stopped_by_watchpoint) (void);
+    int to_have_continuable_watchpoint;
     CORE_ADDR (*to_stopped_data_address) (void);
     int (*to_region_size_ok_for_hw_watchpoint) (int);
     void (*to_terminal_init) (void);
@@ -961,6 +962,13 @@
 #ifndef STOPPED_BY_WATCHPOINT
 #define STOPPED_BY_WATCHPOINT(w) \
    (*current_target.to_stopped_by_watchpoint) ()
+#endif
+
+/* Non-zero if we have continuable watchpoints  */
+
+#ifndef HAVE_CONTINUABLE_WATCHPOINT
+#define HAVE_CONTINUABLE_WATCHPOINT \
+   (current_target.to_have_continuable_watchpoint)
 #endif
 
 /* HP-UX supplies these operations, which respectively disable and enable

^ permalink raw reply	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2003-02-27 20:28 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-02-03 20:19 patch to add QNX NTO i386 support Kris Warkentin
2003-02-04  7:23 ` Eli Zaretskii
2003-02-04 13:33   ` Kris Warkentin
2003-02-04 13:53     ` Kris Warkentin
2003-02-04 19:59       ` Eli Zaretskii
2003-02-04 20:12         ` Kris Warkentin
2003-02-05  5:50           ` Eli Zaretskii
2003-02-04 22:02 ` Andrew Cagney
2003-02-05  1:29   ` Kris Warkentin
2003-02-05  2:40     ` Andrew Cagney
2003-02-05  2:59       ` Andrew Cagney
2003-02-05 12:31         ` Kris Warkentin
2003-02-05  2:55     ` Andrew Cagney
2003-02-05 17:15   ` Kris Warkentin
2003-02-05 18:46     ` Andrew Cagney
2003-02-07  1:48   ` Kris Warkentin
2003-02-07 19:22     ` Mark Kettenis
2003-02-07 20:08       ` Kris Warkentin
2003-02-07 21:59         ` Andrew Cagney
2003-02-11 18:11           ` Kris Warkentin
2003-02-11 18:41             ` patch to add HAVE_CONTINUABLE_BREAKPOINT to target_ops Kris Warkentin
2003-02-12 22:18       ` patch to add QNX NTO i386 support Kris Warkentin
2003-02-12 22:44         ` Daniel Jacobowitz
2003-02-13  0:52           ` Kris Warkentin
2003-02-13 22:21         ` Mark Kettenis
2003-02-13 22:29           ` Kris Warkentin
2003-02-13 22:53             ` Mark Kettenis
2003-02-13 23:55               ` Kris Warkentin
2003-02-14  0:01                 ` Kris Warkentin
2003-02-13 21:56       ` Kris Warkentin
2003-02-13 22:08         ` Daniel Jacobowitz
2003-02-13 22:25           ` Kris Warkentin
2003-02-13 22:29             ` Daniel Jacobowitz
2003-02-13 23:48               ` Kris Warkentin
2003-02-14  0:03                 ` Daniel Jacobowitz
2003-02-14  0:09                   ` Kris Warkentin
2003-02-14  0:13                     ` Daniel Jacobowitz
2003-02-14  0:35                       ` Kris Warkentin
2003-02-17 14:58                         ` Andrew Cagney
2003-02-17 15:44                           ` Daniel Jacobowitz
2003-02-17 16:45                             ` Andrew Cagney
2003-02-17 18:54                               ` Kris Warkentin
2003-02-18 21:26                                 ` Andrew Cagney
2003-02-18 22:30                                   ` Kris Warkentin
2003-02-20  0:42                                     ` Andrew Cagney
2003-02-27 19:02                             ` Kris Warkentin
2003-02-27 19:56                               ` Andrew Cagney
2003-02-27 20:02                               ` Daniel Jacobowitz
2003-02-27 20:10                                 ` Andrew Cagney
2003-02-27 20:11                                 ` Kris Warkentin
2003-02-27 20:23                                   ` Andrew Cagney
2003-02-27 20:28                                     ` Kris Warkentin
2003-02-05 20:48 ` Mark Kettenis
2003-02-05 21:23   ` Kris Warkentin
2003-02-05 21:43     ` Kris Warkentin
2003-02-05 22:24       ` Mark Kettenis
2003-02-06 15:13         ` Kris Warkentin
2003-02-06 18:19           ` Andrew Cagney
2003-02-05 22:48     ` Mark Kettenis
2003-02-06 15:08       ` Kris Warkentin
2003-02-12 19:42 patch to add HAVE_CONTINUABLE_BREAKPOINT to target_ops Kris Warkentin
2003-02-14 18:49 ` Kris Warkentin
2003-02-20  0:41   ` Andrew Cagney
2003-02-20  1:09     ` Kris Warkentin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox