| # Copyright 2009-2014 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/>. |
| |
| |
| # In gdb inferior function calls, if a C++ exception is raised in the |
| # dummy-frame, and the exception handler is (normally, and expected to |
| # be) out-of-frame, the default C++ handler will (wrongly) be called |
| # in an inferior function call. |
| # This is incorrect as an exception can normally and legally be handled |
| # out-of-frame. The confines of the dummy frame prevent the unwinder |
| # from finding the correct handler (or any handler, unless it is |
| # in-frame). The default handler calls std::terminate. This will kill |
| # the inferior. Assert that terminate should never be called in an |
| # inferior function call. These tests test the functionality around |
| # unwinding that sequence and also tests the flag behaviour gating this |
| # functionality. |
| # |
| # PR c++/9600. |
| |
| # This test is largely based of gdb.base/callfuncs.exp. |
| |
| if { [skip_cplus_tests] } { continue } |
| |
| if [target_info exists gdb,nosignals] { |
| verbose "Skipping gdb2495.exp because of nosignals." |
| continue |
| } |
| |
| # On SPU this test fails because the executable exceeds local storage size. |
| if { [istarget "spu*-*-*"] } { |
| return 0 |
| } |
| |
| standard_testfile .cc |
| |
| # Create and source the file that provides information about the compiler |
| # used to compile the test case. |
| if [get_compiler_info "c++"] { |
| return -1 |
| } |
| |
| # Some targets can't do function calls, so don't even bother with this |
| # test. |
| if [target_info exists gdb,cannot_call_functions] { |
| setup_xfail "*-*-*" 2416 |
| fail "This target can not call functions" |
| continue |
| } |
| |
| if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} { |
| return -1 |
| } |
| |
| if ![runto_main] then { |
| perror "couldn't run to main" |
| continue |
| } |
| |
| # See http://sourceware.org/gdb/bugs/2495 |
| |
| # Test normal baseline behaviour. Call a function that |
| # does not raise an exception. |
| gdb_test "p exceptions.no_throw_function()" " = 1" |
| # And one that does but handles it in-frame. |
| gdb_test "p exceptions.throw_function_with_handler()" " = 2" |
| # Both should return normally. |
| |
| # Test basic unwind. Call a function that raises an exception but |
| # does not handle it. It should be rewound. |
| gdb_test "p exceptions.throw_function()" \ |
| "The program being debugged entered a std::terminate call, .*" \ |
| "Call a function that raises an exception without a handler." |
| |
| # Make sure that after rewinding we are back at the call parent. |
| gdb_test "bt" \ |
| "#0 main.*" \ |
| "bt after returning from a popped frame" |
| |
| # Make sure the only breakpoint is the one set via the runto_main |
| # call and that the std::terminate breakpoint has evaporated and |
| # cleaned-up. |
| gdb_test "info breakpoints" \ |
| "gdb2495\.cc.*" |
| |
| # Turn off this new behaviour. |
| gdb_test_multiple "set unwind-on-terminating-exception off" \ |
| "Turn unwind-on-terminating-exception off" { |
| -re "$gdb_prompt $" {pass "set unwinn-on-terminating-exception off"} |
| timeout {fail "(timeout) set unwind-on-terminating-exception off"} |
| } |
| |
| # Check that it is turned off. |
| gdb_test "show unwind-on-terminating-exception" \ |
| "exception is unhandled while in a call dummy is off.*" \ |
| "Turn off unwind on terminating exception flag" |
| |
| # Check that the old behaviour is restored. |
| gdb_test "p exceptions.throw_function()" \ |
| "The program being debugged was signaled while in a function called .*" \ |
| "Call a function that raises an exception with unwinding off.." |
| |
| # Restart the inferior back at main. |
| if ![runto_main] then { |
| perror "couldn't run to main" |
| continue |
| } |
| |
| |
| # Check to see if the new behaviour alters the unwind signal |
| # behaviour; it should not. Test both on and off states. |
| |
| # Turn on unwind on signal behaviour. |
| gdb_test_multiple "set unwindonsignal on" "Turn unwindonsignal on" { |
| -re "$gdb_prompt $" {pass "set unwindonsignal on"} |
| timeout {fail "(timeout) set unwindonsignal on"} |
| } |
| |
| # Check that it is turned on. |
| gdb_test "show unwindonsignal" \ |
| "signal is received while in a call dummy is on.*" \ |
| "Turn on unwind on signal" |
| |
| # Check to see if new behaviour interferes with |
| # normal signal handling in inferior function calls. |
| gdb_test "p exceptions.raise_signal(1)" \ |
| "To change this behavior use \"set unwindonsignal off\".*" |
| |
| # And reverse - turn off again. |
| gdb_test_multiple "set unwindonsignal off" "Turn unwindonsignal off" { |
| -re "$gdb_prompt $" {pass "set unwindonsignal off"} |
| timeout {fail "(timeout) set unwindonsignal off"} |
| } |
| |
| # Check that it is actually turned off. |
| gdb_test "show unwindonsignal" \ |
| "signal is received while in a call dummy is off.*" \ |
| "Turn off unwind on signal" |
| |
| # Check to see if new behaviour interferes with |
| # normal signal handling in inferior function calls. |
| gdb_test "p exceptions.raise_signal(1)" \ |
| "To change this behavior use \"set unwindonsignal on\".*" |