Add target_ops argument to to_pid_to_exec_file
[deliverable/binutils-gdb.git] / gdb / m68klinux-nat.c
index 2a25b342f12a66267013371f837a59aad9449dfb..a512a719e2e5f5c7920ee354595e30aa275427f1 100644 (file)
@@ -1,13 +1,12 @@
 /* Motorola m68k native support for GNU/Linux.
 
-   Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1996-2014 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
+   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,
    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 "frame.h"
 #include "inferior.h"
 #include "language.h"
 #include "gdbcore.h"
-#include "gdb_string.h"
+#include <string.h>
 #include "regcache.h"
 #include "target.h"
 #include "linux-nat.h"
 
 #include "m68k-tdep.h"
 
-#include <sys/param.h>
 #include <sys/dir.h>
 #include <signal.h>
 #include <sys/ptrace.h>
 #endif
 
 #include <sys/file.h>
-#include "gdb_stat.h"
+#include <sys/stat.h>
 
 #include "floatformat.h"
 
-#include "target.h"
-
-/* Prototypes for supply_gregset etc. */
+/* Prototypes for supply_gregset etc.  */
 #include "gregset.h"
+
+/* Defines ps_err_e, struct ps_prochandle.  */
+#include "gdb_proc_service.h"
+
+#ifndef PTRACE_GET_THREAD_AREA
+#define PTRACE_GET_THREAD_AREA 25
+#endif
 \f
