2007-10-02 Mark Mitchell <mark@codesourcery.com>
[deliverable/binutils-gdb.git] / gdb / linux-nat.c
index 3345cb704e38c0fd749d030fa730f34a4efb2988..18c28006b021bc07379966aa04c9fbe7b8cece1b 100644 (file)
@@ -7,7 +7,7 @@
 
    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
 
    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,
    (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
    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"
 
 #include "defs.h"
 #include "inferior.h"
@@ -91,6 +89,9 @@
 static struct target_ops *linux_ops;
 static struct target_ops linux_ops_saved;
 
 static struct target_ops *linux_ops;
 static struct target_ops linux_ops_saved;
 
+/* The method to call, if any, when a new thread is attached.  */
+static void (*linux_nat_new_thread) (ptid_t);
+
 /* The saved to_xfer_partial method, inherited from inf-ptrace.c.
    Called by our to_xfer_partial.  */
 static LONGEST (*super_xfer_partial) (struct target_ops *, 
 /* The saved to_xfer_partial method, inherited from inf-ptrace.c.
    Called by our to_xfer_partial.  */
 static LONGEST (*super_xfer_partial) (struct target_ops *, 
@@ -335,8 +336,8 @@ linux_enable_event_reporting (ptid_t ptid)
   ptrace (PTRACE_SETOPTIONS, pid, 0, options);
 }
 
   ptrace (PTRACE_SETOPTIONS, pid, 0, options);
 }
 
-void
-child_post_attach (int pid)
+static void
+linux_child_post_attach (int pid)
 {
   linux_enable_event_reporting (pid_to_ptid (pid));
   check_for_thread_db ();
 {
   linux_enable_event_reporting (pid_to_ptid (pid));
   check_for_thread_db ();
@@ -349,8 +350,8 @@ linux_child_post_startup_inferior (ptid_t ptid)
   check_for_thread_db ();
 }
 
   check_for_thread_db ();
 }
 
-int
-child_follow_fork (struct target_ops *ops, int follow_child)
+static int
+linux_child_follow_fork (struct target_ops *ops, int follow_child)
 {
   ptid_t last_ptid;
   struct target_waitstatus last_status;
 {
   ptid_t last_ptid;
   struct target_waitstatus last_status;
@@ -505,12 +506,13 @@ child_follow_fork (struct target_ops *ops, int follow_child)
          target_detach (NULL, 0);
        }
 
          target_detach (NULL, 0);
        }
 
-      inferior_ptid = pid_to_ptid (child_pid);
+      inferior_ptid = ptid_build (child_pid, child_pid, 0);
 
       /* Reinstall ourselves, since we might have been removed in
         target_detach (which does other necessary cleanup).  */
 
       push_target (ops);
 
       /* Reinstall ourselves, since we might have been removed in
         target_detach (which does other necessary cleanup).  */
 
       push_target (ops);
+      linux_nat_switch_fork (inferior_ptid);
 
       /* Reset breakpoints in the child as appropriate.  */
       follow_inferior_reset_breakpoints ();
 
       /* Reset breakpoints in the child as appropriate.  */
       follow_inferior_reset_breakpoints ();
@@ -520,22 +522,22 @@ child_follow_fork (struct target_ops *ops, int follow_child)
 }
 
 \f
 }
 
 \f
-void
-child_insert_fork_catchpoint (int pid)
+static void
+linux_child_insert_fork_catchpoint (int pid)
 {
   if (! linux_supports_tracefork (pid))
     error (_("Your system does not support fork catchpoints."));
 }
 
 {
   if (! linux_supports_tracefork (pid))
     error (_("Your system does not support fork catchpoints."));
 }
 
-void
-child_insert_vfork_catchpoint (int pid)
+static void
+linux_child_insert_vfork_catchpoint (int pid)
 {
   if (!linux_supports_tracefork (pid))
     error (_("Your system does not support vfork catchpoints."));
 }
 
 {
   if (!linux_supports_tracefork (pid))
     error (_("Your system does not support vfork catchpoints."));
 }
 
