* configure.ac (AC_CHECK_FUNCS): Add check for setsid.
[deliverable/binutils-gdb.git] / gdb / i386-linux-nat.c
index bfa099dd0118bed0a12d385ae69b0c543aac8449..bff376c2110c8ad348be29b16095038e8825ca37 100644 (file)
@@ -1,13 +1,13 @@
 /* Native-dependent code for GNU/Linux i386.
 
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    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,
@@ -16,9 +16,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"
@@ -142,7 +140,7 @@ int have_ptrace_getfpxregs =
 /* Fetch one register.  */
 
 static void
-fetch_register (int regno)
+fetch_register (struct regcache *regcache, int regno)
 {
   int tid;
   int val;
@@ -150,7 +148,7 @@ fetch_register (int regno)
   gdb_assert (!have_ptrace_getregs);
   if (regmap[regno] == -1)
     {
-      regcache_raw_supply (current_regcache, regno, NULL);
+      regcache_raw_supply (regcache, regno, NULL);
       return;
     }
 
@@ -162,16 +160,17 @@ fetch_register (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 (current_regcache, regno, &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;
@@ -186,10 +185,11 @@ store_register (int regno)
     tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
 
   errno = 0;
-  regcache_raw_collect (current_regcache, regno, &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),
+    error (_("Couldn't write register %s (#%d): %s."),
+          gdbarch_register_name (get_regcache_arch (regcache), regno),
           regno, safe_strerror (errno));
 }
 \f
@@ -209,7 +209,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 +231,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);
 }
@@ -241,9 +243,10 @@ 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;
+  elf_gregset_t *regs_p = &regs;
 
   if (ptrace (PTRACE_GETREGS, tid, 0, (int) &regs) < 0)
     {
@@ -258,21 +261,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_p);
 }
 
 /* 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"));
@@ -280,8 +283,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
@@ -314,28 +317,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"));
@@ -343,8 +346,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
@@ -379,7 +382,7 @@ fill_fpxregset (const struct regcache *regcache,
    Return non-zero if successful, zero otherwise.  */
 
 static int
-fetch_fpxregs (int tid)
+fetch_fpxregs (struct regcache *regcache, int tid)
 {
   elf_fpxregset_t fpxregs;
 
@@ -397,7 +400,7 @@ fetch_fpxregs (int tid)
       perror_with_name (_("Couldn't read floating-point and SSE registers"));
     }
 
-  supply_fpxregset (current_regcache, (const elf_fpxregset_t *) &fpxregs);
+  supply_fpxregset (regcache, (const elf_fpxregset_t *) &fpxregs);
   return 1;
 }
 
@@ -406,7 +409,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;
 
@@ -424,7 +427,7 @@ store_fpxregs (int tid, int regno)
       perror_with_name (_("Couldn't read floating-point and SSE registers"));
     }
 
-  fill_fpxregset (current_regcache, &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"));
@@ -434,8 +437,8 @@ 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
@@ -447,7 +450,7 @@ static int store_fpxregs (int tid, int regno) { return 0; }
    registers).  */
 
 static void
-i386_linux_fetch_inferior_registers (int regno)
+i386_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
 {
   int tid;
 
@@ -457,9 +460,9 @@ i386_linux_fetch_inferior_registers (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 (i);
+         fetch_register (regcache, i);
 
       return;
     }
@@ -475,30 +478,30 @@ i386_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)
        {
-         i386_linux_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
@@ -507,7 +510,7 @@ i386_linux_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;
     }
 
@@ -519,7 +522,7 @@ i386_linux_fetch_inferior_registers (int regno)
    do this for all registers (including the floating point and SSE
    registers).  */
 static void
-i386_linux_store_inferior_registers (int regno)
+i386_linux_store_inferior_registers (struct regcache *regcache, int regno)
 {
   int tid;
 
@@ -529,9 +532,9 @@ i386_linux_store_inferior_registers (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 (i);
+         store_register (regcache, i);
 
       return;
     }
@@ -546,28 +549,28 @@ i386_linux_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;
     }
 
@@ -578,16 +581,17 @@ i386_linux_store_inferior_registers (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 +612,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,
@@ -627,29 +630,48 @@ i386_linux_dr_set (int regnum, unsigned long value)
 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
 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
 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
 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
 
@@ -728,19 +750,17 @@ i386_linux_resume (ptid_t ptid, int step, enum target_signal signal)
 
   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));
+      ULONGEST pc;
       gdb_byte buf[LINUX_SYSCALL_LEN];
 
       request = PTRACE_SINGLESTEP;
 
+      regcache_cooked_read_unsigned
+       (regcache, gdbarch_pc_regnum (get_regcache_arch (regcache)), &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
@@ -753,18 +773,21 @@ i386_linux_resume (ptid_t ptid, int step, enum target_signal signal)
       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,
-                                          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;
+             else
+               addr = sp;
 
              /* Set the trace flag in the context that's about to be
                  restored.  */
@@ -797,6 +820,8 @@ _initialize_i386_linux_nat (void)
   /* Fill in the generic GNU/Linux methods.  */
   t = linux_target ();
 
+  i386_use_watchpoints (t);
+
   /* Override the default ptrace resume method.  */
   t->to_resume = i386_linux_resume;
 
@@ -810,4 +835,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.074937 seconds and 4 git commands to generate.