diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 7222a2d812..e48d7c24fa 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-09-17 Yao Qi + + * gdb.base/disp-step-fork.c: New. + * gdb.base/disp-step-syscall.exp: New. + * gdb.base/disp-step-vfork.c: New. + 2011-09-16 Joel Brobecker * gdb.ada/tasks.exp: Make the expected output for 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 0000000000..ab4f3b475a --- /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 . */ + +#include + +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 0000000000..a84ca29eb7 --- /dev/null +++ b/gdb/testsuite/gdb.base/disp-step-syscall.exp @@ -0,0 +1,138 @@ +# 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 . + +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 "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 0000000000..fdc7914891 --- /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 . */ + +#include + +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; + +}