-void
-child_insert_exec_catchpoint (int pid)
+static void
+linux_child_insert_exec_catchpoint (int pid)
 {
   if (!linux_supports_tracefork (pid))
     error (_("Your system does not support exec catchpoints."));
 {
   if (!linux_supports_tracefork (pid))
     error (_("Your system does not support exec catchpoints."));
@@ -575,7 +577,7 @@ child_insert_exec_catchpoint (int pid)
      because the "zombies" stay around.  */
 
 /* List of known LWPs.  */
      because the "zombies" stay around.  */
 
 /* List of known LWPs.  */
-static struct lwp_info *lwp_list;
+struct lwp_info *lwp_list;
 
 /* Number of LWPs in the list.  */
 static int num_lwps;
 
 /* Number of LWPs in the list.  */
 static int num_lwps;
@@ -616,6 +618,7 @@ static sigset_t blocked_mask;
 /* Prototypes for local functions.  */
 static int stop_wait_callback (struct lwp_info *lp, void *data);
 static int linux_nat_thread_alive (ptid_t ptid);
 /* Prototypes for local functions.  */
 static int stop_wait_callback (struct lwp_info *lp, void *data);
 static int linux_nat_thread_alive (ptid_t ptid);
+static char *linux_child_pid_to_exec_file (int pid);
 \f
 /* Convert wait status STATUS to a string.  Used for printing debug
    messages only.  */
 \f
 /* Convert wait status STATUS to a string.  Used for printing debug
    messages only.  */
@@ -658,7 +661,8 @@ init_lwp_list (void)
 }
 
 /* Add the LWP specified by PID to the list.  Return a pointer to the
 }
 
 /* Add the LWP specified by PID to the list.  Return a pointer to the
-   structure describing the new LWP.  */
+   structure describing the new LWP.  The LWP should already be stopped
+   (with an exception for the very first LWP).  */
 
 static struct lwp_info *
 add_lwp (ptid_t ptid)
 
 static struct lwp_info *
 add_lwp (ptid_t ptid)
@@ -679,6 +683,9 @@ add_lwp (ptid_t ptid)
   lwp_list = lp;
   ++num_lwps;
 
   lwp_list = lp;
   ++num_lwps;
 
+  if (num_lwps > 1 && linux_nat_new_thread != NULL)
+    linux_nat_new_thread (ptid);
+
   return lp;
 }
 
   return lp;
 }
 
@@ -885,6 +892,7 @@ lin_lwp_attach_lwp (ptid_t ptid, int verbose)
     {
       pid_t pid;
       int status;
     {
       pid_t pid;
       int status;
+      int cloned = 0;
 
       if (ptrace (PTRACE_ATTACH, GET_LWP (ptid), 0, 0) < 0)
        {
 
       if (ptrace (PTRACE_ATTACH, GET_LWP (ptid), 0, 0) < 0)
        {
@@ -898,9 +906,6 @@ lin_lwp_attach_lwp (ptid_t ptid, int verbose)
          return -1;
        }
 
          return -1;
        }
 
-      if (lp == NULL)
-       lp = add_lwp (ptid);
-
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
                            "LLAL: PTRACE_ATTACH %s, 0, 0 (OK)\n",
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
                            "LLAL: PTRACE_ATTACH %s, 0, 0 (OK)\n",
@@ -911,12 +916,16 @@ lin_lwp_attach_lwp (ptid_t ptid, int verbose)
        {
          /* Try again with __WCLONE to check cloned processes.  */
          pid = my_waitpid (GET_LWP (ptid), &status, __WCLONE);
        {
          /* Try again with __WCLONE to check cloned processes.  */
          pid = my_waitpid (GET_LWP (ptid), &status, __WCLONE);
-         lp->cloned = 1;
+         cloned = 1;
        }
 
       gdb_assert (pid == GET_LWP (ptid)
                  && WIFSTOPPED (status) && WSTOPSIG (status));
 
        }
 
       gdb_assert (pid == GET_LWP (ptid)
                  && WIFSTOPPED (status) && WSTOPSIG (status));
 
+      if (lp == NULL)
+       lp = add_lwp (ptid);
+      lp->cloned = cloned;
+
       target_post_attach (pid);
 
       lp->stopped = 1;
       target_post_attach (pid);
 
       lp->stopped = 1;
@@ -954,15 +963,12 @@ linux_nat_attach (char *args, int from_tty)
   struct lwp_info *lp;
   pid_t pid;
   int status;
   struct lwp_info *lp;
   pid_t pid;
   int status;
+  int cloned = 0;
 
   /* FIXME: We should probably accept a list of process id's, and
      attach all of them.  */
   linux_ops->to_attach (args, from_tty);
 
 
   /* FIXME: We should probably accept a list of process id's, and
      attach all of them.  */
   linux_ops->to_attach (args, from_tty);
 
-  /* Add the initial process as the first LWP to the list.  */
-  inferior_ptid = BUILD_LWP (GET_PID (inferior_ptid), GET_PID (inferior_ptid));
-  lp = add_lwp (inferior_ptid);
-
   /* Make sure the initial process is stopped.  The user-level threads
      layer might want to poke around in the inferior, and that won't
      work if things haven't stabilized yet.  */
   /* Make sure the initial process is stopped.  The user-level threads
      layer might want to poke around in the inferior, and that won't
      work if things haven't stabilized yet.  */
@@ -973,12 +979,17 @@ linux_nat_attach (char *args, int from_tty)
 
       /* Try again with __WCLONE to check cloned processes.  */
       pid = my_waitpid (GET_PID (inferior_ptid), &status, __WCLONE);
 
       /* Try again with __WCLONE to check cloned processes.  */
       pid = my_waitpid (GET_PID (inferior_ptid), &status, __WCLONE);
-      lp->cloned = 1;
+      cloned = 1;
     }
 
   gdb_assert (pid == GET_PID (inferior_ptid)
              && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP);
 
     }
 
   gdb_assert (pid == GET_PID (inferior_ptid)
              && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP);
 
+  /* Add the initial process as the first LWP to the list.  */
+  inferior_ptid = BUILD_LWP (GET_PID (inferior_ptid), GET_PID (inferior_ptid));
+  lp = add_lwp (inferior_ptid);
+  lp->cloned = cloned;
+
   lp->stopped = 1;
 
   /* Fake the SIGSTOP that core GDB expects.  */
   lp->stopped = 1;
 
   /* Fake the SIGSTOP that core GDB expects.  */
@@ -1078,8 +1089,6 @@ resume_callback (struct lwp_info *lp, void *data)
 {
   if (lp->stopped && lp->status == 0)
     {
 {
   if (lp->stopped && lp->status == 0)
     {
-      struct thread_info *tp;
-
       linux_ops->to_resume (pid_to_ptid (GET_LWP (lp->ptid)),
                            0, TARGET_SIGNAL_0);
       if (debug_linux_nat)
       linux_ops->to_resume (pid_to_ptid (GET_LWP (lp->ptid)),
                            0, TARGET_SIGNAL_0);
       if (debug_linux_nat)
@@ -1088,6 +1097,7 @@ resume_callback (struct lwp_info *lp, void *data)
                            target_pid_to_str (lp->ptid));
       lp->stopped = 0;
       lp->step = 0;
                            target_pid_to_str (lp->ptid));
       lp->stopped = 0;
       lp->step = 0;
+      memset (&lp->siginfo, 0, sizeof (lp->siginfo));
     }
 
   return 0;
     }
 
   return 0;
@@ -1137,68 +1147,69 @@ linux_nat_resume (ptid_t ptid, int step, enum target_signal signo)
     ptid = inferior_ptid;
 
   lp = find_lwp_pid (ptid);
     ptid = inferior_ptid;
 
   lp = find_lwp_pid (ptid);
-  if (lp)
-    {
-      ptid = pid_to_ptid (GET_LWP (lp->ptid));
+  gdb_assert (lp != NULL);
 
 
-      /* Remember if we're stepping.  */
-      lp->step = step;
+  ptid = pid_to_ptid (GET_LWP (lp->ptid));
 
 
-      /* Mark this LWP as resumed.  */
-      lp->resumed = 1;
+  /* Remember if we're stepping.  */
+  lp->step = step;
 
 
-      /* If we have a pending wait status for this thread, there is no
-        point in resuming the process.  But first make sure that
-        linux_nat_wait won't preemptively handle the event - we
-        should never take this short-circuit if we are going to
-        leave LP running, since we have skipped resuming all the
-        other threads.  This bit of code needs to be synchronized
-        with linux_nat_wait.  */
+  /* Mark this LWP as resumed.  */
+  lp->resumed = 1;
 
 
-      if (lp->status && WIFSTOPPED (lp->status))
-       {
-         int saved_signo = target_signal_from_host (WSTOPSIG (lp->status));
+  /* If we have a pending wait status for this thread, there is no
+     point in resuming the process.  But first make sure that
+     linux_nat_wait won't preemptively handle the event - we
+     should never take this short-circuit if we are going to
+     leave LP running, since we have skipped resuming all the
+     other threads.  This bit of code needs to be synchronized
+     with linux_nat_wait.  */
 
 
-         if (signal_stop_state (saved_signo) == 0
-             && signal_print_state (saved_signo) == 0
-             && signal_pass_state (saved_signo) == 1)
-           {
-             if (debug_linux_nat)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "LLR: Not short circuiting for ignored "
-                                   "status 0x%x\n", lp->status);
-
-             /* FIXME: What should we do if we are supposed to continue
-                this thread with a signal?  */
-             gdb_assert (signo == TARGET_SIGNAL_0);
-             signo = saved_signo;
-             lp->status = 0;
-           }
-       }
+  if (lp->status && WIFSTOPPED (lp->status))
+    {
+      int saved_signo = target_signal_from_host (WSTOPSIG (lp->status));
 
 
-      if (lp->status)
+      if (signal_stop_state (saved_signo) == 0
+         && signal_print_state (saved_signo) == 0
+         && signal_pass_state (saved_signo) == 1)
        {
        {
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "LLR: Not short circuiting for ignored "
+                               "status 0x%x\n", lp->status);
+
          /* FIXME: What should we do if we are supposed to continue
             this thread with a signal?  */
          gdb_assert (signo == TARGET_SIGNAL_0);
          /* FIXME: What should we do if we are supposed to continue
             this thread with a signal?  */
          gdb_assert (signo == TARGET_SIGNAL_0);
+         signo = saved_signo;
+         lp->status = 0;
+       }
+    }
 
 
-         if (debug_linux_nat)
-           fprintf_unfiltered (gdb_stdlog,
-                               "LLR: Short circuiting for status 0x%x\n",
-                               lp->status);
+  if (lp->status)
+    {
+      /* FIXME: What should we do if we are supposed to continue
+        this thread with a signal?  */
+      gdb_assert (signo == TARGET_SIGNAL_0);
 
 
-         return;
-       }
+      if (debug_linux_nat)
+       fprintf_unfiltered (gdb_stdlog,
+                           "LLR: Short circuiting for status 0x%x\n",
+                           lp->status);
 
 
-      /* Mark LWP as not stopped to prevent it from being continued by
-         resume_callback.  */
-      lp->stopped = 0;
+      return;
     }
 
     }
 
