constify error_no_arg
[deliverable/binutils-gdb.git] / gdb / linux-nat.c
index 3f6e5ea73195c9c96635cc974e17f298cc8f2de9..0ab0362f1ec3dc981a44482bf411666e7985dde4 100644 (file)
@@ -32,8 +32,8 @@
 #endif
 #include <sys/ptrace.h>
 #include "linux-nat.h"
-#include "linux-ptrace.h"
-#include "linux-procfs.h"
+#include "nat/linux-ptrace.h"
+#include "nat/linux-procfs.h"
 #include "linux-fork.h"
 #include "gdbthread.h"
 #include "gdbcmd.h"
@@ -59,7 +59,7 @@
 #include "terminal.h"
 #include <sys/vfs.h>
 #include "solib.h"
-#include "linux-osdata.h"
+#include "nat/linux-osdata.h"
 #include "linux-tdep.h"
 #include "symfile.h"
 #include "agent.h"
@@ -414,6 +414,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
       if (detach_fork)
        {
          struct cleanup *old_chain;
+         int status = W_STOPCODE (0);
 
          /* Before detaching from the child, remove all breakpoints
             from it.  If we forked, then this has already been taken
@@ -447,7 +448,35 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 
          if (linux_nat_prepare_to_resume != NULL)
            linux_nat_prepare_to_resume (child_lp);
-         ptrace (PTRACE_DETACH, child_pid, 0, 0);
+
+         /* When debugging an inferior in an architecture that supports
+            hardware single stepping on a kernel without commit
+            6580807da14c423f0d0a708108e6df6ebc8bc83d, the vfork child
+            process starts with the TIF_SINGLESTEP/X86_EFLAGS_TF bits
+            set if the parent process had them set.
+            To work around this, single step the child process
+            once before detaching to clear the flags.  */
+
+         if (!gdbarch_software_single_step_p (target_thread_architecture
+                                                  (child_lp->ptid)))
+           {
+             linux_disable_event_reporting (child_pid);
+             if (ptrace (PTRACE_SINGLESTEP, child_pid, 0, 0) < 0)
+               perror_with_name (_("Couldn't do single step"));
+             if (my_waitpid (child_pid, &status, 0) < 0)
+               perror_with_name (_("Couldn't wait vfork process"));
+           }
+
+         if (WIFSTOPPED (status))
+           {
+             int signo;
+
+             signo = WSTOPSIG (status);
+             if (signo != 0
+                 && !signal_pass_state (gdb_signal_from_host (signo)))
+               signo = 0;
+             ptrace (PTRACE_DETACH, child_pid, 0, signo);
+           }
 
          do_cleanups (old_chain);
        }
@@ -1301,7 +1330,7 @@ linux_nat_create_inferior (struct target_ops *ops,
 }
 
 static void
-linux_nat_attach (struct target_ops *ops, char *args, int from_tty)
+linux_nat_attach (struct target_ops *ops, const char *args, int from_tty)
 {
   struct lwp_info *lp;
   int status;
This page took 0.023998 seconds and 4 git commands to generate.