Regenerate tree using Autoconf 2.64 and Automake 1.11.
[deliverable/binutils-gdb.git] / gdb / i386-linux-nat.c
index 7a71c605285d930826bc3a3b62fd583f213f1a82..991b27fdd8ade3dfaab9fef61285734f01a8414e 100644 (file)
@@ -1,13 +1,13 @@
 /* Native-dependent code for GNU/Linux i386.
 
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+   2009 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 "i386-nat.h"
 #include "inferior.h"
 #include "gdbcore.h"
 #include "regcache.h"
@@ -162,7 +161,8 @@ fetch_register (struct regcache *regcache, int regno)
   errno = 0;
   val = ptrace (PTRACE_PEEKUSER, tid, 4 * regmap[regno], 0);
   if (errno != 0)
-    error (_("Couldn't read register %s (#%d): %s."), REGISTER_NAME (regno),
+    error (_("Couldn't read register %s (#%d): %s."), 
+          gdbarch_register_name (get_regcache_arch (regcache), regno),
           regno, safe_strerror (errno));
 
   regcache_raw_supply (regcache, regno, &val);
@@ -189,7 +189,8 @@ store_register (const struct regcache *regcache, int regno)
   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),
+    error (_("Couldn't write register %s (#%d): %s."),
+          gdbarch_register_name (get_regcache_arch (regcache), regno),
           regno, safe_strerror (errno));
 }
 \f
@@ -209,7 +210,8 @@ supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
   for (i = 0; i < I386_NUM_GREGS; i++)
     regcache_raw_supply (regcache, i, regp + regmap[i]);
 
-  if (I386_LINUX_ORIG_EAX_REGNUM < NUM_REGS)
+  if (I386_LINUX_ORIG_EAX_REGNUM
+       < gdbarch_num_regs (get_regcache_arch (regcache)))
     regcache_raw_supply (regcache, I386_LINUX_ORIG_EAX_REGNUM,
                         regp + ORIG_EAX);
 }
@@ -230,7 +232,8 @@ fill_gregset (const struct regcache *regcache,
       regcache_raw_collect (regcache, i, regp + regmap[i]);
 
   if ((regno == -1 || regno == I386_LINUX_ORIG_EAX_REGNUM)
-      && I386_LINUX_ORIG_EAX_REGNUM < NUM_REGS)
+      && I386_LINUX_ORIG_EAX_REGNUM
+          < gdbarch_num_regs (get_regcache_arch (regcache)))
     regcache_raw_collect (regcache, I386_LINUX_ORIG_EAX_REGNUM,
                          regp + ORIG_EAX);
 }
@@ -244,6 +247,7 @@ static void
 fetch_regs (struct regcache *regcache, int tid)
 {
   elf_gregset_t regs;
+  elf_gregset_t *regs_p = &regs;
 
   if (ptrace (PTRACE_GETREGS, tid, 0, (int) &regs) < 0)
     {
@@ -258,7 +262,7 @@ fetch_regs (struct regcache *regcache, int tid)
       perror_with_name (_("Couldn't get registers"));
     }
 
-  supply_gregset (regcache, (const elf_gregset_t *) &regs);
+  supply_gregset (regcache, (const elf_gregset_t *) regs_p);
 }
 
 /* Store all valid general-purpose registers in GDB's register array
@@ -447,7 +451,8 @@ static int store_fpxregs (const struct regcache *regcache, int tid, int regno) {
    registers).  */
 
 static void
-i386_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
+i386_linux_fetch_inferior_registers (struct target_ops *ops,
+                                    struct regcache *regcache, int regno)
 {
   int tid;
 
@@ -457,7 +462,7 @@ i386_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
     {
       int i;
 
-      for (i = 0; i < NUM_REGS; i++)
+      for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
        if (regno == -1 || regno == i)
          fetch_register (regcache, i);
 
@@ -480,7 +485,7 @@ i386_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
       /* The call above might reset `have_ptrace_getregs'.  */
       if (!have_ptrace_getregs)
        {
-         i386_linux_fetch_inferior_registers (regcache, regno);
+         i386_linux_fetch_inferior_registers (ops, regcache, regno);
          return;
        }
 
@@ -519,7 +524,8 @@ i386_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
    do this for all registers (including the floating point and SSE
    registers).  */
 static void
-i386_linux_store_inferior_registers (struct regcache *regcache, int regno)
+i386_linux_store_inferior_registers (struct target_ops *ops,
+                                    struct regcache *regcache, int regno)
 {
   int tid;
 
@@ -529,7 +535,7 @@ i386_linux_store_inferior_registers (struct regcache *regcache, int regno)
     {
       int i;
 
-      for (i = 0; i < NUM_REGS; i++)
+      for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
        if (regno == -1 || regno == i)
          store_register (regcache, i);
 
@@ -578,16 +584,17 @@ i386_linux_store_inferior_registers (struct regcache *regcache, int regno)
 
 /* Support for debug registers.  */
 
+static unsigned long i386_linux_dr[DR_CONTROL + 1];
+
 static unsigned long
-i386_linux_dr_get (int regnum)
+i386_linux_dr_get (ptid_t ptid, int regnum)
 {
   int tid;
   unsigned long value;
 
-  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
-     multi-threaded processes here.  For now, pretend there is just
-     one thread.  */
-  tid = PIDGET (inferior_ptid);
+  tid = TIDGET (ptid);
+  if (tid == 0)
+    tid = PIDGET (ptid);
 
   /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
      ptrace call fails breaks debugging remote targets.  The correct
@@ -608,14 +615,13 @@ i386_linux_dr_get (int regnum)
 }
 
 static void
-i386_linux_dr_set (int regnum, unsigned long value)
+i386_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
 {
   int tid;
 
-  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
-     multi-threaded processes here.  For now, pretend there is just
-     one thread.  */
-  tid = PIDGET (inferior_ptid);
+  tid = TIDGET (ptid);
+  if (tid == 0)
+    tid = PIDGET (ptid);
 
   errno = 0;
   ptrace (PTRACE_POKEUSER, tid,
@@ -624,32 +630,51 @@ i386_linux_dr_set (int regnum, unsigned long value)
     perror_with_name (_("Couldn't write debug register"));
 }
 
-void
+static void
 i386_linux_dr_set_control (unsigned long control)
 {
-  i386_linux_dr_set (DR_CONTROL, control);
+  struct lwp_info *lp;
+  ptid_t ptid;
+
+  i386_linux_dr[DR_CONTROL] = control;
+  ALL_LWPS (lp, ptid)
+    i386_linux_dr_set (ptid, DR_CONTROL, control);
 }
 
-void
+static void
 i386_linux_dr_set_addr (int regnum, CORE_ADDR addr)
 {
+  struct lwp_info *lp;
+  ptid_t ptid;
+
   gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
 
-  i386_linux_dr_set (DR_FIRSTADDR + regnum, addr);
+  i386_linux_dr[DR_FIRSTADDR + regnum] = addr;
+  ALL_LWPS (lp, ptid)
+    i386_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
 }
 
-void
+static void
 i386_linux_dr_reset_addr (int regnum)
 {
-  gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
-
-  i386_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
+  i386_linux_dr_set_addr (regnum, 0);
 }
 
-unsigned long
+static unsigned long
 i386_linux_dr_get_status (void)
 {
-  return i386_linux_dr_get (DR_STATUS);
+  return i386_linux_dr_get (inferior_ptid, DR_STATUS);
+}
+
+static void
+i386_linux_new_thread (ptid_t ptid)
+{
+  int i;
+
+  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+    i386_linux_dr_set (ptid, i, i386_linux_dr[i]);
+
+  i386_linux_dr_set (ptid, DR_CONTROL, i386_linux_dr[DR_CONTROL]);
 }
 \f
 
@@ -722,25 +747,26 @@ static const unsigned char linux_syscall[] = { 0xcd, 0x80 };
    If SIGNAL is nonzero, give it that signal.  */
 
 static void
-i386_linux_resume (ptid_t ptid, int step, enum target_signal signal)
+i386_linux_resume (struct target_ops *ops,
+                  ptid_t ptid, int step, enum target_signal signal)
 {
   int pid = PIDGET (ptid);
 
   int request = PTRACE_CONT;
 
-  if (pid == -1)
-    /* Resume all threads.  */
-    /* I think this only gets used in the non-threaded case, where "resume
-       all threads" and "resume inferior_ptid" are the same.  */
-    pid = PIDGET (inferior_ptid);
-
   if (step)
     {
-      CORE_ADDR pc = read_pc_pid (pid_to_ptid (pid));
+      struct regcache *regcache = get_thread_regcache (pid_to_ptid (pid));
+      struct gdbarch *gdbarch = get_regcache_arch (regcache);
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      ULONGEST pc;
       gdb_byte buf[LINUX_SYSCALL_LEN];
 
       request = PTRACE_SINGLESTEP;
 
+      regcache_cooked_read_unsigned (regcache,
+                                    gdbarch_pc_regnum (gdbarch), &pc);
+
       /* Returning from a signal trampoline is done by calling a
          special system call (sigreturn or rt_sigreturn, see
          i386-linux-tdep.c for more information).  This system call
@@ -750,21 +776,24 @@ i386_linux_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 (read_memory_nobpt (pc, buf, LINUX_SYSCALL_LEN) == 0
+      if (target_read_memory (pc, buf, LINUX_SYSCALL_LEN) == 0
          && memcmp (buf, linux_syscall, LINUX_SYSCALL_LEN) == 0)
        {
-         int syscall = read_register_pid (LINUX_SYSCALL_REGNUM,
-                                          pid_to_ptid (pid));
+         ULONGEST syscall;
+         regcache_cooked_read_unsigned (regcache,
+                                        LINUX_SYSCALL_REGNUM, &syscall);
 
          /* Then check the system call number.  */
          if (syscall == SYS_sigreturn || syscall == SYS_rt_sigreturn)
            {
-             CORE_ADDR sp = read_register (I386_ESP_REGNUM);
-             CORE_ADDR addr = sp;
+             ULONGEST sp, addr;
              unsigned long int eflags;
 
+             regcache_cooked_read_unsigned (regcache, I386_ESP_REGNUM, &sp);
              if (syscall == SYS_rt_sigreturn)
-               addr = read_memory_integer (sp + 8, 4) + 20;
+               addr = read_memory_integer (sp + 8, 4, byte_order) + 20;
+             else
+               addr = sp;
 
              /* Set the trace flag in the context that's about to be
                  restored.  */
@@ -797,6 +826,14 @@ _initialize_i386_linux_nat (void)
   /* Fill in the generic GNU/Linux methods.  */
   t = linux_target ();
 
+  i386_use_watchpoints (t);
+
+  i386_dr_low.set_control = i386_linux_dr_set_control;
+  i386_dr_low.set_addr = i386_linux_dr_set_addr;
+  i386_dr_low.reset_addr = i386_linux_dr_reset_addr;
+  i386_dr_low.get_status = i386_linux_dr_get_status;
+  i386_set_debug_register_length (4);
+
   /* Override the default ptrace resume method.  */
   t->to_resume = i386_linux_resume;
 
@@ -810,4 +847,5 @@ _initialize_i386_linux_nat (void)
 
   /* Register the target.  */
   linux_nat_add_target (t);
+  linux_nat_set_new_thread (t, i386_linux_new_thread);
 }
This page took 0.050836 seconds and 4 git commands to generate.