* libunwind-frame.h (struct regcache): Add forward declaration.
[deliverable/binutils-gdb.git] / gdb / i386-linux-nat.c
index b6c669119a21e777c615afd9be4335aa1be506f3..7a71c605285d930826bc3a3b62fd583f213f1a82 100644 (file)
@@ -1,6 +1,7 @@
 /* Native-dependent code for GNU/Linux i386.
 
-   Copyright 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
    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.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
 #include "inferior.h"
 #include "gdbcore.h"
 #include "regcache.h"
+#include "target.h"
 #include "linux-nat.h"
 
 #include "gdb_assert.h"
@@ -135,40 +137,20 @@ int have_ptrace_getfpxregs =
 ;
 \f
 
-/* Support for the user struct.  */
-
-/* Return the address of register REGNUM.  BLOCKEND is the value of
-   u.u_ar0, which should point to the registers.  */
-
-CORE_ADDR
-register_u_addr (CORE_ADDR blockend, int regnum)
-{
-  return (blockend + 4 * regmap[regnum]);
-}
-
-/* Return the size of the user struct.  */
-
-int
-kernel_u_size (void)
-{
-  return (sizeof (struct user));
-}
-\f
-
 /* Accessing registers through the U area, one at a time.  */
 
 /* Fetch one register.  */
 
 static void
-fetch_register (int regno)
+fetch_register (struct regcache *regcache, int regno)
 {
   int tid;
   int val;
 
   gdb_assert (!have_ptrace_getregs);
-  if (cannot_fetch_register (regno))
+  if (regmap[regno] == -1)
     {
-      regcache_raw_supply (current_regcache, regno, NULL);
+      regcache_raw_supply (regcache, regno, NULL);
       return;
     }
 
@@ -178,24 +160,24 @@ fetch_register (int regno)
     tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
 
   errno = 0;
-  val = ptrace (PTRACE_PEEKUSER, tid, register_addr (regno, 0), 0);
+  val = ptrace (PTRACE_PEEKUSER, tid, 4 * regmap[regno], 0);
   if (errno != 0)
     error (_("Couldn't read register %s (#%d): %s."), REGISTER_NAME (regno),
           regno, safe_strerror (errno));
 
-  regcache_raw_supply (current_regcache, regno, (gdb_byte *) &val);
+  regcache_raw_supply (regcache, regno, &val);
 }
 
 /* Store one register. */
 
 static void
-store_register (int regno)
+store_register (const struct regcache *regcache, int regno)
 {
   int tid;
   int val;
 
   gdb_assert (!have_ptrace_getregs);
-  if (cannot_store_register (regno))
+  if (regmap[regno] == -1)
     return;
 
   /* GNU/Linux LWP ID's are process ID's.  */
@@ -204,8 +186,8 @@ store_register (int regno)
     tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
 
   errno = 0;
-  regcache_raw_collect (current_regcache, regno, (gdb_byte *) &val);
-  ptrace (PTRACE_POKEUSER, tid, register_addr (regno, 0), val);
+  regcache_raw_collect (regcache, regno, &val);
+  ptrace (PTRACE_POKEUSER, tid, 4 * regmap[regno], val);
   if (errno != 0)
     error (_("Couldn't write register %s (#%d): %s."), REGISTER_NAME (regno),
           regno, safe_strerror (errno));
@@ -219,17 +201,17 @@ store_register (int regno)
    in *GREGSETP.  */
 
 void
-supply_gregset (elf_gregset_t *gregsetp)
+supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
 {
-  elf_greg_t *regp = (elf_greg_t *) gregsetp;
+  const elf_greg_t *regp = (const elf_greg_t *) gregsetp;
   int i;
 
   for (i = 0; i < I386_NUM_GREGS; i++)
-    regcache_raw_supply (current_regcache, i, (gdb_byte *) (regp + regmap[i]));
+    regcache_raw_supply (regcache, i, regp + regmap[i]);
 
   if (I386_LINUX_ORIG_EAX_REGNUM < NUM_REGS)
-    regcache_raw_supply (current_regcache, I386_LINUX_ORIG_EAX_REGNUM,
-                        (gdb_byte *) (regp + ORIG_EAX));
+    regcache_raw_supply (regcache, I386_LINUX_ORIG_EAX_REGNUM,
+                        regp + ORIG_EAX);
 }
 
 /* Fill register REGNO (if it is a general-purpose register) in
@@ -237,19 +219,20 @@ supply_gregset (elf_gregset_t *gregsetp)
    do this for all registers.  */
 
 void
-fill_gregset (elf_gregset_t *gregsetp, int regno)
+fill_gregset (const struct regcache *regcache,
+             elf_gregset_t *gregsetp, int regno)
 {
   elf_greg_t *regp = (elf_greg_t *) gregsetp;
   int i;
 
   for (i = 0; i < I386_NUM_GREGS; i++)
     if (regno == -1 || regno == i)
-      regcache_raw_collect (current_regcache, i, (gdb_byte *) (regp + regmap[i]));
+      regcache_raw_collect (regcache, i, regp + regmap[i]);
 
   if ((regno == -1 || regno == I386_LINUX_ORIG_EAX_REGNUM)
       && I386_LINUX_ORIG_EAX_REGNUM < NUM_REGS)
-    regcache_raw_collect (current_regcache, I386_LINUX_ORIG_EAX_REGNUM,
-                         (gdb_byte *) (regp + ORIG_EAX));
+    regcache_raw_collect (regcache, I386_LINUX_ORIG_EAX_REGNUM,
+                         regp + ORIG_EAX);
 }
 
 #ifdef HAVE_PTRACE_GETREGS
@@ -258,7 +241,7 @@ fill_gregset (elf_gregset_t *gregsetp, int regno)
    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;
 
@@ -275,21 +258,21 @@ fetch_regs (int tid)
       perror_with_name (_("Couldn't get registers"));
     }
 
