* ppcnbsd-nat.c: Rewrite.
authorJason Thorpe <thorpej@netbsd.org>
Tue, 28 May 2002 18:43:08 +0000 (18:43 +0000)
committerJason Thorpe <thorpej@netbsd.org>
Tue, 28 May 2002 18:43:08 +0000 (18:43 +0000)
* ppcnbsd-tdep.c: New file.
* ppcnbsd-tdep.h: New file.
* config/powerpc/nbsd.mh (NATDEPFILES): Remove corelow.o,
solib.o, and solib-svr4.o.
* config/powerpc/nbsd.mt (TDEPFILES): Add ppcnbsd-tdep.o,
nbsd-tdep.o, and corelow.o.

gdb/ChangeLog
gdb/config/powerpc/nbsd.mh
gdb/config/powerpc/nbsd.mt
gdb/ppcnbsd-nat.c
gdb/ppcnbsd-tdep.c [new file with mode: 0644]
gdb/ppcnbsd-tdep.h [new file with mode: 0644]

index ffbd7fa..35913de 100644 (file)
@@ -1,3 +1,13 @@
+2002-05-28  Jason Thorpe  <thorpej@wasabisystems.com>
+
+       * ppcnbsd-nat.c: Rewrite.
+       * ppcnbsd-tdep.c: New file.
+       * ppcnbsd-tdep.h: New file.
+       * config/powerpc/nbsd.mh (NATDEPFILES): Remove corelow.o,
+       solib.o, and solib-svr4.o.
+       * config/powerpc/nbsd.mt (TDEPFILES): Add ppcnbsd-tdep.o,
+       nbsd-tdep.o, and corelow.o.
+
 2002-05-28  Andrew Cagney  <ac131313@redhat.com>
 
        * MAINTAINERS (--enable-gdb-build-warnings): Rewrite script to use
index a6de76d..9d29986 100644 (file)
@@ -1,4 +1,3 @@
 # Host: PowerPC, running NetBSD
-NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o ppcnbsd-nat.o \
-       solib.o solib-svr4.o solib-legacy.o
+NATDEPFILES= fork-child.o infptrace.o inftarg.o ppcnbsd-nat.o solib-legacy.o
 NAT_FILE= nm-nbsd.h
index 40a2a99..cbf559b 100644 (file)
@@ -1,5 +1,6 @@
 # Target: PowerPC, running NetBSD
-TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o solib.o solib-svr4.o
+TDEPFILES= rs6000-tdep.o ppcnbsd-tdep.o nbsd-tdep.o ppc-linux-tdep.o corelow.o \
+       solib.o solib-svr4.o
 TM_FILE= tm-nbsd.h
 
 SIM_OBS = remote-sim.o
index 55acf95..2e43ce4 100644 (file)
@@ -1,6 +1,6 @@
 /* Native-dependent code for PowerPC's running NetBSD, for GDB.
-   Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001
-   Free Software Foundation, Inc.
+   Copyright 2002 Free Software Foundation, Inc.
+   Contributed by Wasabi Systems, Inc.
 
    This file is part of GDB.
 
 #include <sys/types.h>
 #include <sys/ptrace.h>
 #include <machine/reg.h>
-#include <machine/frame.h>
 
 #include "defs.h"
 #include "inferior.h"
 #include "gdbcore.h"
-#include "ppc-tdep.h"
 #include "regcache.h"
 
-#define RF(dst, src) \
-        memcpy(&registers[REGISTER_BYTE(dst)], &src, sizeof(src))
-   
-#define RS(src, dst) \
-        memcpy(&dst, &registers[REGISTER_BYTE(src)], sizeof(dst))
+#include "ppc-tdep.h"
+#include "ppcnbsd-tdep.h"
 
-void
-fetch_inferior_registers (int regno)
+/* Returns true if PT_GETREGS fetches this register.  */
+static int
+getregs_supplies (int regno)
 {
-  struct reg inferior_registers;
-#ifdef PT_GETFPREGS
-  struct fpreg inferior_fp_registers;
-#endif
-  int i;
-
-  ptrace (PT_GETREGS, PIDGET (inferior_ptid),
-         (PTRACE_ARG3_TYPE) & inferior_registers, 0);
-  for (i = 0; i < 32; i++)
-    RF (i, inferior_registers.fixreg[i]);
-  RF (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum, inferior_registers.lr);
-  RF (gdbarch_tdep (current_gdbarch)->ppc_cr_regnum, inferior_registers.cr);
-  RF (gdbarch_tdep (current_gdbarch)->ppc_xer_regnum, inferior_registers.xer);
-  RF (gdbarch_tdep (current_gdbarch)->ppc_ctr_regnum, inferior_registers.ctr);
-  RF (PC_REGNUM, inferior_registers.pc);
-
-#ifdef PT_GETFPREGS
-  ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
-         (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
-  for (i = 0; i < 32; i++)
-    RF (FP0_REGNUM + i, inferior_fp_registers.fpreg[i]);
-#endif
-
-  registers_fetched ();
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+  return ((regno >= 0 && regno <= 31)
+          || regno == tdep->ppc_lr_regnum
+          || regno == tdep->ppc_cr_regnum
+          || regno == tdep->ppc_xer_regnum
+          || regno == tdep->ppc_ctr_regnum
+         || regno == PC_REGNUM);
 }
 
-void
-store_inferior_registers (int regno)
+/* Like above, but for PT_GETFPREGS.  */
+static int
+getfpregs_supplies (int regno)
 {
-  struct reg inferior_registers;
-#ifdef PT_SETFPREGS
-  struct fpreg inferior_fp_registers;
-#endif
-  int i;
-
-  for (i = 0; i < 32; i++)
-    RS (i, inferior_registers.fixreg[i]);
-  RS (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum, inferior_registers.lr);
-  RS (gdbarch_tdep (current_gdbarch)->ppc_cr_regnum, inferior_registers.cr);
-  RS (gdbarch_tdep (current_gdbarch)->ppc_xer_regnum, inferior_registers.xer);
-  RS (gdbarch_tdep (current_gdbarch)->ppc_ctr_regnum, inferior_registers.ctr);
-  RS (PC_REGNUM, inferior_registers.pc);
-
-  ptrace (PT_SETREGS, PIDGET (inferior_ptid),
-         (PTRACE_ARG3_TYPE) & inferior_registers, 0);
-
-#ifdef PT_SETFPREGS
-  for (i = 0; i < 32; i++)
-    RS (FP0_REGNUM + i, inferior_fp_registers.fpreg[i]);
-  ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
-         (PTRACE_ARG3_TYPE) & inferior_fp_registers, 0);
-#endif
-}
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
-struct md_core
-{
-  struct reg intreg;
-#ifdef PT_GETFPREGS
-  struct fpreg freg;
-#endif
-};
+  return ((regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31)
+         || regno == tdep->ppc_fpscr_regnum);
+}
 
 void
-fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
-                     CORE_ADDR ignore)
+fetch_inferior_registers (int regno)
 {
-  struct md_core *core_reg = (struct md_core *) core_reg_sect;
-  int i;
-
-  /* Integer registers */
-  for (i = 0; i < 32; i++)
-    RF (i, core_reg->intreg.fixreg[i]);
-  RF (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum, core_reg->intreg.lr);
-  RF (gdbarch_tdep (current_gdbarch)->ppc_cr_regnum, core_reg->intreg.cr);
-  RF (gdbarch_tdep (current_gdbarch)->ppc_xer_regnum, core_reg->intreg.xer);
-  RF (gdbarch_tdep (current_gdbarch)->ppc_ctr_regnum, core_reg->intreg.ctr);
-  RF (PC_REGNUM, core_reg->intreg.pc);
-
-#ifdef PT_FPGETREGS
-  /* Floating point registers */
-  for (i = 0; i < 32; i++)
-    RF (FP0_REGNUM + i, core_reg->freg.fpreg[i]);
-#endif
-
-  registers_fetched ();
+  if (regno == -1 || getregs_supplies (regno))
+    {
+      struct reg regs;
+
+      if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
+                 (PTRACE_ARG3_TYPE) &regs, 0) == -1)
+        perror_with_name ("Couldn't get registers");
+
+      ppcnbsd_supply_reg ((char *) &regs, regno);
+      if (regno != -1)
+       return;
+    }
+
+  if (regno == -1 || getfpregs_supplies (regno))
+    {
+      struct fpreg fpregs;
+
+      if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
+                 (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+       perror_with_name ("Couldn't get FP registers");
+
+      ppcnbsd_supply_fpreg ((char *) &fpregs, regno);
+      if (regno != -1)
+       return;
+    }
 }
 
-/* Register that we are able to handle ppcnbsd core file formats.
-   FIXME: is this really bfd_target_unknown_flavour? */
-
-static struct core_fns ppcnbsd_core_fns =
-{
-  bfd_target_unknown_flavour,          /* core_flavour */
-  default_check_format,                        /* check_format */
-  default_core_sniffer,                        /* core_sniffer */
-  fetch_core_registers,                        /* core_read_registers */
-  NULL                                 /* next */
-};
-
 void
