From 28d41a992fe2b335e93e84f724c76df8ed47fe28 Mon Sep 17 00:00:00 2001 From: Michael Snyder Date: Sat, 27 Jun 2009 18:49:20 +0000 Subject: [PATCH] 2009-06-27 Michael Snyder * gdb.reverse: New directory. * gdb.reverse/break-reverse.c: New test. * gdb.reverse/break-reverse.exp: New test. * gdb.reverse/consecutive-reverse.c: New test. * gdb.reverse/consecutive-reverse.exp: New test. * gdb.reverse/finish-reverse.c: New test. * gdb.reverse/finish-reverse.exp: New test. * gdb.reverse/machinestate.c: New test. * gdb.reverse/ms1.c: New test. * gdb.reverse/machinestate.exp: New test. * gdb.reverse/Makefile.in: New file. * gdb.reverse/shr2.c: New test. * gdb.reverse/solib-reverse.c: New test. * gdb.reverse/solib-reverse.exp: New test. * gdb.reverse/step-reverse.c: New test. * gdb.reverse/step-reverse.exp: New test. * gdb.reverse/until-reverse.c: New test. * gdb.reverse/ur1.c: New test. * gdb.reverse/until-reverse.exp: New test. * gdb.reverse/watch-reverse.c: New test. * gdb.reverse/watch-reverse.exp: New test. * configure.ac (AC_OUTPUT): Add gdb.reverse/Makefile. * configure: Regenerate. --- gdb/testsuite/ChangeLog | 26 ++ gdb/testsuite/configure | 3 +- gdb/testsuite/configure.ac | 2 +- gdb/testsuite/gdb.reverse/Makefile.in | 19 ++ gdb/testsuite/gdb.reverse/break-reverse.c | 37 +++ gdb/testsuite/gdb.reverse/break-reverse.exp | 86 ++++++ .../gdb.reverse/consecutive-reverse.c | 37 +++ .../gdb.reverse/consecutive-reverse.exp | 125 +++++++++ gdb/testsuite/gdb.reverse/finish-reverse.c | 127 +++++++++ gdb/testsuite/gdb.reverse/finish-reverse.exp | 260 ++++++++++++++++++ gdb/testsuite/gdb.reverse/machinestate.c | 101 +++++++ gdb/testsuite/gdb.reverse/machinestate.exp | 230 ++++++++++++++++ gdb/testsuite/gdb.reverse/ms1.c | 25 ++ gdb/testsuite/gdb.reverse/shr2.c | 34 +++ gdb/testsuite/gdb.reverse/solib-reverse.c | 43 +++ gdb/testsuite/gdb.reverse/solib-reverse.exp | 124 +++++++++ gdb/testsuite/gdb.reverse/step-reverse.c | 78 ++++++ gdb/testsuite/gdb.reverse/step-reverse.exp | 251 +++++++++++++++++ gdb/testsuite/gdb.reverse/until-reverse.c | 146 ++++++++++ gdb/testsuite/gdb.reverse/until-reverse.exp | 129 +++++++++ gdb/testsuite/gdb.reverse/ur1.c | 49 ++++ gdb/testsuite/gdb.reverse/watch-reverse.c | 219 +++++++++++++++ gdb/testsuite/gdb.reverse/watch-reverse.exp | 127 +++++++++ 23 files changed, 2276 insertions(+), 2 deletions(-) create mode 100644 gdb/testsuite/gdb.reverse/Makefile.in create mode 100644 gdb/testsuite/gdb.reverse/break-reverse.c create mode 100644 gdb/testsuite/gdb.reverse/break-reverse.exp create mode 100644 gdb/testsuite/gdb.reverse/consecutive-reverse.c create mode 100644 gdb/testsuite/gdb.reverse/consecutive-reverse.exp create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse.c create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse.exp create mode 100644 gdb/testsuite/gdb.reverse/machinestate.c create mode 100644 gdb/testsuite/gdb.reverse/machinestate.exp create mode 100644 gdb/testsuite/gdb.reverse/ms1.c create mode 100644 gdb/testsuite/gdb.reverse/shr2.c create mode 100644 gdb/testsuite/gdb.reverse/solib-reverse.c create mode 100644 gdb/testsuite/gdb.reverse/solib-reverse.exp create mode 100644 gdb/testsuite/gdb.reverse/step-reverse.c create mode 100644 gdb/testsuite/gdb.reverse/step-reverse.exp create mode 100644 gdb/testsuite/gdb.reverse/until-reverse.c create mode 100644 gdb/testsuite/gdb.reverse/until-reverse.exp create mode 100644 gdb/testsuite/gdb.reverse/ur1.c create mode 100644 gdb/testsuite/gdb.reverse/watch-reverse.c create mode 100644 gdb/testsuite/gdb.reverse/watch-reverse.exp diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 2f88eeb14fd..e5bd21bbffe 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,29 @@ +2009-06-27 Michael Snyder + + * gdb.reverse: New directory. + * gdb.reverse/break-reverse.c: New test. + * gdb.reverse/break-reverse.exp: New test. + * gdb.reverse/consecutive-reverse.c: New test. + * gdb.reverse/consecutive-reverse.exp: New test. + * gdb.reverse/finish-reverse.c: New test. + * gdb.reverse/finish-reverse.exp: New test. + * gdb.reverse/machinestate.c: New test. + * gdb.reverse/ms1.c: New test. + * gdb.reverse/machinestate.exp: New test. + * gdb.reverse/Makefile.in: New file. + * gdb.reverse/shr2.c: New test. + * gdb.reverse/solib-reverse.c: New test. + * gdb.reverse/solib-reverse.exp: New test. + * gdb.reverse/step-reverse.c: New test. + * gdb.reverse/step-reverse.exp: New test. + * gdb.reverse/until-reverse.c: New test. + * gdb.reverse/ur1.c: New test. + * gdb.reverse/until-reverse.exp: New test. + * gdb.reverse/watch-reverse.c: New test. + * gdb.reverse/watch-reverse.exp: New test. + * configure.ac (AC_OUTPUT): Add gdb.reverse/Makefile. + * configure: Regenerate. + 2009-06-26 Doug Evans * gdb.base/psymtab.exp: Turn off pending breakpoints. diff --git a/gdb/testsuite/configure b/gdb/testsuite/configure index ef35b138657..3973a2a34b1 100755 --- a/gdb/testsuite/configure +++ b/gdb/testsuite/configure @@ -3131,7 +3131,7 @@ done - ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile" + ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -3699,6 +3699,7 @@ do "gdb.opt/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.opt/Makefile" ;; "gdb.pascal/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.pascal/Makefile" ;; "gdb.python/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.python/Makefile" ;; + "gdb.reverse/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.reverse/Makefile" ;; "gdb.threads/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.threads/Makefile" ;; "gdb.trace/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.trace/Makefile" ;; "gdb.xml/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.xml/Makefile" ;; diff --git a/gdb/testsuite/configure.ac b/gdb/testsuite/configure.ac index 3d8fae4a616..bb98e6f79f6 100644 --- a/gdb/testsuite/configure.ac +++ b/gdb/testsuite/configure.ac @@ -117,5 +117,5 @@ AC_OUTPUT([Makefile \ gdb.fortran/Makefile gdb.server/Makefile \ gdb.java/Makefile gdb.mi/Makefile gdb.modula2/Makefile \ gdb.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile \ - gdb.python/Makefile \ + gdb.python/Makefile gdb.reverse/Makefile \ gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile]) diff --git a/gdb/testsuite/gdb.reverse/Makefile.in b/gdb/testsuite/gdb.reverse/Makefile.in new file mode 100644 index 00000000000..43b2f5816ba --- /dev/null +++ b/gdb/testsuite/gdb.reverse/Makefile.in @@ -0,0 +1,19 @@ +VPATH = @srcdir@ +srcdir = @srcdir@ + +EXECUTABLES = break-reverse consecutive-reverse finish-reverse \ + machinestate solib-reverse step-reverse until-reverse \ + watch-reverse + +MISCELLANEOUS = + +all info install-info dvi install uninstall installcheck check: + @echo "Nothing to be done for $@..." + +clean mostlyclean: + rm -f *~ *.o *.x *.ci *.sl a.out core + rm -f $(EXECUTABLES) $(MISCELLANEOUS) + +distclean maintainer-clean realclean: clean + rm -f Makefile config.status config.log site.* + diff --git a/gdb/testsuite/gdb.reverse/break-reverse.c b/gdb/testsuite/gdb.reverse/break-reverse.c new file mode 100644 index 00000000000..f35e32b52b7 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/break-reverse.c @@ -0,0 +1,37 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009 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 . */ + +int xyz; + +int bar () +{ + xyz = 2; /* break in bar */ + return 1; +} + +int foo () +{ + xyz = 1; /* break in foo */ + return bar (); +} + +int main () +{ + xyz = 0; /* break in main */ + foo (); + return (xyz == 2 ? 0 : 1); +} /* end of main */ diff --git a/gdb/testsuite/gdb.reverse/break-reverse.exp b/gdb/testsuite/gdb.reverse/break-reverse.exp new file mode 100644 index 00000000000..db8f351b089 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/break-reverse.exp @@ -0,0 +1,86 @@ +# Copyright 2008, 2009 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 . + +# This file is part of the GDB testsuite. It tests reverse debugging +# with breakpoints. + +if ![target_info exists gdb,can_reverse] { + return +} + +set testfile "break-reverse" +set srcfile ${testfile}.c + +if { [prepare_for_testing $testfile.exp $testfile $srcfile] } { + return -1 +} + +set foo_location [gdb_get_line_number "break in foo" ] +set bar_location [gdb_get_line_number "break in bar" ] +set main_location [gdb_get_line_number "break in main"] +set end_location [gdb_get_line_number "end of main" ] + +runto main + +if [target_info exists gdb,use_precord] { + # Activate process record/replay + gdb_test "record" "" "Turn on process record" + # FIXME: command ought to acknowledge, so we can test if it succeeded. +} + +gdb_test "break foo" \ + "Breakpoint $decimal at .* line $foo_location\." \ + "set breakpoint on foo" + +gdb_test "break bar" \ + "Breakpoint $decimal at .* line $bar_location\." \ + "set breakpoint on bar" + +gdb_test "break $end_location" \ + "Breakpoint $decimal at .* line $end_location\." \ + set breakpoint at end of main" + +gdb_continue_to_breakpoint "foo" ".*/$srcfile:$foo_location.*" +gdb_continue_to_breakpoint "bar" ".*/$srcfile:$bar_location.*" +gdb_continue_to_breakpoint "end" ".*/$srcfile:$end_location.*" + +# FIXME 'set exec-dir' command should give some output so we can test. +gdb_test "set exec-direction reverse" "" "set reverse" + +gdb_continue_to_breakpoint "bar backward" ".*/$srcfile:$bar_location.*" +gdb_continue_to_breakpoint "foo backward" ".*/$srcfile:$foo_location.*" + +gdb_test_multiple "continue" "main backward" { + -re ".*Breakpoint $decimal,.*/$srcfile:$main_location.*$gdb_prompt $" { + pass "main backward" + } + -re "No more reverse-execution history.* break in main .*$gdb_prompt $" { + pass "main backward" + } +} + +gdb_test "set exec-direction forward" "" "set forward" + +gdb_continue_to_breakpoint "foo" ".*/$srcfile:$foo_location.*" +gdb_continue_to_breakpoint "bar" ".*/$srcfile:$bar_location.*" + +gdb_test_multiple "continue" "end of record log" { + -re ".*Breakpoint $decimal,.*/$srcfile:$end_location.*$gdb_prompt $" { + pass "end of record log" + } + -re "No more reverse-execution history.* end of main .*$gdb_prompt $" { + pass "end of record log" + } +} diff --git a/gdb/testsuite/gdb.reverse/consecutive-reverse.c b/gdb/testsuite/gdb.reverse/consecutive-reverse.c new file mode 100644 index 00000000000..8452141d030 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/consecutive-reverse.c @@ -0,0 +1,37 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009 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 . */ + +/* + Purpose of this test: to test breakpoints on consecutive instructions. +*/ + +int a[7] = {1, 2, 3, 4, 5, 6, 7}; + +/* assert: first line of foo has more than one instruction. */ +int foo () +{ + return a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]; +} + +main() +{ +#ifdef usestubs + set_debug_traps (); + breakpoint (); +#endif + foo (); +} diff --git a/gdb/testsuite/gdb.reverse/consecutive-reverse.exp b/gdb/testsuite/gdb.reverse/consecutive-reverse.exp new file mode 100644 index 00000000000..e2ba83ad7c5 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/consecutive-reverse.exp @@ -0,0 +1,125 @@ +# Copyright 2008, 2009 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 . + +# This file is part of the GDB testsuite. It tests stepping over +# consecutive instructions in reverse. + +if ![target_info exists gdb,can_reverse] { + return +} + +set testfile "consecutive-reverse" +set srcfile ${testfile}.c + +if { [prepare_for_testing $testfile.exp $testfile $srcfile] } { + return -1 +} + +runto main + +if [target_info exists gdb,use_precord] { + # Activate process record/replay + gdb_test "record" "" "Turn on process record" + # FIXME: command ought to acknowledge, so we can test if it succeeded. +} + +gdb_breakpoint foo +gdb_test "continue" "Breakpoint $decimal, foo .*" \ + "continue to breakpoint in foo" + +set foo1_addr 0 +set foo2_addr 0 +set stop_addr 0 + +send_gdb "x /2i \$pc\n" +gdb_expect { + global hex + global foo1_addr + global foo2_addr + global gdb_prompt + + -re "($hex).*\[\r\n\]+($hex).*$gdb_prompt $" { + set foo1_addr $expect_out(1,string) + set foo2_addr $expect_out(2,string) + pass "get breakpoint address for foo" + } + -re ".*$gdb_prompt $" { + fail "get breakpoint address for foo" + return 0; + } + timeout { + fail "get breakpoint address for foo (timeout)" + return 0; + } +} + +gdb_test "break \*$foo2_addr" "Breakpoint $decimal at $foo2_addr: file .*" \ + "set bp, 2nd instr" + +send_gdb "step\n" +gdb_expect { + -re "Breakpoint $decimal, ($hex) in foo.*$gdb_prompt $" { + set stop_addr $expect_out(1,string) + if [eval expr "$foo2_addr == $stop_addr"] then { + pass "stopped at bp, 2nd instr" + } else { + fail "stopped at bp, 2nd instr (wrong address)" + } + } + -re ".*$gdb_prompt $" { + fail "stopped at bp, 2nd instr" + } + timeout { + fail "stopped at bp, 2nd instr (timeout)" + + } +} + +### +### +### + +# Set reverse execution direction +# FIXME: command needs to acknowledge, so we can test if it succeeded. + +gdb_test "set exec-dir reverse" "" "set reverse execution" + +# Now step backward and hope to hit the first breakpoint. + +set test_msg "stopped at bp in reverse, 1st instr" +gdb_test_multiple "step" "$test_msg" { + -re "Breakpoint $decimal, ($hex) in foo.*$gdb_prompt $" { + set stop_addr $expect_out(1,string) + if [eval expr "$foo1_addr == $stop_addr"] then { + pass "$test_msg" + } else { + fail "$test_msg (wrong address)" + } + } + -re "Breakpoint $decimal, foo.*$gdb_prompt $" { + send_gdb "print \$pc == $foo1_addr\n" + gdb_expect { + -re "$decimal = 1\[\r\n\]+$gdb_prompt $" { + pass "$test_msg" + } + -re "$decimal = 0\[\r\n\]+$gdb_prompt $" { + fail "$test_msg (wrong address)" + } + } + } + -re ".*$gdb_prompt $" { + fail "$test_msg" + } +} diff --git a/gdb/testsuite/gdb.reverse/finish-reverse.c b/gdb/testsuite/gdb.reverse/finish-reverse.c new file mode 100644 index 00000000000..aeea295d43a --- /dev/null +++ b/gdb/testsuite/gdb.reverse/finish-reverse.c @@ -0,0 +1,127 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009 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 . */ + +/* Test gdb's "return" command in reverse. */ + +int void_test = 0; +int main_test = 0; + +char char_returnval = '1'; +short short_returnval = 1; +int int_returnval = 1; +long long_returnval = 1; +long long long_long_returnval = 1; +float float_returnval = 1; +double double_returnval = 1; + +union { + char char_testval; + short short_testval; + int int_testval; + long long_testval; + long long long_long_testval; + float float_testval; + double double_testval; + char ffff[80]; +} testval; + +void void_func () +{ + void_test = 1; /* VOID FUNC */ +} + +char char_func () +{ + return char_returnval; /* CHAR FUNC */ +} + +short short_func () +{ + return short_returnval; /* SHORT FUNC */ +} + +int int_func () +{ + return int_returnval; /* INT FUNC */ +} + +long long_func () +{ + return long_returnval; /* LONG FUNC */ +} + +long long long_long_func () +{ + return long_long_returnval; /* LONG LONG FUNC */ +} + +float float_func () +{ + return float_returnval; /* FLOAT FUNC */ +} + +double double_func () +{ + return double_returnval; /* DOUBLE FUNC */ +} + +int main (int argc, char **argv) +{ + char char_resultval; + short short_resultval; + int int_resultval; + long long_resultval; + long long long_long_resultval; + float float_resultval; + double double_resultval; + int i; + + /* A "test load" that will insure that the function really returns + a ${type} (as opposed to just a truncated or part of a ${type}). */ + for (i = 0; i < sizeof (testval.ffff); i++) + testval.ffff[i] = 0xff; + + void_func (); /* call to void_func */ + char_resultval = char_func (); /* void_checkpoint */ + short_resultval = short_func (); /* char_checkpoint */ + int_resultval = int_func (); /* short_checkpoint */ + long_resultval = long_func (); /* int_checkpoint */ + long_long_resultval = long_long_func (); /* long_checkpoint */ + + /* On machines using IEEE floating point, the test pattern of all + 1-bits established above turns out to be a floating-point NaN + ("Not a Number"). According to the IEEE rules, NaN's aren't even + equal to themselves. This can lead to stupid conversations with + GDB like: + + (gdb) p testval.float_testval == testval.float_testval + $7 = 0 + (gdb) + + This is the correct answer, but it's not the sort of thing + return2.exp wants to see. So to make things work the way they + ought, we'll set aside the `union' cleverness and initialize the + test values explicitly here. These values have interesting bits + throughout the value, so we'll still detect truncated values. */ + + testval.float_testval = 2.7182818284590452354;/* long_long_checkpoint */ + float_resultval = float_func (); + testval.double_testval = 3.14159265358979323846; /* float_checkpoint */ + double_resultval = double_func (); + main_test = 1; /* double_checkpoint */ + return 0; +} diff --git a/gdb/testsuite/gdb.reverse/finish-reverse.exp b/gdb/testsuite/gdb.reverse/finish-reverse.exp new file mode 100644 index 00000000000..69d5df2c6d7 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/finish-reverse.exp @@ -0,0 +1,260 @@ +# Copyright 2008, 2009 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 . + +# This file is part of the GDB testsuite. It tests 'finish' with +# reverse debugging. + +if ![target_info exists gdb,can_reverse] { + return +} + +set testfile "finish-reverse" +set srcfile ${testfile}.c + +if { [prepare_for_testing $testfile.exp "$testfile" $srcfile] } { + return -1 +} + +proc test_start_of_line { line_text test_msg } { + global gdb_prompt + global decimal + global hex + + send_gdb "info line\n" + gdb_expect { + -re "Line $decimal of .* starts at address ($hex) .*$gdb_prompt $" { + set line_begin $expect_out(1,string) + } + default { + fail "Get line address in test_start_of_line" + } + } + send_gdb "info reg pc\n" + gdb_expect { + -re ".*: ($hex)\r\n*$gdb_prompt $" { + set stop_pc $expect_out(1,string) + } + default { + fail"Get stop pc in test_start_of_line" + } + } + gdb_test "print $line_begin == $stop_pc" \ + " = 1\[\r\n\]*" \ + "test_start_of_line, $test_msg" +} + +runto main + +if [target_info exists gdb,use_precord] { + # Activate process record/replay + gdb_test "record" "" "Turn on process record" + # FIXME: command ought to acknowledge, so we can test if it succeeded. +} + +# Test finish from void func + +set breakloc [gdb_get_line_number "VOID FUNC" "$srcfile"] +gdb_test "break void_func" \ + "Breakpoint $decimal at .*/$srcfile, line $breakloc\." \ + "set breakpoint on void_func" +gdb_continue_to_breakpoint "void_func" ".*/$srcfile:$breakloc.*" + +set test_msg "finish from void_func" +gdb_test_multiple "finish" "$test_msg" { + -re " call to void_func .*$gdb_prompt $" { + send_gdb "step\n" + exp_continue + } + -re " void_checkpoint .*$gdb_prompt $" { + pass "$test_msg" + } +} + +# Test finish from char func + +set breakloc [gdb_get_line_number "CHAR FUNC" "$srcfile"] +gdb_test "break char_func" \ + "Breakpoint $decimal at .*/$srcfile, line $breakloc\." \ + "set breakpoint on char_func" +gdb_continue_to_breakpoint "char_func" ".*/$srcfile:$breakloc.*" + +set test_msg "finish from char_func" +gdb_test_multiple "finish" "$test_msg" { + -re " void_checkpoint .*$gdb_prompt $" { + send_gdb "step\n" + exp_continue + } + -re " char_checkpoint .*$gdb_prompt $" { + pass "$test_msg" + } +} + +# Test finish from short func + +set breakloc [gdb_get_line_number "SHORT FUNC" "$srcfile"] +gdb_test "break short_func" \ + "Breakpoint $decimal at .* line $breakloc\." \ + "set breakpoint on short_func" +gdb_continue_to_breakpoint "short_func" ".*/$srcfile:$breakloc.*" + +set test_msg "finish from short_func" +gdb_test_multiple "finish" "$test_msg" { + -re " char_checkpoint .*$gdb_prompt $" { + send_gdb "step\n" + exp_continue + } + -re " short_checkpoint .*$gdb_prompt $" { + pass "$test_msg" + } +} + +# Test finish from int func + +set breakloc [gdb_get_line_number "INT FUNC" "$srcfile"] +gdb_test "break int_func" \ + "Breakpoint $decimal at .* line $breakloc\." \ + "set breakpoint on int_func" +gdb_continue_to_breakpoint "int_func" ".*/$srcfile:$breakloc.*" + +set test_msg "finish from int_func" +gdb_test_multiple "finish" "$test_msg" { + -re " short_checkpoint .*$gdb_prompt $" { + send_gdb "step\n" + exp_continue + } + -re " int_checkpoint .*$gdb_prompt $" { + pass "$test_msg" + } +} + +# Test finish from long func + +set breakloc [gdb_get_line_number "LONG FUNC" "$srcfile"] +gdb_test "break long_func" \ + "Breakpoint $decimal at .* line $breakloc\." \ + "set breakpoint on long_func" +gdb_continue_to_breakpoint "long_func" ".*/$srcfile:$breakloc.*" + +set test_msg "finish from long_func" +gdb_test_multiple "finish" "$test_msg" { + -re " int_checkpoint .*$gdb_prompt $" { + send_gdb "step\n" + exp_continue + } + -re " long_checkpoint .*$gdb_prompt $" { + pass "$test_msg" + } +} + +# Test finish from long long func + +set breakloc [gdb_get_line_number "LONG LONG FUNC" "$srcfile"] +gdb_test "break long_long_func" \ + "Breakpoint $decimal at .* line $breakloc\." \ + "set breakpoint on long_long_func" +gdb_continue_to_breakpoint "long_long_func" ".*/$srcfile:$breakloc.*" + +set test_msg "finish from long_long_func" +gdb_test_multiple "finish" "$test_msg" { + -re " long_checkpoint .*$gdb_prompt $" { + send_gdb "step\n" + exp_continue + } + -re " long_long_checkpoint .*$gdb_prompt $" { + pass "$test_msg" + } +} + + +### +### +### + +# Now switch to reverse +gdb_test "set exec-dir reverse" "" "set reverse execution" + +# Test reverse finish from long long func + +set breakloc [gdb_get_line_number "LONG LONG FUNC" "$srcfile"] +gdb_continue_to_breakpoint "long_long_func" ".*/$srcfile:$breakloc.*" + +set test_msg "reverse finish from long_long_func" +gdb_test_multiple "finish" "$test_msg" { + -re ".* long_checkpoint.*$gdb_prompt $" { + test_start_of_line "long_checkpoint" "$test_msg" + } +} + +# Test reverse finish from long func + +set breakloc [gdb_get_line_number "LONG FUNC" "$srcfile"] +gdb_continue_to_breakpoint "long_func" ".*/$srcfile:$breakloc.*" + +set test_msg "reverse finish from long_func" +gdb_test_multiple "finish" "$test_msg" { + -re ".* int_checkpoint.*$gdb_prompt $" { + test_start_of_line "int_checkpoint" "$test_msg" + } +} + +# Test reverse finish from int func + +set breakloc [gdb_get_line_number "INT FUNC" "$srcfile"] +gdb_continue_to_breakpoint "int_func" ".*/$srcfile:$breakloc.*" + +set test_msg "reverse finish from int_func" +gdb_test_multiple "finish" "$test_msg" { + -re ".* short_checkpoint.*$gdb_prompt $" { + test_start_of_line "short_checkpoint" "$test_msg" + } +} + +# Test reverse finish from short func + +set breakloc [gdb_get_line_number "SHORT FUNC" "$srcfile"] +gdb_continue_to_breakpoint "short_func" ".*/$srcfile:$breakloc.*" + +set test_msg "reverse finish from short_func" +gdb_test_multiple "finish" "$test_msg" { + -re ".* char_checkpoint.*$gdb_prompt $" { + test_start_of_line "char_checkpoint" "$test_msg" + } +} + +# Test reverse finish from char func + +set breakloc [gdb_get_line_number "CHAR FUNC" "$srcfile"] +gdb_continue_to_breakpoint "char_func" ".*/$srcfile:$breakloc.*" + +set test_msg "reverse finish from char_func" +gdb_test_multiple "finish" "$test_msg" { + -re ".* void_checkpoint.*$gdb_prompt $" { + test_start_of_line "void_checkpoint" "$test_msg" + } +} + +# Test reverse finish from void func + +set breakloc [gdb_get_line_number "VOID FUNC" "$srcfile"] +gdb_continue_to_breakpoint "void_func" ".*/$srcfile:$breakloc.*" + +set test_msg "reverse finish from void_func" +gdb_test_multiple "finish" "$test_msg" { + -re ".* call to void_func.*$gdb_prompt $" { + test_start_of_line "call to void_func" "$test_msg" + } +} + +return 0 diff --git a/gdb/testsuite/gdb.reverse/machinestate.c b/gdb/testsuite/gdb.reverse/machinestate.c new file mode 100644 index 00000000000..8eb459597e9 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/machinestate.c @@ -0,0 +1,101 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009 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 . */ + +/* + * Test restoration of machine state + */ + +extern void hide (int); + +/* Test register variable + Requires -- compiler honors 'register'. */ + +void +register_state (void) +{ + register int a = 0; + + hide (a); /* External function to defeat optimization. */ + a++; /* register_state: set breakpoint here */ + hide (a); /* register post-change */ +} + +/* Test auto variable (whatever that means). */ + +void +auto_state (void) +{ + auto int a = 0; + + hide (a); /* External function to defeat optimization. */ + a++; /* auto_state: set breakpoint here */ + hide (a); /* auto post-change */ +} + +/* Test function-static variable. */ + +void +function_static_state (void) +{ + static int a = 0; + + hide (a); /* External function to defeat optimization. */ + a++; /* function_static_state: set breakpoint here */ + hide (a); /* function static post-change */ +} + +/* Test module-static variable. */ + +static int astatic; + +void +module_static_state (void) +{ + astatic = 0; + + hide (astatic); /* External function to defeat optimization. */ + astatic++; /* module_static_state: set breakpoint here */ + hide (astatic); /* module static post-change */ +} + +/* Test module-global variable. */ + +int aglobal; + +void +module_global_state (void) +{ + aglobal = 0; + + hide (aglobal); /* External function to defeat optimization. */ + aglobal++; /* module_global_state: set breakpoint here */ + hide (aglobal); /* module global post-change */ +} + +/* main test driver */ + +int +main (int argc, char **argv) +{ + register_state (); /* begin main */ + auto_state (); + function_static_state (); + module_static_state (); + module_global_state (); + + return 0; /* end main */ +} diff --git a/gdb/testsuite/gdb.reverse/machinestate.exp b/gdb/testsuite/gdb.reverse/machinestate.exp new file mode 100644 index 00000000000..97faf2a670c --- /dev/null +++ b/gdb/testsuite/gdb.reverse/machinestate.exp @@ -0,0 +1,230 @@ +# Copyright 2008, 2009 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 . + +# This file is part of the GDB testsuite. +# This test tests the restoration of various kinds of machine state +# to their original values by reverse execution. We will execute +# the program forward while it changes various types of data, and +# then execute it backward to see if their values get restored. +# +# The types of machine state (data) that are tested are: +# register variable +# auto variable +# function static variable +# module static variable +# module global variable +# +# TODO: +# various, possibly including... +# .bss variable, .data variable, ... +# shared library variable +# heap variable (pointer)... +# overlay variables... +# Test forward replay +# + +if ![target_info exists gdb,can_reverse] { + return +} + +set testfile "machinestate" +set srcfile ${testfile}.c +set srcfile1 ms1.c + +if { [prepare_for_testing $testfile.exp $testfile {machinestate.c ms1.c} ] } { + return -1 +} + +set newline "\[\r\n\]+" + +set beginmain [gdb_get_line_number " begin main " $srcfile] +set endmain [gdb_get_line_number " end main " $srcfile] + +# Test begins + +runto main + +if [target_info exists gdb,use_precord] { + # Activate process record/replay + gdb_test "record" "" "Turn on process record" + # FIXME: command ought to acknowledge, so we can test if it succeeded. +} + +# Proceed to end of main + +gdb_test "break $endmain" \ + "Breakpoint.* file .*/$srcfile, line $endmain.*" "" +gdb_continue_to_breakpoint "end of main" ".*/$srcfile:$endmain.*" + +### +### +### + +# Now run backward to each of several points where data is changed. +# + +# Module global variable, reverse + +set breakloc [gdb_get_line_number \ + "module_global_state: set breakpoint here" $srcfile] + +gdb_test "tbreak $breakloc" ".*/$srcfile, line $breakloc.*" "" +gdb_test "reverse-continue" ".*/$srcfile:$breakloc.*" "reverse to $breakloc" + +gdb_test "print aglobal" ".* = 0$newline" "module global reverse-breakpoint" +gdb_test "step" ".* module global post-change .*" "" +gdb_test "print aglobal" ".* = 1$newline" "module global forward past bp" +gdb_test "reverse-step" ".*$newline$breakloc.*" "" +gdb_test "print aglobal" ".* = 0$newline" "module global reverse-step to bp" + + +# Module static variable, reverse + +set breakloc [gdb_get_line_number \ + "module_static_state: set breakpoint here" $srcfile] + +gdb_test "tbreak $breakloc" ".*/$srcfile, line $breakloc.*" "" +gdb_test "reverse-continue" ".*/$srcfile:$breakloc.*" "reverse to $breakloc" + +gdb_test "print astatic" ".* = 0$newline" "module static reverse-breakpoint" +gdb_test "step" ".* module static post-change .*" "" +gdb_test "print astatic" ".* = 1$newline" "module static forward" +gdb_test "reverse-step" ".*$newline$breakloc.*" "" +gdb_test "print astatic" ".* = 0$newline" "module static reverse-step" + +# Function static variable, reverse + +set breakloc [gdb_get_line_number \ + "function_static_state: set breakpoint here" $srcfile] + +gdb_test "tbreak $breakloc" ".*/$srcfile, line $breakloc.*" "" +gdb_test "reverse-continue" ".*/$srcfile:$breakloc.*" "reverse to $breakloc" + +gdb_test "print a" ".* = 0$newline" "function static reverse-breakpoint" +gdb_test "step" ".* function static post-change .*" "" +gdb_test "print a" ".* = 1$newline" "function static forward" +gdb_test "reverse-step" ".*$newline$breakloc.*" "" +gdb_test "print a" ".* = 0$newline" "function static reverse-step" + +# Auto variable, reverse + +set breakloc [gdb_get_line_number \ + "auto_state: set breakpoint here" $srcfile] + +gdb_test "tbreak $breakloc" ".*/$srcfile, line $breakloc.*" "" +gdb_test "reverse-continue" ".*/$srcfile:$breakloc.*" "reverse to $breakloc" + +gdb_test "print a" ".* = 0$newline" "auto var reverse-breakpoint" +gdb_test "step" ".* auto post-change .*" "" +gdb_test "print a" ".* = 1$newline" "auto var forward" +gdb_test "reverse-step" ".*$newline$breakloc.*" "" +gdb_test "print a" ".* = 0$newline" "auto var reverse-step" + +# Register variable, reverse + +set breakloc [gdb_get_line_number \ + "register_state: set breakpoint here" $srcfile] + +gdb_test "tbreak $breakloc" ".*/$srcfile, line $breakloc.*" "" +gdb_test "reverse-continue" ".*/$srcfile:$breakloc.*" "reverse to $breakloc" + +gdb_test "print a" ".* = 0$newline" "register var reverse-breakpoint" +gdb_test "step" ".* register post-change .*" "" +gdb_test "print a" ".* = 1$newline" "register var step post-change" +gdb_test "reverse-step" ".*$newline$breakloc.*" "" +gdb_test "print a" ".* = 0$newline" "register var reverse step-to" + +# Proceed to beginning of main + +gdb_test "tbreak $beginmain" ".*/$srcfile, line $beginmain.*" "" +gdb_test "reverse-continue" ".*/$srcfile:$beginmain.*" "reverse to main" + +# Now repeat tests while replaying forward. + +# Register variable, forward + +set breakloc [gdb_get_line_number \ + "register_state: set breakpoint here" $srcfile] + +gdb_test "tbreak $breakloc" ".*/$srcfile, line $breakloc.*" "" +gdb_test "continue" ".*/$srcfile:$breakloc.*" "forward to $breakloc" + +gdb_test "print a" ".* = 0$newline" "register var forward-breakpoint" +gdb_test "reverse-step" ".*hide.*" "" +gdb_test "step" ".*$newline$breakloc.*" "" +gdb_test "print a" ".* = 0$newline" "register var forward step-to" +gdb_test "step" ".* register post-change .*" "" +gdb_test "print a" ".* = 1$newline" "register var step post-change" + +# Auto variable, forward + +set breakloc [gdb_get_line_number \ + "auto_state: set breakpoint here" $srcfile] + +gdb_test "tbreak $breakloc" ".*/$srcfile, line $breakloc.*" "" +gdb_test "continue" ".*/$srcfile:$breakloc.*" "forward to $breakloc" + +gdb_test "print a" ".* = 0$newline" "auto var forward-breakpoint" +gdb_test "reverse-step" ".*hide.*" "" +gdb_test "step" ".*$newline$breakloc.*" "" +gdb_test "print a" ".* = 0$newline" "auto var forward step-to" +gdb_test "step" ".* auto post-change .*" "" +gdb_test "print a" ".* = 1$newline" "auto var step post-change" + +# Function static variable, forward + +set breakloc [gdb_get_line_number \ + "function_static_state: set breakpoint here" $srcfile] + +gdb_test "tbreak $breakloc" ".*/$srcfile, line $breakloc.*" "" +gdb_test "continue" ".*/$srcfile:$breakloc.*" "forward to $breakloc" + +gdb_test "print a" ".* = 0$newline" "function static forward-breakpoint" +gdb_test "reverse-step" ".*hide.*" "" +gdb_test "step" ".*$newline$breakloc.*" "" +gdb_test "print a" ".* = 0$newline" "function static forward step-to" +gdb_test "step" ".* function static post-change .*" "" +gdb_test "print a" ".* = 1$newline" "function static step post-change" + +# Module static variable, forward + +set breakloc [gdb_get_line_number \ + "module_static_state: set breakpoint here" $srcfile] + +gdb_test "tbreak $breakloc" ".*/$srcfile, line $breakloc.*" "" +gdb_test "continue" ".*/$srcfile:$breakloc.*" "forward to $breakloc" + +gdb_test "print astatic" ".* = 0$newline" "module static forward-breakpoint" +gdb_test "reverse-step" ".*hide.*" "" +gdb_test "step" ".*$newline$breakloc.*" "" +gdb_test "print astatic" ".* = 0$newline" "module static forward step-to" +gdb_test "step" ".* module static post-change .*" "" +gdb_test "print astatic" ".* = 1$newline" "module static step post-change" + +# Module global variable, forward + +set breakloc [gdb_get_line_number \ + "module_global_state: set breakpoint here" $srcfile] + +gdb_test "tbreak $breakloc" ".*/$srcfile, line $breakloc.*" "" +gdb_test "continue" ".*/$srcfile:$breakloc.*" "forward to $breakloc" + +gdb_test "print aglobal" ".* = 0$newline" "module global forward-breakpoint" +gdb_test "reverse-step" ".*hide.*" "" +gdb_test "step" ".*$newline$breakloc.*" "" +gdb_test "print aglobal" ".* = 0$newline" "module global forward step-to" +gdb_test "step" ".* module global post-change .*" "" +gdb_test "print aglobal" ".* = 1$newline" "module global step post-change" + diff --git a/gdb/testsuite/gdb.reverse/ms1.c b/gdb/testsuite/gdb.reverse/ms1.c new file mode 100644 index 00000000000..435ff12bd66 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/ms1.c @@ -0,0 +1,25 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008 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 . */ + +/* + * Aux function for machine state test. + */ + +void +hide (int x) +{ +} diff --git a/gdb/testsuite/gdb.reverse/shr2.c b/gdb/testsuite/gdb.reverse/shr2.c new file mode 100644 index 00000000000..1aa3ff335b8 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/shr2.c @@ -0,0 +1,34 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009 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 . */ + +#ifdef PROTOTYPES +int shr2(int x) +#else +int shr2(x) int x; +#endif +{ + return 2*x; +} + +#ifdef PROTOTYPES +int shr2_local(int x) +#else +int shr2_local(x) int x; +#endif +{ + return 2*x; +} diff --git a/gdb/testsuite/gdb.reverse/solib-reverse.c b/gdb/testsuite/gdb.reverse/solib-reverse.c new file mode 100644 index 00000000000..cf96ee941a4 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/solib-reverse.c @@ -0,0 +1,43 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009 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 . */ + +/* Test reverse debugging of shared libraries. */ + +#include + +/* Shared library function */ +extern int shr2(int); + +int main () +{ + char* cptr = "String 1"; + int b[2] = {5,8}; + + b[0] = shr2(12); /* begin part two */ + b[1] = shr2(17); /* middle part two */ + + b[0] = 6; b[1] = 9; /* generic statement, end part two */ + printf ("message 1\n"); /* printf one */ + printf ("message 2\n"); /* printf two */ + printf ("message 3\n"); /* printf three */ + sleep (0); /* sleep one */ + sleep (0); /* sleep two */ + sleep (0); /* sleep three */ + + return 0; /* end part one */ +} + diff --git a/gdb/testsuite/gdb.reverse/solib-reverse.exp b/gdb/testsuite/gdb.reverse/solib-reverse.exp new file mode 100644 index 00000000000..8ad2be8b8da --- /dev/null +++ b/gdb/testsuite/gdb.reverse/solib-reverse.exp @@ -0,0 +1,124 @@ +# Copyright 2009 +# 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 . + +# This file is part of the GDB testsuite. It tests reverse debugging +# with shared libraries. + +if ![target_info exists gdb,can_reverse] { + return +} + +set testfile "solib-reverse" +set srcfile ${testfile}.c +set libfile "shr2" +set libsrc ${libfile}.c +set library ${objdir}/${subdir}/${libfile}.sl +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile}] { + return -1 +} + +if { [gdb_compile_shlib ${srcdir}/${subdir}/${libsrc} ${library} "debug"] != "" } { + untested "Could not compile shared library." + return -1 +} + +set exec_opts [list debug shlib=${library}] + +if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable $exec_opts] != "" } { + untested "Could not compile $binfile." + return -1 +} + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + +runto main + +if [target_info exists gdb,use_precord] { + # Activate process record/replay + gdb_test "record" "" "Turn on process record" + # FIXME: command ought to acknowledge, so we can test if it succeeded. +} + +# +# Test reverse-step over undebuggable solib functions. +# + +# Run forward past some solib function calls. + +set end_part_one [gdb_get_line_number " end part one" "$srcfile"] +set end_part_two [gdb_get_line_number " end part two" "$srcfile"] +gdb_test "until $end_part_one" " end part one.*" "run until end part one" + +gdb_test "reverse-step" " sleep three .*" "reverse-step third sleep" +gdb_test "reverse-step" " sleep two .*" "reverse-step second sleep" +gdb_test "reverse-step" " sleep one .*" \ + "reverse-step first sleep, dynsym resolve" + +gdb_test "reverse-step" " printf three .*" "reverse-step third printf" +gdb_test "reverse-step" " printf two .*" "reverse-step second printf" +gdb_test "reverse-step" " printf one .*" \ + "reverse-step first printf, dynsym resolve" +gdb_test "reverse-step" " generic statement.*" "reverse-step generic" + + +# +# Test reverse-next over undebuggable solib functions. +# + +# Run forward again... + +gdb_test "until $end_part_one" " end part one.*" "forward to end part one" + +gdb_test "reverse-next" " sleep three .*" "reverse-next third sleep" +gdb_test "reverse-next" " sleep two .*" "reverse-next second sleep" +gdb_test "reverse-next" " sleep one .*" \ + "reverse-next first sleep, dynsym resolve" + +gdb_test "reverse-next" " printf three .*" "reverse-next third printf" +gdb_test "reverse-next" " printf two .*" "reverse-next second printf" +gdb_test "reverse-next" " printf one .*" \ + "reverse-next first printf, dynsym resolve" +gdb_test "reverse-next" " generic statement.*" "reverse-next generic" + + +# +# Test reverse-step into debuggable solib function +# + +gdb_test "reverse-step" "${libsrc}.*" "reverse-step into solib function one" +gdb_test "reverse-step" "return 2.x.*" "reverse-step within solib function one" +gdb_test "reverse-step" " middle part two.*" "reverse-step back to main one" + +gdb_test "reverse-step" "${libsrc}.*" "reverse-step into solib function two" +gdb_test "reverse-step" "return 2.x.*" "reverse-step within solib function two" +gdb_test "reverse-step" " begin part two.*" "reverse-step back to main two" + +# +# Test reverse-next over debuggable solib function +# + +gdb_test "until $end_part_two" " end part two.*" "run until end part two" + +gdb_test "reverse-next" " middle part two.*" "reverse-next over solib function one" +gdb_test "reverse-next" " begin part two.*" "reverse-next over solib function two" diff --git a/gdb/testsuite/gdb.reverse/step-reverse.c b/gdb/testsuite/gdb.reverse/step-reverse.c new file mode 100644 index 00000000000..1584bd2d5a5 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/step-reverse.c @@ -0,0 +1,78 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009 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 +#include + +/* Test various kinds of stepping. +*/ +int myglob = 0; + +int callee() { /* ENTER CALLEE */ + myglob++; return 0; /* ARRIVED IN CALLEE */ +} /* RETURN FROM CALLEE */ + +/* A structure which, we hope, will need to be passed using memcpy. */ +struct rhomboidal { + int rather_large[100]; +}; + +void +large_struct_by_value (struct rhomboidal r) +{ + myglob += r.rather_large[42]; /* step-test.exp: arrive here 1 */ +} + +int main () { + int w,x,y,z; + int a[10], b[10]; + + /* Test "next" and "step" */ + w = 0; /* BREAK AT MAIN */ + x = 1; /* NEXT TEST 1 */ + y = 2; /* STEP TEST 1 */ + z = 3; /* REVERSE NEXT TEST 1 */ + w = w + 2; /* NEXT TEST 2 */ + x = x + 3; /* REVERSE STEP TEST 1 */ + y = y + 4; + z = z + 5; /* STEP TEST 2 */ + + /* Test that "next" goes over a call */ + callee(); /* NEXT OVER THIS CALL */ + + /* Test that "step" doesn't */ + callee(); /* STEP INTO THIS CALL */ + + /* Test "stepi" */ + a[5] = a[3] - a[4]; /* FINISH TEST */ + callee(); /* STEPI TEST */ + + /* Test "nexti" */ + callee(); /* NEXTI TEST */ + + y = w + z; + + { + struct rhomboidal r; + memset (r.rather_large, 0, sizeof (r.rather_large)); + r.rather_large[42] = 10; + large_struct_by_value (r); /* step-test.exp: large struct by value */ + } + + exit (0); +} + diff --git a/gdb/testsuite/gdb.reverse/step-reverse.exp b/gdb/testsuite/gdb.reverse/step-reverse.exp new file mode 100644 index 00000000000..050b75058a6 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/step-reverse.exp @@ -0,0 +1,251 @@ +# Copyright 2008, 2009 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 . */ + +# This file is part of the GDB testsuite. It tests reverse stepping. +# Lots of code borrowed from "step-test.exp". + +# +# Test step and next in reverse +# + +if ![target_info exists gdb,can_reverse] { + return +} + +set testfile "step-reverse" +set srcfile ${testfile}.c + +if { [prepare_for_testing $testfile.exp $testfile $srcfile] } { + return -1 +} + +runto main + +if [target_info exists gdb,use_precord] { + # Activate process record/replay + gdb_test "record" "" "Turn on process record" + # FIXME: command ought to acknowledge, so we can test if it succeeded. +} + +# plain vanilla step/next (no count) + +gdb_test "next" ".*NEXT TEST 1.*" "next test 1" +gdb_test "step" ".*STEP TEST 1.*" "step test 1" + +# step/next with count + +gdb_test "next 2" ".*NEXT TEST 2.*" "next test 2" +gdb_test "step 3" ".*STEP TEST 2.*" "step test 2" + +# step over call + +gdb_test "step" ".*NEXT OVER THIS CALL.*" "step up to call" +gdb_test "next" ".*STEP INTO THIS CALL.*" "next over call" + +# step into call + +gdb_test "step" ".*ARRIVED IN CALLEE.*" "step into call" + +# finish out of call + +set test_message "finish out of fn call" +gdb_test_multiple "finish" "$test_message" { + -re "FINISH TEST.*$gdb_prompt $" { + pass "$test_message" + } + -re "STEP INTO THIS CALL.*$gdb_prompt $" { + send_gdb "step\n" + exp_continue + } +} + +# stepi over flat code (no calls) + +set test_message "simple stepi" +gdb_test_multiple "stepi" "$test_message" { + -re "STEPI TEST.*$gdb_prompt $" { + pass "$test_message" + } + -re "FINISH TEST.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "NEXTI TEST.*$gdb_prompt $" { + fail "$test_message (too far)" + } +} + +# stepi into a function call + +set test_message "stepi into function call" +gdb_test_multiple "stepi" "$test_message" { + -re "ARRIVED IN CALLEE.*$gdb_prompt $" { + pass "$test_message" + } + -re "NEXTI TEST.*$gdb_prompt $" { + fail "$test_message (too far)" + } + -re "RETURN FROM CALLEE.*$gdb_prompt $" { + fail "$test_message (too far)" + } + -re "ENTER CALLEE.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } +} + +# stepi thru return of a function call + +set test_message "stepi back from function call" +gdb_test_multiple "stepi" "$test_message" { + -re "NEXTI TEST.*$gdb_prompt $" { + pass "$test_message" + } + -re "ARRIVED IN CALLEE.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "RETURN FROM CALLEE.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "STEPI TEST.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "ENTER CALLEE.*$gdb_prompt $" { + fail "$test_message (too far)" + } +} + +### +### +### + +# Set reverse execution direction +# FIXME: command needs to acknowledge, so we can test if it succeeded. + +gdb_test "set exec-dir reverse" "" "set reverse execution" + +# stepi backward thru return and into a function + +set stepi_location [gdb_get_line_number "ARRIVED IN CALLEE" "$srcfile"] +set test_message "reverse stepi thru function return" +gdb_test_multiple "stepi" "$test_message" { + -re "NEXTI TEST.*$gdb_prompt $" { + fail "$test_message (start statement)" + } + -re "RETURN FROM CALLEE.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "$hex\[ \t\]*$stepi_location.*ARRIVED IN CALLEE.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "ARRIVED IN CALLEE.*$gdb_prompt $" { + pass "$test_message" + } + -re "ENTER CALLEE.*$gdb_prompt $" { + fail "$test_message (too far)" + } + -re "STEPI TEST.*$gdb_prompt $" { + fail "$test_message (too far)" + } +} + +# stepi backward out of a function call + +set stepi_location [gdb_get_line_number "FINISH TEST" "$srcfile"] +set test_message "reverse stepi from a function call" +gdb_test_multiple "stepi" "$test_message" { + -re "ARRIVED IN CALLEE.*$gdb_prompt $" { + fail "$test_message (start statement)" + } + -re "ENTER CALLEE.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "${hex}\[ \t\]*$stepi_location.*STEPI TEST.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "STEPI TEST.*$gdb_prompt $" { + pass "$test_message" + } + -re "STEP INTO THIS CALL.*$gdb_prompt $" { + fail "$test_message (too far)" + } +} + +# stepi backward over flat code (no calls) + +set stepi_location [gdb_get_line_number "FINISH TEST" "$srcfile"] +set test_message "simple reverse stepi" +gdb_test_multiple "stepi" "$test_message" { + -re "STEPI TEST.*$gdb_prompt $" { + fail "$test_message (start statement)" + } + -re "$hex\[ \t\]*$stepi_location.* FINISH TEST.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "$stepi_location.* FINISH TEST.*$gdb_prompt $" { + pass "$test_message" + } + -re "STEP INTO THIS CALL.*$gdb_prompt $" { + fail "$test_message (too far)" + } +} + +# step backward into function (thru return) + +set test_message "reverse step into fn call" +gdb_test_multiple "step" "$test_message" { + -re "RETURN FROM CALLEE.*$gdb_prompt $" { + send_gdb "step\n" + exp_continue + } + -re "ARRIVED IN CALLEE.*$gdb_prompt $" { + pass "$test_message" + } +} + +# step backward out of called function (thru call) + +gdb_test "step" ".*STEP INTO THIS CALL.*" "reverse step out of called fn" + +# next backward over call + +gdb_test "next" ".*NEXT OVER THIS CALL.*" "reverse next over call" + +# step/next backward with count + +gdb_test "step 3" ".*REVERSE STEP TEST 1.*" "reverse step test 1" +gdb_test "next 2" ".*REVERSE NEXT TEST 1.*" "reverse next test 1" + +# step/next backward without count + +gdb_test "step" ".*STEP TEST 1.*" "reverse step test 2" +gdb_test "next" ".*NEXT TEST 1.*" "reverse next test 2" + + + +# Finish test by running forward to the end. +# FIXME return to this later... +# gdb_test "set exec-dir forward" "" "set forward execution" +# gdb_continue_to_end "step-reverse.exp" + +return 0 diff --git a/gdb/testsuite/gdb.reverse/until-reverse.c b/gdb/testsuite/gdb.reverse/until-reverse.c new file mode 100644 index 00000000000..b1d1d3b3674 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/until-reverse.c @@ -0,0 +1,146 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009 + 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 . */ + +#ifdef vxworks + +# include + +/* VxWorks does not supply atoi. */ +static int +atoi (z) + char *z; +{ + int i = 0; + + while (*z >= '0' && *z <= '9') + i = i * 10 + (*z++ - '0'); + return i; +} + +/* I don't know of any way to pass an array to VxWorks. This function + can be called directly from gdb. */ + +vxmain (arg) +char *arg; +{ + char *argv[2]; + + argv[0] = ""; + argv[1] = arg; + main (2, argv, (char **) 0); +} + +#else /* ! vxworks */ +# include +# include +#endif /* ! vxworks */ + +#ifdef PROTOTYPES +extern int marker1 (void); +extern int marker2 (int a); +extern void marker3 (char *a, char *b); +extern void marker4 (long d); +#else +extern int marker1 (); +extern int marker2 (); +extern void marker3 (); +extern void marker4 (); +#endif + +/* + * This simple classical example of recursion is useful for + * testing stack backtraces and such. + */ + +#ifdef PROTOTYPES +int factorial(int); + +int +main (int argc, char **argv, char **envp) +#else +int +main (argc, argv, envp) +int argc; +char *argv[], **envp; +#endif +{ +#ifdef usestubs + set_debug_traps(); /* set breakpoint 5 here */ + breakpoint(); +#endif + if (argc == 12345) { /* an unlikely value < 2^16, in case uninited */ /* set breakpoint 6 here */ + fprintf (stderr, "usage: factorial \n"); + return 1; + } + printf ("%d\n", factorial (atoi ("6"))); /* set breakpoint 1 here */ + /* set breakpoint 12 here */ + marker1 (); /* set breakpoint 11 here */ + marker2 (43); /* set breakpoint 20 here */ + marker3 ("stack", "trace"); /* set breakpoint 21 here */ + marker4 (177601976L); + /* We're used by a test that requires malloc, so make sure it is + in the executable. */ + (void)malloc (1); + + argc = (argc == 12345); /* This is silly, but we can step off of it */ /* set breakpoint 2 here */ + return argc; /* set breakpoint 10 here */ +} /* set breakpoint 10a here */ + +#ifdef PROTOTYPES +int factorial (int value) +#else +int factorial (value) +int value; +#endif +{ + if (value > 1) { /* set breakpoint 7 here */ + value *= factorial (value - 1); + } + return (value); /* set breakpoint 19 here */ +} + +#ifdef PROTOTYPES +int multi_line_if_conditional (int a, int b, int c) +#else +int multi_line_if_conditional (a, b, c) + int a, b, c; +#endif +{ + if (a /* set breakpoint 3 here */ + && b + && c) + return 0; + else + return 1; +} + +#ifdef PROTOTYPES +int multi_line_while_conditional (int a, int b, int c) +#else +int multi_line_while_conditional (a, b, c) + int a, b, c; +#endif +{ + while (a /* set breakpoint 4 here */ + && b + && c) + { + a--, b--, c--; + } + return 0; +} diff --git a/gdb/testsuite/gdb.reverse/until-reverse.exp b/gdb/testsuite/gdb.reverse/until-reverse.exp new file mode 100644 index 00000000000..6667fa24574 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/until-reverse.exp @@ -0,0 +1,129 @@ +# Copyright 2008, 2009 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 . */ + +# This file is part of the GDB testsuite. It tests 'until' and +# 'advance' in reverse debugging. + +if ![target_info exists gdb,can_reverse] { + return +} + +set testfile "until-reverse" +set srcfile ${testfile}.c +set srcfile1 ur1.c + +if { [prepare_for_testing $testfile.exp $testfile {until-reverse.c ur1.c} ] } { + return -1 +} + +set bp_location1 [gdb_get_line_number "set breakpoint 1 here"] +set bp_location7 [gdb_get_line_number "set breakpoint 7 here"] +set bp_location9 [gdb_get_line_number "set breakpoint 9 here" "$srcfile1"] +set bp_location19 [gdb_get_line_number "set breakpoint 19 here"] +set bp_location20 [gdb_get_line_number "set breakpoint 20 here"] +set bp_location21 [gdb_get_line_number "set breakpoint 21 here"] + +runto main + +if [target_info exists gdb,use_precord] { + # Activate process record/replay + gdb_test "record" "" "Turn on process record" + # FIXME: command ought to acknowledge, so we can test if it succeeded. +} + +# Verify that plain vanilla "until " works. +# +gdb_test "until $bp_location1" \ + "main .* at .*:$bp_location1.*" \ + "until line number" + +# Advance up to factorial, outer invocation +# +gdb_test "advance factorial" \ + "factorial .value=6..*$srcfile:$bp_location7.*" \ + "advance to factorial" + +# At this point, 'until' should continue the inferior up to when all the +# inner invocations of factorial() are completed and we are back at this +# frame. +# +gdb_test "until $bp_location19" \ + "factorial .value=720.*${srcfile}:$bp_location19.*" \ + "until factorial, recursive function" + +# Finish out to main scope +# +gdb_test "finish" \ + " in main .*$srcfile:$bp_location1.*" \ + "finish to main" + +# Advance to a function called by main (marker2) +# +gdb_test "advance marker2" \ + "marker2 .a=43.*$srcfile1:$bp_location9.*" \ + "advance to marker2" + +# Now issue an until with another function, not called by the current +# frame, as argument. This should not work, i.e. the program should +# stop at main, the caller, where we put the 'guard' breakpoint. +# +set test_msg "until func, not called by current frame" +gdb_test_multiple "until marker3" "$test_msg" { + -re "main .*at .*${srcfile}:$bp_location20.*$gdb_prompt $" { + pass "$test_msg" + } + -re "main .*at .*${srcfile}:$bp_location21.*$gdb_prompt $" { + pass "$test_msg" + } +} + +### +### +### + +# Set reverse execution direction +# FIXME: command needs to acknowledge, so we can test if it succeeded. + +gdb_test "set exec-dir reverse" "" "set reverse execution" + +# +# We should now be at main, after the return from marker2. +# "Advance" backward into marker2. +# + +gdb_test "advance marker2" \ + "marker2 .a=43.*$srcfile1:$bp_location9.*" \ + "reverse-advance to marker2" + +# Finish out to main scope (backward) + +gdb_test "finish" \ + " in main .*$srcfile:$bp_location20.*" \ + "reverse-finish from marker2" + +# Advance backward to last line of factorial (outer invocation) + +gdb_test "advance $bp_location19" \ + "factorial .value=720.*${srcfile}:$bp_location19.*" \ + "reverse-advance to final return of factorial" + +# Now do "until" across the recursive calls, +# ending up in the same frame where we are now. + +gdb_test "until $bp_location7" \ + "factorial .value=6..*$srcfile:$bp_location7.*" \ + "reverse-until to entry of factorial" + + diff --git a/gdb/testsuite/gdb.reverse/ur1.c b/gdb/testsuite/gdb.reverse/ur1.c new file mode 100644 index 00000000000..dc8bef42847 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/ur1.c @@ -0,0 +1,49 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 1992, 1993, 1994, 1995, 1999, 2002, 2003, 2007, 2008 + 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 . */ + +/* The code for this file was extracted from the gdb testsuite + testcase "break.c". */ + +/* The following functions do nothing useful. They are included + simply as places to try setting breakpoints at. They are + explicitly "one-line functions" to verify that this case works + (some versions of gcc have or have had problems with this). + + These functions are in a separate source file to prevent an + optimizing compiler from inlining them and optimizing them away. */ + +#ifdef PROTOTYPES +int marker1 (void) { return (0); } /* set breakpoint 15 here */ +int marker2 (int a) { return (1); } /* set breakpoint 8 here */ +void marker3 (char *a, char *b) {} /* set breakpoint 17 here */ +void marker4 (long d) {} /* set breakpoint 14 here */ +#else +int marker1 () { return (0); } /* set breakpoint 16 here */ +int marker2 (a) int a; { return (1); } /* set breakpoint 9 here */ +void marker3 (a, b) char *a, *b; {} /* set breakpoint 18 here */ +void marker4 (d) long d; {} /* set breakpoint 13 here */ +#endif + +/* A structure we use for field name completion tests. */ +struct some_struct +{ + int a_field; + int b_field; +}; + +struct some_struct values[50]; diff --git a/gdb/testsuite/gdb.reverse/watch-reverse.c b/gdb/testsuite/gdb.reverse/watch-reverse.c new file mode 100644 index 00000000000..e487f2cda53 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/watch-reverse.c @@ -0,0 +1,219 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008, 2009 + 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 +#include +/* + * Since using watchpoints can be very slow, we have to take some pains to + * ensure that we don't run too long with them enabled or we run the risk + * of having the test timeout. To help avoid this, we insert some marker + * functions in the execution stream so we can set breakpoints at known + * locations, without worrying about invalidating line numbers by changing + * this file. We use null bodied functions are markers since gdb does + * not support breakpoints at labeled text points at this time. + * + * One place we need is a marker for when we start executing our tests + * instructions rather than any process startup code, so we insert one + * right after entering main(). Another is right before we finish, before + * we start executing any process termination code. + * + * Another problem we have to guard against, at least for the test + * suite, is that we need to ensure that the line that causes the + * watchpoint to be hit is still the current line when gdb notices + * the hit. Depending upon the specific code generated by the compiler, + * the instruction after the one that triggers the hit may be part of + * the same line or part of the next line. Thus we ensure that there + * are always some instructions to execute on the same line after the + * code that should trigger the hit. + */ + +int count = -1; +int ival1 = -1; +int ival2 = -1; +int ival3 = -1; +int ival4 = -1; +int ival5 = -1; +char buf[10]; +struct foo +{ + int val; +}; +struct foo struct1, struct2, *ptr1, *ptr2; + +int doread = 0; + +char *global_ptr; + +void marker1 () +{ +} + +void marker2 () +{ +} + +void marker4 () +{ +} + +void marker5 () +{ +} + +void marker6 () +{ +} + +#ifdef PROTOTYPES +void recurser (int x) +#else +void recurser (x) int x; +#endif +{ + int local_x; + + if (x > 0) + recurser (x-1); + local_x = x; +} + +void +func2 () +{ + int local_a; + static int static_b; + + ival5++; + local_a = ival5; + static_b = local_a; +} + +void +func3 () +{ + int x; + int y; + + x = 0; + x = 1; /* second x assignment */ + y = 1; + y = 2; +} + +int +func1 () +{ + /* The point of this is that we will set a breakpoint at this call. + + Then, if DECR_PC_AFTER_BREAK equals the size of a function call + instruction (true on a sun3 if this is gcc-compiled--FIXME we + should use asm() to make it work for any compiler, present or + future), then we will end up branching to the location just after + the breakpoint. And we better not confuse that with hitting the + breakpoint. */ + func2 (); + return 73; +} + +void +func4 () +{ + buf[0] = 3; + global_ptr = buf; + buf[0] = 7; +} + +int main () +{ +#ifdef usestubs + set_debug_traps(); + breakpoint(); +#endif + struct1.val = 1; + struct2.val = 2; + ptr1 = &struct1; + ptr2 = &struct2; + marker1 (); + func1 (); + for (count = 0; count < 4; count++) { + ival1 = count; + ival3 = count; ival4 = count; + } + ival1 = count; /* Outside loop */ + ival2 = count; + ival3 = count; ival4 = count; + marker2 (); + if (doread) + { + static char msg[] = "type stuff for buf now:"; + write (1, msg, sizeof (msg) - 1); + read (0, &buf[0], 5); + } + marker4 (); + + /* We have a watchpoint on ptr1->val. It should be triggered if + ptr1's value changes. */ + ptr1 = ptr2; + + /* This should not trigger the watchpoint. If it does, then we + used the wrong value chain to re-insert the watchpoints or we + are not evaluating the watchpoint expression correctly. */ + struct1.val = 5; + marker5 (); + + /* We have a watchpoint on ptr1->val. It should be triggered if + ptr1's value changes. */ + ptr1 = ptr2; + + /* This should not trigger the watchpoint. If it does, then we + used the wrong value chain to re-insert the watchpoints or we + are not evaluating the watchpoint expression correctly. */ + struct1.val = 5; + marker5 (); + + /* We're going to watch locals of func2, to see that out-of-scope + watchpoints are detected and properly deleted. + */ + marker6 (); + + /* This invocation is used for watches of a single + local variable. */ + func2 (); + + /* This invocation is used for watches of an expression + involving a local variable. */ + func2 (); + + /* This invocation is used for watches of a static + (non-stack-based) local variable. */ + func2 (); + + /* This invocation is used for watches of a local variable + when recursion happens. + */ + marker6 (); + recurser (2); + + marker6 (); + + func3 (); + + func4 (); + + return 0; +} diff --git a/gdb/testsuite/gdb.reverse/watch-reverse.exp b/gdb/testsuite/gdb.reverse/watch-reverse.exp new file mode 100644 index 00000000000..ab9efa89fb6 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/watch-reverse.exp @@ -0,0 +1,127 @@ +# Copyright 2008, 2009 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 . + +# Based on a file written by Fred Fish. (fnf@cygnus.com) +# This file is part of the GDB testsuite. It tests reverse debugging +# with watchpoints. + + +if ![target_info exists gdb,can_reverse] { + return +} + +set testfile "watch-reverse" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [prepare_for_testing $testfile.exp $testfile $srcfile] } { + return -1 +} + +runto main + +if [target_info exists gdb,use_precord] { + # Activate process record/replay + gdb_test "record" "" "Turn on process record" + # FIXME: command ought to acknowledge, so we can test if it succeeded. +} + +# Only software watchpoints can be used in reverse +gdb_test "set can-use-hw-watchpoints 0" "" "" + +gdb_test "break marker1" \ + "Breakpoint $decimal at $hex: file .*$srcfile, line $decimal.*" \ + "set breakpoint at marker1" + +gdb_test "break marker2" \ + "Breakpoint $decimal at $hex: file .*$srcfile, line $decimal.*" \ + "set breakpoint at marker2" + +gdb_continue_to_breakpoint "marker1" ".*/$srcfile:.*" + +gdb_test "watch ival3" \ + ".*\[Ww\]atchpoint $decimal: ival3.*" \ + "set watchpoint on ival3" + +# Continue until first change, from -1 to 0 + +gdb_test "continue" \ + ".*\[Ww\]atchpoint.*ival3.*Old value = -1.*New value = 0.*ival3 = count; ival4 = count;.*" \ + "watchpoint hit, first time" + +# Continue until the next change, from 0 to 1. +gdb_test "continue" \ + ".*\[Ww\]atchpoint.*ival3.*Old value = 0.*New value = 1.*ival3 = count; ival4 = count;.*" \ + "watchpoint hit, second time" + +# Continue until the next change, from 1 to 2. +gdb_test "continue" \ + ".*\[Ww\]atchpoint.*ival3.*Old value = 1.*New value = 2.*ival3 = count; ival4 = count;.*" \ + "watchpoint hit, third time" + +# Continue until the next change, from 2 to 3. +gdb_test "continue" \ + ".*\[Ww\]atchpoint.*ival3.*Old value = 2.*New value = 3.*ival3 = count; ival4 = count;.*" \ + "watchpoint hit, fourth time" + +# Continue until the next change, from 3 to 4. +# Note that this one is outside the loop. + +gdb_test "continue" \ + ".*\[Ww\]atchpoint.*ival3.*Old value = 3.*New value = 4.*ival3 = count; ival4 = count;.*" \ + "watchpoint hit, fifth time" + +# Continue until we hit the finishing marker function. +# Make sure we hit no more watchpoints. + +gdb_continue_to_breakpoint "marker2" ".*/$srcfile:.*" + +### +### +### + +# FIXME 'set exec-dir' command should give some output so we can test. +gdb_test "set exec-direction reverse" "" "set reverse" + +# Reverse until the previous change, from 4 to 3 +# Note that this one is outside the loop + +gdb_test "continue" \ + ".*\[Ww\]atchpoint.*ival3.*Old value = 4.*New value = 3.*ival3 = count; ival4 = count;.*" \ + "watchpoint hit in reverse, first time" + +# Reverse until the previous change, from 3 to 2. +gdb_test "continue" \ + ".*\[Ww\]atchpoint.*ival3.*Old value = 3.*New value = 2.*ival3 = count; ival4 = count;.*" \ + "watchpoint hit in reverse, second time" + +# Reverse until the previous change, from 2 to 1. +gdb_test "continue" \ + ".*\[Ww\]atchpoint.*ival3.*Old value = 2.*New value = 1.*ival3 = count; ival4 = count;.*" \ + "watchpoint hit in reverse, third time" + +# Reverse until the previous change, from 1 to 0. +gdb_test "continue" \ + ".*\[Ww\]atchpoint.*ival3.*Old value = 1.*New value = 0.*ival3 = count; ival4 = count;.*" \ + "watchpoint hit in reverse, fourth time" + +# Reverse until first change, from 0 to -1 + +gdb_test "continue" \ + ".*\[Ww\]atchpoint.*ival3.*Old value = 0.*New value = -1.*ival3 = count; ival4 = count;.*" \ + "watchpoint hit in reverse, fifth time" + + +return 0 -- 2.30.2