Added i386 QNX Neutrino support.
authorKris Warkentin <kewarken@qnx.com>
Mon, 5 May 2003 13:57:21 +0000 (13:57 +0000)
committerKris Warkentin <kewarken@qnx.com>
Mon, 5 May 2003 13:57:21 +0000 (13:57 +0000)
gdb/config/i386/nto.mt [new file with mode: 0644]
gdb/config/i386/tm-nto.h [new file with mode: 0644]
gdb/config/tm-nto.h [new file with mode: 0644]
gdb/configure.tgt
gdb/i386-nto-tdep.c [new file with mode: 0644]
gdb/nto-tdep.c [new file with mode: 0644]
gdb/nto-tdep.h [new file with mode: 0644]

diff --git a/gdb/config/i386/nto.mt b/gdb/config/i386/nto.mt
new file mode 100644 (file)
index 0000000..6655f3e
--- /dev/null
@@ -0,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-nto.h
diff --git a/gdb/config/i386/tm-nto.h b/gdb/config/i386/tm-nto.h
new file mode 100644 (file)
index 0000000..ff5eb78
--- /dev/null
@@ -0,0 +1,33 @@
+/* QNX Neutrino target header.
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This code was donated by QNX Software Systems Ltd.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef TM_NTO_H
+#define TM_NTO_H 1
+
+/* Pick up most of what we need from the generic i386 target include file.  */
+#include "i386/tm-i386.h"
+#include "tm-nto.h"
+
+#include "solib.h"
+
+#endif /* TM_NTO_H */
diff --git a/gdb/config/tm-nto.h b/gdb/config/tm-nto.h
new file mode 100644 (file)
index 0000000..359ff06
--- /dev/null
@@ -0,0 +1,61 @@
+/* Target machine sub-description for QNX Neutrino version 6.
+   This is included by other tm-*.h files to specify nto specific
+   stuff. 
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This code was donated by QNX Software Systems Ltd.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#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 */
index aeb9e2718e1d2b2377968bafe4190744e50bb37a..fe4cc5d485677c10e817cd180f3e9d55de1a0b2f 100644 (file)
@@ -51,6 +51,7 @@ arm*-*-linux*)                gdb_target=linux
                        ;;
 arm*-*-netbsd*)                gdb_target=nbsd
                        gdb_multi_arch=yes ;;
+arm-*-nto*)            gdb_target=nto ;;
 arm*-*-* | thumb*-*-* | strongarm*-*-*)
                        gdb_target=embed
                         configdirs="$configdirs rdi-share"
@@ -90,6 +91,7 @@ i[3456]86-*-netbsd*)  gdb_target=nbsd ;;
 i[3456]86-*-openbsd*)  gdb_target=obsd ;;
 i[3456]86-*-go32*)     gdb_target=i386aout ;;
 i[3456]86-*-msdosdjgpp*) gdb_target=go32 ;;
+i[3456]86-*-nto*)      gdb_target=nto ;;
 i[3456]86-*-lynxos*)   gdb_target=i386lynx ;;
 i[3456]86-*-solaris*)  gdb_target=i386sol2 ;;
 i[3456]86-*-sco*)      gdb_target=i386v ;;
@@ -216,6 +218,7 @@ sh-*-linux*)                gdb_target=linux
                        build_gdbserver=yes
                        ;;
 sh*-*-netbsdelf*)      gdb_target=nbsd ;;
+sh-*-nto*)             gdb_target=nto ;;
 sh*)                   gdb_target=embed ;;
 
 sparc-*-aout*)         gdb_target=sparc-em ;;
@@ -280,5 +283,6 @@ esac
 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 --git a/gdb/i386-nto-tdep.c b/gdb/i386-nto-tdep.c
