| # This testcase is part of GDB, the GNU debugger. |
| |
| # Copyright 1998, 1999, 2000, 2001, 2002, 2004, 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 <http://www.gnu.org/licenses/>. |
| |
| # Test GDB's ability to restore saved registers from stack frames |
| # when using the `return' command. |
| # |
| # This file was written by Jim Blandy <jimb@cygnus.com>, with |
| # fragments borrowed from return.exp. |
| |
| if $tracelevel then { |
| strace $tracelevel |
| } |
| |
| set prms_id 0 |
| set bug_id 0 |
| |
| set testfile "restore" |
| set srcfile ${testfile}.c |
| set binfile ${objdir}/${subdir}/${testfile} |
| if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { |
| untested restore.exp |
| return -1 |
| } |
| |
| proc restore_tests { } { |
| global gdb_prompt |
| |
| if { ! [ runto driver ] } { |
| return 0 |
| } |
| |
| set limit 5 |
| |
| # For each caller function, |
| # call each of the callee functions, |
| # force a return from the callee, and |
| # make sure that the local variables still have the right values. |
| |
| for {set c 1} {$c <= $limit} {incr c} { |
| |
| # Set a breakpoint at the next caller function. |
| gdb_test "tbreak caller$c" "Temporary breakpoint.*\[0-9\]*\\." \ |
| "tbreak caller$c" |
| |
| # Continue to the next caller function. |
| gdb_test "continue" " caller$c prologue .*" "run to caller$c" |
| |
| # Do each callee function. |
| for {set e 1} {$e <= $limit} {incr e} { |
| |
| gdb_test "tbreak callee$e" "Temporary breakpoint.*\[0-9\]*\\." \ |
| "caller$c calls callee$e; tbreak callee" |
| |
| gdb_test "continue" " callee$e prologue .*/" \ |
| "caller$c calls callee$e; continue to callee" |
| |
| # Do a forced return from the callee. |
| set test "caller$c calls callee$e; return callee now" |
| gdb_test_multiple "return 0" "$test" { |
| -re "Make .* return now.*y or n. $" { |
| send_gdb "y\n" |
| exp_continue |
| } |
| -re " caller$c .*$gdb_prompt $" { |
| pass "$test" |
| } |
| } |
| |
| # Check that the values of the local variables are what |
| # they should be. |
| for {set var 1} {$var <= $c} {incr var} { |
| set expected [expr 0x7eeb + $var] |
| gdb_test "print l$var" " = $expected" \ |
| "caller$c calls callee$e; return restored l$var to $expected" |
| } |
| } |
| } |
| |
| if ![gdb_skip_stdio_test "run to completion"] { |
| send_gdb "continue\n" |
| |
| gdb_expect { |
| -re "exiting" { |
| pass "run to completion" |
| } |
| timeout { |
| fail "(timeout) run to completion" |
| } |
| } |
| } else { |
| gdb_test "continue" "" "" |
| } |
| } |
| |
| |
| |
| # Start with a fresh gdb. |
| |
| gdb_exit |
| gdb_start |
| gdb_reinitialize_dir $srcdir/$subdir |
| gdb_load ${binfile} |
| |
| set timeout 30 |
| restore_tests |