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 + #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 + #endif + + #include + #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 + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #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 ' 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 "; + 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 + #include + #include + + #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 + + /* 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 */ + } 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 + #include + #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 + #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 (-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", "" }; 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