Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Yao Qi <qiyaoltc@gmail.com>
To: gdb-patches@sourceware.org
Subject: [PATCH 04/12] Delete reinsert breakpoints from forked child
Date: Thu, 02 Jun 2016 09:31:00 -0000	[thread overview]
Message-ID: <1464859846-15619-5-git-send-email-yao.qi@linaro.org> (raw)
In-Reply-To: <1464859846-15619-1-git-send-email-yao.qi@linaro.org>

When a thread is stepping over a syscall instruction with software
single step, GDBserver inserts reinsert breakpoints at the next pcs.
If the syscall call is fork, the forked child has reinsert breakpoint
in its space, and GDBserver clones parent's breakpoint list to child's.
When GDBserver resumes the child, its bp_reinsert is zero, but has
reinsert breakpoints, so the following assert is triggered.

gdb/gdbserver/linux-low.c:4292: A problem internal to GDBserver has been detected.^M
void linux_resume_one_lwp_throw(lwp_info*, int, int, siginfo_t*): Assertion `!has_reinsert_breakpoints (proc)' failed.

gdb/gdbserver:

2016-05-20  Yao Qi  <yao.qi@linaro.org>

	* linux-low.c (handle_extended_wait): If the parent is doing
	step-over, remove the reinsert breakpoints from the forked child.

gdb/testsuite:

2016-05-26  Yao Qi  <yao.qi@linaro.org>

	* gdb.base/step-over-fork-1.c: New file.
	* gdb.base/step-over-fork-1.exp: New file.
---
 gdb/gdbserver/linux-low.c                   |  21 ++++++
 gdb/testsuite/gdb.base/step-over-fork-1.c   |  51 +++++++++++++
 gdb/testsuite/gdb.base/step-over-fork-1.exp | 106 ++++++++++++++++++++++++++++
 3 files changed, 178 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/step-over-fork-1.c
 create mode 100644 gdb/testsuite/gdb.base/step-over-fork-1.exp

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 95104d2..3f2d08e 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -569,6 +569,27 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
 	  event_lwp->status_pending_p = 1;
 	  event_lwp->status_pending = wstat;
 
+	  /* If the parent thread is doing step-over with reinsert
+	     breakpoints, the reinsert breakpoints are still in forked
+	     child's process space and cloned to its breakpoint list
+	     from the parent's.  Remove them from the child process.  */
+	  if (event_lwp->bp_reinsert != 0
+	      && can_software_single_step ()
+	      && event == PTRACE_EVENT_FORK)
+	    {
+	      struct thread_info *saved_thread = current_thread;
+
+	      /* The child process is forked and stopped, so it is safe
+		 to access its memory without stopping all other threads
+		 from other processes.  */
+	      current_thread = child_thr;
+	      delete_reinsert_breakpoints ();
+	      current_thread = saved_thread;
+
+	      gdb_assert (has_reinsert_breakpoints (parent_proc));
+	      gdb_assert (!has_reinsert_breakpoints (child_proc));
+	    }
+
 	  /* Report the event.  */
 	  return 0;
 	}
diff --git a/gdb/testsuite/gdb.base/step-over-fork-1.c b/gdb/testsuite/gdb.base/step-over-fork-1.c
new file mode 100644
index 0000000..2ca145b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/step-over-fork-1.c
@@ -0,0 +1,51 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011-2016 Free Software Foundation, Inc.
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+static void
+marker (void)
+{}
+
+int
+main (void)
+{
+  int  pid;
+
+  pid = FUNC ();
+  if (pid == 0) /* child */
+    {
+      exit (0);
+    }
+  else
+    {
+    }
+
+  marker ();
+
+  pid = FUNC ();
+  if (pid == 0) /* child */
+    {
+      marker ();
+      exit (0);
+    }
+  else
+    {
+      marker ();
+    }
+}
diff --git a/gdb/testsuite/gdb.base/step-over-fork-1.exp b/gdb/testsuite/gdb.base/step-over-fork-1.exp
new file mode 100644
index 0000000..4a34e61
--- /dev/null
+++ b/gdb/testsuite/gdb.base/step-over-fork-1.exp
@@ -0,0 +1,106 @@
+#   Copyright 2016 Free Software Foundation, Inc.
+#
+# 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# 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, see <http://www.gnu.org/licenses/>.
+
+# Test a thread is stepping over a syscall instruction which does
+# fork, and GDB (or GDBserver) can update its state on both parent
+# process and child process correctly.
+
+standard_testfile
+
+proc test { syscall } {
+    global testfile srcfile
+    global gdb_prompt
+    global decimal hex
+
+    if {[prepare_for_testing $testfile.exp $testfile $srcfile "debug additional_flags=-DFUNC=$syscall"]} {
+	untested $testfile.exp
+	return -1
+    }
+
+    # Start with a fresh gdb.
+    clean_restart ${testfile}
+    if ![runto_main] {
+	fail "Can't run to main"
+	return -1
+    }
+
+    # Step 1, find the syscall instruction address by "catch $syscall".
+    # Verify that the system supports "catch $syscall".
+    gdb_test "catch $syscall" "Catchpoint \[0-9\]* \\($syscall\\)" \
+	"insert first catchpoint"
+    set test "continue to first catchpoint"
+    gdb_test_multiple "continue" $test {
+	-re ".*Your system does not support this type\r\nof catchpoint.*$gdb_prompt $" {
+	    unsupported "catchpoint $syscall"
+	    return
+	}
+	-re ".*Catchpoint.*$gdb_prompt $" {
+	    pass $test
+	}
+    }
+
+    set syscall_insn_addr ""
+    set test "get syscall_insn_addr"
+    gdb_test_multiple "disassemble \$pc - 20,+30" $test {
+	-re " ($hex)\[^\r\n\]+\r\n=> .*$gdb_prompt $" {
+	    set syscall_insn_addr $expect_out(1,string)
+	    pass $test
+	}
+    }
+
+    if { $syscall_insn_addr == "" } {
+	fail $test
+	return
+    }
+
+    delete_breakpoints
+
+    gdb_test "break marker"
+
+    gdb_test "continue" "Continuing\\..*Breakpoint $decimal, .*" \
+	"continue to marker (1)"
+
+    gdb_test "set follow-fork-mode child"
+    gdb_test "set detach-on-fork off"
+
+    set test "set breakpoint condition-evaluation target"
+    gdb_test_multiple $test $test {
+	-re "warning: Target does not support breakpoint condition evaluation.\r\nUsing host evaluation mode instead.\r\n$gdb_prompt $" {
+	    # Target doesn't support breakpoint condition
+	    # evaluation on its side.
+	}
+	-re "^$test\r\n$gdb_prompt $" {
+	}
+    }
+
+    # Create a breakpoint which evaluates false.
+    gdb_test "break \*$syscall_insn_addr if main == 0" \
+	"Breakpoint \[0-9\]* at .*"
+
+    gdb_test "continue" "Continuing\\..*Breakpoint $decimal, marker \\(\\).*" \
+	"continue to marker (2)"
+
+    gdb_test "continue" "exited normally.*" "continue to end of inf 2"
+
+    gdb_test "inferior 1"
+    gdb_test "continue" \
+	"Continuing\\..*Breakpoint $decimal, marker \\(\\).*" \
+	"continue to marker (3)"
+    gdb_exit
+}
+
+foreach_with_prefix syscall { "fork" } {
+    test $syscall
+}
-- 
1.9.1


  parent reply	other threads:[~2016-06-02  9:31 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-02  9:31 [PATCH 00/12 V2] Use reinsert breakpoint for vCont;s Yao Qi
2016-06-02  9:31 ` [PATCH 06/12] Pass breakpoint type in set_breakpoint_at Yao Qi
2016-06-13 15:07   ` Pedro Alves
2016-06-02  9:31 ` [PATCH 03/12] Step over exit with reinsert breakpoints Yao Qi
2016-06-13 14:37   ` Pedro Alves
2016-06-13 14:52     ` Yao Qi
2016-06-13 15:01       ` Pedro Alves
2016-06-17  9:50         ` Yao Qi
2016-06-02  9:31 ` [PATCH 01/12] Switch to current thread in finish_step_over Yao Qi
2016-06-13 14:25   ` Pedro Alves
2016-06-02  9:31 ` [PATCH 09/12] Make reinsert_breakpoint thread specific Yao Qi
     [not found]   ` <71a5322e-41e3-9e23-df73-e14b14c1d656@redhat.com>
2016-06-14 12:52     ` Yao Qi
2016-06-14 12:57       ` Pedro Alves
2016-06-02  9:31 ` [PATCH 08/12] Refactor clone_all_breakpoints Yao Qi
2016-06-13 15:14   ` Pedro Alves
2016-06-02  9:31 ` [PATCH 07/12] Create sub classes of 'struct breakpoint' Yao Qi
2016-06-13 15:09   ` Pedro Alves
2016-06-02  9:31 ` [PATCH 12/12] Support vCont s and S actions with software single step Yao Qi
2016-06-13 15:56   ` Pedro Alves
2016-06-02  9:31 ` [PATCH 02/12] More assert checks on reinsert breakpoint Yao Qi
2016-06-13 14:25   ` Pedro Alves
2016-06-02  9:31 ` Yao Qi [this message]
2016-06-13 15:02   ` [PATCH 04/12] Delete reinsert breakpoints from forked child Pedro Alves
2016-06-13 16:53     ` Yao Qi
2016-06-13 17:29       ` Pedro Alves
2016-06-14 11:17         ` Yao Qi
2016-06-14 11:40           ` Pedro Alves
2016-06-17  9:53             ` Yao Qi
2016-06-02  9:31 ` [PATCH 11/12] Use reinsert_breakpoint for vCont;s Yao Qi
2016-06-13 15:55   ` Pedro Alves
2016-06-14 13:14     ` Yao Qi
2016-06-14 15:48       ` Pedro Alves
2016-06-15 16:41         ` Yao Qi
2016-06-17 15:10           ` Pedro Alves
2016-06-20 18:09             ` Antoine Tremblay
2016-06-02  9:31 ` [PATCH 10/12] Switch current_thread to lwp's thread in install_software_single_step_breakpoints Yao Qi
2016-06-13 15:26   ` Pedro Alves
2016-06-02  9:31 ` [PATCH 05/12] Handle reinsert breakpoints for vforked child Yao Qi
2016-06-13 15:07   ` Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1464859846-15619-5-git-send-email-yao.qi@linaro.org \
    --to=qiyaoltc@gmail.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox