2007-10-02 Mark Mitchell <mark@codesourcery.com>
[deliverable/binutils-gdb.git] / gdb / rs6000-nat.c
index 986f9a0cc8f12a42d4e192df37ca8b3a64b39091..3d51b3be49b3281e4bd00a99c10dd9acec1ec7f7 100644 (file)
@@ -8,7 +8,7 @@
 
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +17,7 @@
    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., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "inferior.h"
@@ -39,6 +37,7 @@
 #include "rs6000-tdep.h"
 #include "exec.h"
 #include "gdb_stdint.h"
+#include "observer.h"
 
 #include <sys/ptrace.h>
 #include <sys/reg.h>
 # define ARCH64() (register_size (current_gdbarch, 0) == 8)
 #endif
 
-/* Union of 32-bit and 64-bit ".reg" core file sections. */
-
-typedef union {
-#ifdef ARCH3264
-  struct __context64 r64;
-#else
-  struct mstsave r64;
-#endif
-  struct mstsave r32;
-} CoreRegs;
-
 /* Union of 32-bit and 64-bit versions of ld_info. */
 
 typedef union {
@@ -142,8 +130,6 @@ static int objfile_symbol_add (void *);
 
 static void vmap_symtab (struct vmap *);
 
-static void fetch_core_registers (char *, unsigned int, int, CORE_ADDR);
-
 static void exec_one_dummy_insn (void);
 
 extern void fixup_breakpoints (CORE_ADDR low, CORE_ADDR high, CORE_ADDR delta);
@@ -169,7 +155,7 @@ regmap (int regno, int *isfloat)
       *isfloat = 1;
       return regno - tdep->ppc_fp0_regnum + FPR0;
     }
-  else if (regno == PC_REGNUM)
+  else if (regno == gdbarch_pc_regnum (current_gdbarch))
     return IAR;
   else if (regno == tdep->ppc_ps_regnum)
     return MSR;
@@ -223,7 +209,7 @@ rs6000_ptrace64 (int req, int id, long long addr, int data, void *buf)
 /* Fetch register REGNO from the inferior. */
 
 static void
-fetch_register (int regno)
+fetch_register (struct regcache *regcache, int regno)
 {
   int addr[MAX_REGISTER_SIZE];
   int nr, isfloat;
@@ -240,7 +226,7 @@ fetch_register (int regno)
   /* Bogus register number. */
   else if (nr < 0)
     {
-      if (regno >= NUM_REGS)
+      if (regno >= gdbarch_num_regs (current_gdbarch))
        fprintf_unfiltered (gdb_stderr,
                            "gdb error: register no %d not implemented.\n",
                            regno);
@@ -266,7 +252,7 @@ fetch_register (int regno)
     }
 
   if (!errno)
-    regcache_raw_supply (current_regcache, regno, (char *) addr);
+    regcache_raw_supply (regcache, regno, (char *) addr);
   else
     {
 #if 0
@@ -280,13 +266,13 @@ fetch_register (int regno)
 /* Store register REGNO back into the inferior. */
 
 static void
-store_register (int regno)
+store_register (const struct regcache *regcache, int regno)
 {
   int addr[MAX_REGISTER_SIZE];
   int nr, isfloat;
 
   /* Fetch the register's value from the register cache.  */
-  regcache_raw_collect (current_regcache, regno, addr);
+  regcache_raw_collect (regcache, regno, addr);
 
   /* -1 can be a successful return value, so infer errors from errno. */
   errno = 0;
@@ -300,7 +286,7 @@ store_register (int regno)
   /* Bogus register number. */
   else if (nr < 0)
     {
-      if (regno >= NUM_REGS)
+      if (regno >= gdbarch_num_regs (current_gdbarch))
        fprintf_unfiltered (gdb_stderr,
                            "gdb error: register no %d not implemented.\n",
                            regno);
@@ -309,7 +295,7 @@ store_register (int regno)
   /* Fixed-point registers. */
   else
     {
-      if (regno == SP_REGNUM)
+      if (regno == gdbarch_sp_regnum (current_gdbarch))
        /* Execute one dummy instruction (which is a breakpoint) in inferior
           process to give kernel a chance to do internal housekeeping.
           Otherwise the following ptrace(2) calls will mess up user stack
@@ -346,10 +332,10 @@ store_register (int regno)
    REGNO otherwise. */
 
 static void
-rs6000_fetch_inferior_registers (int regno)
+rs6000_fetch_inferior_registers (struct regcache *regcache, int regno)
 {
   if (regno != -1)
-    fetch_register (regno);
+    fetch_register (regcache, regno);
 
   else
     {
@@ -360,25 +346,25 @@ rs6000_fetch_inferior_registers (int regno)
            regno < tdep->ppc_gp0_regnum + ppc_num_gprs;
           regno++)
        {
-         fetch_register (regno);
+         fetch_register (regcache, regno);
        }
 
       /* Read general purpose floating point registers.  */
       if (tdep->ppc_fp0_regnum >= 0)
         for (regno = 0; regno < ppc_num_fprs; regno++)
-          fetch_register (tdep->ppc_fp0_regnum + regno);
+          fetch_register (regcache, tdep->ppc_fp0_regnum + regno);
 
       /* Read special registers.  */
-      fetch_register (PC_REGNUM);
-      fetch_register (tdep->ppc_ps_regnum);
-      fetch_register (tdep->ppc_cr_regnum);
-      fetch_register (tdep->ppc_lr_regnum);
-      fetch_register (tdep->ppc_ctr_regnum);
-      fetch_register (tdep->ppc_xer_regnum);
+      fetch_register (regcache, gdbarch_pc_regnum (current_gdbarch));
+      fetch_register (regcache, tdep->ppc_ps_regnum);
+      fetch_register (regcache, tdep->ppc_cr_regnum);
+      fetch_register (regcache, tdep->ppc_lr_regnum);
+      fetch_register (regcache, tdep->ppc_ctr_regnum);
+      fetch_register (regcache, tdep->ppc_xer_regnum);
       if (tdep->ppc_fpscr_regnum >= 0)
-        fetch_register (tdep->ppc_fpscr_regnum);
+        fetch_register (regcache, tdep->ppc_fpscr_regnum);
       if (tdep->ppc_mq_regnum >= 0)
-       fetch_register (tdep->ppc_mq_regnum);
+       fetch_register (regcache, tdep->ppc_mq_regnum);
     }
 }
 
@@ -387,10 +373,10 @@ rs6000_fetch_inferior_registers (int regno)
    Otherwise, REGNO specifies which register (so we can save time).  */
 
 static void
-rs6000_store_inferior_registers (int regno)
+rs6000_store_inferior_registers (struct regcache *regcache, int regno)
 {
   if (regno != -1)
-    store_register (regno);
+    store_register (regcache, regno);
 
   else
     {
@@ -401,25 +387,25 @@ rs6000_store_inferior_registers (int regno)
            regno < tdep->ppc_gp0_regnum + ppc_num_gprs;
           regno++)
        {
-         store_register (regno);
+         store_register (regcache, regno);
        }
 
       /* Write floating point registers.  */
       if (tdep->ppc_fp0_regnum >= 0)
         for (regno = 0; regno < ppc_num_fprs; regno++)
-          store_register (tdep->ppc_fp0_regnum + regno);
+          store_register (regcache, tdep->ppc_fp0_regnum + regno);
 
       /* Write special registers.  */
-      store_register (PC_REGNUM);
-      store_register (tdep->ppc_ps_regnum);
-      store_register (tdep->ppc_cr_regnum);
-      store_register (tdep->ppc_lr_regnum);
-      store_register (tdep->ppc_ctr_regnum);
-      store_register (tdep->ppc_xer_regnum);
+      store_register (regcache, gdbarch_pc_regnum (current_gdbarch));
+      store_register (regcache, tdep->ppc_ps_regnum);
+      store_register (regcache, tdep->ppc_cr_regnum);
+      store_register (regcache, tdep->ppc_lr_regnum);
+      store_register (regcache, tdep->ppc_ctr_regnum);
+      store_register (regcache, tdep->ppc_xer_regnum);
       if (tdep->ppc_fpscr_regnum >= 0)
-        store_register (tdep->ppc_fpscr_regnum);
+        store_register (regcache, tdep->ppc_fpscr_regnum);
       if (tdep->ppc_mq_regnum >= 0)
-       store_register (tdep->ppc_mq_regnum);
+       store_register (regcache, tdep->ppc_mq_regnum);
     }
 }
 
@@ -523,6 +509,63 @@ rs6000_xfer_partial (struct target_ops *ops, enum target_object object,
     }
 }
 
+/* Wait for the child specified by PTID to do something.  Return the
+   process ID of the child, or MINUS_ONE_PTID in case of error; store
+   the status in *OURSTATUS.  */
+
+static ptid_t
+rs6000_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
+{
+  pid_t pid;
+  int status, save_errno;
+
+  do
+    {
+      set_sigint_trap ();
+      set_sigio_trap ();
+
+      do
+       {
+         pid = waitpid (ptid_get_pid (ptid), &status, 0);
+         save_errno = errno;
+       }
+      while (pid == -1 && errno == EINTR);
+
+      clear_sigio_trap ();
+      clear_sigint_trap ();
+
+      if (pid == -1)
+       {
+         fprintf_unfiltered (gdb_stderr,
+                             _("Child process unexpectedly missing: %s.\n"),
+                             safe_strerror (save_errno));
+
+         /* Claim it exited with unknown signal.  */
+         ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+         ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+         return minus_one_ptid;
+       }
+
+      /* Ignore terminated detached child processes.  */
+      if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid))
+       pid = -1;
+    }
+  while (pid == -1);
+
+  /* AIX has a couple of strange returns from wait().  */
+
+  /* stop after load" status.  */
+  if (status == 0x57c)
+    ourstatus->kind = TARGET_WAITKIND_LOADED;
+  /* signal 0. I have no idea why wait(2) returns with this status word.  */
+  else if (status == 0x7f)
+    ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+  /* A normal waitstatus.  Let the usual macros deal with it.  */
+  else
+    store_waitstatus (ourstatus, status);
+
+  return pid_to_ptid (pid);
+}
 
 /* Execute one dummy breakpoint instruction.  This way we give the kernel
    a chance to do some housekeeping and update inferior's internal data,
@@ -567,87 +610,6 @@ exec_one_dummy_insn (void)
   write_pc (prev_pc);
   deprecated_remove_raw_breakpoint (bp);
 }
-
-/* Fetch registers from the register section in core bfd. */
-
-static void
-fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
-                     int which, CORE_ADDR reg_addr)
-{
-  CoreRegs *regs;
-  int regi;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); 
-
-  if (which != 0)
-    {
-      fprintf_unfiltered
-       (gdb_stderr,
-        "Gdb error: unknown parameter to fetch_core_registers().\n");
-      return;
-    }
-
-  regs = (CoreRegs *) core_reg_sect;
-
-  /* Put the register values from the core file section in the regcache.  */
-
-  if (ARCH64 ())
-    {
-      for (regi = 0; regi < ppc_num_gprs; regi++)
-        regcache_raw_supply (current_regcache, tdep->ppc_gp0_regnum + regi,
-                            (char *) &regs->r64.gpr[regi]);
-
-      if (tdep->ppc_fp0_regnum >= 0)
-        for (regi = 0; regi < ppc_num_fprs; regi++)
-          regcache_raw_supply (current_regcache, tdep->ppc_fp0_regnum + regi,
-                              (char *) &regs->r64.fpr[regi]);
-
-      regcache_raw_supply (current_regcache, PC_REGNUM,
-                          (char *) &regs->r64.iar);
-      regcache_raw_supply (current_regcache, tdep->ppc_ps_regnum,
-                          (char *) &regs->r64.msr);
-      regcache_raw_supply (current_regcache, tdep->ppc_cr_regnum,
-                          (char *) &regs->r64.cr);
-      regcache_raw_supply (current_regcache, tdep->ppc_lr_regnum,
-                          (char *) &regs->r64.lr);
-      regcache_raw_supply (current_regcache, tdep->ppc_ctr_regnum,
-                          (char *) &regs->r64.ctr);
-      regcache_raw_supply (current_regcache, tdep->ppc_xer_regnum,
-                          (char *) &regs->r64.xer);
-      if (tdep->ppc_fpscr_regnum >= 0)
-        regcache_raw_supply (current_regcache, tdep->ppc_fpscr_regnum,
-                            (char *) &regs->r64.fpscr);
-    }
-  else
-    {
-      for (regi = 0; regi < ppc_num_gprs; regi++)
-        regcache_raw_supply (current_regcache, tdep->ppc_gp0_regnum + regi,
-                            (char *) &regs->r32.gpr[regi]);
-
-      if (tdep->ppc_fp0_regnum >= 0)
-        for (regi = 0; regi < ppc_num_fprs; regi++)
-          regcache_raw_supply (current_regcache, tdep->ppc_fp0_regnum + regi,
-                              (char *) &regs->r32.fpr[regi]);
-
-      regcache_raw_supply (current_regcache, PC_REGNUM,
-                          (char *) &regs->r32.iar);
-      regcache_raw_supply (current_regcache, tdep->ppc_ps_regnum,
-                          (char *) &regs->r32.msr);
-      regcache_raw_supply (current_regcache, tdep->ppc_cr_regnum,
-                          (char *) &regs->r32.cr);
-      regcache_raw_supply (current_regcache, tdep->ppc_lr_regnum,
-                          (char *) &regs->r32.lr);
-      regcache_raw_supply (current_regcache, tdep->ppc_ctr_regnum,
-                          (char *) &regs->r32.ctr);
-      regcache_raw_supply (current_regcache, tdep->ppc_xer_regnum,
-                          (char *) &regs->r32.xer);
-      if (tdep->ppc_fpscr_regnum >= 0)
-        regcache_raw_supply (current_regcache, tdep->ppc_fpscr_regnum,
-                            (char *) &regs->r32.fpscr);
-      if (tdep->ppc_mq_regnum >= 0)
-       regcache_raw_supply (current_regcache, tdep->ppc_mq_regnum,
-                            (char *) &regs->r32.mq);
-    }
-}
 \f
 
 /* Copy information about text and data sections from LDI to VP for a 64-bit
@@ -917,8 +879,8 @@ vmap_ldinfo (LdInfo *ldi)
 
          /* Announce new object files.  Doing this after symbol relocation
             makes aix-thread.c's job easier.  */
-         if (deprecated_target_new_objfile_hook && vp->objfile)
-           deprecated_target_new_objfile_hook (vp->objfile);
+         if (vp->objfile)
+           observer_notify_new_objfile (vp->objfile);
 
          /* There may be more, so we don't break out of the loop.  */
        }
@@ -999,14 +961,18 @@ vmap_exec (void)
 /* Set the current architecture from the host running GDB.  Called when
    starting a child process. */
 
-void
-rs6000_create_inferior (int pid)
+static void (*super_create_inferior) (char *exec_file, char *allargs,
+                                     char **env, int from_tty);
+static void
+rs6000_create_inferior (char *exec_file, char *allargs, char **env, int from_tty)
 {
   enum bfd_architecture arch;
   unsigned long mach;
   bfd abfd;
   struct gdbarch_info info;
 
+  super_create_inferior (exec_file, allargs, env, from_tty);
+
   if (__power_rs ())
     {
       arch = bfd_arch_rs6000;
@@ -1048,7 +1014,9 @@ rs6000_create_inferior (int pid)
 
 \f
 /* xcoff_relocate_symtab -      hook for symbol table relocation.
-   also reads shared libraries.  */
+   
+   This is only applicable to live processes, and is a no-op when
+   debugging a core file.  */
 
 void
 xcoff_relocate_symtab (unsigned int pid)
@@ -1060,6 +1028,9 @@ xcoff_relocate_symtab (unsigned int pid)
   int ldisize = arch64 ? sizeof (ldi->l64) : sizeof (ldi->l32);
   int size;
 
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return;
+
   do
     {
       size = load_segs * ldisize;
@@ -1197,8 +1168,8 @@ xcoff_relocate_core (struct target_ops *target)
 
       vmap_symtab (vp);
 
-      if (deprecated_target_new_objfile_hook && vp != vmap && vp->objfile)
-       deprecated_target_new_objfile_hook (vp->objfile);
+      if (vp != vmap && vp->objfile)
+       observer_notify_new_objfile (vp->objfile);
     }
   while (LDI_NEXT (ldi, arch64) != 0);
   vmap_exec ();
@@ -1230,19 +1201,9 @@ find_toc_address (CORE_ADDR pc)
   error (_("Unable to find TOC entry for pc %s."), hex_string (pc));
 }
 \f
-/* Register that we are able to handle rs6000 core file formats. */
-
-static struct core_fns rs6000_core_fns =
-{
-  bfd_target_xcoff_flavour,            /* core_flavour */
-  default_check_format,                        /* check_format */
-  default_core_sniffer,                        /* core_sniffer */
-  fetch_core_registers,                        /* core_read_registers */
-  NULL                                 /* next */
-};
 
 void
-_initialize_core_rs6000 (void)
+_initialize_rs6000_nat (void)
 {
   struct target_ops *t;
 
@@ -1250,11 +1211,15 @@ _initialize_core_rs6000 (void)
   t->to_fetch_registers = rs6000_fetch_inferior_registers;
   t->to_store_registers = rs6000_store_inferior_registers;
   t->to_xfer_partial = rs6000_xfer_partial;
+
+  super_create_inferior = t->to_create_inferior;
+  t->to_create_inferior = rs6000_create_inferior;
+
+  t->to_wait = rs6000_wait;
+
   add_target (t);
 
   /* Initialize hook in rs6000-tdep.c for determining the TOC address
      when calling functions in the inferior.  */
   rs6000_find_toc_address_hook = find_toc_address;
-
-  deprecated_add_core_fns (&rs6000_core_fns);
 }
This page took 0.031091 seconds and 4 git commands to generate.