-_initialize_ppcnbsd_nat (void)
+store_inferior_registers (int regno)
 {
-  add_core_fns (&ppcnbsd_core_fns);
+  if (regno == -1 || getregs_supplies (regno))
+    {
+      struct reg regs;
+
+      if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
+                 (PTRACE_ARG3_TYPE) &regs, 0) == -1)
+       perror_with_name ("Couldn't get registers");
+
+      ppcnbsd_fill_reg ((char *) &regs, regno);
+
+      if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
+                 (PTRACE_ARG3_TYPE) &regs, 0) == -1)
+       perror_with_name ("Couldn't write registers");
+
+      if (regno != -1)
+       return;
+    }
+
+  if (regno == -1 || getfpregs_supplies (regno))
+    {
+      struct fpreg fpregs;
+
+      if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
+                 (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+       perror_with_name ("Couldn't get FP registers");
+
+      ppcnbsd_fill_fpreg ((char *) &fpregs, regno);
+      
+      if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
+                 (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+       perror_with_name ("Couldn't set FP registers");
+    }
 }
diff --git a/gdb/ppcnbsd-tdep.c b/gdb/ppcnbsd-tdep.c
new file mode 100644 (file)
index 0000000..16662fd
--- /dev/null
@@ -0,0 +1,222 @@
+/* Target-dependent code for PowerPC systems running NetBSD.
+   Copyright 2002 Free Software Foundation, Inc.
+   Contributed by Wasabi Systems, 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.  */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "regcache.h"
+#include "target.h"
+#include "breakpoint.h"
+#include "value.h"
+
+#include "ppc-tdep.h"
+#include "ppcnbsd-tdep.h"
+#include "nbsd-tdep.h"
+
+#include "solib-svr4.h"
+
+#define REG_FIXREG_OFFSET(x)   ((x) * 4)
+#define REG_LR_OFFSET          (32 * 4)
+#define REG_CR_OFFSET          (33 * 4)
+#define REG_XER_OFFSET         (34 * 4)
+#define REG_CTR_OFFSET         (35 * 4)
+#define REG_PC_OFFSET          (36 * 4)
+#define SIZEOF_STRUCT_REG      (37 * 4)
+
+#define FPREG_FPR_OFFSET(x)    ((x) * 8)
+#define FPREG_FPSCR_OFFSET     (32 * 8)
+#define SIZEOF_STRUCT_FPREG    (33 * 8)
+
+void
+ppcnbsd_supply_reg (char *regs, int regno)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  int i;
+
+  for (i = 0; i <= 31; i++)
+    {
+      if (regno == i || regno == -1)
+       supply_register (i, regs + REG_FIXREG_OFFSET (i));
+    }
+
+  if (regno == tdep->ppc_lr_regnum || regno == -1)
+    supply_register (tdep->ppc_lr_regnum, regs + REG_LR_OFFSET);
+
+  if (regno == tdep->ppc_cr_regnum || regno == -1)
+    supply_register (tdep->ppc_cr_regnum, regs + REG_CR_OFFSET);
+
+  if (regno == tdep->ppc_xer_regnum || regno == -1)
+    supply_register (tdep->ppc_xer_regnum, regs + REG_XER_OFFSET);
+
+  if (regno == tdep->ppc_ctr_regnum || regno == -1)
+    supply_register (tdep->ppc_ctr_regnum, regs + REG_CTR_OFFSET);
+
+  if (regno == PC_REGNUM || regno == -1)
+    supply_register (PC_REGNUM, regs + REG_PC_OFFSET);
+}
+
+void
+ppcnbsd_fill_reg (char *regs, int regno)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  int i;
+
+  for (i = 0; i <= 31; i++)
+    {
+      if (regno == i || regno == -1)
+       regcache_collect (i, regs + REG_FIXREG_OFFSET (i));
+    }
+
+  if (regno == tdep->ppc_lr_regnum || regno == -1)
+    regcache_collect (tdep->ppc_lr_regnum, regs + REG_LR_OFFSET);
+
+  if (regno == tdep->ppc_cr_regnum || regno == -1)
+    regcache_collect (tdep->ppc_cr_regnum, regs + REG_CR_OFFSET);
+
+  if (regno == tdep->ppc_xer_regnum || regno == -1)
+    regcache_collect (tdep->ppc_xer_regnum, regs + REG_XER_OFFSET);
+
+  if (regno == tdep->ppc_ctr_regnum || regno == -1)
+    regcache_collect (tdep->ppc_ctr_regnum, regs + REG_CTR_OFFSET);
+
+  if (regno == PC_REGNUM || regno == -1)
+    regcache_collect (PC_REGNUM, regs + REG_PC_OFFSET);
+}
+
+void
+ppcnbsd_supply_fpreg (char *fpregs, int regno)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  int i;
+
+  for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
+    {
+      if (regno == i || regno == -1)
+       supply_register (i, fpregs + FPREG_FPR_OFFSET (i - FP0_REGNUM));
+    }
+
+  if (regno == tdep->ppc_fpscr_regnum || regno == -1)
+    supply_register (tdep->ppc_fpscr_regnum, fpregs + FPREG_FPSCR_OFFSET);
+}
+
+void
+ppcnbsd_fill_fpreg (char *fpregs, int regno)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  int i;
+
+  for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
+    {
+      if (regno == i || regno == -1)
+       regcache_collect (i, fpregs + FPREG_FPR_OFFSET (i - FP0_REGNUM));
+    }
+
+  if (regno == tdep->ppc_fpscr_regnum || regno == -1)
+    regcache_collect (tdep->ppc_fpscr_regnum, fpregs + FPREG_FPSCR_OFFSET);
+}
+
+static void
+fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
+                      CORE_ADDR ignore)
+{
+  char *regs, *fpregs;
+
+  /* We get everything from one section.  */
+  if (which != 0)
+    return;
+
+  regs = core_reg_sect;
+  fpregs = core_reg_sect + SIZEOF_STRUCT_REG;
+
+  /* Integer registers.  */
+  ppcnbsd_supply_reg (regs, -1);
+
+  /* Floating point registers.  */
+  ppcnbsd_supply_fpreg (fpregs, -1);
+}
+
+static void
+fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which,
+                         CORE_ADDR ignore)
+{
+  switch (which)
+    {
+    case 0:  /* Integer registers.  */
+      if (core_reg_size != SIZEOF_STRUCT_REG)
+       warning ("Wrong size register set in core file.");
+      else
+       ppcnbsd_supply_reg (core_reg_sect, -1);
+      break;
+
+    case 2:  /* Floating point registers.  */
+      if (core_reg_size != SIZEOF_STRUCT_FPREG)
+       warning ("Wrong size FP register set in core file.");
+      else
+       ppcnbsd_supply_fpreg (core_reg_sect, -1);
+      break;
+
+    default:
+      /* Don't know what kind of register request this is; just ignore it.  */
+      break;
+    }
+}
+
+static struct core_fns ppcnbsd_core_fns =
+{
+  bfd_target_unknown_flavour,          /* core_flavour */
+  default_check_format,                        /* check_format */
+  default_core_sniffer,                        /* core_sniffer */
+  fetch_core_registers,                        /* core_read_registers */
+  NULL                                 /* next */
+};
+
+static struct core_fns ppcnbsd_elfcore_fns =
+{
+  bfd_target_elf_flavour,              /* core_flavour */
+  default_check_format,                        /* check_format */
+  default_core_sniffer,                        /* core_sniffer */
+  fetch_elfcore_registers,             /* core_read_registers */
+  NULL                                 /* next */
+};
+
+static void
+ppcnbsd_init_abi (struct gdbarch_info info,
+                  struct gdbarch *gdbarch)
+{
+  /* Until November 2001, gcc was not complying to the SYSV ABI for
+     returning structures less than or equal to 8 bytes in size. It was
+     returning everything in memory. When this was corrected, it wasn't
+     fixed for native platforms.  */
+  set_gdbarch_use_struct_convention (gdbarch,
+                                   ppc_sysv_abi_broken_use_struct_convention);
+
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+                                nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
+}
+
+void
+_initialize_ppcnbsd_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_powerpc, GDB_OSABI_NETBSD_ELF,
+                         ppcnbsd_init_abi);
+
+  add_core_fns (&ppcnbsd_core_fns);
+  add_core_fns (&ppcnbsd_elfcore_fns);
+}
diff --git a/gdb/ppcnbsd-tdep.h b/gdb/ppcnbsd-tdep.h
new file mode 100644 (file)
index 0000000..3eae72d
--- /dev/null
@@ -0,0 +1,30 @@
+/* Common target dependent code for GDB on PowerPC systems running NetBSD.
+   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 PPCNBSD_TDEP_H
+#define PPCNBSD_TDEP_H
+
+void ppcnbsd_supply_reg (char *, int);
+void ppcnbsd_fill_reg (char *, int);
+
+void ppcnbsd_supply_fpreg (char *, int);
+void ppcnbsd_fill_fpreg (char *, int);
+
+#endif /* PPCNBSD_TDEP_H */