blob: e6f06931c3005e15330110991a2f2795e8ff52e4 [file] [log] [blame]
# Copyright 2025 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 multiple situations in which we may use the maintenance command to
# disable and enable frame unwinders, and check that they really are
# disabled when they say the are.
standard_testfile
# Proc to check if the unwinder of the given name is in the desired state.
# STATE can be either Y or N.
proc check_unwinder_state { unwinder_name state {testname ""} } {
set should_pass false
set command "maint info frame-unwinders"
if {${testname} == ""} {
set testname "checking state ${state} for ${unwinder_name}"
}
gdb_test_multiple ${command} ${testname} -lbl {
-re "${unwinder_name}\\s+\\w+\\s+\\w+\\s+${state}\\s+(?=\r\n)" {
set should_pass true
exp_continue
}
-re ${command} {
exp_continue
}
-re "\\w+\\s+\\w+\\s+\\w+\\s+\\w+\\s+(?=\r\n)" {
exp_continue
}
-re -wrap "" {
gdb_assert ${should_pass} ${gdb_test_name}
}
}
}
# Check if all unwinders of class UNWINDER_CLASS are in the state STATE.
# STATE can be either Y or N.
# UNWINDER_CLASS can be one of: GDB, ARCH, EXTENSION, DEBUGINFO. It can
# also be \\w+ if checking all unwinders.
proc check_unwinder_class { unwinder_class state {testname ""} } {
set command "maint info frame-unwinders"
set should_pass true
if {$testname == ""} {
set testname "checking if ${unwinder_class} state is ${state}"
}
gdb_test_multiple ${command} ${testname} -lbl {
-re "^\[^\r\n\]+\\s+\\w+\\s+${unwinder_class}\\s+\(\[YN\]\)\\s+(?=\r\n)" {
# The unwinder name may have multiple words, so we need to use the
# more generic [^\r\n] pattern to match the unwinders.
set cur_state $expect_out(1,string)
if {$cur_state == $state} {
set should_pass false
}
exp_continue
}
-re ${command} {
exp_continue
}
-re -wrap "" {
gdb_assert ${should_pass} ${gdb_test_name}
}
}
}
if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
return -1
}
if {![runto_main]} {
untested "couldn't run to main"
return
}
# Test disabling all unwinders.
check_unwinder_class "\\w+" "Y" \
"all unwinders enabled before any changes"
gdb_test_no_output "maint frame-unwinder disable -all"
check_unwinder_class "\\w+" "N" \
"all unwinders were properly disabled"
# Test if GDB can still make a backtrace once all unwinders are disabled.
# It should be impossible.
gdb_test "backtrace" \
".*Required frame unwinder may have been disabled, see 'maint info frame-unwinders'.*" \
"no suitable unwinders should be found"
# Reenable all unwinders.
gdb_test_no_output "maint frame-unwinder enable -all"
check_unwinder_class "\\w+" "Y" \
"all unwinders should be re-enabled"
# Check that we are able to get backtraces once again.
gdb_test "backtrace" ".0\\s+main .. at.*" \
"we can get usable backtraces again"
# Check if we can disable an unwinder based on the name.
check_unwinder_state "dummy" "Y"
gdb_test_no_output "maint frame-unwinder disable -name dummy"
check_unwinder_state "dummy" "N"
# And verify what happens if you try to disable it again.
gdb_test "maint frame-unwinder disable -name dummy" \
"unwinder dummy is already disabled" \
"disable already disabled unwinder"
check_unwinder_state "dummy" "N" "dummy should continue disabled"
foreach class {GDB ARCH DEBUGINFO EXTENSION} {
# Disable all unwinders of type CLASS, and check that the command worked.
gdb_test_no_output "maint frame-unwinder disable ${class}"
check_unwinder_class ${class} "N"
}
# Now check if we are able to enable a single unwinder, and what happens if we
# enable it twice.
gdb_test_no_output "maint frame-unwinder enable -name dummy"
check_unwinder_state "dummy" "Y" "successfully enabled dummy unwinder"
gdb_test "maint frame-unwinder enable -name dummy" \
"unwinder dummy is already enabled" \
"enable already enabled unwinder"
check_unwinder_state "dummy" "Y" "dummy should continue enabled"
foreach class {GDB ARCH DEBUGINFO EXTENSION} {
# Enable all unwinders of type CLASS, and check that the command worked,
# using "-class" option to ensure it works. Should make no difference.
gdb_test_no_output "maint frame-unwinder enable -class ${class}"
check_unwinder_class ${class} "Y"
}