Introduce procedure use_gdb_stub
[deliverable/binutils-gdb.git] / gdb / m68klinux-nat.c
index 8f5b7c2ed5e0ab5284de79a3466b4048656bbe78..24b6242ba39cf71bf31b573617a660add00b23cc 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-2016 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 "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>
+#include "nat/gdb_ptrace.h"
 #include <sys/user.h>
 #include <sys/ioctl.h>
 #include <fcntl.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 +72,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,65 +97,41 @@ 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 (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 (gdbarch_cannot_fetch_register (current_gdbarch, regno))
-    {
-      memset (buf, '\0', register_size (current_gdbarch, regno));      /* Supply zeroes */
-      regcache_raw_supply (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 (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 (struct regcache *regcache, int regno)
@@ -166,52 +142,48 @@ old_fetch_inferior_registers (struct regcache *regcache, int regno)
     }
   else
     {
-      for (regno = 0; regno < NUM_REGS; regno++)
+      for (regno = 0;
+          regno < gdbarch_num_regs (get_regcache_arch (regcache));
+          regno++)
        {
          fetch_register (regcache, regno);
        }
     }
 }
 
-/* Store one register. */
+/* Store one register.  */
 
 static void
 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 (gdbarch_cannot_store_register (current_gdbarch, 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 */
+  /* 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));
     }
 }
 
@@ -228,7 +200,9 @@ old_store_inferior_registers (const struct regcache *regcache, int regno)
     }
   else
     {
-      for (regno = 0; regno < NUM_REGS; regno++)
+      for (regno = 0;
+          regno < gdbarch_num_regs (get_regcache_arch (regcache));
+          regno++)
        {
          store_register (regcache, regno);
        }
@@ -237,18 +211,23 @@ old_store_inferior_registers (const struct regcache *regcache, int 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
@@ -311,8 +290,13 @@ store_regs (const struct regcache *regcache, int tid, int regno)
 
 #else
 
-static void fetch_regs (struct regcache *regcache, int tid) {}
-static void store_regs (const struct regcache *regcache, 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
 
@@ -328,11 +312,14 @@ static void store_regs (const struct regcache *regcache, 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]);
@@ -346,13 +333,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++)
@@ -396,8 +386,13 @@ store_fpregs (const struct regcache *regcache, int tid, int regno)
 
 #else
 
-static void fetch_fpregs (struct regcache *regcache, int tid) {}
-static void store_fpregs (const struct regcache *regcache, 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
@@ -408,7 +403,8 @@ static void store_fpregs (const struct regcache *regcache, int tid, int regno) {
    registers).  */
 
 static void
-m68k_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
+m68k_linux_fetch_inferior_registers (struct target_ops *ops,
+                                    struct regcache *regcache, int regno)
 {
   int tid;
 
@@ -421,9 +417,9 @@ m68k_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
     }
 
   /* 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
@@ -464,7 +460,8 @@ m68k_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
    do this for all registers (including the floating point and SSE
    registers).  */
 static void
-m68k_linux_store_inferior_registers (struct regcache *regcache, int regno)
+m68k_linux_store_inferior_registers (struct target_ops *ops,
+                                    struct regcache *regcache, int regno)
 {
   int tid;
 
@@ -477,9 +474,9 @@ m68k_linux_store_inferior_registers (struct regcache *regcache, int regno)
     }
 
   /* 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
@@ -507,75 +504,25 @@ m68k_linux_store_inferior_registers (struct regcache *regcache, int regno)
                  _("Got request to store bad register number %d."), regno);
 }
 \f
-/* Interpreting register set info found in core files.  */
 
-/* Provide registers to GDB from a core file.
+/* Fetch the thread-local storage pointer for libthread_db.  */
 
-   (We can't use the generic version of this function in
-   core-regset.c, because we need to use elf_gregset_t instead of
-   gregset_t.)
-
-   CORE_REG_SECT points to an array of bytes, which are the contents
-   of a `note' from a core file which BFD thinks might contain
-   register contents.  CORE_REG_SIZE is its size.
-
-   WHICH says which register set corelow suspects this is:
-     0 --- the general-purpose register set, in elf_gregset_t format
-     2 --- the floating-point register set, in elf_fpregset_t format
-
-   REG_ADDR isn't used on GNU/Linux.  */
-
-static void
-fetch_core_registers (struct regcache *regcache,
-                     char *core_reg_sect, unsigned core_reg_size,
-                     int which, CORE_ADDR reg_addr)
+ps_err_e
+ps_get_thread_area (const struct ps_prochandle *ph, 
+                   lwpid_t lwpid, int idx, void **base)
 {
-  elf_gregset_t gregset;
-  elf_fpregset_t fpregset;
+  if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) < 0)
+    return PS_ERR;
 
-  switch (which)
-    {
-    case 0:
-      if (core_reg_size != sizeof (gregset))
-       warning (_("Wrong size gregset in core file."));
-      else
-       {
-         memcpy (&gregset, core_reg_sect, sizeof (gregset));
-         supply_gregset (regcache, (const elf_gregset_t *) &gregset);
-       }
-      break;
-
-    case 2:
-      if (core_reg_size != sizeof (fpregset))
-       warning (_("Wrong size fpregset in core file."));
-      else
-       {
-         memcpy (&fpregset, core_reg_sect, sizeof (fpregset));
-         supply_fpregset (regcache, (const elf_fpregset_t *) &fpregset);
-       }
-      break;
+  /* 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;
 
-    default:
-      /* We've covered all the kinds of registers we know about here,
-         so this must be something we wouldn't know what to do with
-         anyway.  Just ignore it.  */
-      break;
-    }
+  return PS_OK;
 }
 \f
 
-/* Register that we are able to handle GNU/Linux ELF core file
-   formats.  */
-
-static struct core_fns linux_elf_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_m68k_linux_nat (void);
 
 void
@@ -592,6 +539,4 @@ _initialize_m68k_linux_nat (void)
 
   /* Register the target.  */
   linux_nat_add_target (t);
-
-  deprecated_add_core_fns (&linux_elf_core_fns);
 }
This page took 0.029074 seconds and 4 git commands to generate.