Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [patch 2/2] Displaced stepping across fork/vfork : test case
@ 2011-09-11  9:55 Yao Qi
  2011-09-12 15:03 ` Pedro Alves
  0 siblings, 1 reply; 9+ messages in thread
From: Yao Qi @ 2011-09-11  9:55 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 880 bytes --]

Hi,
These test cases are to expose the problems I mentioned in patch #1. 
Without patch #1 applied, there are three new failures,

+FAIL: gdb.base/disp-step-fork.exp: single step over fork (timeout)
+FAIL: gdb.base/disp-step-vfork.exp: continue to marker (the program is 
no longer running)
+FAIL: gdb.base/disp-step-vfork.exp: print global

After patch #1 applied, these three failures are fixed,

+PASS: gdb.base/disp-step-fork.exp: single step over fork
+PASS: gdb.base/disp-step-vfork.exp: continue to marker
+PASS: gdb.base/disp-step-vfork.exp: print global

In short, these two test cases do something similar.  First, they will 
look for syscall instruction in vfork () or fork (), and set breakpoint 
on it.  Then, continue to syscall insn, turn displaced stepping on, and 
step over that breakpoint.

Regression tested on x86_64-unknow-linux-gnu.

-- 
Yao (齐尧)

[-- Attachment #2: 0015-disp-step-fork-testcase.patch --]
[-- Type: text/x-patch, Size: 9654 bytes --]

	gdb/testsuite/
	* gdb.base/disp-step-fork.c: New.
	* gdb.base/disp-step-fork.exp: New.
	* gdb.base/disp-step-vfork.c: New.
	* gdb.base/disp-step-vfork.exp: New.
---
 gdb/testsuite/gdb.base/disp-step-fork.c    |   42 ++++++++++
 gdb/testsuite/gdb.base/disp-step-fork.exp  |  115 ++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/disp-step-vfork.c   |   47 +++++++++++
 gdb/testsuite/gdb.base/disp-step-vfork.exp |   81 +++++++++++++++++++
 4 files changed, 285 insertions(+), 0 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/disp-step-fork.c
 create mode 100644 gdb/testsuite/gdb.base/disp-step-fork.exp
 create mode 100644 gdb/testsuite/gdb.base/disp-step-vfork.c
 create mode 100644 gdb/testsuite/gdb.base/disp-step-vfork.exp

diff --git a/gdb/testsuite/gdb.base/disp-step-fork.c b/gdb/testsuite/gdb.base/disp-step-fork.c
new file mode 100644
index 0000000..38df3b8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-fork.c
@@ -0,0 +1,42 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 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>
+int
+main (void)
+{
+  int  pid;
+
+  pid = fork ();
+  if (pid == 0) /* child */
+    {
+      exit (0); /* at exit */
+    }
+  else
+    {
+    }
+
+  pid = fork ();
+  if (pid == 0) /* child */
+    {
+      exit (0); /* at exit */
+    }
+  else
+    {
+    }
+
+}
diff --git a/gdb/testsuite/gdb.base/disp-step-fork.exp b/gdb/testsuite/gdb.base/disp-step-fork.exp
new file mode 100644
index 0000000..a044d3e
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-fork.exp
@@ -0,0 +1,115 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2011 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/>.
+
+if { ![support_displaced_stepping] } {
+    unsupported "displaced stepping"
+    return -1
+}
+
+global srcfile
+set testfile "disp-step-fork"
+
+if [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c {debug}] {
+    untested ${testfile}.exp
+    return -1
+}
+
+set syscall_insn ""
+
+# Define the syscall instruction for each target.
+
+if { [istarget "i\[34567\]86-*-linux*"] } {
+    set syscall_insn "int"
+} elseif { [istarget "x86_64-*-linux*"] } {
+    set syscall_insn "syscall"
+} else {
+    return -1
+}
+
+if { ![runto main] } then {
+    fail "run to main ($teststr)"
+    return
+}
+
+gdb_test "break fork" "Breakpoint.*at.*"
+gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in fork ().*" \
+    "continue to fork (1st time)"
+
+# Hit the breakpoint on fork for the first time.  In this time, the address
+# of syscall insn and next insn of syscall are recorded.
+
+gdb_test "display/i \$pc" ".*"
+
+set see_syscall_insn 0
+
+# Single step until we see sysall insn.
+while { $see_syscall_insn == 0 } {
+    send_gdb "stepi\n"
+    gdb_expect {
+	-re ".*$syscall_insn.*$gdb_prompt $" {
+	    set see_syscall_insn 1
+	}
+	-re ".*$gdb_prompt $" {}
+    }
+}
+
+set syscall_insn_addr ""
+set test "extract syscall insn address"
+
+send_gdb "print \$pc\n"
+gdb_expect {
+    -re "\\$\[0-9\]+ = (\[^\r\n\]+).*$gdb_prompt $" {
+	if [regexp "0x\[0-9a-fA-F\]+" $expect_out(0,string) syscall_insn_addr] {
+	    pass "$test"
+	} else {
+	    fail "$test"
+	}
+    }
+    -re ".*$gdb_prompt $" {
+	fail "$test"
+    }
+}
+
+set syscall_insn_next_addr ""
+set test "extract syscall insn address"
+
+send_gdb "stepi\n"
+gdb_expect {
+    -re "0x\[0-9a-fA-F\]+ in .*$gdb_prompt $" {
+	if [regexp "0x\[0-9a-fA-F\]+" $expect_out(0,string) syscall_insn_next_addr] {
+	    pass "$test"
+	} else {
+	    fail "$test"
+	}
+    }
+}
+
+gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in fork ().*" \
+    "continue to fork (2nd time)"
+
+# Hit the breakpoint on fork for the second time.  In this time, we'll set breakpoint
+# on the syscall insn we recorded previously, and single step over it.
+
+gdb_test "break \*$syscall_insn_addr" "Breakpoint \[0-9\]+ at.*" \
+    "break on syscall insn"
+
+gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .*" \
+    "continue to syscall insn"
+
+gdb_test_no_output "set displaced-stepping on"
+# Check the address of next instruction of syscall.
+gdb_test "stepi" ".*$syscall_insn_next_addr.*" "single step over fork"
\ No newline at end of file
diff --git a/gdb/testsuite/gdb.base/disp-step-vfork.c b/gdb/testsuite/gdb.base/disp-step-vfork.c
new file mode 100644
index 0000000..84e79b0
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-vfork.c
@@ -0,0 +1,47 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 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 <unistd.h>
+
+int global = 0;
+
+static void
+marker () {}
+
+int
+main (void)
+{
+  int pid;
+
+  pid = vfork ();
+  if (pid == -1)
+    {
+      return 1;
+    }
+  else if (pid != 0)
+    {
+    }
+  else
+    {
+      global = 1;
+      _exit (0);
+    }
+
+  marker ();
+  return 0;
+
+}
diff --git a/gdb/testsuite/gdb.base/disp-step-vfork.exp b/gdb/testsuite/gdb.base/disp-step-vfork.exp
new file mode 100644
index 0000000..65b7bdc
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-vfork.exp
@@ -0,0 +1,81 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2011 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/>.
+
+if { ![support_displaced_stepping] } {
+    unsupported "displaced stepping"
+    return -1
+}
+
+global srcfile
+set testfile "disp-step-vfork"
+
+if [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c {debug}] {
+    untested ${testfile}.exp
+    return -1
+}
+
+set syscall_insn ""
+
+# Define the syscall instruction for each target.
+
+if { [istarget "i\[34567\]86-*-linux*"] } {
+    set syscall_insn "int"
+} elseif { [istarget "x86_64-*-linux*"] } {
+    set syscall_insn "syscall"
+} else {
+    return -1
+}
+
+if { ![runto main] } then {
+    fail "run to main ($teststr)"
+    return
+}
+
+gdb_test "break marker" "Breakpoint.*at.* file .*${testfile}.c, line.*"
+
+set syscall_insn_line ""
+set syscall_insn_addr ""
+
+# Disassemble vfork to extract the address of syscall instruction.
+gdb_test_multiple "disassemble vfork" "disassemble vfork" {
+    -re "Dump of assembler code for function vfork.*$gdb_prompt $" {
+	pass "disassemble vfork"
+	if [regexp "0x\[0-9a-fA-F\]+\[ \t\]<\\+\[0-9\]+>:\[ \t\]$syscall_insn" $expect_out(0,string) syscall_insn_line] {
+	    pass "find syscall insn address"
+
+	    regexp "0x\[0-9a-fA-F\]+" $syscall_insn_line syscall_insn_addr
+	} else {
+	    fail "find syscall insn address"
+	    return -1
+	}
+    }
+    -re ".*$gdb_prompt $" {
+	fail "disassemble vfork"
+	return -1
+    }
+}
+
+gdb_test "break \*$syscall_insn_addr" "Breakpoint \[0-9\]+ at .*" "break on syscall insn"
+gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in vfork ().*" \
+    "continue to vfork"
+
+gdb_test_no_output "set displaced-stepping on"
+gdb_test "stepi" ".*" "single step over vfork"
+gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, marker \\(\\) at.*" \
+    "continue to marker"
+# Make sure child process is executed correctly
+gdb_test "print global" ".* = 1"
\ No newline at end of file
-- 
1.7.0.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch 2/2] Displaced stepping across fork/vfork : test case
  2011-09-11  9:55 [patch 2/2] Displaced stepping across fork/vfork : test case Yao Qi
@ 2011-09-12 15:03 ` Pedro Alves
  2011-09-14 11:32   ` Yao Qi
  0 siblings, 1 reply; 9+ messages in thread
From: Pedro Alves @ 2011-09-12 15:03 UTC (permalink / raw)
  To: gdb-patches; +Cc: Yao Qi

On Sunday 11 September 2011 01:55:00, Yao Qi wrote:
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/disp-step-fork.c
> @@ -0,0 +1,42 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2011 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>
> +int

Newline between #include and int, please.

> +main (void)
> +{
> +  int  pid;
> +
> +  pid = fork ();
> +  if (pid == 0) /* child */
> +    {
> +      exit (0); /* at exit */
> +    }
> +  else
> +    {
> +    }
> +
> +  pid = fork ();
> +  if (pid == 0) /* child */
> +    {
> +      exit (0); /* at exit */
> +    }
> +  else
> +    {
> +    }
> +
> +}
> diff --git a/gdb/testsuite/gdb.base/disp-step-fork.exp b/gdb/testsuite/gdb.base/disp-step-fork.exp
> new file mode 100644
> index 0000000..a044d3e
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/disp-step-fork.exp
> @@ -0,0 +1,115 @@
> +# This testcase is part of GDB, the GNU debugger.
> +
> +# Copyright 2011 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/>.
> +
> +if { ![support_displaced_stepping] } {
> +    unsupported "displaced stepping"
> +    return -1
> +}
> +
> +global srcfile

Did you mean to do:

 set srcfile ${testfile}.c

and use $srcfile below instead?  Otherwise, this var looks write-only.

> +set testfile "disp-step-fork"
> +
> +if [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c {debug}] {
> +    untested ${testfile}.exp
> +    return -1
> +}
> +
> +set syscall_insn ""
> +
> +# Define the syscall instruction for each target.
> +
> +if { [istarget "i\[34567\]86-*-linux*"] } {
> +    set syscall_insn "int"
> +} elseif { [istarget "x86_64-*-linux*"] } {
> +    set syscall_insn "syscall"
> +} else {
> +    return -1
> +}

You could do this before trying to compile the program.  I'll
be cheaper on !x86-linux targets.

Very recent kernels will allow choosing the syscall instruction
in the vsyscall page.  It'll be better to make the test
skip on !x86-linux at the top, and then, change the test
to look for all alternatives of the syscall insn.

> +
> +if { ![runto main] } then {
> +    fail "run to main ($teststr)"

teststr doesn't exist in this test.  Looks like a pasto.

> +    return
> +}
> +
> +gdb_test "break fork" "Breakpoint.*at.*"
> +gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in fork ().*" \
> +    "continue to fork (1st time)"
> +
> +# Hit the breakpoint on fork for the first time.  In this time, the address
> +# of syscall insn and next insn of syscall are recorded.
> +
> +gdb_test "display/i \$pc" ".*"
> +
> +set see_syscall_insn 0
> +
> +# Single step until we see sysall insn.
> +while { $see_syscall_insn == 0 } {
> +    send_gdb "stepi\n"
> +    gdb_expect {
> +       -re ".*$syscall_insn.*$gdb_prompt $" {
> +           set see_syscall_insn 1
> +       }
> +       -re ".*$gdb_prompt $" {}
> +    }
> +}

Best put an upper cap on number of steps.  Do you need to 
step through PLT resolution within the dynamic linker
this way?  That'll be a bunch more steps than required.
You can work around it by instead letting the program
call fork once (so the plt resolves), and then do this
stepping dance on the second fork call.

> +
> +set syscall_insn_addr ""
> +set test "extract syscall insn address"
> +
> +send_gdb "print \$pc\n"
> +gdb_expect {

gdb_test_multiple, please.  Or better still, just do:

set pc [get_hexadecimal_valueof "\$pc" "0"]

> +    -re "\\$\[0-9\]+ = (\[^\r\n\]+).*$gdb_prompt $" {
> +       if [regexp "0x\[0-9a-fA-F\]+" $expect_out(0,string) syscall_insn_addr] {
> +           pass "$test"
> +       } else {
> +           fail "$test"
> +       }
> +    }
> +    -re ".*$gdb_prompt $" {
> +       fail "$test"
> +    }
> +}
> +
> +set syscall_insn_next_addr ""
> +set test "extract syscall insn address"
> +
> +send_gdb "stepi\n"
> +gdb_expect {
> +    -re "0x\[0-9a-fA-F\]+ in .*$gdb_prompt $" {
> +       if [regexp "0x\[0-9a-fA-F\]+" $expect_out(0,string) syscall_insn_next_addr] {
> +           pass "$test"
> +       } else {
> +           fail "$test"
> +       }
> +    }
> +}

Does this work instead?

gdb_test "stepi" "" "stepi over fork syscall"
set syscall_insn_next_addr [get_hexadecimal_valueof "\$pc" "0"]

> +
> +gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in fork ().*" \
> +    "continue to fork (2nd time)"
> +
> +# Hit the breakpoint on fork for the second time.  In this time, we'll set breakpoint
> +# on the syscall insn we recorded previously, and single step over it.
> +
> +gdb_test "break \*$syscall_insn_addr" "Breakpoint \[0-9\]+ at.*" \
> +    "break on syscall insn"
> +
> +gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .*" \
> +    "continue to syscall insn"
> +
> +gdb_test_no_output "set displaced-stepping on"
> +# Check the address of next instruction of syscall.
> +gdb_test "stepi" ".*$syscall_insn_next_addr.*" "single step over fork"
> \ No newline at end of file

Please add one.

> diff --git a/gdb/testsuite/gdb.base/disp-step-vfork.c b/gdb/testsuite/gdb.base/disp-step-vfork.c
> new file mode 100644
> index 0000000..84e79b0
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/disp-step-vfork.c
> @@ -0,0 +1,47 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2011 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 <unistd.h>
> +
> +int global = 0;
> +
> +static void
> +marker () {}
> +
> +int
> +main (void)
> +{
> +  int pid;
> +
> +  pid = vfork ();
> +  if (pid == -1)
> +    {
> +      return 1;
> +    }
> +  else if (pid != 0)
> +    {
> +    }
> +  else
> +    {
> +      global = 1;
> +      _exit (0);
> +    }
> +
> +  marker ();
> +  return 0;
> +
> +}
> diff --git a/gdb/testsuite/gdb.base/disp-step-vfork.exp b/gdb/testsuite/gdb.base/disp-step-vfork.exp
> new file mode 100644
> index 0000000..65b7bdc
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/disp-step-vfork.exp
> @@ -0,0 +1,81 @@
> +# This testcase is part of GDB, the GNU debugger.
> +
> +# Copyright 2011 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/>.
> +
> +if { ![support_displaced_stepping] } {
> +    unsupported "displaced stepping"
> +    return -1
> +}
> +
> +global srcfile
> +set testfile "disp-step-vfork"
> +
> +if [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c {debug}] {
> +    untested ${testfile}.exp
> +    return -1
> +}
> +
> +set syscall_insn ""
> +
> +# Define the syscall instruction for each target.
> +
> +if { [istarget "i\[34567\]86-*-linux*"] } {
> +    set syscall_insn "int"
> +} elseif { [istarget "x86_64-*-linux*"] } {
> +    set syscall_insn "syscall"
> +} else {
> +    return -1
> +}
> +
> +if { ![runto main] } then {
> +    fail "run to main ($teststr)"
> +    return
> +}
> +
> +gdb_test "break marker" "Breakpoint.*at.* file .*${testfile}.c, line.*"
> +
> +set syscall_insn_line ""
> +set syscall_insn_addr ""
> +
> +# Disassemble vfork to extract the address of syscall instruction.
> +gdb_test_multiple "disassemble vfork" "disassemble vfork" {
> +    -re "Dump of assembler code for function vfork.*$gdb_prompt $" {
> +       pass "disassemble vfork"
> +       if [regexp "0x\[0-9a-fA-F\]+\[ \t\]<\\+\[0-9\]+>:\[ \t\]$syscall_insn" $expect_out(0,string) syscall_insn_line] {
> +           pass "find syscall insn address"
> +
> +           regexp "0x\[0-9a-fA-F\]+" $syscall_insn_line syscall_insn_addr
> +       } else {
> +           fail "find syscall insn address"
> +           return -1
> +       }
> +    }
> +    -re ".*$gdb_prompt $" {
> +       fail "disassemble vfork"
> +       return -1
> +    }
> +}

Why can you do a disassemble here, while you did the stepi thing
for fork?  The comments to the fork tests apply equally to this
file.  Just a suggestion, not use it'd be better: would it be possible to
merge the .exp files, by putting the tests under a proc/function that
takes fork/vfork and .c file to build as arg?

> +
> +gdb_test "break \*$syscall_insn_addr" "Breakpoint \[0-9\]+ at .*" "break on syscall insn"
> +gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in vfork ().*" \
> +    "continue to vfork"
> +
> +gdb_test_no_output "set displaced-stepping on"
> +gdb_test "stepi" ".*" "single step over vfork"
> +gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, marker \\(\\) at.*" \
> +    "continue to marker"
> +# Make sure child process is executed correctly
> +gdb_test "print global" ".* = 1"
> \ No newline at end of file
> -- 
> 1.7.0.4

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch 2/2] Displaced stepping across fork/vfork : test case
  2011-09-12 15:03 ` Pedro Alves