-  supply_gregset (&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 (&regs, regno);
+  fill_gregset (regcache, &regs, regno);
   
   if (ptrace (PTRACE_SETREGS, tid, 0, (int) &regs) < 0)
     perror_with_name (_("Couldn't write registers"));
@@ -297,8 +280,8 @@ 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
 \f
@@ -309,9 +292,9 @@ static void store_regs (int tid, int regno) {}
    *FPREGSETP.  */
 
 void 
-supply_fpregset (elf_fpregset_t *fpregsetp)
+supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
 {
-  i387_supply_fsave (current_regcache, -1, fpregsetp);
+  i387_supply_fsave (regcache, -1, fpregsetp);
 }
 
 /* Fill register REGNO (if it is a floating-point register) in
@@ -319,9 +302,10 @@ supply_fpregset (elf_fpregset_t *fpregsetp)
    do this for all registers.  */
 
 void
-fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
+fill_fpregset (const struct regcache *regcache,
+              elf_fpregset_t *fpregsetp, int regno)
 {
-  i387_fill_fsave ((char *) fpregsetp, regno);
+  i387_collect_fsave (regcache, regno, fpregsetp);
 }
 
 #ifdef HAVE_PTRACE_GETREGS
@@ -330,28 +314,28 @@ fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
    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 (&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 (&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"));
@@ -359,8 +343,8 @@ 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
@@ -373,9 +357,10 @@ static void store_fpregs (int tid, int regno) {}
    values in *FPXREGSETP.  */
 
 void
-supply_fpxregset (elf_fpxregset_t *fpxregsetp)
+supply_fpxregset (struct regcache *regcache,
+                 const elf_fpxregset_t *fpxregsetp)
 {
-  i387_supply_fxsave (current_regcache, -1, fpxregsetp);
+  i387_supply_fxsave (regcache, -1, fpxregsetp);
 }
 
 /* Fill register REGNO (if it is a floating-point or SSE register) in
@@ -383,9 +368,10 @@ supply_fpxregset (elf_fpxregset_t *fpxregsetp)
    -1, do this for all registers.  */
 
 void
-fill_fpxregset (elf_fpxregset_t *fpxregsetp, int regno)
+fill_fpxregset (const struct regcache *regcache,
+               elf_fpxregset_t *fpxregsetp, int regno)
 {
-  i387_fill_fxsave ((char *) fpxregsetp, regno);
+  i387_collect_fxsave (regcache, regno, fpxregsetp);
 }
 
 /* Fetch all registers covered by the PTRACE_GETFPXREGS request from
@@ -393,7 +379,7 @@ fill_fpxregset (elf_fpxregset_t *fpxregsetp, int regno)
    Return non-zero if successful, zero otherwise.  */
 
 static int
-fetch_fpxregs (int tid)
+fetch_fpxregs (struct regcache *regcache, int tid)
 {
   elf_fpxregset_t fpxregs;
 
@@ -411,7 +397,7 @@ fetch_fpxregs (int tid)
       perror_with_name (_("Couldn't read floating-point and SSE registers"));
     }
 
-  supply_fpxregset (&fpxregs);
+  supply_fpxregset (regcache, (const elf_fpxregset_t *) &fpxregs);
   return 1;
 }
 
@@ -420,7 +406,7 @@ fetch_fpxregs (int tid)
    Return non-zero if successful, zero otherwise.  */
 
 static int
-store_fpxregs (int tid, int regno)
+store_fpxregs (const struct regcache *regcache, int tid, int regno)
 {
   elf_fpxregset_t fpxregs;
 
@@ -438,7 +424,7 @@ store_fpxregs (int tid, int regno)
       perror_with_name (_("Couldn't read floating-point and SSE registers"));
     }
 
-  fill_fpxregset (&fpxregs, regno);
+  fill_fpxregset (regcache, &fpxregs, regno);
 
   if (ptrace (PTRACE_SETFPXREGS, tid, 0, &fpxregs) == -1)
     perror_with_name (_("Couldn't write floating-point and SSE registers"));
@@ -448,39 +434,20 @@ store_fpxregs (int tid, int regno)
 
 #else
 
-static int fetch_fpxregs (int tid) { return 0; }
-static int store_fpxregs (int tid, int regno) { return 0; }
+static int fetch_fpxregs (struct regcache *regcache, int tid) { return 0; }
+static int store_fpxregs (const struct regcache *regcache, int tid, int regno) { return 0; }
 
 #endif /* HAVE_PTRACE_GETFPXREGS */
 \f
 
 /* Transferring arbitrary registers between GDB and inferior.  */
 
-/* Check if register REGNO in the child process is accessible.
-   If we are accessing registers directly via the U area, only the
-   general-purpose registers are available.
-   All registers should be accessible if we have GETREGS support.  */
-   
-int
-cannot_fetch_register (int regno)
-{
-  gdb_assert (regno >= 0 && regno < NUM_REGS);
-  return (!have_ptrace_getregs && regmap[regno] == -1);
-}
-
-int
-cannot_store_register (int regno)
-{
-  gdb_assert (regno >= 0 && regno < NUM_REGS);
-  return (!have_ptrace_getregs && regmap[regno] == -1);
-}
-
 /* Fetch register REGNO from the child process.  If REGNO is -1, do
    this for all registers (including the floating point and SSE
    registers).  */
 
-void
-fetch_inferior_registers (int regno)
+static void
+i386_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
 {
   int tid;
 
@@ -492,7 +459,7 @@ fetch_inferior_registers (int regno)
 
       for (i = 0; i < NUM_REGS; i++)
        if (regno == -1 || regno == i)
-         fetch_register (i);
+         fetch_register (regcache, i);
 
       return;
     }
@@ -508,30 +475,30 @@ 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)
        {
-         fetch_inferior_registers (regno);
+         i386_linux_fetch_inferior_registers (regcache, regno);
          return;
        }
 
-      if (fetch_fpxregs (tid))
+      if (fetch_fpxregs (regcache, tid))
        return;
-      fetch_fpregs (tid);
+      fetch_fpregs (regcache, tid);
       return;
     }
 
   if (GETREGS_SUPPLIES (regno))
     {
-      fetch_regs (tid);
+      fetch_regs (regcache, tid);
       return;
     }
 
   if (GETFPXREGS_SUPPLIES (regno))
     {
-      if (fetch_fpxregs (tid))
+      if (fetch_fpxregs (regcache, tid))
        return;
 
       /* Either our processor or our kernel doesn't support the SSE
@@ -540,7 +507,7 @@ fetch_inferior_registers (int regno)
         more graceful to handle differences in the register set using
         gdbarch.  Until then, this will at least make things work
         plausibly.  */
-      fetch_fpregs (tid);
+      fetch_fpregs (regcache, tid);
       return;
     }
 
@@ -551,8 +518,8 @@ fetch_inferior_registers (int regno)
 /* Store register REGNO back into the child process.  If REGNO is -1,
    do this for all registers (including the floating point and SSE
    registers).  */
-void
-store_inferior_registers (int regno)
+static void
+i386_linux_store_inferior_registers (struct regcache *regcache, int regno)
 {
   int tid;
 
@@ -564,7 +531,7 @@ store_inferior_registers (int regno)
 
       for (i = 0; i < NUM_REGS; i++)
        if (regno == -1 || regno == i)
-         store_register (i);
+         store_register (regcache, i);
 
       return;
     }
@@ -579,28 +546,28 @@ store_inferior_registers (int regno)
      store_fpxregs can fail, and return zero.  */
   if (regno == -1)
     {
-      store_regs (tid, regno);
-      if (store_fpxregs (tid, regno))
+      store_regs (regcache, tid, regno);
+      if (store_fpxregs (regcache, tid, regno))
        return;
-      store_fpregs (tid, regno);
+      store_fpregs (regcache, tid, regno);
       return;
     }
 
   if (GETREGS_SUPPLIES (regno))
     {
-      store_regs (tid, regno);
+      store_regs (regcache, tid, regno);
       return;
     }
 
   if (GETFPXREGS_SUPPLIES (regno))
     {
-      if (store_fpxregs (tid, regno))
+      if (store_fpxregs (regcache, tid, regno))
        return;
 
       /* Either our processor or our kernel doesn't support the SSE
         registers, so just write the FP registers in the traditional
         way.  */
-      store_fpregs (tid, regno);
+      store_fpregs (regcache, tid, regno);
       return;
     }
 
@@ -754,8 +721,8 @@ static const unsigned char linux_syscall[] = { 0xcd, 0x80 };
    If STEP is nonzero, single-step it.
    If SIGNAL is nonzero, give it that signal.  */
 
-void
-child_resume (ptid_t ptid, int step, enum target_signal signal)
+static void
+i386_linux_resume (ptid_t ptid, int step, enum target_signal signal)
 {
   int pid = PIDGET (ptid);
 
@@ -783,7 +750,7 @@ child_resume (ptid_t ptid, int step, enum target_signal signal)
          that's about to be restored, and set the trace flag there.  */
 
       /* First check if PC is at a system call.  */
-      if (deprecated_read_memory_nobpt (pc, buf, LINUX_SYSCALL_LEN) == 0
+      if (read_memory_nobpt (pc, buf, LINUX_SYSCALL_LEN) == 0
          && memcmp (buf, linux_syscall, LINUX_SYSCALL_LEN) == 0)
        {
          int syscall = read_register_pid (LINUX_SYSCALL_REGNUM,
@@ -813,9 +780,34 @@ child_resume (ptid_t ptid, int step, enum target_signal signal)
     perror_with_name (("ptrace"));
 }
 
-void
-child_post_startup_inferior (ptid_t ptid)
+static void (*super_post_startup_inferior) (ptid_t ptid);
+
+static void
+i386_linux_child_post_startup_inferior (ptid_t ptid)
 {
   i386_cleanup_dregs ();
-  linux_child_post_startup_inferior (ptid);
+  super_post_startup_inferior (ptid);
+}
+
+void
+_initialize_i386_linux_nat (void)
+{
+  struct target_ops *t;
+
+  /* Fill in the generic GNU/Linux methods.  */
+  t = linux_target ();
+
+  /* Override the default ptrace resume method.  */
+  t->to_resume = i386_linux_resume;
+
+  /* Override the GNU/Linux inferior startup hook.  */
+  super_post_startup_inferior = t->to_post_startup_inferior;
+  t->to_post_startup_inferior = i386_linux_child_post_startup_inferior;
+
+  /* Add our register access methods.  */
+  t->to_fetch_registers = i386_linux_fetch_inferior_registers;
+  t->to_store_registers = i386_linux_store_inferior_registers;
+
+  /* Register the target.  */
+  linux_nat_add_target (t);
 }
This page took 0.045058 seconds and 4 git commands to generate.