new file mode 100644 (file)
index 0000000..42eb9ce
--- /dev/null
@@ -0,0 +1,298 @@
+/* i386-nto-tdep.c - i386 specific functionality for QNX Neutrino.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by QNX Software Systems Ltd.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "gdb_string.h"
+#include "gdb_assert.h"
+#include "defs.h"
+#include "frame.h"
+#include "target.h"
+#include "regcache.h"
+#include "solib-svr4.h"
+#include "i386-tdep.h"
+#include "nto-tdep.h"
+#include "osabi.h"
+#include "i387-tdep.h"
+
+#ifndef X86_CPU_FXSR
+#define X86_CPU_FXSR (1L << 12)
+#endif
+
+/* Why 13?  Look in our /usr/include/x86/context.h header at the
+   x86_cpu_registers structure and you'll see an 'exx' junk register
+   that is just filler.  Don't ask me, ask the kernel guys.  */
+#define NUM_GPREGS 13
+
+/* Map a GDB register number to an offset in the reg structure.  */
+static int regmap[] = {
+  (7 * 4),                     /* eax */
+  (6 * 4),                     /* ecx */
+  (5 * 4),                     /* edx */
+  (4 * 4),                     /* ebx */
+  (11 * 4),                    /* esp */
+  (2 * 4),                     /* epb */
+  (1 * 4),                     /* esi */
+  (0 * 4),                     /* edi */
+  (8 * 4),                     /* eip */
+  (10 * 4),                    /* eflags */
+  (9 * 4),                     /* cs */
+  (12 * 4),                    /* ss */
+  (-1 * 4)                     /* filler */
+};
+
+/* Given a gdb regno, return the offset into Neutrino's register structure
+   or -1 if register is unknown.  */
+static int
+nto_reg_offset (int regno)
+{
+  return (regno >= 0 && regno < NUM_GPREGS) ? regmap[regno] : -1;
+}
+
+static void
+i386nto_supply_gregset (char *gpregs)
+{
+  unsigned regno;
+  int empty = 0;
+
+  for (regno = 0; regno < FP0_REGNUM; regno++)
+    {
+      int offset = nto_reg_offset (regno);
+      if (offset == -1)
+       supply_register (regno, (char *) &empty);
+      else
+       supply_register (regno, gpregs + offset);
+    }
+}
+
+static void
+i386nto_supply_fpregset (char *fpregs)
+{
+  if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
+    i387_supply_fxsave (fpregs);
+  else
+    i387_supply_fsave (fpregs);
+}
+
+static void
+i386nto_supply_regset (int regset, char *data)
+{
+  switch (regset)
+    {
+    case NTO_REG_GENERAL:      /* QNX has different ordering of GP regs than GDB.  */
+      i386nto_supply_gregset (data);
+      break;
+    case NTO_REG_FLOAT:
+      i386nto_supply_fpregset (data);
+      break;
+    }
+}
+
+static int
+i386nto_regset_id (int regno)
+{
+  if (regno == -1)
+    return NTO_REG_END;
+  else if (regno < FP0_REGNUM)
+    return NTO_REG_GENERAL;
+  else if (regno < FPC_REGNUM)
+    return NTO_REG_FLOAT;
+
+  return -1;                   /* Error.  */
+}
+
+static int
+i386nto_register_area (int regno, int regset, unsigned *off)
+{
+  int len;
+
+  *off = 0;
+  if (regset == NTO_REG_GENERAL)
+    {
+      if (regno == -1)
+       return NUM_GPREGS * 4;
+
+      *off = nto_reg_offset (regno);
+      if (*off == -1)
+       return 0;
+      return 4;
+    }
+  else if (regset == NTO_REG_FLOAT)
+    {
+      unsigned off_adjust, regsize, regset_size;
+
+      if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
+       {
+         off_adjust = 32;
+         regsize = 16;
+         regset_size = 512;
+       }
+      else
+       {
+         off_adjust = 28;
+         regsize = 10;
+         regset_size = 128;
+       }
+
+      if (regno == -1)
+       return regset_size;
+
+      *off = (regno - FP0_REGNUM) * regsize + off_adjust;
+      return 10;
+      /* Why 10 instead of regsize?  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.  */
+    }
+  return -1;
+}
+
+static int
+i386nto_regset_fill (int regset, char *data)
+{
+  if (regset == NTO_REG_GENERAL)
+    {
+      int regno;
+
+      for (regno = 0; regno < NUM_GPREGS; regno++)
+       {
+         int offset = nto_reg_offset (regno);
+         if (offset != -1)
+           regcache_collect (regno, data + offset);
+       }
+    }
+  else if (regset == NTO_REG_FLOAT)
+    {
+      if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
+       i387_fill_fxsave (data, -1);
+      else
+       i387_fill_fsave (data, -1);
+    }
+  else
+    return -1;
+
+  return 0;
+}
+
+static struct link_map_offsets *
+i386nto_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
+                                  only 8 bytes are used.  */
+      lmo.r_map_offset = 4;
+      lmo.r_map_size = 4;
+
+      lmo.link_map_size = 20;  /* The actual size is 552 bytes, but
+                                  only 20 bytes are used.  */
+      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;
+}
+
+static int
+i386nto_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  return name && strcmp ("__signalstub", name) == 0;
+}
+
+#define SIGCONTEXT_OFFSET 136
+static CORE_ADDR
+i386nto_sigcontext_addr (struct frame_info *frame)
+{
+  if (get_next_frame (frame))
+    return get_frame_base (get_next_frame (frame)) + SIGCONTEXT_OFFSET;
+
+  return read_register (SP_REGNUM) + SIGCONTEXT_OFFSET;
+}
+
+static void
+init_i386nto_ops ()
+{
+  current_nto_target.nto_regset_id = i386nto_regset_id;
+  current_nto_target.nto_supply_gregset = i386nto_supply_gregset;
+  current_nto_target.nto_supply_fpregset = i386nto_supply_fpregset;
+  current_nto_target.nto_supply_altregset = nto_dummy_supply_regset;
+  current_nto_target.nto_supply_regset = i386nto_supply_regset;
+  current_nto_target.nto_register_area = i386nto_register_area;
+  current_nto_target.nto_regset_fill = i386nto_regset_fill;
+  current_nto_target.nto_fetch_link_map_offsets =
+    i386nto_svr4_fetch_link_map_offsets;
+}
+
+static void
+i386nto_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, i386nto_pc_in_sigtramp);
+  tdep->sigcontext_addr = i386nto_sigcontext_addr;
+  tdep->sc_pc_offset = 56;
+  tdep->sc_sp_offset = 68;
+
+  /* Setjmp()'s return PC saved in EDX (5).  */
+  tdep->jb_pc_offset = 20;     /* 5x32 bit ints in.  */
+
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+                                        i386nto_svr4_fetch_link_map_offsets);
+
+  /* Our loader handles solib relocations slightly differently than svr4.  */
+  TARGET_SO_RELOCATE_SECTION_ADDRESSES = nto_relocate_section_addresses;
+
+  /* Supply a nice function to find our solibs.  */
+  TARGET_SO_FIND_AND_OPEN_SOLIB = nto_find_and_open_solib;
+
+  init_i386nto_ops ();
+}
+
+void
+_initialize_i386nto_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_QNXNTO,
+                         i386nto_init_abi);
+}
diff --git a/gdb/nto-tdep.c b/gdb/nto-tdep.c
new file mode 100644 (file)
index 0000000..abf63b9
--- /dev/null
@@ -0,0 +1,341 @@
+/* nto-tdep.c - general QNX Neutrino target functionality.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by QNX Software Systems Ltd.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <sys/stat.h>
+#include "gdb_string.h"
+#include "nto-tdep.h"
+#include "top.h"
+#include "cli/cli-decode.h"
+#include "cli/cli-cmds.h"
+#include "inferior.h"
+#include "gdbarch.h"
+#include "bfd.h"
+#include "elf-bfd.h"
+#include "solib-svr4.h"
+#include "gdbcore.h"
+
+#ifdef __CYGWIN__
+#include <sys/cygwin.h>
+#endif
+
+#ifdef __CYGWIN__
+static char default_nto_target[] = "C:\\QNXsdk\\target\\qnx6";
+#elif defined(__sun__) || defined(linux)
+static char default_nto_target[] = "/opt/QNXsdk/target/qnx6";
+#else
+static char default_nto_target[] = "";
+#endif
+
+struct nto_target_ops current_nto_target;
+
+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
+}
+
+/* Take a string such as i386, rs6000, etc. and map it onto CPUTYPE_X86,
+   CPUTYPE_PPC, etc. as defined in nto-share/dsmsgs.h.  */
+int
+nto_map_arch_to_cputype (const char *arch)
+{
+  if (!strcmp (arch, "i386") || !strcmp (arch, "x86"))
+    return CPUTYPE_X86;
+  if (!strcmp (arch, "rs6000") || !strcmp (arch, "ppc"))
+    return CPUTYPE_PPC;
+  if (!strcmp (arch, "mips"))
+    return CPUTYPE_MIPS;
+  if (!strcmp (arch, "arm"))
+    return CPUTYPE_ARM;
+  if (!strcmp (arch, "sh"))
+    return CPUTYPE_SH;
+  return CPUTYPE_UNKNOWN;
+}
+
+int
+nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
+{
+  char *buf, arch_path[PATH_MAX], *nto_root, *endian;
+  const char *arch;
+  char *path_fmt = "%s/lib:%s/usr/lib:%s/usr/photon/lib\
+:%s/usr/photon/dll:%s/lib/dll";
+
+  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);
+
+  buf = alloca (strlen (path_fmt) + strlen (arch_path) * 5 + 1);
+  sprintf (buf, path_fmt, arch_path, arch_path, arch_path, arch_path,
+          arch_path);
+
+  return openp (buf, 1, solib, o_flags, 0, temp_pathname);
+}
+
+void
+nto_init_solib_absolute_prefix (void)
+{
+  char buf[PATH_MAX * 2], arch_path[PATH_MAX];
+  char *nto_root, *endian;
+  const char *arch;
+
+  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);
+}
+
+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;
+}
+
+/* The 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)
+{
+  /* Neutrino treats the l_addr base address field in link.h as different than
+     the base address in the System V ABI and so the offset needs to be
+     calculated and applied to relocations.  */
+  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 (char *core_reg_sect, unsigned core_reg_size,
+                     int which, CORE_ADDR reg_addr)
+{
+  nto_regset_t regset;
+
+  nto_init_solib_absolute_prefix ();
+
+  if (which == NTO_REG_GENERAL)
+    {
+      memcpy ((char *) &regset, core_reg_sect,
+             min (core_reg_size, sizeof (regset)));
+      nto_supply_gregset ((char *) &regset);
+    }
+  else if (which == NTO_REG_FLOAT)
+    {
+      memcpy ((char *) &regset, core_reg_sect,
+             min (core_reg_size, sizeof (regset)));
+      nto_supply_fpregset ((char *) &regset);
+    }
+  else if (which == NTO_REG_ALT)
+    {
+      memcpy ((char *) &regset, core_reg_sect,
+             min (core_reg_size, sizeof (regset)));
+      nto_supply_altregset ((char *) &regset);
+    }
+}
+
+void
+nto_dummy_supply_regset (char *regs)
+{
+  /* Do nothing.  */
+}
+
+/* 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 (&regset_core_fns);
+}
diff --git a/gdb/nto-tdep.h b/gdb/nto-tdep.h
new file mode 100644 (file)
index 0000000..ac6f628
--- /dev/null
@@ -0,0 +1,157 @@
+/* nto-tdep.h - QNX Neutrino target header.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by QNX Software Systems Ltd.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _NTO_TDEP_H
+#define _NTO_TDEP_H
+
+#include "defs.h"
+#include "solist.h"
+
+/* Generic functions in nto-tdep.c.  */
+
+extern void nto_init_solib_absolute_prefix 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_relocate_section_addresses
+PARAMS ((struct so_list *, struct section_table *));
+
+int nto_map_arch_to_cputype PARAMS ((const char *));
+
+int nto_find_and_open_solib PARAMS ((char *, unsigned, char **));
+
+/* Dummy function for initializing nto_target_ops on targets which do
+   not define a particular regset.  */
+void nto_dummy_supply_regset PARAMS ((char *regs));
+
+/* Target operations defined for Neutrino targets (<target>-nto-tdep.c).  */
+
+struct nto_target_ops
+{
+  int nto_internal_debugging;
+  unsigned nto_cpuinfo_flags;
+  int nto_cpuinfo_valid;
+
+  int (*nto_regset_id) (int);
+  void (*nto_supply_gregset) (char *);
+  void (*nto_supply_fpregset) (char *);
+  void (*nto_supply_altregset) (char *);
+  void (*nto_supply_regset) (int, char *);
+  int (*nto_register_area) (int, int, unsigned *);
+  int (*nto_regset_fill) (int, char *);
+  struct link_map_offsets *(*nto_fetch_link_map_offsets) (void);
+};
+
+extern struct nto_target_ops current_nto_target;
+
+/* For 'maintenance debug nto-debug' command.  */
+#define nto_internal_debugging \
+       (current_nto_target.nto_internal_debugging)
+
+/* The CPUINFO flags from the remote.  Currently used by
+   i386 for fxsave but future proofing other hosts.
+   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.  */
+#define nto_cpuinfo_flags \
+       (current_nto_target.nto_cpuinfo_flags)
+
+/* True if successfully retrieved cpuinfo from remote.  */
+#define nto_cpuinfo_valid \
+       (current_nto_target.nto_cpuinfo_valid)
+
+/* Given a register, return an id that represents the Neutrino
+   regset it came from.  If reg == -1 update all regsets.  */
+#define nto_regset_id(reg) \
+       (*current_nto_target.nto_regset_id) (reg)
+
+#define nto_supply_gregset(regs) \
+       (*current_nto_target.nto_supply_gregset) (regs)
+
+#define nto_supply_fpregset(regs) \
+       (*current_nto_target.nto_supply_fpregset) (regs)
+
+#define nto_supply_altregset(regs) \
+       (*current_nto_target.nto_supply_altregset) (regs)
+
+/* Given a regset, tell gdb about registers stored in data.  */
+#define nto_supply_regset(regset, data) \
+       (*current_nto_target.nto_supply_regset) (regset, data)
+
+/* Given a register and regset, calculate the offset into the regset
+   and stuff it into the last argument.  If regno is -1, calculate the
+   size of the entire regset.  Returns length of data, -1 if unknown
+   regset, 0 if unknown register.  */
+#define nto_register_area(reg, regset, off) \
+       (*current_nto_target.nto_register_area) (reg, regset, off)
+
+/* Build the Neutrino register set info into the data buffer.  
+   Return -1 if unknown regset, 0 otherwise.  */
+#define nto_regset_fill(regset, data) \
+       (*current_nto_target.nto_regset_fill) (regset, data)
+
+/* Gives the fetch_link_map_offsets function exposure outside of
+   solib-svr4.c so that we can override relocate_section_addresses().  */
+#define nto_fetch_link_map_offsets() \
+       (*current_nto_target.nto_fetch_link_map_offsets) ()
+
+/* Keep this consistant with neutrino syspage.h.  */
+enum
+{
+  CPUTYPE_X86,
+  CPUTYPE_PPC,
+  CPUTYPE_MIPS,
+  CPUTYPE_SPARE,
+  CPUTYPE_ARM,
+  CPUTYPE_SH,
+  CPUTYPE_UNKNOWN
+};
+
+enum
+{
+  OSTYPE_QNX4,
+  OSTYPE_NTO
+};
+
+/* These correspond to the DSMSG_* versions in dsmsgs.h. */
+enum
+{
+  NTO_REG_GENERAL,
+  NTO_REG_FLOAT,
+  NTO_REG_SYSTEM,
+  NTO_REG_ALT,
+  NTO_REG_END
+};
+
+typedef char qnx_reg64[8];
+
+typedef struct _debug_regs
+{
+  qnx_reg64 padding[1024];
+} nto_regset_t;
+
+#endif