@ 2011-09-14 11:32   ` Yao Qi
  2011-09-14 12:32     ` Pedro Alves
  0 siblings, 1 reply; 9+ messages in thread
From: Yao Qi @ 2011-09-14 11:32 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 6204 bytes --]

On 09/12/2011 10:59 PM, Pedro Alves wrote:
> On Sunday 11 September 2011 01:55:00, Yao Qi wrote:
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.base/disp-step-fork.c
>> @@ -0,0 +1,42 @@
>> +
>> +#include<stdlib.h>
>> +int
>
> Newline between #include and int, please.
>

Fixed.

>> +
>> +if { ![support_displaced_stepping] } {
>> +    unsupported "displaced stepping"
>> +    return -1
>> +}
>> +
>> +global srcfile
>
> Did you mean to do:
>
>   set srcfile ${testfile}.c
>
> and use $srcfile below instead?  Otherwise, this var looks write-only.
>

This line is copied from other test case.  It is not needed.  Removed.

>> +set testfile "disp-step-fork"
>> +
>> +if [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c {debug}] {
>> +    untested ${testfile}.exp
>> +    return -1
>> +}
>> +
>> +set syscall_insn ""
>> +
>> +# Define the syscall instruction for each target.
>> +
>> +if { [istarget "i\[34567\]86-*-linux*"] } {
>> +    set syscall_insn "int"
>> +} elseif { [istarget "x86_64-*-linux*"] } {
>> +    set syscall_insn "syscall"
>> +} else {
>> +    return -1
>> +}
>
> You could do this before trying to compile the program.  I'll
> be cheaper on !x86-linux targets.
>

