1 # Copyright 2025 Free Software Foundation, Inc. 2 3 # This program is free software; you can redistribute it and/or modify 4 # it under the terms of the GNU General Public License as published by 5 # the Free Software Foundation; either version 3 of the License, or 6 # (at your option) any later version. 7 # 8 # This program is distributed in the hope that it will be useful, 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 # GNU General Public License for more details. 12 # 13 # You should have received a copy of the GNU General Public License 14 # along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 # Test multiple situations in which we may use the maintenance command to 17 # disable and enable frame unwinders, and check that they really are 18 # disabled when they say the are. 19 20 standard_testfile 21 22 # Proc to check if the unwinder of the given name is in the desired state. 23 # STATE can be either Y or N. 24 proc check_unwinder_state { unwinder_name state {testname ""} } { 25 set should_pass false 26 set command "maint info frame-unwinders" 27 if {${testname} == ""} { 28 set testname "checking state ${state} for ${unwinder_name}" 29 } 30 gdb_test_multiple ${command} ${testname} -lbl { 31 -re "${unwinder_name}\\s+\\w+\\s+\\w+\\s+${state}\\s+(?=\r\n)" { 32 set should_pass true 33 exp_continue 34 } 35 -re ${command} { 36 exp_continue 37 } 38 -re "\\w+\\s+\\w+\\s+\\w+\\s+\\w+\\s+(?=\r\n)" { 39 exp_continue 40 } 41 -re -wrap "" { 42 gdb_assert ${should_pass} ${gdb_test_name} 43 } 44 } 45 } 46 47 # Check if all unwinders of class UNWINDER_CLASS are in the state STATE. 48 # STATE can be either Y or N. 49 # UNWINDER_CLASS can be one of: GDB, ARCH, EXTENSION, DEBUGINFO. It can 50 # also be \\w+ if checking all unwinders. 51 proc check_unwinder_class { unwinder_class state {testname ""} } { 52 set command "maint info frame-unwinders" 53 set should_pass true 54 if {$testname == ""} { 55 set testname "checking if ${unwinder_class} state is ${state}" 56 } 57 gdb_test_multiple ${command} ${testname} -lbl { 58 -re "^\[^\r\n\]+\\s+\\w+\\s+${unwinder_class}\\s+\(\[YN\]\)\\s+(?=\r\n)" { 59 # The unwinder name may have multiple words, so we need to use the 60 # more generic [^\r\n] pattern to match the unwinders. 61 set cur_state $expect_out(1,string) 62 if {$cur_state == $state} { 63 set should_pass false 64 } 65 exp_continue 66 } 67 -re ${command} { 68 exp_continue 69 } 70 -re -wrap "" { 71 gdb_assert ${should_pass} ${gdb_test_name} 72 } 73 } 74 } 75 76 if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} { 77 return -1 78 } 79 80 if {![runto_main]} { 81 untested "couldn't run to main" 82 return 83 } 84 85 # Test disabling all unwinders. 86 check_unwinder_class "\\w+" "Y" \ 87 "all unwinders enabled before any changes" 88 gdb_test_no_output "maint frame-unwinder disable -all" 89 check_unwinder_class "\\w+" "N" \ 90 "all unwinders were properly disabled" 91 92 # Test if GDB can still make a backtrace once all unwinders are disabled. 93 # It should be impossible. 94 gdb_test "backtrace" \ 95 ".*Required frame unwinder may have been disabled, see 'maint info frame-unwinders'.*" \ 96 "no suitable unwinders should be found" 97 98 # Reenable all unwinders. 99 gdb_test_no_output "maint frame-unwinder enable -all" 100 check_unwinder_class "\\w+" "Y" \ 101 "all unwinders should be re-enabled" 102 103 # Check that we are able to get backtraces once again. 104 gdb_test "backtrace" ".0\\s+main .. at.*" \ 105 "we can get usable backtraces again" 106 107 # Check if we can disable an unwinder based on the name. 108 check_unwinder_state "dummy" "Y" 109 gdb_test_no_output "maint frame-unwinder disable -name dummy" 110 check_unwinder_state "dummy" "N" 111 # And verify what happens if you try to disable it again. 112 gdb_test "maint frame-unwinder disable -name dummy" \ 113 "unwinder dummy is already disabled" \ 114 "disable already disabled unwinder" 115 check_unwinder_state "dummy" "N" "dummy should continue disabled" 116 117 foreach class {GDB ARCH DEBUGINFO EXTENSION} { 118 # Disable all unwinders of type CLASS, and check that the command worked. 119 gdb_test_no_output "maint frame-unwinder disable ${class}" 120 check_unwinder_class ${class} "N" 121 } 122 123 # Now check if we are able to enable a single unwinder, and what happens if we 124 # enable it twice. 125 gdb_test_no_output "maint frame-unwinder enable -name dummy" 126 check_unwinder_state "dummy" "Y" "successfully enabled dummy unwinder" 127 gdb_test "maint frame-unwinder enable -name dummy" \ 128 "unwinder dummy is already enabled" \ 129 "enable already enabled unwinder" 130 check_unwinder_state "dummy" "Y" "dummy should continue enabled" 131 132 foreach class {GDB ARCH DEBUGINFO EXTENSION} { 133 # Enable all unwinders of type CLASS, and check that the command worked, 134 # using "-class" option to ensure it works. Should make no difference. 135 gdb_test_no_output "maint frame-unwinder enable -class ${class}" 136 check_unwinder_class ${class} "Y" 137 } 138