-/* This table must line up with REGISTER_NAME in "m68k-tdep.c".  */
+/* This table must line up with gdbarch_register_name in "m68k-tdep.c".  */
 static const int regmap[] =
 {
   PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7,
@@ -72,20 +73,20 @@ static const int regmap[] =
 #define NUM_GREGS (18)
 #define MAX_NUM_REGS (NUM_GREGS + 11)
 
-int
+static int
 getregs_supplies (int regno)
 {
   return 0 <= regno && regno < NUM_GREGS;
 }
 
-int
+static int
 getfpregs_supplies (int regno)
 {
-  return FP0_REGNUM <= regno && regno <= M68K_FPI_REGNUM;
+  return M68K_FP0_REGNUM <= regno && regno <= M68K_FPI_REGNUM;
 }
 
 /* Does the current host support the GETREGS request?  */
-int have_ptrace_getregs =
+static int have_ptrace_getregs =
 #ifdef HAVE_PTRACE_GETREGS
   1
 #else
@@ -97,123 +98,93 @@ int have_ptrace_getregs =
 
 /* Fetching registers directly from the U area, one at a time.  */
 
-/* FIXME: This duplicates code from `inptrace.c'.  The problem is that we
-   define FETCH_INFERIOR_REGISTERS since we want to use our own versions
-   of {fetch,store}_inferior_registers that use the GETREGS request.  This
-   means that the code in `infptrace.c' is #ifdef'd out.  But we need to
-   fall back on that code when GDB is running on top of a kernel that
-   doesn't support the GETREGS request.  */
-
-#ifndef PT_READ_U
-#define PT_READ_U PTRACE_PEEKUSR
-#endif
-#ifndef PT_WRITE_U
-#define PT_WRITE_U PTRACE_POKEUSR
-#endif
-
 /* Fetch one register.  */
 
 static void
-fetch_register (int regno)
+fetch_register (struct regcache *regcache, int regno)
 {
-  /* This isn't really an address.  But ptrace thinks of it as one.  */
-  CORE_ADDR regaddr;
-  char mess[128];              /* For messages */
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  long regaddr, val;
   int i;
-  char buf[MAX_REGISTER_SIZE];
+  gdb_byte buf[MAX_REGISTER_SIZE];
   int tid;
 
-  if (CANNOT_FETCH_REGISTER (regno))
-    {
-      memset (buf, '\0', register_size (current_gdbarch, regno));      /* Supply zeroes */
-      regcache_raw_supply (current_regcache, regno, buf);
-      return;
-    }
-
-  /* Overload thread id onto process id */
-  tid = TIDGET (inferior_ptid);
+  /* Overload thread id onto process id.  */
+  tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
-    tid = PIDGET (inferior_ptid);      /* no thread id, just use process id */
+    tid = ptid_get_pid (inferior_ptid);        /* no thread id, just use
+                                          process id.  */
 
   regaddr = 4 * regmap[regno];
-  for (i = 0; i < register_size (current_gdbarch, regno);
-       i += sizeof (PTRACE_TYPE_RET))
+  for (i = 0; i < register_size (gdbarch, regno); i += sizeof (long))
     {
       errno = 0;
-      *(PTRACE_TYPE_RET *) &buf[i] = ptrace (PT_READ_U, tid,
-                                             (PTRACE_TYPE_ARG3) regaddr, 0);
-      regaddr += sizeof (PTRACE_TYPE_RET);
+      val = ptrace (PTRACE_PEEKUSER, tid, regaddr, 0);
+      memcpy (&buf[i], &val, sizeof (long));
+      regaddr += sizeof (long);
       if (errno != 0)
-       {
-         sprintf (mess, "reading register %s (#%d)", 
-                  REGISTER_NAME (regno), regno);
-         perror_with_name (mess);
-       }
+       error (_("Couldn't read register %s (#%d): %s."), 
+              gdbarch_register_name (gdbarch, regno),
+              regno, safe_strerror (errno));
     }
-  regcache_raw_supply (current_regcache, regno, buf);
+  regcache_raw_supply (regcache, regno, buf);
 }
 
 /* Fetch register values from the inferior.
    If REGNO is negative, do this for all registers.
-   Otherwise, REGNO specifies which register (so we can save time). */
+   Otherwise, REGNO specifies which register (so we can save time).  */
 
 static void
-old_fetch_inferior_registers (int regno)
+old_fetch_inferior_registers (struct regcache *regcache, int regno)
 {
   if (regno >= 0)
     {
-      fetch_register (regno);
+      fetch_register (regcache, regno);
     }
   else
     {
-      for (regno = 0; regno < NUM_REGS; regno++)
+      for (regno = 0;
+          regno < gdbarch_num_regs (get_regcache_arch (regcache));
+          regno++)
        {
-         fetch_register (regno);
+         fetch_register (regcache, regno);
        }
     }
 }
 
-/* Store one register. */
+/* Store one register.  */
 
 static void
-store_register (int regno)
+store_register (const struct regcache *regcache, int regno)
 {
-  /* This isn't really an address.  But ptrace thinks of it as one.  */
-  CORE_ADDR regaddr;
-  char mess[128];              /* For messages */
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  long regaddr, val;
   int i;
   int tid;
-  char buf[MAX_REGISTER_SIZE];
-
-  if (CANNOT_STORE_REGISTER (regno))
-    {
-      return;
-    }
+  gdb_byte buf[MAX_REGISTER_SIZE];
 
-  /* Overload thread id onto process id */
-  tid = TIDGET (inferior_ptid);
+  /* Overload thread id onto process id */
+  tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
-    tid = PIDGET (inferior_ptid);      /* no thread id, just use process id */
+    tid = ptid_get_pid (inferior_ptid);        /* no thread id, just use
+                                          process id.  */
 
   regaddr = 4 * regmap[regno];
 
-  /* Put the contents of regno into a local buffer */
-  regcache_raw_collect (current_regcache, regno, buf);
+  /* Put the contents of regno into a local buffer */
+  regcache_raw_collect (regcache, regno, buf);
 
-  /* Store the local buffer into the inferior a chunk at the time. */
-  for (i = 0; i < register_size (current_gdbarch, regno);
-       i += sizeof (PTRACE_TYPE_RET))
+  /* Store the local buffer into the inferior a chunk at the time.  */
+  for (i = 0; i < register_size (gdbarch, regno); i += sizeof (long))
     {
       errno = 0;
-      ptrace (PT_WRITE_U, tid, (PTRACE_TYPE_ARG3) regaddr,
-             *(PTRACE_TYPE_RET *) (buf + i));
-      regaddr += sizeof (PTRACE_TYPE_RET);
+      memcpy (&val, &buf[i], sizeof (long));
+      ptrace (PTRACE_POKEUSER, tid, regaddr, val);
+      regaddr += sizeof (long);
       if (errno != 0)
-       {
-         sprintf (mess, "writing register %s (#%d)", 
-                  REGISTER_NAME (regno), regno);
-         perror_with_name (mess);
-       }
+       error (_("Couldn't write register %s (#%d): %s."),
+              gdbarch_register_name (gdbarch, regno),
+              regno, safe_strerror (errno));
     }
 }
 
@@ -222,35 +193,42 @@ store_register (int regno)
    Otherwise, REGNO specifies which register (so we can save time).  */
 
 static void
-old_store_inferior_registers (int regno)
+old_store_inferior_registers (const struct regcache *regcache, int regno)
 {
   if (regno >= 0)
     {
-      store_register (regno);
+      store_register (regcache, regno);
     }
   else
     {
-      for (regno = 0; regno < NUM_REGS; regno++)
+      for (regno = 0;
+          regno < gdbarch_num_regs (get_regcache_arch (regcache));
+          regno++)
        {
-         store_register (regno);
+         store_register (regcache, regno);
        }
     }
 }
 \f
 /*  Given a pointer to a general register set in /proc format
    (elf_gregset_t *), unpack the register contents and supply
-   them as gdb's idea of the current register values. */
+   them as gdb's idea of the current register values.  */
 
 void
 supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
 {
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
   const elf_greg_t *regp = (const elf_greg_t *) gregsetp;
   int regi;
 
-  for (regi = M68K_D0_REGNUM; regi <= SP_REGNUM; regi++)
+  for (regi = M68K_D0_REGNUM;
+       regi <= gdbarch_sp_regnum (gdbarch);
+       regi++)
     regcache_raw_supply (regcache, regi, &regp[regmap[regi]]);
-  regcache_raw_supply (regcache, PS_REGNUM, &regp[PT_SR]);
-  regcache_raw_supply (regcache, PC_REGNUM, &regp[PT_PC]);
+  regcache_raw_supply (regcache, gdbarch_ps_regnum (gdbarch),
+                      &regp[PT_SR]);
+  regcache_raw_supply (regcache,
+                      gdbarch_pc_regnum (gdbarch), &regp[PT_PC]);
 }
 
 /* Fill register REGNO (if it is a general-purpose register) in
@@ -274,7 +252,7 @@ fill_gregset (const struct regcache *regcache,
    store their values in GDB's register array.  */
 
 static void
-fetch_regs (int tid)
+fetch_regs (struct regcache *regcache, int tid)
 {
   elf_gregset_t regs;
 
@@ -291,21 +269,21 @@ fetch_regs (int tid)
       perror_with_name (_("Couldn't get registers"));
     }
 
-  supply_gregset (current_regcache, (const elf_gregset_t *) &regs);
+  supply_gregset (regcache, (const elf_gregset_t *) &regs);
 }
 
 /* Store all valid general-purpose registers in GDB's register array
    into the process/thread specified by TID.  */
 
 static void
-store_regs (int tid, int regno)
+store_regs (const struct regcache *regcache, int tid, int regno)
 {
   elf_gregset_t regs;
 
   if (ptrace (PTRACE_GETREGS, tid, 0, (int) &regs) < 0)
     perror_with_name (_("Couldn't get registers"));
 
-  fill_gregset (current_regcache, &regs, regno);
+  fill_gregset (regcache, &regs, regno);
 
   if (ptrace (PTRACE_SETREGS, tid, 0, (int) &regs) < 0)
     perror_with_name (_("Couldn't write registers"));
@@ -313,8 +291,13 @@ store_regs (int tid, int regno)
 
 #else
 
-static void fetch_regs (int tid) {}
-static void store_regs (int tid, int regno) {}
+static void fetch_regs (struct regcache *regcache, int tid)
+{
+}
+
+static void store_regs (const struct regcache *regcache, int tid, int regno)
+{
+}
 
 #endif
 
@@ -330,11 +313,14 @@ static void store_regs (int tid, int regno) {}
 void
 supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
 {
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
   int regi;
 
-  for (regi = FP0_REGNUM; regi < FP0_REGNUM + 8; regi++)
+  for (regi = gdbarch_fp0_regnum (gdbarch);
+       regi < gdbarch_fp0_regnum (gdbarch) + 8; regi++)
     regcache_raw_supply (regcache, regi,
-                        FPREG_ADDR (fpregsetp, regi - FP0_REGNUM));
+                        FPREG_ADDR (fpregsetp,
+                                    regi - gdbarch_fp0_regnum (gdbarch)));
   regcache_raw_supply (regcache, M68K_FPC_REGNUM, &fpregsetp->fpcntl[0]);
   regcache_raw_supply (regcache, M68K_FPS_REGNUM, &fpregsetp->fpcntl[1]);
   regcache_raw_supply (regcache, M68K_FPI_REGNUM, &fpregsetp->fpcntl[2]);
@@ -348,13 +334,16 @@ void
 fill_fpregset (const struct regcache *regcache,
               elf_fpregset_t *fpregsetp, int regno)
 {
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
   int i;
 
   /* Fill in the floating-point registers.  */
-  for (i = FP0_REGNUM; i < FP0_REGNUM + 8; i++)
+  for (i = gdbarch_fp0_regnum (gdbarch);
+       i < gdbarch_fp0_regnum (gdbarch) + 8; i++)
     if (regno == -1 || regno == i)
       regcache_raw_collect (regcache, i,
-                           FPREG_ADDR (fpregsetp, i - FP0_REGNUM));
+                           FPREG_ADDR (fpregsetp,
+                                       i - gdbarch_fp0_regnum (gdbarch)));
 
   /* Fill in the floating-point control registers.  */
   for (i = M68K_FPC_REGNUM; i <= M68K_FPI_REGNUM; i++)
@@ -369,28 +358,28 @@ fill_fpregset (const struct regcache *regcache,
    thier values in GDB's register array.  */
 
 static void
-fetch_fpregs (int tid)
+fetch_fpregs (struct regcache *regcache, int tid)
 {
   elf_fpregset_t fpregs;
 
   if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0)
     perror_with_name (_("Couldn't get floating point status"));
 
-  supply_fpregset (current_regcache, (const elf_fpregset_t *) &fpregs);
+  supply_fpregset (regcache, (const elf_fpregset_t *) &fpregs);
 }
 
 /* Store all valid floating-point registers in GDB's register array
    into the process/thread specified by TID.  */
 
 static void
-store_fpregs (int tid, int regno)
+store_fpregs (const struct regcache *regcache, int tid, int regno)
 {
   elf_fpregset_t fpregs;
 
   if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0)
     perror_with_name (_("Couldn't get floating point status"));
 
-  fill_fpregset (current_regcache, &fpregs, regno);
+  fill_fpregset (regcache, &fpregs, regno);
 
   if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0)
     perror_with_name (_("Couldn't write floating point status"));
