Fix gdb.base/watch-vfork.exp: Watchpoint triggers after vfork (sw) (timeout) with...
authorHui Zhu <teawater@gmail.com>
Sun, 8 Jun 2014 11:11:09 +0000 (19:11 +0800)
committerHui Zhu <teawater@gmail.com>
Sun, 8 Jun 2014 11:14:06 +0000 (19:14 +0800)
https://sourceware.org/ml/gdb-patches/2014-04/msg00047.html

Got gdb.base/watch-vfork.exp: Watchpoint triggers after vfork (sw)
(timeout) with Linux 2.6.32 and older version.

The rootcause is after the test use "set can-use-hw-watchpoints 0" let GDB
doesn't use hardware breakpoint and set a watchpoint on "global", GDB
continue will keep single step inside function "vfork".
The Linux 2.6.32 and older version doesn't have commit
6580807da14c423f0d0a708108e6df6ebc8bc83d (get more info please goto
http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/commit/?id=6580807da14c423f0d0a708108e6df6ebc8bc83d).
When the function "vfork" do syscall, the single step flag TIF_SINGLESTEP
will copy to child process.
Then GDB detach it, child process and parent process will be hanged.

So I make a patch that do a single step before detach.  Then TIF_SINGLESTEP
of child process in old Linux kernel will be cleared before detach.
Child process in new Linux kernel will not be affected by this single step.

2014-06-08  Hui Zhu  <hui@codesourcery.com>

* common/linux-ptrace.c (linux_disable_event_reporting): New
function.
* common/linux-ptrace.h (linux_disable_event_reporting): New
declaration.
* linux-nat.c (linux_child_follow_fork): Do a single step before
detach.

gdb/ChangeLog
gdb/common/linux-ptrace.c
gdb/common/linux-ptrace.h
gdb/linux-nat.c

index dc638635522abdb8fb3dd57fb77b83c46114791d..79aded4bb2a6af941a723884f5f48712c8108d6a 100644 (file)
@@ -1,3 +1,12 @@
+2014-06-08  Hui Zhu  <hui@codesourcery.com>
+
+       * common/linux-ptrace.c (linux_disable_event_reporting): New
+       function.
+       * common/linux-ptrace.h (linux_disable_event_reporting): New
+       declaration.
+       * linux-nat.c (linux_child_follow_fork): Do a single step before
+       detach.
+
 2014-06-07  Keith Seitz  <keiths@redhat.com>
 
        Revert:
index efbd1ea10bc44aa8d679077e32b1181ff1b04da2..b140b0811b7916a909b6661dcdd84a0c8ceac902 100644 (file)
@@ -476,6 +476,15 @@ linux_enable_event_reporting (pid_t pid)
          (PTRACE_TYPE_ARG4) (uintptr_t) current_ptrace_options);
 }
 
+/* Disable reporting of all currently supported ptrace events.  */
+
+void
+linux_disable_event_reporting (pid_t pid)
+{
+  /* Set the options.  */
+  ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0, 0);
+}
+
 /* Returns non-zero if PTRACE_OPTIONS is contained within
    CURRENT_PTRACE_OPTIONS, therefore supported.  Returns 0
    otherwise.  */
index 881d9c99628f5e891eb56b1c336755f2805ccdc9..cffb5ce18de16ba70ef539d33718cb968b6b6ab3 100644 (file)
@@ -86,6 +86,7 @@ struct buffer;
 extern void linux_ptrace_attach_fail_reason (pid_t pid, struct buffer *buffer);
 extern void linux_ptrace_init_warnings (void);
 extern void linux_enable_event_reporting (pid_t pid);
+extern void linux_disable_event_reporting (pid_t pid);
 extern int linux_supports_tracefork (void);
 extern int linux_supports_traceclone (void);
 extern int linux_supports_tracevforkdone (void);
index 6ca5c7e3fe8cebe91b12f78321cd25b7c3d15ee0..3b117b529e657fad860af1971fd28121e8ddef5d 100644 (file)
@@ -414,6 +414,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
       if (detach_fork)
        {
          struct cleanup *old_chain;
+         int status = 0;
 
          /* Before detaching from the child, remove all breakpoints
             from it.  If we forked, then this has already been taken
@@ -447,7 +448,29 @@ 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)))
+           {
+             int status;
+
+             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))
+           ptrace (PTRACE_DETACH, child_pid, 0, WSTOPSIG (status));
 
          do_cleanups (old_chain);
        }