# Copyright 2009, 2010 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 . # 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 $tracelevel then { strace $tracelevel } 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 } set testfile "gdb2495" set srcfile ${testfile}.cc set binfile $objdir/$subdir/$testfile # Create and source the file that provides information about the compiler # used to compile the test case. if [get_compiler_info ${binfile} "c++"] { return -1 } if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { untested gdb2495.exp 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 } gdb_exit gdb_start gdb_reinitialize_dir $srcdir/$subdir gdb_load ${binfile} 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" \ "gdb.cp/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\".*"