* [Patch] QNX i386 native support take 2
@ 2003-02-17 20:56 Kris Warkentin
[not found] ` <86lm06oaf9.fsf@elgar.kettenis.dyndns.org>
0 siblings, 1 reply; 6+ messages in thread
From: Kris Warkentin @ 2003-02-17 20:56 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1995 bytes --]
Here is take 2 of the patch. I decided not to make remote support
configurable. It's a lot of work for the inclusion of one object and it's
really just not done. If someone REALLY doesn't want remote support in a
native configuration, they can just comment out remote-nto.c (as I have for
this submission).
cheers,
Kris
Top Level ChangeLog entry:
2003-03-02 Kris Warkentin kewarken@qnx.com
* config.sub: Add nto i386 and multi-arch support
* configure.in: add i[3456]86-*-nto*
* configure: regenerate
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 - need to move it's define to configure
or run time.
* config/i386/nto.mh: New file
* config/i386/tm-i386nto.h: New file - only solib stuff.
* config/djgpp/fnchange.lst: add tm-i386nto.h
* config/tm-qnxnto.h: New file - some signal stuff.
* configure.host: add gdb_host=nto.
* configure.tgt: add gdb_target=i386nto and gdb osabi GDB_OSABI_QNXNTO.
* defs.h: add GDB_OSABI_QNXNTO.
* nto-procfs.c: New file - native Neutrino procfs support.
* nto-share/debug.h: New file - debug interface to our kernel.
* nto-share/dsmsgs.h: New file - definitions for our remote protocol.
* i386-nto-tdep.c: New file - i386 target specific functionality.
* nto-tdep.c: New file - architecture independent functionality.
* nto-tdep.h: New file - exports for nto-tdep.c
* osabi.c: add "QNX Neutrino" to gdb_osabi_name array
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: 111114 bytes --]
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/bfd/elf.c src.new/bfd/elf.c
*** src.orig/bfd/elf.c Fri Feb 14 13:38:21 2003
--- src.new/bfd/elf.c Fri Feb 14 12:55:54 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)
*** 7200,7205 ****
--- 7206,7216 ----
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
*** 7402,7404 ****
--- 7413,7516 ----
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 */
+ }
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/config.sub src.new/config.sub
*** src.orig/config.sub Wed Jan 8 17:09:30 2003
--- src.new/config.sub Fri Feb 14 16:07:18 2003
*************** case $basic_machine in
*** 727,732 ****
--- 727,736 ----
nsr-tandem)
basic_machine=nsr-tandem
;;
+ ntox86)
+ basic_machine=i386${os:--unknown}
+ os=-nto
+ ;;
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.new/configure.in
*** src.orig/configure.in Fri Feb 14 13:38:30 2003
--- src.new/configure.in Fri Feb 14 15:57:58 2003
*************** case "${host}" in
*** 1089,1094 ****
--- 1089,1096 ----
tentative_cc="/usr/ccs/ATT/cc"
host_makefile_frag="config/mh-ncr3000"
;;
+ i[3456]86-*-nto*)
+ ;;
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/djgpp/fnchange.lst src.new/gdb/config/djgpp/fnchange.lst
*** src.orig/gdb/config/djgpp/fnchange.lst Fri Feb 14 13:38:19 2003
--- src.new/gdb/config/djgpp/fnchange.lst Fri Feb 14 16:04:58 2003
***************
*** 90,95 ****
--- 90,96 ----
@V@/gdb/config/i386/nm-i386v4.h @V@/gdb/config/i386/nm-v4.h
@V@/gdb/config/i386/nm-i386v42mp.h @V@/gdb/config/i386/nm-v42mp.h
@V@/gdb/config/i386/tm-i386mk.h @V@/gdb/config/i386/tm-mk.h
+ @V@/gdb/config/i386/tm-i386nto.h @V@/gdb/config/i386/tm-nto.h
@V@/gdb/config/i386/tm-i386sol2.h @V@/gdb/config/i386/tm-sol2.h
@V@/gdb/config/i386/tm-i386v42mp.h @V@/gdb/config/i386/tm-v42mp.h
@V@/gdb/config/i386/xm-i386mach.h @V@/gdb/config/i386/xm-mach.h
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/config/i386/i386nto.mt src.new/gdb/config/i386/i386nto.mt
*** src.orig/gdb/config/i386/i386nto.mt Wed Dec 31 19:00:00 1969
--- src.new/gdb/config/i386/i386nto.mt Fri Feb 14 16:02:03 2003
***************
*** 0 ****
--- 1,4 ----
+ # Target: Intel 386 running qnx6
+ TDEPFILES= i386-tdep.o i387-tdep.o corelow.o solib.o solib-svr4.o \
+ i386-nto-tdep.o nto-tdep.o # remote-nto.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.new/gdb/config/i386/nm-nto.h
*** src.orig/gdb/config/i386/nm-nto.h Wed Dec 31 19:00:00 1969
--- src.new/gdb/config/i386/nm-nto.h Fri Feb 14 13:28:11 2003
***************
*** 0 ****
--- 1,6 ----
+ #ifndef _NM_NTO_H
+ #define _NM_NTO_H
+
+ #define QNX_TARGET_CPUTYPE CPUTYPE_X86
+
+ #endif /* _NM_NTO_H */
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/config/i386/nto.mh src.new/gdb/config/i386/nto.mh
*** src.orig/gdb/config/i386/nto.mh Wed Dec 31 19:00:00 1969
--- src.new/gdb/config/i386/nto.mh Thu Feb 13 13:18:02 2003
***************
*** 0 ****
--- 1,5 ----
+ # Host: Intel 386 running QNX
+
+ NAT_FILE= nm-nto.h
+
+ NATDEPFILES= nto-procfs.o
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/config/i386/tm-i386nto.h src.new/gdb/config/i386/tm-i386nto.h
*** src.orig/gdb/config/i386/tm-i386nto.h Wed Dec 31 19:00:00 1969
--- src.new/gdb/config/i386/tm-i386nto.h Mon Feb 17 15:21:22 2003
***************
*** 0 ****
--- 1,13 ----
+ #ifndef TM_I386NTO_H
+ #define TM_I386NTO_H 1
+
+ /* Pick up most of what we need from the generic i386 target include file. */
+ #include "i386/tm-i386.h"
+ #include "tm-qnxnto.h"
+
+ /* Temporary until this is multi-arched */
+ #define HAVE_CONTINUABLE_WATCHPOINT 1
+
+ #include "solib.h" /* shared lib support */
+
+ #endif /* ifndef TM_I386NTO_H */
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/config/tm-qnxnto.h src.new/gdb/config/tm-qnxnto.h
*** src.orig/gdb/config/tm-qnxnto.h Wed Dec 31 19:00:00 1969
--- src.new/gdb/config/tm-qnxnto.h Fri Feb 14 13:28:11 2003
***************
*** 0 ****
--- 1,57 ----
+ /* 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. */
+
+ #ifndef _TM_QNXNTO_H
+ #define _TM_QNXNTO_H
+
+ #include "tm-sysv4.h"
+
+ /* 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"}
+
+ #endif /* _TM_QNXNTO_H */
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/configure.host src.new/gdb/configure.host
*** src.orig/gdb/configure.host Fri Feb 14 13:38:15 2003
--- src.new/gdb/configure.host Tue Feb 11 14:29:59 2003
*************** i[3456]86-*-msdosdjgpp*) gdb_host=go32 ;
*** 63,68 ****
--- 63,69 ----
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.new/gdb/configure.tgt
*** src.orig/gdb/configure.tgt Fri Feb 14 13:38:15 2003
--- src.new/gdb/configure.tgt Tue Feb 11 16:53:32 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* | x86-*-nto*) gdb_target=i386nto;;
i[3456]86-*-lynxos*) gdb_target=i386lynx ;;
i[3456]86-*-solaris*) gdb_target=i386sol2 ;;
i[3456]86-*-sco*) gdb_target=i386v ;;
*************** esac
*** 280,284 ****
--- 281,286 ----
case "${target}" in
*-*-linux*) gdb_osabi=GDB_OSABI_LINUX ;;
*-*-gnu*) gdb_osabi=GDB_OSABI_HURD ;;
+ *-*-nto*) gdb_osabi=GDB_OSABI_QNXNTO ;;
*-*-solaris*) gdb_osabi=GDB_OSABI_SOLARIS ;;
esac
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/defs.h src.new/gdb/defs.h
*** src.orig/gdb/defs.h Fri Feb 14 13:38:15 2003
--- src.new/gdb/defs.h Fri Feb 14 13:29:01 2003
*************** enum gdb_osabi
*** 1008,1013 ****
--- 1008,1014 ----
GDB_OSABI_ARM_EABI_V1,
GDB_OSABI_ARM_EABI_V2,
GDB_OSABI_ARM_APCS,
+ GDB_OSABI_QNXNTO,
GDB_OSABI_INVALID /* keep this last */
};
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/i386-nto-tdep.c src.new/gdb/i386-nto-tdep.c
*** src.orig/gdb/i386-nto-tdep.c Wed Dec 31 19:00:00 1969
--- src.new/gdb/i386-nto-tdep.c Mon Feb 17 15:25:27 2003
***************
*** 0 ****
--- 1,419 ----
+ #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"
+ #include "i386-tdep.h"
+ #include "nto-tdep.h"
+ #include "osabi.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 nto_cpuinfo;
+ extern int nto_cpuinfo_valid;
+ extern int nto_ostype, nto_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
+ nto_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 (nto_cpuinfo_valid && nto_cpuinfo.cpuflags | X86_CPU_FXSR)
+ i387_supply_fxsave (data);
+ else
+ i387_supply_fsave (data);
+ }
+
+ void
+ nto_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
+ nto_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
+ nto_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 (nto_cpuinfo_valid && nto_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
+ nto_cpu_register_fetch (endian, first_regno, last_regno, data)
+ int endian;
+ unsigned first_regno;
+ unsigned last_regno;
+ void *data;
+ {
+ fprintf_unfiltered (gdb_stderr, "warning: nto_cpu_register_fetch called \
+ in remote-nto-i386.c. This shouldn't happen\n");
+ /* If remote-nto-i386.c calls nto_supply_register in remote-nto.c,
+ * then remote-nto.c calls nto_cpu_register_fetch. Since this never
+ * happens, this function is left unimplemented. */
+ }
+
+ /* Build the Neutrino register set info into the 'data' buffer */
+
+ int
+ nto_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 nto_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 *) ®p[i]);
+ }
+ }
+
+ void
+ nto_supply_fpregset (fpregsetp)
+ nto_fpregset_t *fpregsetp;
+ {
+ if (nto_cpuinfo_valid && nto_cpuinfo.cpuflags | X86_CPU_FXSR)
+ i387_supply_fxsave ((char *) fpregsetp);
+ else
+ i387_supply_fsave ((char *) fpregsetp);
+ }
+
+ /* 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). */
+
+ static struct link_map_offsets *
+ i386_nto_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;
+ }
+
+ struct link_map_offsets *
+ nto_fetch_link_map_offsets (void)
+ {
+ return i386_nto_svr4_fetch_link_map_offsets ();
+ }
+
+ static int
+ i386_nto_pc_in_sigtramp (CORE_ADDR pc, char *name)
+ {
+ return name && strcmp ("__signalstub", name) == 0;
+ }
+
+ static CORE_ADDR
+ i386_nto_sigcontext_addr (struct frame_info *frame)
+ {
+ int sigcontext_offset = 136;
+
+ if (get_next_frame (frame))
+ return get_frame_base (get_next_frame (frame)) + sigcontext_offset;
+
+ return read_register (SP_REGNUM) + sigcontext_offset;
+ }
+
+ static void
+ i386_nto_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+ {
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ /* NTO uses ELF. */
+ i386_elf_init_abi (info, gdbarch);
+
+ /* neutrino rewinds to look more normal */
+ set_gdbarch_decr_pc_after_break (gdbarch, 0);
+
+ /* NTO has shared libraries. */
+ set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
+ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+
+ set_gdbarch_pc_in_sigtramp (gdbarch, i386_nto_pc_in_sigtramp);
+ tdep->sigcontext_addr = i386_nto_sigcontext_addr;
+ tdep->sc_pc_offset = 56;
+ tdep->sc_sp_offset = 68;
+
+ /* setjmp()'s return PC saved in EDX (5) */
+ tdep->jb_pc_offset = 5 * sizeof (int);
+
+ set_solib_svr4_fetch_link_map_offsets (gdbarch,
+ i386_nto_svr4_fetch_link_map_offsets);
+
+ /* Our loader handles solib relocations slightly differently than svr4 */
+ current_target_so_ops->relocate_section_addresses =
+ nto_relocate_section_addresses;
+
+ /* FIXME: Re-enable this and remove define from config/i386/tm-i386nto.h
+ once it is multi-arched. */
+ #if 0
+ /* 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. */
+ HAVE_CONTINUABLE_WATCHPOINT = 1;
+ #endif
+ }
+
+ void
+ _initialize_i386_nto_tdep (void)
+ {
+ gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
+ i386_nto_init_abi);
+
+ /* read our extra gdbinit file */
+ nto_source_extra_gdbinit (".ntox86-gdbinit");
+ }
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/nto-procfs.c src.new/gdb/nto-procfs.c
*** src.orig/gdb/nto-procfs.c Wed Dec 31 19:00:00 1969
--- src.new/gdb/nto-procfs.c Fri Feb 14 13:28:11 2003
***************
*** 0 ****
--- 1,1520 ----
+ /* 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 "nto-tdep.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));
+
+ static int procfs_can_use_hw_breakpoint PARAMS ((int, int, int));
+
+ static int procfs_insert_hw_breakpoint PARAMS ((CORE_ADDR, char *));
+
+ static int procfs_remove_hw_breakpoint PARAMS ((CORE_ADDR addr, char *));
+
+ static int procfs_insert_hw_watchpoint
+ PARAMS ((CORE_ADDR addr, int len, int type));
+
+ static int procfs_remove_hw_watchpoint
+ PARAMS ((CORE_ADDR addr, int len, int type));
+
+ static int procfs_stopped_by_watchpoint PARAMS ((void));
+
+ /*
+ These two globals are only ever set in procfs_open(), but are
+ referenced elsewhere. 'nto_procfs_node' is a flag used to say
+ whether we are local, or we should get the current node descriptor
+ for the remote QNX node.
+ */
+ static char nto_procfs_path[PATH_MAX] = { "/proc" };
+ static unsigned nto_procfs_node = ND_LOCAL_NODE;
+
+ /*
+ This is a simple wrapper for the netmgr_strtond() function. It is
+ only called from the QNX_NODE macro declared below. The reason for
+ the macro and function are because QNX node descriptors are transient,
+ so we have to re-acquire them every time.
+ */
+ static unsigned
+ procfs_nto_node (unsigned node)
+ {
+ if (node == -1)
+ {
+ error ("Lost the QNX node. Debug session probably over.");
+ /* 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_nto_node(netmgr_strtond(nto_procfs_path, 0)))
+
+ /*
+ This is called when we call 'target procfs <arg>' from the (gdb) prompt.
+ For QNX6 (nto), the only valid arg will be a QNX node string,
+ eg: "/net/some_node". If arg is not a valid QNX node, we will
+ default to local.
+ */
+ static void
+ procfs_open (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
+ {
+ /* FIXME: do this dynamically to get rid of QNX_TARGET_CPUTYPE. */
+ 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, 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;
+ nto_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
+ nto_interrupt_twice (signo)
+ int signo;
+ {
+ signal (signo, ofunc);
+ interrupt_query ();
+ signal (signo, nto_interrupt_twice);
+ }
+
+ static void
+ nto_interrupt (int signo)
+ {
+ /* If this doesn't work, try more severe steps. */
+ signal (signo, nto_interrupt_twice);
+
+ target_stop ();
+ }
+
+ static ptid_t
+ procfs_wait (ptid, 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, nto_interrupt);
+ sigwaitinfo (&set, &info);
+ signal (SIGINT, ofunc);
+ devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
+ }
+
+ if (status.flags & _DEBUG_FLAG_SSTEP)
+ {
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ /* Was it a breakpoint? */
+ else if (status.flags & _DEBUG_FLAG_TRACE)
+ {
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ else if (status.flags & _DEBUG_FLAG_ISTOP)
+ {
+ switch (status.why)
+ {
+ case _DEBUG_WHY_SIGNALLED:
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ ourstatus->value.sig =
+ target_signal_from_host (status.info.si_signo);
+ exit_signo = 0;
+ break;
+ case _DEBUG_WHY_FAULTED:
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ if (status.info.si_signo == SIGTRAP)
+ {
+ ourstatus->value.sig = 0;
+ exit_signo = 0;
+ }
+ else
+ {
+ ourstatus->value.sig =
+ target_signal_from_host (status.info.si_signo);
+ exit_signo = ourstatus->value.sig;
+ }
+ break;
+
+ case _DEBUG_WHY_TERMINATED:
+ {
+ int waitval = 0;
+
+ waitpid (PIDGET (inferior_ptid), &waitval, WNOHANG);
+ if (exit_signo)
+ {
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED; /* abnormal death */
+ ourstatus->value.sig = exit_signo;
+ }
+ else
+ {
+ ourstatus->kind = TARGET_WAITKIND_EXITED; /* normal death */
+ ourstatus->value.integer = WEXITSTATUS (waitval);
+ }
+ exit_signo = 0;
+ break;
+ }
+
+ case _DEBUG_WHY_REQUESTED:
+ /* we are assuming a requested stop is due to a SIGINT */
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ ourstatus->value.sig = TARGET_SIGNAL_INT;
+ exit_signo = 0;
+ break;
+ }
+ }
+
+ return inferior_ptid;
+ }
+
+ /*
+
+ 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.
+
+ */
+
+ 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, ®, sizeof (reg), ®size) == EOK)
+ {
+ nto_supply_gregset (®.greg);
+ }
+ if (devctl (ctl_fd, DCMD_PROC_GETFPREG, ®, sizeof (reg), ®size) ==
+ EOK)
+ {
+ nto_supply_fpregset (®.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
+ procfs_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 procfs_breakpoint (addr, _DEBUG_BREAK_EXEC, 0);
+ }
+
+ static int
+ procfs_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+ {
+ return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC, -1);
+ }
+
+ static int
+ procfs_insert_hw_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+ {
+ return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, 0);
+ }
+
+ static int
+ procfs_remove_hw_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+ {
+ return procfs_breakpoint (addr, _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, -1);
+ }
+
+ static void
+ procfs_resume (ptid_t ptid, int step, enum target_signal signo)
+ {
+ int signal_to_pass;
+ procfs_status status;
+
+ if (ptid_equal (inferior_ptid, null_ptid))
+ return;
+
+ procfs_set_thread (ptid_equal (ptid, minus_one_ptid) ? inferior_ptid :
+ ptid);
+
+
+ run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
+ if (step)
+ run.flags |= _DEBUG_RUN_STEP;
+
+ sigemptyset ((sigset_t *) & run.fault);
+ sigaddset ((sigset_t *) & run.fault, FLTBPT);
+ sigaddset ((sigset_t *) & run.fault, FLTTRACE);
+ sigaddset ((sigset_t *) & run.fault, FLTILL);
+ sigaddset ((sigset_t *) & run.fault, FLTPRIV);
+ sigaddset ((sigset_t *) & run.fault, FLTBOUNDS);
+ sigaddset ((sigset_t *) & run.fault, FLTIOVF);
+ sigaddset ((sigset_t *) & run.fault, FLTIZDIV);
+ sigaddset ((sigset_t *) & run.fault, FLTFPE);
+ /* Peter V will be changing this at some point... */
+ sigaddset ((sigset_t *) & run.fault, FLTPAGE);
+
+ run.flags |= _DEBUG_RUN_ARM;
+
+ sigemptyset (&run.trace);
+ notice_signals ();
+ signal_to_pass = target_signal_to_host (signo);
+
+ if (signal_to_pass)
+ {
+ devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
+ signal_to_pass = target_signal_to_host (signo);
+ if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
+ {
+ if (signal_to_pass != status.info.si_signo)
+ {
+ SignalKill (QNX_NODE, PIDGET (inferior_ptid), 0, signal_to_pass,
+ 0, 0);
+ run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
+ }
+ else
+ {
+ /* let it kill the program without telling us */
+ sigdelset (&run.trace, signal_to_pass);
+ }
+ }
+ }
+ else
+ {
+ run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
+ }
+ if ((errno = devctl (ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0)) != EOK)
+ {
+ perror ("run error!\n");
+ return;
+ }
+ }
+
+ static void
+ procfs_mourn_inferior ()
+ {
+ if (!ptid_equal (inferior_ptid, null_ptid))
+ {
+ SignalKill (QNX_NODE, PIDGET (inferior_ptid), 0, SIGKILL, 0, 0);
+ close (ctl_fd);
+ }
+ inferior_ptid = null_ptid;
+ init_thread_list ();
+ unpush_target (&procfs_ops);
+ generic_mourn_inferior ();
+ attach_flag = 0;
+ }
+
+ /* This function breaks up an argument string into an argument
+ * vector suitable for passing to execvp().
+ * E.g., on "run a b c d" this routine would get as input
+ * the string "a b c d", and as output it would fill in argv with
+ * the four arguments "a", "b", "c", "d". The only additional
+ * functionality is simple quoting. The gdb command:
+ * run a "b c d" f
+ * will fill in argv with the three args "a", "b c d", "e".
+ */
+ static void
+ breakup_args (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 = nto_parse_redirection (argv, &in, &out, &err);
+
+ fds[0] = STDIN_FILENO;
+ fds[1] = STDOUT_FILENO;
+ fds[2] = STDERR_FILENO;
+
+ /* If the user specified I/O via gdb's --tty= arg, use it, but only
+ if the i/o is not also being specified via redirection. */
+ if (inferior_io_terminal)
+ {
+ if (!in[0])
+ in = inferior_io_terminal;
+ if (!out[0])
+ out = inferior_io_terminal;
+ if (!err[0])
+ err = inferior_io_terminal;
+ }
+
+ if (in[0])
+ {
+ if ((fd = open (in, O_RDONLY)) == -1)
+ {
+ perror (in);
+ }
+ else
+ fds[0] = fd;
+ }
+ if (out[0])
+ {
+ if ((fd = open (out, O_WRONLY)) == -1)
+ {
+ perror (out);
+ }
+ else
+ fds[1] = fd;
+ }
+ if (err[0])
+ {
+ if ((fd = open (err, O_WRONLY)) == -1)
+ {
+ perror (err);
+ }
+ else
+ fds[2] = fd;
+ }
+
+ /* Clear any pending SIGUSR1's but keep the behavior the same. */
+ signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
+
+ sigemptyset (&set);
+ sigaddset (&set, SIGUSR1);
+ sigprocmask (SIG_UNBLOCK, &set, NULL);
+
+ memset (&inherit, 0, sizeof (inherit));
+
+ if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) != 0)
+ {
+ inherit.nd = QNX_NODE;
+ inherit.flags |= SPAWN_SETND;
+ inherit.flags &= ~SPAWN_EXEC;
+ }
+ inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
+ inherit.pgroup = SPAWN_NEWPGROUP;
+ pid =
+ spawnp (argv[0], 3, fds, &inherit, argv,
+ ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0 ? env : 0);
+ xfree (args);
+
+ sigprocmask (SIG_BLOCK, &set, NULL);
+
+ if (pid == -1)
+ error ("Error spawning %s: %d (%s)", argv[0], errno, strerror (errno));
+
+ if (fds[0] != STDIN_FILENO)
+ close (fds[0]);
+ if (fds[1] != STDOUT_FILENO)
+ close (fds[1]);
+ if (fds[2] != STDERR_FILENO)
+ close (fds[2]);
+
+ inferior_ptid = do_attach (pid_to_ptid (pid));
+
+ attach_flag = 0;
+ flags = _DEBUG_FLAG_KLC; /* Kill-on-Last-Close flag */
+ if ((errn =
+ devctl (ctl_fd, DCMD_PROC_SET_FLAG, &flags, sizeof (flags), 0)) != EOK)
+ {
+ /* warning( "Failed to set Kill-on-Last-Close flag: errno = %d(%s)\n", errn, strerror(errn) ); */
+ }
+ push_target (&procfs_ops);
+ target_terminal_init ();
+
+ #ifdef SOLIB_CREATE_INFERIOR_HOOK
+ if (exec_bfd != NULL
+ || (symfile_objfile != NULL && symfile_objfile->obfd != NULL))
+ SOLIB_CREATE_INFERIOR_HOOK (pid);
+ #endif
+ }
+
+ static void
+ procfs_stop ()
+ {
+ devctl (ctl_fd, DCMD_PROC_STOP, NULL, 0, 0);
+ }
+
+ static void
+ procfs_kill_inferior ()
+ {
+ target_mourn_inferior ();
+ }
+
+ /* Store register REGNO, or all registers if REGNO == -1, from the contents
+ of REGISTERS. */
+
+ static void
+ procfs_prepare_to_store ()
+ {
+ }
+
+ 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 = nto_cpu_register_area (first, last, &subcmd, &off, &len);
+ switch (subcmd)
+ {
+ case DSMSG_REG_GENERAL:
+ if (devctl
+ (ctl_fd, DCMD_PROC_GETGREG, ®.greg, sizeof (reg.greg),
+ 0) != EOK)
+ {
+ printf ("error fetching general registers\n");
+ break;
+ }
+ data = (char *) ®.greg + off;
+ if (nto_cpu_register_store (0, first, end, data))
+ {
+ devctl (ctl_fd, DCMD_PROC_SETGREG, ®.greg,
+ sizeof (reg.greg), 0);
+ }
+ break;
+ case DSMSG_REG_FLOAT:
+ if (devctl
+ (ctl_fd, DCMD_PROC_GETFPREG, ®.fpreg,
+ sizeof (reg.fpreg), 0) != EOK)
+ {
+ /* Do not print a warning. Not all inferiors
+ have fpregs. */
+ break;
+ }
+ data = (char *) ®.fpreg + off;
+ if (nto_cpu_register_store (0, first, end, data))
+ {
+ devctl (ctl_fd, DCMD_PROC_SETFPREG, ®.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 struct tidinfo *
+ procfs_thread_info (pid_t pid, short tid)
+ {
+ /* NYI */
+ return NULL;
+ }
+
+ char *
+ procfs_pid_to_str (ptid_t ptid)
+ {
+ static char buf[1024];
+ int pid, tid, n;
+ struct tidinfo *tip;
+
+ pid = ptid_get_pid (ptid);
+ tid = ptid_get_tid (ptid);
+
+ n = sprintf (buf, "process %d", pid);
+
+ tip = procfs_thread_info (pid, tid);
+ if (tip != NULL)
+ sprintf (&buf[n], " (state = 0x%02x)", tip->state);
+
+ return buf;
+ }
+
+ static void
+ init_procfs_ops ()
+ {
+ procfs_ops.to_shortname = "procfs";
+ procfs_ops.to_longname = "QNX Neutrino procfs child process";
+ procfs_ops.to_doc =
+ "QNX Neutrino procfs child process (started by the \"run\" command).\n\
+ target procfs <node>";
+ procfs_ops.to_open = procfs_open;
+ procfs_ops.to_attach = procfs_attach;
+ procfs_ops.to_detach = procfs_detach;
+ procfs_ops.to_resume = procfs_resume;
+ procfs_ops.to_wait = procfs_wait;
+ procfs_ops.to_fetch_registers = procfs_fetch_registers;
+ procfs_ops.to_store_registers = procfs_store_registers;
+ procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
+ procfs_ops.to_xfer_memory = procfs_xfer_memory;
+ procfs_ops.to_files_info = procfs_files_info;
+ procfs_ops.to_insert_breakpoint = procfs_insert_breakpoint;
+ procfs_ops.to_remove_breakpoint = procfs_remove_breakpoint;
+ procfs_ops.to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
+ procfs_ops.to_insert_hw_breakpoint = procfs_insert_hw_breakpoint;
+ procfs_ops.to_remove_hw_breakpoint = procfs_remove_breakpoint;
+ procfs_ops.to_insert_watchpoint = procfs_insert_hw_watchpoint;
+ procfs_ops.to_remove_watchpoint = procfs_remove_hw_watchpoint;
+ procfs_ops.to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
+ procfs_ops.to_terminal_init = terminal_init_inferior;
+ procfs_ops.to_terminal_inferior = terminal_inferior;
+ procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ procfs_ops.to_terminal_ours = terminal_ours;
+ procfs_ops.to_terminal_info = child_terminal_info;
+ procfs_ops.to_kill = procfs_kill_inferior;
+ procfs_ops.to_create_inferior = procfs_create_inferior;
+ procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
+ procfs_ops.to_can_run = procfs_can_run;
+ procfs_ops.to_notice_signals = procfs_notice_signals;
+ procfs_ops.to_thread_alive = procfs_thread_alive;
+ procfs_ops.to_find_new_threads = procfs_find_new_threads;
+ procfs_ops.to_pid_to_str = procfs_pid_to_str;
+ procfs_ops.to_stop = procfs_stop;
+ procfs_ops.to_stratum = process_stratum;
+ procfs_ops.to_has_all_memory = 1;
+ procfs_ops.to_has_memory = 1;
+ procfs_ops.to_has_stack = 1;
+ procfs_ops.to_has_registers = 1;
+ procfs_ops.to_has_execution = 1;
+ procfs_ops.to_magic = OPS_MAGIC;
+ }
+
+ extern int nto_ostype;
+
+ void
+ _initialize_procfs ()
+ {
+ sigset_t set;
+ extern struct dscpuinfo nto_cpuinfo;
+ extern int nto_cpuinfo_valid;
+
+ init_procfs_ops ();
+ add_target (&procfs_ops);
+ nto_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 */
+ nto_cpuinfo.cpuflags = SYSPAGE_ENTRY (cpuinfo)->flags;
+ nto_cpuinfo_valid = 1;
+
+ add_info ("pidlist", procfs_pidlist, "pidlist");
+ add_info ("meminfo", procfs_meminfo, "memory information");
+ }
+
+
+ static int
+ procfs_hw_watchpoint (int addr, int len, int type)
+ {
+ procfs_break brk;
+ int err;
+
+ switch (type)
+ {
+ case 1: /* Read */
+ brk.type = _DEBUG_BREAK_RD;
+ break;
+ case 2: /* Read/Write */
+ brk.type = _DEBUG_BREAK_RW;
+ break;
+ default: /* Modify */
+ /* brk.type = _DEBUG_BREAK_RWM; This should work, shouldn't it? I get EINVAL */
+ brk.type = _DEBUG_BREAK_RW;
+ }
+ brk.type |= _DEBUG_BREAK_HW; /* always ask for HW */
+ brk.addr = addr;
+ brk.size = len;
+
+ if ((err = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0)) != EOK)
+ {
+ errno = err;
+ perror ("Failed to set hardware watchpoint");
+ return -1;
+ }
+ return 0;
+ }
+
+ static int
+ procfs_can_use_hw_breakpoint (int type, int cnt, int othertype)
+ {
+ return 1;
+ }
+
+ static int
+ procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type)
+ {
+ return procfs_hw_watchpoint (addr, -1, type);
+ }
+
+ static int
+ procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type)
+ {
+ return procfs_hw_watchpoint (addr, len, type);
+ }
+
+ static int
+ procfs_stopped_by_watchpoint (void)
+ {
+ return 0;
+ }
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/nto-share/debug.h src.new/gdb/nto-share/debug.h
*** src.orig/gdb/nto-share/debug.h Wed Dec 31 19:00:00 1969
--- src.new/gdb/nto-share/debug.h Fri Feb 14 13:28:11 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_nto_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.new/gdb/nto-share/dsmsgs.h
*** src.orig/gdb/nto-share/dsmsgs.h Wed Dec 31 19:00:00 1969
--- src.new/gdb/nto-share/dsmsgs.h Fri Feb 14 15:37:26 2003
***************
*** 0 ****
--- 1,714 ----
+ #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/nto-tdep.c src.new/gdb/nto-tdep.c
*** src.orig/gdb/nto-tdep.c Wed Dec 31 19:00:00 1969
--- src.new/gdb/nto-tdep.c Fri Feb 14 13:28:11 2003
***************
*** 0 ****
--- 1,309 ----
+ #include <sys/stat.h>
+ #include <string.h>
+ #include "nto-tdep.h"
+ #include "top.h"
+ #include "cli/cli-decode.h"
+ #include "cli/cli-cmds.h"
+ #include "inferior.h"
+ #include "gdbarch.h"
+ #include "bfd.h"
+ #include "elf-bfd.h"
+ #include "solib-svr4.h"
+ #include "gdbcore.h"
+
+ #ifdef __CYGWIN__
+ #include <sys/cygwin.h>
+ #endif
+
+ #ifdef __CYGWIN__
+ static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
+ #elif defined(__sun__) || defined(linux)
+ static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
+ #else
+ static char default_nto_target[] = "";
+ #endif
+
+ /* Maintenance debugging flag */
+ int nto_internal_debugging;
+
+ /* Filled in cpu info structure and flag to indicate its validity.
+ * This is initialized in procfs_attach or nto_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 nto_cpuinfo;
+ int nto_cpuinfo_valid;
+ int nto_ostype = -1;
+
+ static char *
+ nto_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_nto_target, buf);
+ return buf;
+ #else
+ return p ? p : default_nto_target;
+ #endif
+ }
+
+ void
+ nto_init_solib_search_path (void)
+ {
+ char buf[PATH_MAX * 2], arch_path[PATH_MAX];
+ char *nto_root, *endian;
+ const char *arch;
+ 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 = nto_target ();
+ if (strcmp (TARGET_ARCHITECTURE->arch_name, "i386") == 0)
+ {
+ arch = "x86";
+ endian = "";
+ }
+ else if (strcmp (TARGET_ARCHITECTURE->arch_name, "rs6000") == 0)
+ {
+ arch = "ppc";
+ endian = "be";
+ }
+ else
+ {
+ arch = TARGET_ARCHITECTURE->arch_name;
+ endian = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "be" : "le";
+ }
+
+ sprintf (arch_path, "%s/%s%s", nto_root, arch, endian);
+
+ sprintf (buf, "set solib-absolute-prefix %s", arch_path);
+ execute_command (buf, 0);
+
+ sprintf (buf, "%s/lib:%s/usr/lib:%s/usr/photon/lib\
+ :%s/usr/photon/dll:%s/lib/dll", arch_path, arch_path, arch_path, arch_path, arch_path);
+ /* we already looked up the command...might as well use it */
+ *((char **) c->var) = xstrdup (buf);
+ }
+
+ char **
+ nto_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;
+ }
+
+ void
+ nto_source_extra_gdbinit (char *file)
+ {
+ char *homedir, *homeinit;
+ struct stat statbuf;
+
+ homedir = getenv ("HOME");
+
+ if (homedir && !inhibit_gdbinit)
+ {
+ homeinit = (char *) alloca (strlen (homedir) + strlen (file) + 10);
+ sprintf (homeinit, "%s/%s", homedir, file);
+ if (stat (homeinit, &statbuf) == 0)
+ catch_command_errors (source_command, homeinit, 0, RETURN_MASK_ALL);
+ }
+ }
+
+ /* struct lm_info, LM_ADDR, and nto_truncate_ptr are copied from
+ solib-svr4.c to support nto_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 = nto_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
+ nto_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);
+ }
+
+ 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;
+ }
+
+ void
+ nto_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 = nto_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
+ sec->endaddr = nto_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
+ }
+
+ 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;
+ {
+ nto_gregset_t gregset;
+ nto_fpregset_t fpregset;
+
+ nto_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);
+ }
+ }
+
+ /* 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_tdep ()
+ {
+ 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);
+
+ /* 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);
+
+ /* by default we don't want to stop on these two, but we do want to pass */
+ #if defined(SIGSELECT)
+ 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 (®set_core_fns);
+ }
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/nto-tdep.h src.new/gdb/nto-tdep.h
*** src.orig/gdb/nto-tdep.h Wed Dec 31 19:00:00 1969
--- src.new/gdb/nto-tdep.h Fri Feb 14 13:28:11 2003
***************
*** 0 ****
--- 1,54 ----
+ #ifndef _NTO_TDEP_H
+ #define _NTO_TDEP_H
+
+ #include "defs.h"
+ #include "nto-share/debug.h"
+ #include "nto-share/dsmsgs.h"
+ #include "solist.h"
+
+ /* Generic functions in nto-tdep.c */
+
+ extern void nto_init_solib_search_path PARAMS ((void));
+
+ char **nto_parse_redirection
+ PARAMS ((char *start_argv[], char **in, char **out, char **err));
+
+ int proc_iterate_over_mappings PARAMS ((int (*func) (int, CORE_ADDR)));
+
+ void nto_source_extra_gdbinit PARAMS ((char *));
+
+ void nto_relocate_section_addresses
+ PARAMS ((struct so_list *, struct section_table *));
+
+ /* Functions exported from all Neutrino targets (<target>-nto-tdep.c) */
+
+ unsigned nto_get_regset_id PARAMS ((int regno));
+
+ void nto_cpu_regset_fetch PARAMS ((int endian, int regset, void *data));
+
+ unsigned nto_get_regset_area PARAMS ((unsigned regset, char *subcmd));
+
+ unsigned nto_cpu_register_area
+ PARAMS ((unsigned first_regno, unsigned last_regno, unsigned char *subcmd,
+ unsigned *off, unsigned *len));
+
+ void nto_cpu_register_fetch
+ PARAMS ((int endian, unsigned first_regno, unsigned last_regno, void *data));
+
+ int nto_cpu_register_store
+ PARAMS ((int endian, unsigned first_regno, unsigned last_regno, void *data));
+
+ void nto_supply_gregset PARAMS ((union _debug_gregs *));
+
+ void nto_supply_fpregset PARAMS ((union _debug_fpregs *));
+
+ struct link_map_offsets *nto_fetch_link_map_offsets PARAMS ((void));
+
+ /* Globals */
+
+ extern int nto_internal_debugging;
+ extern struct dscpuinfo nto_cpuinfo;
+ extern int nto_cpuinfo_valid;
+ extern int nto_ostype;
+
+ #endif
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/gdb/osabi.c src.new/gdb/osabi.c
*** src.orig/gdb/osabi.c Sat Jan 4 18:47:13 2003
--- src.new/gdb/osabi.c Fri Feb 7 11:27:35 2003
*************** static const char * const gdb_osabi_name
*** 72,77 ****
--- 72,78 ----
"ARM EABI v1",
"ARM EABI v2",
"ARM APCS",
+ "QNX Neutrino",
"<invalid>"
};
diff -rc3p -N -x '.#*' -x CVS -x'*.cache' -xMakefile.in -x configure src.orig/readline/aclocal.m4 src.new/readline/aclocal.m4
*** src.orig/readline/aclocal.m4 Sun Dec 8 17:31:37 2002
--- src.new/readline/aclocal.m4 Fri Feb 7 11:27:59 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([
*** src.orig//readline/Makefile.in Sun Dec 8 17:31:37 2002
--- src.new//readline/Makefile.in Fri Feb 7 11:28:00 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
*** src.orig//readline/shlib/Makefile.in Sun Dec 8 17:31:38 2002
--- src.new//readline/shlib/Makefile.in Fri Feb 7 11:28:00 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] 6+ messages in thread
* [Patch] add GDB_OSABI_QNXNTO
[not found] ` <86lm06oaf9.fsf@elgar.kettenis.dyndns.org>
@ 2003-02-24 15:56 ` Kris Warkentin
2003-02-25 16:31 ` Kevin Buettner
2003-02-25 16:44 ` pending/1094: " Andrew Cagney
0 siblings, 2 replies; 6+ messages in thread
From: Kris Warkentin @ 2003-02-24 15:56 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 90 bytes --]
Attached find a patch and changelog for gdb osabi support for QNX Neutrino.
cheers,
Kris
[-- Attachment #2: osabi.diff --]
[-- Type: application/octet-stream, Size: 805 bytes --]
Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.113
diff -u -r1.113 defs.h
--- defs.h 14 Feb 2003 13:58:05 -0000 1.113
+++ defs.h 24 Feb 2003 15:51:34 -0000
@@ -1008,6 +1008,7 @@
GDB_OSABI_ARM_EABI_V1,
GDB_OSABI_ARM_EABI_V2,
GDB_OSABI_ARM_APCS,
+ GDB_OSABI_QNXNTO,
GDB_OSABI_INVALID /* keep this last */
};
Index: osabi.c
===================================================================
RCS file: /cvs/src/src/gdb/osabi.c,v
retrieving revision 1.12
diff -u -r1.12 osabi.c
--- osabi.c 4 Jan 2003 23:47:13 -0000 1.12
+++ osabi.c 24 Feb 2003 15:51:34 -0000
@@ -72,6 +72,7 @@
"ARM EABI v1",
"ARM EABI v2",
"ARM APCS",
+ "QNX Neutrino",
"<invalid>"
};
[-- Attachment #3: osabi.changelog --]
[-- Type: application/octet-stream, Size: 145 bytes --]
2003-02-24 Kris Warkentin <kewarken@qnx.com>
* defs.h (gdb_osabi): add GDB_OSABI_QNXNTO
* osabi.c (gdb_osabi_names): add "QNX Neutrino"
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Patch] add GDB_OSABI_QNXNTO
2003-02-24 15:56 ` [Patch] add GDB_OSABI_QNXNTO Kris Warkentin
@ 2003-02-25 16:31 ` Kevin Buettner
2003-02-26 15:13 ` Kris Warkentin
2003-02-25 16:44 ` pending/1094: " Andrew Cagney
1 sibling, 1 reply; 6+ messages in thread
From: Kevin Buettner @ 2003-02-25 16:31 UTC (permalink / raw)
To: Kris Warkentin; +Cc: gdb-patches
On Feb 24, 10:56am, Kris Warkentin wrote:
> Attached find a patch and changelog for gdb osabi support for QNX Neutrino.
[From attachment...]
> 2003-02-24 Kris Warkentin <kewarken@qnx.com>
>
> * defs.h (gdb_osabi): add GDB_OSABI_QNXNTO
> * osabi.c (gdb_osabi_names): add "QNX Neutrino"
This is approved. But, please make sure that you've fixed the punctuation
and capitalization in your ChangeLog entry before committing it.
Kevin
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: pending/1094: [Patch] add GDB_OSABI_QNXNTO
2003-02-24 15:56 ` [Patch] add GDB_OSABI_QNXNTO Kris Warkentin
2003-02-25 16:31 ` Kevin Buettner
@ 2003-02-25 16:44 ` Andrew Cagney
1 sibling, 0 replies; 6+ messages in thread
From: Andrew Cagney @ 2003-02-25 16:44 UTC (permalink / raw)
To: Kris Warkentin; +Cc: gdb-gnats, gdb-patches
Kris,
Actually, this is approved (now that I've unexpectedly managed to see
the contents of the patch).
Andrew
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Patch] add GDB_OSABI_QNXNTO
2003-02-25 16:31 ` Kevin Buettner
@ 2003-02-26 15:13 ` Kris Warkentin
0 siblings, 0 replies; 6+ messages in thread
From: Kris Warkentin @ 2003-02-26 15:13 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches
> > Attached find a patch and changelog for gdb osabi support for QNX
Neutrino.
>
> [From attachment...]
>
> > 2003-02-24 Kris Warkentin <kewarken@qnx.com>
> >
> > * defs.h (gdb_osabi): add GDB_OSABI_QNXNTO
> > * osabi.c (gdb_osabi_names): add "QNX Neutrino"
>
> This is approved. But, please make sure that you've fixed the punctuation
> and capitalization in your ChangeLog entry before committing it.
Committed.
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [Patch] QNX i386 native support take 2
@ 2003-02-18 6:20 Zaretskii Eli
0 siblings, 0 replies; 6+ messages in thread
From: Zaretskii Eli @ 2003-02-18 6:20 UTC (permalink / raw)
To: Kris Warkentin, gdb-patches
This message was scanned for viruses and other malicious code by PrivaWall.
This mail was sent from ELTA SYS LTD.
> From: Kris Warkentin [mailto:kewarken@qnx.com]
> Sent: Monday, February 17, 2003 10:56 PM
> Here is take 2 of the patch.
The fnchange.lst patch is approved. Thanks.
This message is processed by the PrivaWall Email Security Server.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2003-02-26 15:13 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-02-17 20:56 [Patch] QNX i386 native support take 2 Kris Warkentin
[not found] ` <86lm06oaf9.fsf@elgar.kettenis.dyndns.org>
2003-02-24 15:56 ` [Patch] add GDB_OSABI_QNXNTO Kris Warkentin
2003-02-25 16:31 ` Kevin Buettner
2003-02-26 15:13 ` Kris Warkentin
2003-02-25 16:44 ` pending/1094: " Andrew Cagney
2003-02-18 6:20 [Patch] QNX i386 native support take 2 Zaretskii Eli
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox