Home | History | Annotate | Line # | Download | only in gdb.base
      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