+  /* Mark LWP as not stopped to prevent it from being continued by
+     resume_callback.  */
+  lp->stopped = 0;
+
   if (resume_all)
     iterate_over_lwps (resume_callback, NULL);
 
   linux_ops->to_resume (ptid, step, signo);
   if (resume_all)
     iterate_over_lwps (resume_callback, NULL);
 
   linux_ops->to_resume (ptid, step, signo);
+  memset (&lp->siginfo, 0, sizeof (lp->siginfo));
+
   if (debug_linux_nat)
     fprintf_unfiltered (gdb_stdlog,
                        "LLR: %s %s, %s (resume event thread)\n",
   if (debug_linux_nat)
     fprintf_unfiltered (gdb_stdlog,
                        "LLR: %s %s, %s (resume event thread)\n",
@@ -1325,7 +1336,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
     {
       ourstatus->kind = TARGET_WAITKIND_EXECD;
       ourstatus->value.execd_pathname
     {
       ourstatus->kind = TARGET_WAITKIND_EXECD;
       ourstatus->value.execd_pathname
-       = xstrdup (child_pid_to_exec_file (pid));
+       = xstrdup (linux_child_pid_to_exec_file (pid));
 
       if (linux_parent_pid)
        {
 
       if (linux_parent_pid)
        {
@@ -1417,6 +1428,22 @@ wait_lwp (struct lwp_info *lp)
   return status;
 }
 
   return status;
 }
 
+/* Save the most recent siginfo for LP.  This is currently only called
+   for SIGTRAP; some ports use the si_addr field for
+   target_stopped_data_address.  In the future, it may also be used to
+   restore the siginfo of requeued signals.  */
+
+static void
+save_siginfo (struct lwp_info *lp)
+{
+  errno = 0;
+  ptrace (PTRACE_GETSIGINFO, GET_LWP (lp->ptid),
+         (PTRACE_TYPE_ARG3) 0, &lp->siginfo);
+
+  if (errno != 0)
+    memset (&lp->siginfo, 0, sizeof (lp->siginfo));
+}
+
 /* Send a SIGSTOP to LP.  */
 
 static int
 /* Send a SIGSTOP to LP.  */
 
 static int
@@ -1502,6 +1529,9 @@ stop_wait_callback (struct lwp_info *lp, void *data)
                 user will delete or disable the breakpoint, but the
                 thread will have already tripped on it.  */
 
                 user will delete or disable the breakpoint, but the
                 thread will have already tripped on it.  */
 
+             /* Save the trap's siginfo in case we need it later.  */
+             save_siginfo (lp);
+
              /* Now resume this LWP and get the SIGSTOP event. */
              errno = 0;
              ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
              /* Now resume this LWP and get the SIGSTOP event. */
              errno = 0;
              ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
@@ -1766,7 +1796,8 @@ cancel_breakpoints_callback (struct lwp_info *lp, void *data)
   if (lp->status != 0
       && WIFSTOPPED (lp->status) && WSTOPSIG (lp->status) == SIGTRAP
       && breakpoint_inserted_here_p (read_pc_pid (lp->ptid) -
   if (lp->status != 0
       && WIFSTOPPED (lp->status) && WSTOPSIG (lp->status) == SIGTRAP
       && breakpoint_inserted_here_p (read_pc_pid (lp->ptid) -
-                                    DECR_PC_AFTER_BREAK))
+                                    gdbarch_decr_pc_after_break
+                                      (current_gdbarch)))
     {
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
     {
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
@@ -1774,8 +1805,10 @@ cancel_breakpoints_callback (struct lwp_info *lp, void *data)
                            target_pid_to_str (lp->ptid));
 
       /* Back up the PC if necessary.  */
                            target_pid_to_str (lp->ptid));
 
       /* Back up the PC if necessary.  */
-      if (DECR_PC_AFTER_BREAK)
-       write_pc_pid (read_pc_pid (lp->ptid) - DECR_PC_AFTER_BREAK, lp->ptid);
+      if (gdbarch_decr_pc_after_break (current_gdbarch))
+       write_pc_pid (read_pc_pid (lp->ptid) - gdbarch_decr_pc_after_break
+                                                (current_gdbarch),
+                     lp->ptid);
 
       /* Throw away the SIGTRAP.  */
       lp->status = 0;
 
       /* Throw away the SIGTRAP.  */
       lp->status = 0;
@@ -2056,6 +2089,10 @@ retry:
                                 target_pid_to_str (lp->ptid));
            }
 
                                 target_pid_to_str (lp->ptid));
            }
 
+         /* Save the trap's siginfo in case we need it later.  */
+         if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
+           save_siginfo (lp);
+
          /* Handle GNU/Linux's extended waitstatus for trace events.  */
          if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
            {
          /* Handle GNU/Linux's extended waitstatus for trace events.  */
          if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
            {
@@ -2463,8 +2500,8 @@ sigchld_handler (int signo)
 /* Accepts an integer PID; Returns a string representing a file that
    can be opened to get the symbols for the child process.  */
 
 /* Accepts an integer PID; Returns a string representing a file that
    can be opened to get the symbols for the child process.  */
 
-char *
-child_pid_to_exec_file (int pid)
+static char *
+linux_child_pid_to_exec_file (int pid)
 {
   char *name1, *name2;
 
 {
   char *name1, *name2;
 
@@ -2579,19 +2616,26 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid,
   gdb_fpxregset_t fpxregs;
 #endif
   unsigned long lwp = ptid_get_lwp (ptid);
   gdb_fpxregset_t fpxregs;
 #endif
   unsigned long lwp = ptid_get_lwp (ptid);
-  struct gdbarch *gdbarch = current_gdbarch;
+  struct regcache *regcache = get_thread_regcache (ptid);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
   const struct regset *regset;
   int core_regset_p;
   const struct regset *regset;
   int core_regset_p;
+  struct cleanup *old_chain;
+
+  old_chain = save_inferior_ptid ();
+  inferior_ptid = ptid;
+  target_fetch_registers (regcache, -1);
+  do_cleanups (old_chain);
 
   core_regset_p = gdbarch_regset_from_core_section_p (gdbarch);
   if (core_regset_p
       && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg",
                                                     sizeof (gregs))) != NULL
       && regset->collect_regset != NULL)
 
   core_regset_p = gdbarch_regset_from_core_section_p (gdbarch);
   if (core_regset_p
       && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg",
                                                     sizeof (gregs))) != NULL
       && regset->collect_regset != NULL)
-    regset->collect_regset (regset, current_regcache, -1,
+    regset->collect_regset (regset, regcache, -1,
                            &gregs, sizeof (gregs));
   else
                            &gregs, sizeof (gregs));
   else
-    fill_gregset (current_regcache, &gregs, -1);
+    fill_gregset (regcache, &gregs, -1);
 
   note_data = (char *) elfcore_write_prstatus (obfd,
                                               note_data,
 
   note_data = (char *) elfcore_write_prstatus (obfd,
                                               note_data,
@@ -2603,10 +2647,10 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid,
       && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2",
                                                     sizeof (fpregs))) != NULL
       && regset->collect_regset != NULL)
       && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2",
                                                     sizeof (fpregs))) != NULL
       && regset->collect_regset != NULL)
-    regset->collect_regset (regset, current_regcache, -1,
+    regset->collect_regset (regset, regcache, -1,
                            &fpregs, sizeof (fpregs));
   else
                            &fpregs, sizeof (fpregs));
   else
-    fill_fpregset (current_regcache, &fpregs, -1);
+    fill_fpregset (regcache, &fpregs, -1);
 
   note_data = (char *) elfcore_write_prfpreg (obfd,
                                              note_data,
 
   note_data = (char *) elfcore_write_prfpreg (obfd,
                                              note_data,
@@ -2618,10 +2662,10 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid,
       && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg-xfp",
                                                     sizeof (fpxregs))) != NULL
       && regset->collect_regset != NULL)
       && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg-xfp",
                                                     sizeof (fpxregs))) != NULL
       && regset->collect_regset != NULL)
-    regset->collect_regset (regset, current_regcache, -1,
+    regset->collect_regset (regset, regcache, -1,
                            &fpxregs, sizeof (fpxregs));
   else
                            &fpxregs, sizeof (fpxregs));
   else
-    fill_fpxregset (current_regcache, &fpxregs, -1);
+    fill_fpxregset (regcache, &fpxregs, -1);
 
   note_data = (char *) elfcore_write_prxfpreg (obfd,
                                               note_data,
 
   note_data = (char *) elfcore_write_prxfpreg (obfd,
                                               note_data,
@@ -2646,21 +2690,12 @@ static int
 linux_nat_corefile_thread_callback (struct lwp_info *ti, void *data)
 {
   struct linux_nat_corefile_thread_data *args = data;
 linux_nat_corefile_thread_callback (struct lwp_info *ti, void *data)
 {
   struct linux_nat_corefile_thread_data *args = data;
-  ptid_t saved_ptid = inferior_ptid;
 
 
-  inferior_ptid = ti->ptid;
-  registers_changed ();
-  /* FIXME should not be necessary; fill_gregset should do it automatically. */
-  target_fetch_registers (current_regcache, -1);
   args->note_data = linux_nat_do_thread_registers (args->obfd,
                                                   ti->ptid,
                                                   args->note_data,
                                                   args->note_size);
   args->num_notes++;
   args->note_data = linux_nat_do_thread_registers (args->obfd,
                                                   ti->ptid,
                                                   args->note_data,
                                                   args->note_size);
   args->num_notes++;
-  inferior_ptid = saved_ptid;
-  registers_changed ();
-  /* FIXME should not be necessary; fill_gregset should do it automatically. */
-  target_fetch_registers (current_regcache, -1);
 
   return 0;
 }
 
   return 0;
 }
@@ -2671,15 +2706,11 @@ static char *
 linux_nat_do_registers (bfd *obfd, ptid_t ptid,
                        char *note_data, int *note_size)
 {
 linux_nat_do_registers (bfd *obfd, ptid_t ptid,
                        char *note_data, int *note_size)
 {
-  registers_changed ();
-  /* FIXME should not be necessary; fill_gregset should do it automatically. */
-  target_fetch_registers (current_regcache, -1);
   return linux_nat_do_thread_registers (obfd,
                                        ptid_build (ptid_get_pid (inferior_ptid),
                                                    ptid_get_pid (inferior_ptid),
                                                    0),
                                        note_data, note_size);
   return linux_nat_do_thread_registers (obfd,
                                        ptid_build (ptid_get_pid (inferior_ptid),
                                                    ptid_get_pid (inferior_ptid),
                                                    0),
                                        note_data, note_size);
-  return note_data;
 }
 
 /* Fills the "to_make_corefile_note" target vector.  Builds the note
 }
 
 /* Fills the "to_make_corefile_note" target vector.  Builds the note
@@ -2690,7 +2721,9 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size)
 {
   struct linux_nat_corefile_thread_data thread_args;
   struct cleanup *old_chain;
 {
   struct linux_nat_corefile_thread_data thread_args;
   struct cleanup *old_chain;
+  /* The variable size must be >= sizeof (prpsinfo_t.pr_fname).  */
   char fname[16] = { '\0' };
   char fname[16] = { '\0' };
+  /* The variable size must be >= sizeof (prpsinfo_t.pr_psargs).  */
   char psargs[80] = { '\0' };
   char *note_data = NULL;
   ptid_t current_ptid = inferior_ptid;
   char psargs[80] = { '\0' };
   char *note_data = NULL;
   ptid_t current_ptid = inferior_ptid;
@@ -2703,9 +2736,18 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size)
       strncpy (psargs, get_exec_file (0), sizeof (psargs));
       if (get_inferior_args ())
        {
       strncpy (psargs, get_exec_file (0), sizeof (psargs));
       if (get_inferior_args ())
        {
-         strncat (psargs, " ", sizeof (psargs) - strlen (psargs));
-         strncat (psargs, get_inferior_args (),
-                  sizeof (psargs) - strlen (psargs));
+         char *string_end;
+         char *psargs_end = psargs + sizeof (psargs);
+
+         /* linux_elfcore_write_prpsinfo () handles zero unterminated
+            strings fine.  */
+         string_end = memchr (psargs, 0, sizeof (psargs));
+         if (string_end != NULL)
+           {
+             *string_end++ = ' ';
+             strncpy (string_end, get_inferior_args (),
+                      psargs_end - string_end);
+           }
        }
       note_data = (char *) elfcore_write_prpsinfo (obfd,
                                                   note_data,
        }
       note_data = (char *) elfcore_write_prpsinfo (obfd,
                                                   note_data,
@@ -2858,7 +2900,7 @@ linux_nat_info_proc_cmd (char *args, int from_tty)
          char permissions[8], device[8], filename[MAXPATHLEN];
 
          printf_filtered (_("Mapped address spaces:\n\n"));
          char permissions[8], device[8], filename[MAXPATHLEN];
 
          printf_filtered (_("Mapped address spaces:\n\n"));
-         if (TARGET_ADDR_BIT == 32)
+         if (gdbarch_addr_bit (current_gdbarch) == 32)
            {
              printf_filtered ("\t%10s %10s %10s %10s %7s\n",
                           "Start Addr",
            {
              printf_filtered ("\t%10s %10s %10s %10s %7s\n",
                           "Start Addr",
@@ -2884,7 +2926,7 @@ linux_nat_info_proc_cmd (char *args, int from_tty)
                 a generic local_address_string instead to print out
                 the addresses; that makes sense to me, too.  */
 
                 a generic local_address_string instead to print out
                 the addresses; that makes sense to me, too.  */
 
-             if (TARGET_ADDR_BIT == 32)
+             if (gdbarch_addr_bit (current_gdbarch) == 32)
                {
                  printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n",
                               (unsigned long) addr,    /* FIXME: pr_addr */
                {
                  printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n",
                               (unsigned long) addr,    /* FIXME: pr_addr */
@@ -2928,10 +2970,11 @@ linux_nat_info_proc_cmd (char *args, int from_tty)
        {
          int itmp;
          char ctmp;
        {
          int itmp;
          char ctmp;
+         long ltmp;
 
          if (fscanf (procfile, "%d ", &itmp) > 0)
            printf_filtered (_("Process: %d\n"), itmp);
 
          if (fscanf (procfile, "%d ", &itmp) > 0)
            printf_filtered (_("Process: %d\n"), itmp);
-         if (fscanf (procfile, "%s ", &buffer[0]) > 0)
+         if (fscanf (procfile, "(%[^)]) ", &buffer[0]) > 0)
            printf_filtered (_("Exec file: %s\n"), buffer);
          if (fscanf (procfile, "%c ", &ctmp) > 0)
            printf_filtered (_("State: %c\n"), ctmp);
            printf_filtered (_("Exec file: %s\n"), buffer);
          if (fscanf (procfile, "%c ", &ctmp) > 0)
            printf_filtered (_("State: %c\n"), ctmp);
@@ -2945,71 +2988,71 @@ linux_nat_info_proc_cmd (char *args, int from_tty)
            printf_filtered (_("TTY: %d\n"), itmp);
          if (fscanf (procfile, "%d ", &itmp) > 0)
            printf_filtered (_("TTY owner process group: %d\n"), itmp);
            printf_filtered (_("TTY: %d\n"), itmp);
          if (fscanf (procfile, "%d ", &itmp) > 0)
            printf_filtered (_("TTY owner process group: %d\n"), itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered (_("Flags: 0x%x\n"), itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered (_("Minor faults (no memory page): %u\n"),
-                            (unsigned int) itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered (_("Minor faults, children: %u\n"),
-                            (unsigned int) itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered (_("Major faults (memory page faults): %u\n"),
-                            (unsigned int) itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered (_("Major faults, children: %u\n"),
-                            (unsigned int) itmp);
-         if (fscanf (procfile, "%d ", &itmp) > 0)
-           printf_filtered ("utime: %d\n", itmp);
-         if (fscanf (procfile, "%d ", &itmp) > 0)
-           printf_filtered ("stime: %d\n", itmp);
-         if (fscanf (procfile, "%d ", &itmp) > 0)
-           printf_filtered ("utime, children: %d\n", itmp);
-         if (fscanf (procfile, "%d ", &itmp) > 0)
-           printf_filtered ("stime, children: %d\n", itmp);
-         if (fscanf (procfile, "%d ", &itmp) > 0)
-           printf_filtered (_("jiffies remaining in current time slice: %d\n"),
-                            itmp);
-         if (fscanf (procfile, "%d ", &itmp) > 0)
-           printf_filtered ("'nice' value: %d\n", itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered (_("jiffies until next timeout: %u\n"),
-                            (unsigned int) itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered ("jiffies until next SIGALRM: %u\n",
-                            (unsigned int) itmp);
-         if (fscanf (procfile, "%d ", &itmp) > 0)
-           printf_filtered (_("start time (jiffies since system boot): %d\n"),
-                            itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered (_("Virtual memory size: %u\n"),
-                            (unsigned int) itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered (_("Resident set size: %u\n"), (unsigned int) itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered ("rlim: %u\n", (unsigned int) itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered (_("Start of text: 0x%x\n"), itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered (_("End of text: 0x%x\n"), itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)
-           printf_filtered (_("Start of stack: 0x%x\n"), itmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("Flags: 0x%lx\n"), ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("Minor faults (no memory page): %lu\n"),
+                            (unsigned long) ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("Minor faults, children: %lu\n"),
+                            (unsigned long) ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("Major faults (memory page faults): %lu\n"),
+                            (unsigned long) ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("Major faults, children: %lu\n"),
+                            (unsigned long) ltmp);
+         if (fscanf (procfile, "%ld ", &ltmp) > 0)
+           printf_filtered (_("utime: %ld\n"), ltmp);
+         if (fscanf (procfile, "%ld ", &ltmp) > 0)
+           printf_filtered (_("stime: %ld\n"), ltmp);
+         if (fscanf (procfile, "%ld ", &ltmp) > 0)
+           printf_filtered (_("utime, children: %ld\n"), ltmp);
+         if (fscanf (procfile, "%ld ", &ltmp) > 0)
+           printf_filtered (_("stime, children: %ld\n"), ltmp);
+         if (fscanf (procfile, "%ld ", &ltmp) > 0)
+           printf_filtered (_("jiffies remaining in current time slice: %ld\n"),
+                            ltmp);
+         if (fscanf (procfile, "%ld ", &ltmp) > 0)
+           printf_filtered (_("'nice' value: %ld\n"), ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("jiffies until next timeout: %lu\n"),
+                            (unsigned long) ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("jiffies until next SIGALRM: %lu\n"),
+                            (unsigned long) ltmp);
+         if (fscanf (procfile, "%ld ", &ltmp) > 0)
+           printf_filtered (_("start time (jiffies since system boot): %ld\n"),
+                            ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("Virtual memory size: %lu\n"),
+                            (unsigned long) ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("Resident set size: %lu\n"), (unsigned long) ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("rlim: %lu\n"), (unsigned long) ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("Start of text: 0x%lx\n"), ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("End of text: 0x%lx\n"), ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)
+           printf_filtered (_("Start of stack: 0x%lx\n"), ltmp);
 #if 0                          /* Don't know how architecture-dependent the rest is...
                                   Anyway the signal bitmap info is available from "status".  */
 #if 0                          /* Don't know how architecture-dependent the rest is...
                                   Anyway the signal bitmap info is available from "status".  */
-         if (fscanf (procfile, "%u ", &itmp) > 0)      /* FIXME arch? */
-           printf_filtered (_("Kernel stack pointer: 0x%x\n"), itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)      /* FIXME arch? */
-           printf_filtered (_("Kernel instr pointer: 0x%x\n"), itmp);
-         if (fscanf (procfile, "%d ", &itmp) > 0)
-           printf_filtered (_("Pending signals bitmap: 0x%x\n"), itmp);
-         if (fscanf (procfile, "%d ", &itmp) > 0)
-           printf_filtered (_("Blocked signals bitmap: 0x%x\n"), itmp);
-         if (fscanf (procfile, "%d ", &itmp) > 0)
-           printf_filtered (_("Ignored signals bitmap: 0x%x\n"), itmp);
-         if (fscanf (procfile, "%d ", &itmp) > 0)
-           printf_filtered (_("Catched signals bitmap: 0x%x\n"), itmp);
-         if (fscanf (procfile, "%u ", &itmp) > 0)      /* FIXME arch? */
-           printf_filtered (_("wchan (system call): 0x%x\n"), itmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)     /* FIXME arch? */
+           printf_filtered (_("Kernel stack pointer: 0x%lx\n"), ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)     /* FIXME arch? */
+           printf_filtered (_("Kernel instr pointer: 0x%lx\n"), ltmp);
+         if (fscanf (procfile, "%ld ", &ltmp) > 0)
+           printf_filtered (_("Pending signals bitmap: 0x%lx\n"), ltmp);
+         if (fscanf (procfile, "%ld ", &ltmp) > 0)
+           printf_filtered (_("Blocked signals bitmap: 0x%lx\n"), ltmp);
+         if (fscanf (procfile, "%ld ", &ltmp) > 0)
+           printf_filtered (_("Ignored signals bitmap: 0x%lx\n"), ltmp);
+         if (fscanf (procfile, "%ld ", &ltmp) > 0)
+           printf_filtered (_("Catched signals bitmap: 0x%lx\n"), ltmp);
+         if (fscanf (procfile, "%lu ", &ltmp) > 0)     /* FIXME arch? */
+           printf_filtered (_("wchan (system call): 0x%lx\n"), ltmp);
 #endif
          fclose (procfile);
        }
 #endif
          fclose (procfile);
        }
@@ -3171,13 +3214,13 @@ linux_xfer_partial (struct target_ops *ops, enum target_object object,
 static void
 linux_target_install_ops (struct target_ops *t)
 {
 static void
 linux_target_install_ops (struct target_ops *t)
 {
-  t->to_insert_fork_catchpoint = child_insert_fork_catchpoint;
-  t->to_insert_vfork_catchpoint = child_insert_vfork_catchpoint;
-  t->to_insert_exec_catchpoint = child_insert_exec_catchpoint;
-  t->to_pid_to_exec_file = child_pid_to_exec_file;
+  t->to_insert_fork_catchpoint = linux_child_insert_fork_catchpoint;
+  t->to_insert_vfork_catchpoint = linux_child_insert_vfork_catchpoint;
+  t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint;
+  t->to_pid_to_exec_file = linux_child_pid_to_exec_file;
   t->to_post_startup_inferior = linux_child_post_startup_inferior;
   t->to_post_startup_inferior = linux_child_post_startup_inferior;
-  t->to_post_attach = child_post_attach;
-  t->to_follow_fork = child_follow_fork;
+  t->to_post_attach = linux_child_post_attach;
+  t->to_follow_fork = linux_child_follow_fork;
   t->to_find_memory_regions = linux_nat_find_memory_regions;
   t->to_make_corefile_notes = linux_nat_make_corefile_notes;
 
   t->to_find_memory_regions = linux_nat_find_memory_regions;
   t->to_make_corefile_notes = linux_nat_make_corefile_notes;
 
@@ -3197,7 +3240,7 @@ linux_target (void)
 }
 
 struct target_ops *
 }
 
 struct target_ops *
-linux_trad_target (CORE_ADDR (*register_u_offset)(int))
+linux_trad_target (CORE_ADDR (*register_u_offset)(struct gdbarch *, int, int))
 {
   struct target_ops *t;
 
 {
   struct target_ops *t;
 
@@ -3242,6 +3285,27 @@ linux_nat_add_target (struct target_ops *t)
   thread_db_init (t);
 }
 
   thread_db_init (t);
 }
 
+/* Register a method to call whenever a new thread is attached.  */
+void
+linux_nat_set_new_thread (struct target_ops *t, void (*new_thread) (ptid_t))
+{
+  /* Save the pointer.  We only support a single registered instance
+     of the GNU/Linux native target, so we do not need to map this to
+     T.  */
+  linux_nat_new_thread = new_thread;
+}
+
+/* Return the saved siginfo associated with PTID.  */
+struct siginfo *
+linux_nat_get_siginfo (ptid_t ptid)
+{
+  struct lwp_info *lp = find_lwp_pid (ptid);
+
+  gdb_assert (lp != NULL);
+
+  return &lp->siginfo;
+}
+
 void
 _initialize_linux_nat (void)
 {
 void
 _initialize_linux_nat (void)
 {
This page took 0.039116 seconds and 4 git commands to generate.