OK.

> Very recent kernels will allow choosing the syscall instruction
> in the vsyscall page.  It'll be better to make the test
> skip on !x86-linux at the top, and then, change the test
> to look for all alternatives of the syscall insn.
>

I read some pages on vsyscall, and thought we can fetch the value of 
AT_SYSINFO in auxv to get the address of __kernel_vsyscall.  However, 
another simpler way comes up in my mind is to set possible syscall insn 
to $syscall_insn like this,

   set syscall_insn "(int|syscall|sysenter)"

If we match either of them in instruction stream, we are sure program 
will enter to syscall, so we don't have to worry about vsyscall page.

>> +
>> +if { ![runto main] } then {
>> +    fail "run to main ($teststr)"
>
> teststr doesn't exist in this test.  Looks like a pasto.
>

Sorry.  Removed $teststr.

>> +
>> +# Single step until we see sysall insn.
>> +while { $see_syscall_insn == 0 } {
>> +    send_gdb "stepi\n"
>> +    gdb_expect {
>> +       -re ".*$syscall_insn.*$gdb_prompt $" {
>> +           set see_syscall_insn 1
>> +       }
>> +       -re ".*$gdb_prompt $" {}
>> +    }
>> +}
>
> Best put an upper cap on number of steps.  Do you need to
> step through PLT resolution within the dynamic linker
> this way?  That'll be a bunch more steps than required.
> You can work around it by instead letting the program
> call fork once (so the plt resolves), and then do this
> stepping dance on the second fork call.

The upper bound of steps is added in loop.

We don't need to step through PLT resolution.  Now, each syscall 
function is called three times.  For the first time, it is for PLT 
resolution, for the second time, it is for locating the address of 
syscall insn, for the third time, single-step over syscall insn.

>
>> +
>> +set syscall_insn_addr ""
>> +set test "extract syscall insn address"
>> +
>> +send_gdb "print \$pc\n"
>> +gdb_expect {
>
> gdb_test_multiple, please.  Or better still, just do:
>
> set pc [get_hexadecimal_valueof "\$pc" "0"]
>

Oh, get_hexadecimal_valueof is better.  I am not aware of it before.

>> +
>> +set syscall_insn_next_addr ""
>> +set test "extract syscall insn address"
>> +
>> +send_gdb "stepi\n"
>> +gdb_expect {
>> +    -re "0x\[0-9a-fA-F\]+ in .*$gdb_prompt $" {
>> +       if [regexp "0x\[0-9a-fA-F\]+" $expect_out(0,string) syscall_insn_next_addr] {
>> +           pass "$test"
>> +       } else {
>> +           fail "$test"
>> +       }
>> +    }
>> +}
>
> Does this work instead?
>
> gdb_test "stepi" "" "stepi over fork syscall"
> set syscall_insn_next_addr [get_hexadecimal_valueof "\$pc" "0"]
>

Yes, fixed like this.

>> +
>> +gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in fork ().*" \
>> +    "continue to fork (2nd time)"
>> +
>> +# Hit the breakpoint on fork for the second time.  In this time, we'll set breakpoint
>> +# on the syscall insn we recorded previously, and single step over it.
>> +
>> +gdb_test "break \*$syscall_insn_addr" "Breakpoint \[0-9\]+ at.*" \
>> +    "break on syscall insn"
>> +
>> +gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .*" \
>> +    "continue to syscall insn"
>> +
>> +gdb_test_no_output "set displaced-stepping on"
>> +# Check the address of next instruction of syscall.
>> +gdb_test "stepi" ".*$syscall_insn_next_addr.*" "single step over fork"
>> \ No newline at end of file
>
> Please add one.
>

Added a new line.

>> +
>> +gdb_test "break marker" "Breakpoint.*at.* file .*${testfile}.c, line.*"
>> +
>> +set syscall_insn_line ""
>> +set syscall_insn_addr ""
>> +
>> +# Disassemble vfork to extract the address of syscall instruction.
>> +gdb_test_multiple "disassemble vfork" "disassemble vfork" {
>> +    -re "Dump of assembler code for function vfork.*$gdb_prompt $" {
>> +       pass "disassemble vfork"
>> +       if [regexp "0x\[0-9a-fA-F\]+\[ \t\]<\\+\[0-9\]+>:\[ \t\]$syscall_insn" $expect_out(0,string) syscall_insn_line] {
>> +           pass "find syscall insn address"
>> +
>> +           regexp "0x\[0-9a-fA-F\]+" $syscall_insn_line syscall_insn_addr
>> +       } else {
>> +           fail "find syscall insn address"
>> +           return -1
>> +       }
>> +    }
>> +    -re ".*$gdb_prompt $" {
>> +       fail "disassemble vfork"
>> +       return -1
>> +    }
>> +}
>
> Why can you do a disassemble here, while you did the stepi thing
> for fork?  The comments to the fork tests apply equally to this
> file.  Just a suggestion, not use it'd be better: would it be possible to
> merge the .exp files, by putting the tests under a proc/function that
> takes fork/vfork and .c file to build as arg?
>

The reason I choose disassembly here is that disassembly is cheaper than 
multiple stepi to locate the address of syscall insn.

In this version, there is only one .exp file, which is 
disp-step-syscall.exp, and common test logic is moved to a single proc.

b.t.w, the test to TARGET_WAITKIND_EXECD event can be added into 
disp-step-syscall.exp easily, but that is the work in next step.

-- 
Yao (齐尧)

[-- Attachment #2: 0015-disp-step-fork-testcase.patch --]
[-- Type: text/x-patch, Size: 8258 bytes --]


	gdb/testsuite/
	* gdb.base/disp-step-fork.c: New.
	* gdb.base/disp-step-syscall.exp: New.
	* gdb.base/disp-step-vfork.c: New.
---
 gdb/testsuite/gdb.base/disp-step-fork.c      |   57 +++++++++++
 gdb/testsuite/gdb.base/disp-step-syscall.exp |  131 ++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/disp-step-vfork.c     |   75 +++++++++++++++
 3 files changed, 263 insertions(+), 0 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/disp-step-fork.c
 create mode 100644 gdb/testsuite/gdb.base/disp-step-syscall.exp
 create mode 100644 gdb/testsuite/gdb.base/disp-step-vfork.c

diff --git a/gdb/testsuite/gdb.base/disp-step-fork.c b/gdb/testsuite/gdb.base/disp-step-fork.c
new file mode 100644
index 0000000..ab4f3b4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-fork.c
@@ -0,0 +1,57 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 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>
+
+static void
+marker () {}
+
+int
+main (void)
+{
+  int  pid;
+
+  pid = fork ();
+  if (pid == 0) /* child */
+    {
+      exit (0); /* at exit */
+    }
+  else
+    {
+    }
+
+  pid = fork ();
+  if (pid == 0) /* child */
+    {
+      exit (0); /* at exit */
+    }
+  else
+    {
+    }
+
+  pid = fork ();
+  if (pid == 0) /* child */
+    {
+      exit (0); /* at exit */
+    }
+  else
+    {
+    }
+
+  marker ();
+
+}
diff --git a/gdb/testsuite/gdb.base/disp-step-syscall.exp b/gdb/testsuite/gdb.base/disp-step-syscall.exp
new file mode 100644
index 0000000..5fa10c1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-syscall.exp
@@ -0,0 +1,131 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2011 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/>.
+
+if { ![support_displaced_stepping] } {
+    unsupported "displaced stepping"
+    return -1
+}
+
+
+
+set syscall_insn ""
+
+# Define the syscall instruction for each target.
+
+if { [istarget "i\[34567\]86-*-linux*"] || [istarget "x86_64-*-linux*"] } {
+    set syscall_insn "(int|syscall|sysenter)"
+} else {
+    return -1
+}
+
+proc disp_step_cross_syscall { syscall } {
+    global syscall_insn
+    global gdb_prompt
+
+    set testfile "disp-step-$syscall"
+
+    if [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c {debug}] {
+	untested ${testfile}.exp
+	return -1
+    }
+
+    if { ![runto main] } then {
+	fail "run to main ($syscall)"
+	return
+    }
+    # Delete the breakpoint on main.
+    gdb_test_no_output "delete break 1"
+
+    gdb_test "break marker" "Breakpoint.*at.* file .*${testfile}.c, line.*"
+    gdb_test_no_output "set displaced-stepping off"
+
+    set syscall_bp 0
+    gdb_test_multiple "break $syscall"  "break $syscall" {
+	-re "Breakpoint (\[0-9\]*) at .*$gdb_prompt $" {
+	    set syscall_bp $expect_out(1,string)
+	    pass "break $syscall"
+	}
+    }
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in $syscall ().*" \
+	"continue to $syscall (1st time)"
+    # Hit the breakpoint on $syscall for the first time.  In this time, we will let PLT
+    # resolution done, and the number single steps we will do later will be
+    # reduced.
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in $syscall ().*" \
+	"continue to $syscall (2nd time)"
+    # Hit the breakpoint on $syscall for the second time.  In this time, the address
+    # of syscall insn and next insn of syscall are recorded.
+
+    gdb_test "display/i \$pc" ".*"
+
+
+    # Single step until we see sysall insn or we reach the upper bound of loop
+    # iterations.
+    set see_syscall_insn 0
+
+    for {set i 0} {$i < 1000 && $see_syscall_insn == 0} {incr i} {
+	send_gdb "stepi\n"
+	gdb_expect {
+	    -re ".*$syscall_insn.*$gdb_prompt $" {
+		set see_syscall_insn 1
+	    }
+	    -re ".*$gdb_prompt $" {}
+	}
+    }
+
+    if {$see_syscall_insn == 0} then {
+	fail "find syscall insn in $syscall"
+	return -1
+    }
+
+    set syscall_insn_addr [get_hexadecimal_valueof "\$pc" "0"]
+    gdb_test "stepi" ".*" "stepi $syscall insn"
+    set syscall_insn_next_addr [get_hexadecimal_valueof "\$pc" "0"]
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in $syscall ().*" \
+	"continue to $syscall (3rd time)"
+
+    # Hit the breakpoint on $syscall for the third time.  In this time, we'll set
+    # breakpoint on the syscall insn we recorded previously, and single step over it.
+
+    set syscall_insn_bp 0
+    gdb_test_multiple "break \*$syscall_insn_addr"  "break on syscall insn" {
+	-re "Breakpoint (\[0-9\]*) at .*$gdb_prompt $" {
+	    set syscall_insn_bp $expect_out(1,string)
+	    pass "break on syscall insns"
+	}
+    }
+    gdb_test_no_output "delete $syscall_bp" "delete break $syscall"
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .*" \
+	"continue to syscall insn"
+
+    gdb_test_no_output "set displaced-stepping on"
+    # Check the address of next instruction of syscall.
+    gdb_test "stepi" ".*$syscall_insn_next_addr.*" "single step over $syscall"
+
+    # Delete breakpoint syscall insns to avoid interference to other syscalls.
+    gdb_test_no_output "delete $syscall_insn_bp" "delete break $syscall insn"
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, marker \\(\\) at.*" \
+	"continue to marker ($syscall)"
+}
+
+disp_step_cross_syscall "fork"
+disp_step_cross_syscall "vfork"
diff --git a/gdb/testsuite/gdb.base/disp-step-vfork.c b/gdb/testsuite/gdb.base/disp-step-vfork.c
new file mode 100644
index 0000000..1e705df
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-vfork.c
@@ -0,0 +1,75 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 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 <unistd.h>
+
+int global = 0;
+
+static void
+marker () {}
+
+int
+main (void)
+{
+  int pid;
+
+  pid = vfork ();
+  if (pid == -1)
+    {
+      return 1;
+    }
+  else if (pid != 0)
+    {
+    }
+  else
+    {
+      global = 1;
+      _exit (0);
+    }
+
+  pid = vfork ();
+  if (pid == -1)
+    {
+      return 1;
+    }
+  else if (pid != 0)
+    {
+    }
+  else
+    {
+      global = 1;
+      _exit (0);
+    }
+
+  pid = vfork ();
+  if (pid == -1)
+    {
+      return 1;
+    }
+  else if (pid != 0)
+    {
+    }
+  else
+    {
+      global = 1;
+      _exit (0);
+    }
+
+  marker ();
+  return 0;
+
+}
-- 
1.7.0.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch 2/2] Displaced stepping across fork/vfork : test case
  2011-09-14 11:32   ` Yao Qi
@ 2011-09-14 12:32     ` Pedro Alves
  2011-09-15 15:32       ` Yao Qi
  0 siblings, 1 reply; 9+ messages in thread
From: Pedro Alves @ 2011-09-14 12:32 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On Wednesday 14 September 2011 12:09:50, Yao Qi wrote:
> > Very recent kernels will allow choosing the syscall instruction
> > in the vsyscall page.  It'll be better to make the test
> > skip on !x86-linux at the top, and then, change the test
> > to look for all alternatives of the syscall insn.
> >
> 
> I read some pages on vsyscall, and thought we can fetch the value of 
> AT_SYSINFO in auxv to get the address of __kernel_vsyscall.  However, 
> another simpler way comes up in my mind is to set possible syscall insn 
> to $syscall_insn like this,
> 
>    set syscall_insn "(int|syscall|sysenter)"
> 
> If we match either of them in instruction stream, we are sure program 
> will enter to syscall, so we don't have to worry about vsyscall page.

Yes, exactly what I meant.  Thanks.



> +       "continue to marker ($syscall)"
> +}

> +disp_step_cross_syscall "fork"
> +disp_step_cross_syscall "vfork"

There may be some fail/passes done from within gdb.exp procedures that
won't get that $syscall diferenciator, thus we can end up with
more than one UNTESTED/FAIL/PASS with the same message on gdb.sum/gdb.log.
It'd be better to use $pf_prefix instead (grep for uses in the testsuite).



We need to do something for systems that can't set a breakpoint in
the vsyscall page though (mine can't).  The test is surely failing there.



In the vfork test:

> +      global = 1;

Is the variable used for anything?


Otherwise, this looks okay to me.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch 2/2] Displaced stepping across fork/vfork : test case
  2011-09-14 12:32     ` Pedro Alves
@ 2011-09-15 15:32       ` Yao Qi
  2011-09-15 16:13         ` Pedro Alves
  0 siblings, 1 reply; 9+ messages in thread
From: Yao Qi @ 2011-09-15 15:32 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1261 bytes --]

On 09/14/2011 07:55 PM, Pedro Alves wrote:

>
> There may be some fail/passes done from within gdb.exp procedures that
> won't get that $syscall diferenciator, thus we can end up with
> more than one UNTESTED/FAIL/PASS with the same message on gdb.sum/gdb.log.
> It'd be better to use $pf_prefix instead (grep for uses in the testsuite).
>
>

pf_prefix is set at the entry of proc disp_step_cross_syscall, and 
restored at the end of it.

>
> We need to do something for systems that can't set a breakpoint in
> the vsyscall page though (mine can't).  The test is surely failing there.
>

This is improved by adding another matching in inserting breakpoint on 
syscall insns like this,

        -re "Cannot insert breakpoint .*${gdb_prompt} $" {
            # This syscall insn may be in vsyscall page, and we can't 
set a breakpoint
            # there on some systems.
            fail "break on syscall insns"
            set pf_prefix $old_pf_prefix
            return -1
        }

>
> In the vfork test:
>
>> +      global = 1;
>
> Is the variable used for anything?
>

It was for checking vfork'ed child process executed correctly.  variable 
`global' is useless now.  Removed.

I'll check this patch in tomorrow, if no comments.

-- 
Yao (齐尧)

[-- Attachment #2: 0015-disp-step-fork-testcase.patch --]
[-- Type: text/x-patch, Size: 8603 bytes --]


	gdb/testsuite/
	* gdb.base/disp-step-fork.c: New.
	* gdb.base/disp-step-syscall.exp: New.
	* gdb.base/disp-step-vfork.c: New.
---
 gdb/testsuite/gdb.base/disp-step-fork.c      |   57 ++++++++++
 gdb/testsuite/gdb.base/disp-step-syscall.exp |  147 ++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/disp-step-vfork.c     |   70 ++++++++++++
 3 files changed, 274 insertions(+), 0 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/disp-step-fork.c
 create mode 100644 gdb/testsuite/gdb.base/disp-step-syscall.exp
 create mode 100644 gdb/testsuite/gdb.base/disp-step-vfork.c

diff --git a/gdb/testsuite/gdb.base/disp-step-fork.c b/gdb/testsuite/gdb.base/disp-step-fork.c
new file mode 100644
index 0000000..ab4f3b4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-fork.c
@@ -0,0 +1,57 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 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>
+
+static void
+marker () {}
+
+int
+main (void)
+{
+  int  pid;
+
+  pid = fork ();
+  if (pid == 0) /* child */
+    {
+      exit (0); /* at exit */
+    }
+  else
+    {
+    }
+
+  pid = fork ();
+  if (pid == 0) /* child */
+    {
+      exit (0); /* at exit */
+    }
+  else
+    {
+    }
+
+  pid = fork ();
+  if (pid == 0) /* child */
+    {
+      exit (0); /* at exit */
+    }
+  else
+    {
+    }
+
+  marker ();
+
+}
diff --git a/gdb/testsuite/gdb.base/disp-step-syscall.exp b/gdb/testsuite/gdb.base/disp-step-syscall.exp
new file mode 100644
index 0000000..a1e2642
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-syscall.exp
@@ -0,0 +1,147 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2011 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/>.
+
+if { ![support_displaced_stepping] } {
+    unsupported "displaced stepping"
+    return -1
+}
+
+set syscall_insn ""
+
+# Define the syscall instruction for each target.
+
+if { [istarget "i\[34567\]86-*-linux*"] || [istarget "x86_64-*-linux*"] } {
+    set syscall_insn "(int|syscall|sysenter)"
+} else {
+    return -1
+}
+
+proc disp_step_cross_syscall { syscall } {
+    global syscall_insn
+    global gdb_prompt
+    global pf_prefix
+
+    set testfile "disp-step-$syscall"
+
+    if [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c {debug}] {
+	untested ${testfile}.exp
+	return -1
+    }
+
+    if { ![runto main] } then {
+	fail "run to main ($syscall)"
+	return
+    }
+
+    set old_pf_prefix $pf_prefix
+    lappend pf_prefix "$syscall:"
+
+    # Delete the breakpoint on main.
+    gdb_test_no_output "delete break 1"
+
+    gdb_test "break marker" "Breakpoint.*at.* file .*${testfile}.c, line.*"
+    gdb_test_no_output "set displaced-stepping off"
+
+    set syscall_bp 0
+    gdb_test_multiple "break $syscall"  "break $syscall" {
+	-re "Breakpoint (\[0-9\]*) at .*$gdb_prompt $" {
+	    set syscall_bp $expect_out(1,string)
+	    pass "break $syscall"
+	}
+    }
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in $syscall ().*" \
+	"continue to $syscall (1st time)"
+    # Hit the breakpoint on $syscall for the first time.  In this time, we will let PLT
+    # resolution done, and the number single steps we will do later will be
+    # reduced.
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in $syscall ().*" \
+	"continue to $syscall (2nd time)"
+    # Hit the breakpoint on $syscall for the second time.  In this time, the address
+    # of syscall insn and next insn of syscall are recorded.
+
+    gdb_test "display/i \$pc" ".*"
+
+
+    # Single step until we see sysall insn or we reach the upper bound of loop
+    # iterations.
+    set see_syscall_insn 0
+
+    for {set i 0} {$i < 1000 && $see_syscall_insn == 0} {incr i} {
+	send_gdb "stepi\n"
+	gdb_expect {
+	    -re ".*$syscall_insn.*$gdb_prompt $" {
+		set see_syscall_insn 1
+	    }
+	    -re ".*$gdb_prompt $" {}
+	}
+    }
+
+    if {$see_syscall_insn == 0} then {
+	fail "find syscall insn in $syscall"
+	set pf_prefix $old_pf_prefix
+	return -1
+    }
+
+    set syscall_insn_addr [get_hexadecimal_valueof "\$pc" "0"]
+    gdb_test "stepi" ".*" "stepi $syscall insn"
+    set syscall_insn_next_addr [get_hexadecimal_valueof "\$pc" "0"]
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in $syscall ().*" \
+	"continue to $syscall (3rd time)"
+
+    # Hit the breakpoint on $syscall for the third time.  In this time, we'll set
+    # breakpoint on the syscall insn we recorded previously, and single step over it.
+
+    set syscall_insn_bp 0
+    gdb_test_multiple "break \*$syscall_insn_addr"  "break on syscall insn" {
+	-re "Breakpoint (\[0-9\]*) at .*$gdb_prompt $" {
+	    set syscall_insn_bp $expect_out(1,string)
+	    pass "break on syscall insns"
+	}
+	-re "Cannot insert breakpoint .*${gdb_prompt} $" {
+	    # This syscall insn may be in vsyscall page, and we can't set a breakpoint
+	    # there on some systems.
+	    fail "break on syscall insns"
+	    set pf_prefix $old_pf_prefix
+	    return -1
+	}
+    }
+    gdb_test_no_output "delete $syscall_bp" "delete break $syscall"
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .*" \
+	"continue to syscall insn $syscall"
+
+    gdb_test_no_output "set displaced-stepping on"
+
+    # Check the address of next instruction of syscall.
+    gdb_test "stepi" ".*$syscall_insn_next_addr.*" "single step over $syscall"
+
+    # Delete breakpoint syscall insns to avoid interference to other syscalls.
+    gdb_test_no_output "delete $syscall_insn_bp" "delete break $syscall insn"
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, marker \\(\\) at.*" \
+	"continue to marker ($syscall)"
+
+    set pf_prefix $old_pf_prefix
+}
+
+disp_step_cross_syscall "fork"
+disp_step_cross_syscall "vfork"
diff --git a/gdb/testsuite/gdb.base/disp-step-vfork.c b/gdb/testsuite/gdb.base/disp-step-vfork.c
new file mode 100644
index 0000000..fdc7914
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-vfork.c
@@ -0,0 +1,70 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 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 <unistd.h>
+
+static void
+marker () {}
+
+int
+main (void)
+{
+  int pid;
+
+  pid = vfork ();
+  if (pid == -1)
+    {
+      return 1;
+    }
+  else if (pid != 0)
+    {
+    }
+  else
+    {
+      _exit (0);
+    }
+
+  pid = vfork ();
+  if (pid == -1)
+    {
+      return 1;
+    }
+  else if (pid != 0)
+    {
+    }
+  else
+    {
+      _exit (0);
+    }
+
+  pid = vfork ();
+  if (pid == -1)
+    {
+      return 1;
+    }
+  else if (pid != 0)
+    {
+    }
+  else
+    {
+      _exit (0);
+    }
+
+  marker ();
+  return 0;
+
+}
-- 
1.7.0.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch 2/2] Displaced stepping across fork/vfork : test case
  2011-09-15 15:32       ` Yao Qi
@ 2011-09-15 16:13         ` Pedro Alves
  2011-09-16  6:49           ` Yao Qi
  0 siblings, 1 reply; 9+ messages in thread
From: Pedro Alves @ 2011-09-15 16:13 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On Thursday 15 September 2011 16:27:04, Yao Qi wrote:
> This is improved by adding another matching in inserting breakpoint on 
> syscall insns like this,

...

> +    set syscall_insn_bp 0
> +    gdb_test_multiple "break \*$syscall_insn_addr"  "break on syscall insn" {
> +       -re "Breakpoint (\[0-9\]*) at .*$gdb_prompt $" {
> +           set syscall_insn_bp $expect_out(1,string)
> +           pass "break on syscall insns"
> +       }
> +       -re "Cannot insert breakpoint .*${gdb_prompt} $" {
> +           # This syscall insn may be in vsyscall page, and we can't set a breakpoint
> +           # there on some systems.
> +           fail "break on syscall insns"

Please don't make this is a fail.  It is not GDB's fault.  "unsupported"
or "xfail" would be better.

> +           set pf_prefix $old_pf_prefix
> +           return -1
> +       }
> +    }

But this won't work as is.  Breakpoints will only be inserted on the
next resume, not immediately.  Unless you enable always-inserted mode,
that is.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch 2/2] Displaced stepping across fork/vfork : test case
  2011-09-15 16:13         ` Pedro Alves
@ 2011-09-16  6:49           ` Yao Qi
  2011-09-16 10:44             ` Pedro Alves
  0 siblings, 1 reply; 9+ messages in thread
From: Yao Qi @ 2011-09-16  6:49 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 09/15/2011 11:52 PM, Pedro Alves wrote:
>> > +    set syscall_insn_bp 0
>> > +    gdb_test_multiple "break \*$syscall_insn_addr"  "break on syscall insn" {
>> > +       -re "Breakpoint (\[0-9\]*) at .*$gdb_prompt $" {
>> > +           set syscall_insn_bp $expect_out(1,string)
>> > +           pass "break on syscall insns"
>> > +       }
>> > +       -re "Cannot insert breakpoint .*${gdb_prompt} $" {
>> > +           # This syscall insn may be in vsyscall page, and we can't set a breakpoint
>> > +           # there on some systems.
>> > +           fail "break on syscall insns"
> Please don't make this is a fail.  It is not GDB's fault.  "unsupported"
> or "xfail" would be better.
> 

"unsupported" is used here.

>> > +           set pf_prefix $old_pf_prefix
>> > +           return -1
>> > +       }
>> > +    }
> But this won't work as is.  Breakpoints will only be inserted on the
> next resume, not immediately.  Unless you enable always-inserted mode,
> that is.

I can set breakpoint on vsyscall page of my system, so I have to imagine
what will happen if I can't set breakpoint.  As you said, breakpoints
will be inserted on the next resume, so I check the "Cannot insert
breakpoint" in next "continue" operation, like this,

    gdb_test_multiple "continue" "continue to syscall insn $syscall" {
	-re "Cannot insert breakpoint .*${gdb_prompt} $" {
	    # This syscall insn may be in vsyscall page, and we can't set a
breakpoint
	    # there on some systems.
	    unsupported "break on syscall insns"
	    set pf_prefix $old_pf_prefix
	    return -1
	}
	-re "Continuing\\..*Breakpoint \[0-9\]+, .*${gdb_prompt} $" {
	    pass "break on syscall insns"
	}
    }

-- 
Yao (齐尧)

	gdb/testsuite/
	* gdb.base/disp-step-fork.c: New.
	* gdb.base/disp-step-syscall.exp: New.
	* gdb.base/disp-step-vfork.c: New.
---
 gdb/testsuite/gdb.base/disp-step-fork.c      |   57 ++++++++++
 gdb/testsuite/gdb.base/disp-step-syscall.exp |  148
++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/disp-step-vfork.c     |   70 ++++++++++++
 3 files changed, 275 insertions(+), 0 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/disp-step-fork.c
 create mode 100644 gdb/testsuite/gdb.base/disp-step-syscall.exp
 create mode 100644 gdb/testsuite/gdb.base/disp-step-vfork.c

diff --git a/gdb/testsuite/gdb.base/disp-step-fork.c
b/gdb/testsuite/gdb.base/disp-step-fork.c
new file mode 100644
index 0000000..ab4f3b4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-fork.c
@@ -0,0 +1,57 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 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>
+
+static void
+marker () {}
+
+int
+main (void)
+{
+  int  pid;
+
+  pid = fork ();
+  if (pid == 0) /* child */
+    {
+      exit (0); /* at exit */
+    }
+  else
+    {
+    }
+
+  pid = fork ();
+  if (pid == 0) /* child */
+    {
+      exit (0); /* at exit */
+    }
+  else
+    {
+    }
+
+  pid = fork ();
+  if (pid == 0) /* child */
+    {
+      exit (0); /* at exit */
+    }
+  else
+    {
+    }
+
+  marker ();
+
+}
diff --git a/gdb/testsuite/gdb.base/disp-step-syscall.exp
b/gdb/testsuite/gdb.base/disp-step-syscall.exp
new file mode 100644
index 0000000..4860c48
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-syscall.exp
@@ -0,0 +1,148 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2011 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/>.
+
+if { ![support_displaced_stepping] } {
+    unsupported "displaced stepping"
+    return -1
+}
+
+set syscall_insn ""
+
+# Define the syscall instruction for each target.
+
+if { [istarget "i\[34567\]86-*-linux*"] || [istarget "x86_64-*-linux*"] } {
+    set syscall_insn "(int|syscall|sysenter)"
+} else {
+    return -1
+}
+
+proc disp_step_cross_syscall { syscall } {
+    global syscall_insn
+    global gdb_prompt
+    global pf_prefix
+
+    set testfile "disp-step-$syscall"
+
+    if [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c
{debug}] {
+	untested ${testfile}.exp
+	return -1
+    }
+
+    if { ![runto main] } then {
+	fail "run to main ($syscall)"
+	return
+    }
+
+    set old_pf_prefix $pf_prefix
+    lappend pf_prefix "$syscall:"
+
+    # Delete the breakpoint on main.
+    gdb_test_no_output "delete break 1"
+
+    gdb_test "break marker" "Breakpoint.*at.* file .*${testfile}.c, line.*"
+    gdb_test_no_output "set displaced-stepping off"
+
+    set syscall_bp 0
+    gdb_test_multiple "break $syscall"  "break $syscall" {
+	-re "Breakpoint (\[0-9\]*) at .*$gdb_prompt $" {
+	    set syscall_bp $expect_out(1,string)
+	    pass "break $syscall"
+	}
+    }
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in
$syscall ().*" \
+	"continue to $syscall (1st time)"
+    # Hit the breakpoint on $syscall for the first time.  In this time,
we will let PLT
+    # resolution done, and the number single steps we will do later will be
+    # reduced.
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in
$syscall ().*" \
+	"continue to $syscall (2nd time)"
+    # Hit the breakpoint on $syscall for the second time.  In this
time, the address
+    # of syscall insn and next insn of syscall are recorded.
+
+    gdb_test "display/i \$pc" ".*"
+
+
+    # Single step until we see sysall insn or we reach the upper bound
of loop
+    # iterations.
+    set see_syscall_insn 0
+
+    for {set i 0} {$i < 1000 && $see_syscall_insn == 0} {incr i} {
+	send_gdb "stepi\n"
+	gdb_expect {
+	    -re ".*$syscall_insn.*$gdb_prompt $" {
+		set see_syscall_insn 1
+	    }
+	    -re ".*$gdb_prompt $" {}
+	}
+    }
+
+    if {$see_syscall_insn == 0} then {
+	fail "find syscall insn in $syscall"
+	set pf_prefix $old_pf_prefix
+	return -1
+    }
+
+    set syscall_insn_addr [get_hexadecimal_valueof "\$pc" "0"]
+    gdb_test "stepi" ".*" "stepi $syscall insn"
+    set syscall_insn_next_addr [get_hexadecimal_valueof "\$pc" "0"]
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .* in
$syscall ().*" \
+	"continue to $syscall (3rd time)"
+
+    # Hit the breakpoint on $syscall for the third time.  In this time,
we'll set
+    # breakpoint on the syscall insn we recorded previously, and single
step over it.
+
+    set syscall_insn_bp 0
+    gdb_test_multiple "break \*$syscall_insn_addr"  "break on syscall
insn" {
+	-re "Breakpoint (\[0-9\]*) at .*$gdb_prompt $" {
+	    set syscall_insn_bp $expect_out(1,string)
+	    pass "break on syscall insns"
+	}
+    }
+    gdb_test_no_output "delete $syscall_bp" "delete break $syscall"
+
+    gdb_test_multiple "continue" "continue to syscall insn $syscall" {
+	-re "Cannot insert breakpoint .*${gdb_prompt} $" {
+	    # This syscall insn may be in vsyscall page, and we can't set a
breakpoint
+	    # there on some systems.
+	    unsupported "break on syscall insns"
+	    set pf_prefix $old_pf_prefix
+	    return -1
+	}
+	-re "Continuing\\..*Breakpoint \[0-9\]+, .*${gdb_prompt} $" {
+	    pass "break on syscall insns"
+	}
+    }
+
+    gdb_test_no_output "set displaced-stepping on"
+
+    # Check the address of next instruction of syscall.
+    gdb_test "stepi" ".*$syscall_insn_next_addr.*" "single step over
$syscall"
+
+    # Delete breakpoint syscall insns to avoid interference to other
syscalls.
+    gdb_test_no_output "delete $syscall_insn_bp" "delete break $syscall
insn"
+
+    gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, marker
\\(\\) at.*" \
+	"continue to marker ($syscall)"
+
+    set pf_prefix $old_pf_prefix
+}
+
+disp_step_cross_syscall "fork"
+disp_step_cross_syscall "vfork"
diff --git a/gdb/testsuite/gdb.base/disp-step-vfork.c
b/gdb/testsuite/gdb.base/disp-step-vfork.c
new file mode 100644
index 0000000..fdc7914
--- /dev/null
+++ b/gdb/testsuite/gdb.base/disp-step-vfork.c
@@ -0,0 +1,70 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 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 <unistd.h>
+
+static void
+marker () {}
+
+int
+main (void)
+{
+  int pid;
+
+  pid = vfork ();
+  if (pid == -1)
+    {
+      return 1;
+    }
+  else if (pid != 0)
+    {
+    }
+  else
+    {
+      _exit (0);
+    }
+
+  pid = vfork ();
+  if (pid == -1)
+    {
+      return 1;
+    }
+  else if (pid != 0)
+    {
+    }
+  else
+    {
+      _exit (0);
+    }
+
+  pid = vfork ();
+  if (pid == -1)
+    {
+      return 1;
+    }
+  else if (pid != 0)
+    {
+    }
+  else
+    {
+      _exit (0);
+    }
+
+  marker ();
+  return 0;
+
+}
-- 
1.7.0.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch 2/2] Displaced stepping across fork/vfork : test case
  2011-09-16  6:49           ` Yao Qi
@ 2011-09-16 10:44             ` Pedro Alves
  2011-09-17 14:35               ` [committed]: " Yao Qi
  0 siblings, 1 reply; 9+ messages in thread
From: Pedro Alves @ 2011-09-16 10:44 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On Friday 16 September 2011 05:09:24, Yao Qi wrote:

> I can set breakpoint on vsyscall page of my system, so I have to imagine
> what will happen if I can't set breakpoint.  As you said, breakpoints
> will be inserted on the next resume, so I check the "Cannot insert
> breakpoint" in next "continue" operation, like this,

I'm sorry for making you go round.  Looking again, the error I was
seeing might have been something else.  Please remove the
handling for the breakpoint failing to insert, and apply.  Let's
deal with failures if and how they appear.

Thanks,
-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [committed]: [patch 2/2] Displaced stepping across fork/vfork : test case
  2011-09-16 10:44             ` Pedro Alves
@ 2011-09-17 14:35               ` Yao Qi
  0 siblings, 0 replies; 9+ messages in thread
From: Yao Qi @ 2011-09-17 14:35 UTC (permalink / raw)
  Cc: gdb-patches

On 09/16/2011 06:34 PM, Pedro Alves wrote:
> I'm sorry for making you go round.  Looking again, the error I was
> seeing might have been something else.  Please remove the
> handling for the breakpoint failing to insert, and apply.  Let's
> deal with failures if and how they appear.

OK, patch is committed.
http://sourceware.org/ml/gdb-cvs/2011-09/msg00110.html

-- 
Yao (齐尧)


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2011-09-17 13:43 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-11  9:55 [patch 2/2] Displaced stepping across fork/vfork : test case Yao Qi
2011-09-12 15:03 ` Pedro Alves
2011-09-14 11:32   ` Yao Qi
2011-09-14 12:32     ` Pedro Alves
2011-09-15 15:32       ` Yao Qi
2011-09-15 16:13         ` Pedro Alves
2011-09-16  6:49           ` Yao Qi
2011-09-16 10:44             ` Pedro Alves
2011-09-17 14:35               ` [committed]: " Yao Qi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox