| # Copyright 2004-2021 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/>. |
| |
| |
| # The program sigaltstack.c creates a backtrace containing nested |
| # signal handlers on an alternative stack. This in turn leads to a |
| # non-contiguous (and possibly non-monotonic) backtrace - stack |
| # address jump at the normal-alt stack boundary. |
| |
| # This test confirms that GDB can both backtrace through and finish |
| # such a stack. |
| |
| if [target_info exists gdb,nosignals] { |
| verbose "Skipping sigaltstack.exp because of nosignals." |
| continue |
| } |
| |
| |
| standard_testfile .c |
| |
| if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { |
| untested "failed to compile" |
| return -1 |
| } |
| |
| # get things started |
| clean_restart ${binfile} |
| |
| # Pass all the alarms straight through (but verbosely) |
| gdb_test "handle SIGALRM print pass nostop" |
| gdb_test "handle SIGVTALRM print pass nostop" |
| gdb_test "handle SIGPROF print pass nostop" |
| |
| # Advance to main |
| if ![runto_main] then { |
| return 0 |
| } |
| |
| # Stop in handle, when at the inner most level |
| gdb_test "break catcher if level == INNER" |
| gdb_test "continue" ".* catcher .*" "continue to catch" |
| # step off the assignment |
| gdb_test "next" |
| |
| # Full backtrace? |
| gdb_test_sequence "bt" "backtrace" { |
| "\[\r\n\]+.0 \[^\r\n\]* catcher " |
| "\[\r\n\]+.1 .signal handler called." |
| "\[\r\n\]+.2 \[^\r\n\]* thrower .next_level=INNER" |
| "\[\r\n\]+.3 \[^\r\n\]* catcher " |
| "\[\r\n\]+.4 .signal handler called." |
| "\[\r\n\]+.5 \[^\r\n\]* thrower .next_level=OUTER" |
| "\[\r\n\]+.6 \[^\r\n\]* catcher " |
| "\[\r\n\]+.7 \[^\r\n\]* main " |
| } |
| |
| proc finish_test { pattern msg } { |
| global gdb_prompt |
| |
| gdb_test_multiple "finish" $msg { |
| -re "Cannot insert breakpoint 0.*${gdb_prompt} $" { |
| # Some platforms use a special read-only page for signal |
| # trampolines. We can't set a breakpoint there, and we |
| # don't gracefully fall back to single-stepping. |
| setup_kfail gdb/8841 "i?86-*-linux*" |
| setup_kfail gdb/8841 "*-*-openbsd*" |
| setup_kfail gdb/8841 "nios2-*-linux*" |
| fail "$msg (could not set breakpoint)" |
| } |
| -re "$pattern.*${gdb_prompt} $" { |
| pass $msg |
| } |
| } |
| } |
| |
| # Finish? |
| finish_test "signal handler called." "finish from catch LEAF" |
| finish_test "thrower .next_level=INNER, .*" "finish to throw INNER" |
| finish_test "catcher .*" "finish to catch INNER" |
| finish_test "signal handler called.*" "finish from catch INNER" |
| finish_test "thrower .next_level=OUTER, .*" "finish to OUTER" |
| finish_test "catcher .*" "finish to catch MAIN" |
| finish_test "main .*" "finish to MAIN" |