@@ -398,8 +387,13 @@ store_fpregs (int tid, int regno)
 
 #else
 
-static void fetch_fpregs (int tid) {}
-static void store_fpregs (int tid, int regno) {}
+static void fetch_fpregs (struct regcache *regcache, int tid)
+{
+}
+
+static void store_fpregs (const struct regcache *regcache, int tid, int regno)
+{
+}
 
 #endif
 \f
@@ -410,7 +404,8 @@ static void store_fpregs (int tid, int regno) {}
    registers).  */
 
 static void
-m68k_linux_fetch_inferior_registers (int regno)
+m68k_linux_fetch_inferior_registers (struct target_ops *ops,
+                                    struct regcache *regcache, int regno)
 {
   int tid;
 
@@ -418,14 +413,14 @@ m68k_linux_fetch_inferior_registers (int regno)
      GETREGS request isn't available.  */
   if (! have_ptrace_getregs)
     {
-      old_fetch_inferior_registers (regno);
+      old_fetch_inferior_registers (regcache, regno);
       return;
     }
 
   /* GNU/Linux LWP ID's are process ID's.  */
-  tid = TIDGET (inferior_ptid);
+  tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
-    tid = PIDGET (inferior_ptid);              /* Not a threaded program.  */
+    tid = ptid_get_pid (inferior_ptid);        /* Not a threaded program.  */
 
   /* Use the PTRACE_GETFPXREGS request whenever possible, since it
      transfers more registers in one system call, and we'll cache the
@@ -433,28 +428,28 @@ m68k_linux_fetch_inferior_registers (int regno)
      zero.  */
   if (regno == -1)
     {
-      fetch_regs (tid);
+      fetch_regs (regcache, tid);
 
       /* The call above might reset `have_ptrace_getregs'.  */
       if (! have_ptrace_getregs)
        {
-         old_fetch_inferior_registers (-1);
+         old_fetch_inferior_registers (regcache, -1);
          return;
        }
 
-      fetch_fpregs (tid);
+      fetch_fpregs (regcache, tid);
       return;
     }
 
   if (getregs_supplies (regno))
     {
-      fetch_regs (tid);
+      fetch_regs (regcache, tid);
       return;
     }
 
   if (getfpregs_supplies (regno))
     {
-      fetch_fpregs (tid);
+      fetch_fpregs (regcache, tid);
       return;
     }
 
@@ -466,7 +461,8 @@ m68k_linux_fetch_inferior_registers (int regno)
    do this for all registers (including the floating point and SSE
    registers).  */
 static void
-m68k_linux_store_inferior_registers (int regno)
+m68k_linux_store_inferior_registers (struct target_ops *ops,
+                                    struct regcache *regcache, int regno)
 {
   int tid;
 
@@ -474,34 +470,34 @@ m68k_linux_store_inferior_registers (int regno)
      SETREGS request isn't available.  */
   if (! have_ptrace_getregs)
     {
-      old_store_inferior_registers (regno);
+      old_store_inferior_registers (regcache, regno);
       return;
     }
 
   /* GNU/Linux LWP ID's are process ID's.  */
-  tid = TIDGET (inferior_ptid);
+  tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
-    tid = PIDGET (inferior_ptid);      /* Not a threaded program.  */
+    tid = ptid_get_pid (inferior_ptid);        /* Not a threaded program.  */
 
   /* Use the PTRACE_SETFPREGS requests whenever possible, since it
      transfers more registers in one system call.  But remember that
      store_fpregs can fail, and return zero.  */
   if (regno == -1)
     {
-      store_regs (tid, regno);
-      store_fpregs (tid, regno);
+      store_regs (regcache, tid, regno);
+      store_fpregs (regcache, tid, regno);
       return;
     }
 
   if (getregs_supplies (regno))
     {
-      store_regs (tid, regno);
+      store_regs (regcache, tid, regno);
       return;
     }
 
   if (getfpregs_supplies (regno))
     {
-      store_fpregs (tid, regno);
+      store_fpregs (regcache, tid, regno);
       return;
     }
 
@@ -566,6 +562,24 @@ fetch_core_registers (struct regcache *regcache,
 }
 \f
 
+/* Fetch the thread-local storage pointer for libthread_db.  */
+
+ps_err_e
+ps_get_thread_area (const struct ps_prochandle *ph, 
+                   lwpid_t lwpid, int idx, void **base)
+{
+  if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) < 0)
+    return PS_ERR;
+
+  /* IDX is the bias from the thread pointer to the beginning of the
+     thread descriptor.  It has to be subtracted due to implementation
+     quirks in libthread_db.  */
+  *base = (char *) *base - idx;
+
+  return PS_OK;
+}
+\f
+
 /* Register that we are able to handle GNU/Linux ELF core file
    formats.  */
 
This page took 0.042601 seconds and 4 git commands to generate.