Home | History | Annotate | Line # | Download | only in gdb.base
      1  1.1  christos # Copyright 2021-2024 Free Software Foundation, Inc.
      2  1.1  christos 
      3  1.1  christos # This program is free software; you can redistribute it and/or modify
      4  1.1  christos # it under the terms of the GNU General Public License as published by
      5  1.1  christos # the Free Software Foundation; either version 3 of the License, or
      6  1.1  christos # (at your option) any later version.
      7  1.1  christos #
      8  1.1  christos # This program is distributed in the hope that it will be useful,
      9  1.1  christos # but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  1.1  christos # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  1.1  christos # GNU General Public License for more details.
     12  1.1  christos #
     13  1.1  christos # You should have received a copy of the GNU General Public License
     14  1.1  christos # along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15  1.1  christos 
     16  1.1  christos # Test that string values are correctly allocated inside GDB when doing
     17  1.1  christos # various operations that yield strings.
     18  1.1  christos #
     19  1.1  christos # The issue that lead to this test was a missing NULL terminator in the
     20  1.1  christos # C-string values.  We verify that we can print the null terminator of these
     21  1.1  christos # strings.
     22  1.1  christos 
     23  1.1  christos load_lib "trace-support.exp"
     24  1.1  christos load_lib "gdb-guile.exp"
     25  1.1  christos 
     26  1.1  christos standard_testfile
     27  1.1  christos 
     28  1.1  christos if {[build_executable "failed to prepare" $testfile $srcfile ]} {
     29  1.1  christos     return
     30  1.1  christos }
     31  1.1  christos 
     32  1.1  christos set user_conv_funcs {$_gdb_setting $_gdb_setting_str}
     33  1.1  christos set maint_conv_funcs {$_gdb_maint_setting $_gdb_maint_setting_str}
     34  1.1  christos 
     35  1.1  christos # Add language (LANG) appropriate quotation marks around string STR.
     36  1.1  christos proc quote_for_lang {lang str} {
     37  1.1  christos     if {$lang == "fortran"} {
     38  1.1  christos 	return "'$str'"
     39  1.1  christos     } else {
     40  1.1  christos 	return "\"$str\""
     41  1.1  christos     }
     42  1.1  christos }
     43  1.1  christos 
     44  1.1  christos # Check that the string contained in the convenienced variable $v is
     45  1.1  christos # EXPECTED_STR.
     46  1.1  christos #
     47  1.1  christos # In particular, check that the null terminator is there and that we can't
     48  1.1  christos # access a character past the end of the string.
     49  1.1  christos 
     50  1.1  christos proc check_v_string { expected_str } {
     51  1.1  christos     set len [string length $expected_str]
     52  1.1  christos 
     53  1.1  christos     for { set i 0 } { $i < $len } { incr i } {
     54  1.1  christos 	set c [string index $expected_str $i]
     55  1.1  christos 	gdb_test "print \$v\[$i\]" "= $::decimal '$c'"
     56  1.1  christos     }
     57  1.1  christos 
     58  1.1  christos     # Check that the string ends with a null terminator.
     59  1.1  christos     gdb_test "print \$v\[$i\]" {= 0 '\\000'}
     60  1.1  christos 
     61  1.1  christos     # Check that we can't access a character after the end of the string.
     62  1.1  christos     incr i
     63  1.1  christos     gdb_test "print \$v\[$i\]" "no such vector element"
     64  1.1  christos }
     65  1.1  christos 
     66  1.1  christos # Test with string values made by $_gdb_setting & co.
     67  1.1  christos 
     68  1.1  christos proc_with_prefix test_setting { } {
     69  1.1  christos     clean_restart
     70  1.1  christos 
     71  1.1  christos     # This is an internal GDB implementation detail, but the variable backing
     72  1.1  christos     # a string setting starts as nullptr (unless explicitly initialized at
     73  1.1  christos     # startup).  When assigning an empty value, the variable then points to an
     74  1.1  christos     # empty string.  Test both cases, as it triggers different code paths (in
     75  1.1  christos     # addition to a non-empty value).
     76  1.1  christos     #
     77  1.1  christos     # Use "set trace-user" and "maintenance set test-settings string" as they
     78  1.1  christos     # are both not initialized at startup.
     79  1.1  christos     with_test_prefix "user setting" {
     80  1.1  christos 	with_test_prefix "not set" {
     81  1.1  christos 	    foreach_with_prefix conv_func $::user_conv_funcs {
     82  1.1  christos 		gdb_test_no_output "set \$v = ${conv_func}(\"trace-user\")"
     83  1.1  christos 		check_v_string ""
     84  1.1  christos 	    }
     85  1.1  christos 	}
     86  1.1  christos 
     87  1.1  christos 	with_test_prefix "set to empty" {
     88  1.1  christos 	    gdb_test "set trace-user"
     89  1.1  christos 	    foreach_with_prefix conv_func $::user_conv_funcs {
     90  1.1  christos 		gdb_test_no_output "set \$v = ${conv_func}(\"trace-user\")"
     91  1.1  christos 		check_v_string ""
     92  1.1  christos 	    }
     93  1.1  christos 	}
     94  1.1  christos 
     95  1.1  christos 	with_test_prefix "set" {
     96  1.1  christos 	    gdb_test "set trace-user poulet"
     97  1.1  christos 	    foreach_with_prefix conv_func $::user_conv_funcs {
     98  1.1  christos 		gdb_test_no_output {set $v = $_gdb_setting("trace-user")}
     99  1.1  christos 		check_v_string "poulet"
    100  1.1  christos 	    }
    101  1.1  christos 	}
    102  1.1  christos     }
    103  1.1  christos 
    104  1.1  christos     with_test_prefix "maintenance setting" {
    105  1.1  christos 	with_test_prefix "not set" {
    106  1.1  christos 	    foreach_with_prefix conv_func $::maint_conv_funcs {
    107  1.1  christos 		gdb_test_no_output \
    108  1.1  christos 		    "set \$v = ${conv_func}(\"test-settings string\")"
    109  1.1  christos 		check_v_string ""
    110  1.1  christos 	    }
    111  1.1  christos 	}
    112  1.1  christos 
    113  1.1  christos 	with_test_prefix "set to empty" {
    114  1.1  christos 	    gdb_test "maintenance set test-settings string"
    115  1.1  christos 	    foreach_with_prefix conv_func $::maint_conv_funcs {
    116  1.1  christos 		gdb_test_no_output \
    117  1.1  christos 		    "set \$v = ${conv_func}(\"test-settings string\")"
    118  1.1  christos 		check_v_string ""
    119  1.1  christos 	    }
    120  1.1  christos 	}
    121  1.1  christos 
    122  1.1  christos 	with_test_prefix "set" {
    123  1.1  christos 	    gdb_test "maintenance set test-settings string perchaude"
    124  1.1  christos 	    foreach_with_prefix conv_func $::maint_conv_funcs {
    125  1.1  christos 		gdb_test_no_output \
    126  1.1  christos 		    "set \$v = ${conv_func}(\"test-settings string\")"
    127  1.1  christos 		check_v_string "perchaude"
    128  1.1  christos 	    }
    129  1.1  christos 	}
    130  1.1  christos     }
    131  1.1  christos 
    132  1.1  christos     # Test with a non-string setting, this tests yet another code path.
    133  1.1  christos     with_test_prefix "integer setting" {
    134  1.1  christos 	gdb_test_no_output {set $v = $_gdb_setting_str("remotetimeout")}
    135  1.1  christos 	check_v_string "2"
    136  1.1  christos     }
    137  1.1  christos 
    138  1.1  christos     # Test string values made by $_gdb_setting & co. in all languages.
    139  1.1  christos     with_test_prefix "all langs" {
    140  1.1  christos 	# Get list of supported languages.
    141  1.1  christos 	set langs [gdb_supported_languages]
    142  1.1  christos 
    143  1.1  christos 	gdb_test "maintenance set test-settings string foo"
    144  1.1  christos 	foreach_with_prefix lang $langs {
    145  1.1  christos 	    gdb_test_no_output "set language $lang"
    146  1.1  christos 
    147  1.1  christos 	    if {$lang == "modula-2"} {
    148  1.1  christos 		# The Modula-2 parser doesn't know how to build a
    149  1.1  christos 		# suitable string expression.
    150  1.1  christos 		gdb_test "print \"foo\"" "strings are not implemented"
    151  1.1  christos 		continue
    152  1.1  christos 	    }
    153  1.1  christos 
    154  1.1  christos 	    if {$lang == "rust"} {
    155  1.1  christos 		# Rust strings are actually structs, without a running
    156  1.1  christos 		# inferior into which the string data can be pushed
    157  1.1  christos 		# GDB can't print anything.
    158  1.1  christos 		gdb_test "print \"foo\"" \
    159  1.1  christos 		    "evaluation of this expression requires the target program to be active"
    160  1.1  christos 		gdb_test "print \$_gdb_maint_setting(\"test-settings string\")" \
    161  1.1  christos 		    "evaluation of this expression requires the target program to be active"
    162  1.1  christos 		continue
    163  1.1  christos 	    }
    164  1.1  christos 
    165  1.1  christos 	    if {$lang == "unknown"} {
    166  1.1  christos 		# Skipped because expression parsing is not supported
    167  1.1  christos 		# for the "unknown" language.  See gdb/28093 for more
    168  1.1  christos 		# details.
    169  1.1  christos 		continue
    170  1.1  christos 	    }
    171  1.1  christos 
    172  1.1  christos 	    set print_output ""
    173  1.1  christos 	    set ptype_output ""
    174  1.1  christos 
    175  1.1  christos 	    set foo_str [quote_for_lang $lang foo]
    176  1.1  christos 	    gdb_test_multiple "print $foo_str" "" {
    177  1.1  christos 		-wrap -re " = (.*)" {
    178  1.1  christos 		    set print_output $expect_out(1,string)
    179  1.1  christos 		    pass $gdb_test_name
    180  1.1  christos 		}
    181  1.1  christos 	    }
    182  1.1  christos 
    183  1.1  christos 	    gdb_test_multiple "ptype $foo_str" "" {
    184  1.1  christos 		-wrap -re " = (.*)" {
    185  1.1  christos 		    set ptype_output $expect_out(1,string)
    186  1.1  christos 		    pass $gdb_test_name
    187  1.1  christos 		}
    188  1.1  christos 	    }
    189  1.1  christos 
    190  1.1  christos 	    set cmd_str [quote_for_lang $lang "test-settings string"]
    191  1.1  christos 	    set ptype_output_re [string_to_regexp $ptype_output]
    192  1.1  christos 	    set print_output_re [string_to_regexp $print_output]
    193  1.1  christos 
    194  1.1  christos 	    foreach_with_prefix conv_func $::maint_conv_funcs {
    195  1.1  christos 		gdb_test "print ${conv_func}($cmd_str)" \
    196  1.1  christos 		    " = $print_output_re"
    197  1.1  christos 		gdb_test "ptype \$" \
    198  1.1  christos 		    " = $ptype_output_re"
    199  1.1  christos 	    }
    200  1.1  christos 	}
    201  1.1  christos     }
    202  1.1  christos }
    203  1.1  christos 
    204  1.1  christos # Test with a string value created by gdb.Value in Python.
    205  1.1  christos 
    206  1.1  christos proc_with_prefix test_python_value { } {
    207  1.1  christos     clean_restart
    208  1.1  christos 
    209  1.1  christos     if {![allow_python_tests]} {
    210  1.1  christos 	untested "skipping test_python_value"
    211  1.1  christos 	return
    212  1.1  christos     }
    213  1.1  christos 
    214  1.1  christos     gdb_test_no_output "python gdb.set_convenience_variable(\"v\", \"bar\")" \
    215  1.1  christos 	"set convenience var"
    216  1.1  christos     check_v_string "bar"
    217  1.1  christos }
    218  1.1  christos 
    219  1.1  christos # Test with a string value created by make-value in Guile.
    220  1.1  christos 
    221  1.1  christos proc_with_prefix test_guile_value { } {
    222  1.1  christos     clean_restart
    223  1.1  christos 
    224  1.1  christos     if {![allow_guile_tests]} {
    225  1.1  christos 	untested "skipping test_guile_value"
    226  1.1  christos 	return
    227  1.1  christos     }
    228  1.1  christos 
    229  1.1  christos     # We can't set a convenience var from Guile, but we can append to history.
    230  1.1  christos     # Do that, then transfer to a convenience var with a CLI command.
    231  1.1  christos     gdb_test_no_output "guile (use-modules (gdb))"
    232  1.1  christos     gdb_test_multiple "guile (history-append! (make-value \"foo\"))" "make value" {
    233  1.1  christos 	-re -wrap "($::decimal)" {
    234  1.1  christos 	    set histnum $expect_out(1,string)
    235  1.1  christos 	}
    236  1.1  christos     }
    237  1.1  christos 
    238  1.1  christos     gdb_test_no_output "set \$v = \$$histnum"
    239  1.1  christos     check_v_string "foo"
    240  1.1  christos }
    241  1.1  christos 
    242  1.1  christos # Test with a string value coming from a string internal var.  The only internal
    243  1.1  christos # vars of this type, at the time of writing, are $trace_func and $trace_file.
    244  1.1  christos # They both require inspecting a trace frame.  So if the target is capable start
    245  1.1  christos # tracing, record one trace frame, and use $trace_func.
    246  1.1  christos 
    247  1.1  christos proc_with_prefix test_internal_var { } {
    248  1.1  christos     if {![gdb_trace_common_supports_arch]} {
    249  1.1  christos 	unsupported "arch does not support trace"
    250  1.1  christos 	return
    251  1.1  christos     }
    252  1.1  christos 
    253  1.1  christos     clean_restart $::binfile
    254  1.1  christos 
    255  1.1  christos     if {![runto_main]} {
    256  1.1  christos 	fail "could not run to main"
    257  1.1  christos 	return
    258  1.1  christos     }
    259  1.1  christos 
    260  1.1  christos     if {![gdb_target_supports_trace]} {
    261  1.1  christos 	unsupported "target does not support trace"
    262  1.1  christos 	return
    263  1.1  christos     }
    264  1.1  christos 
    265  1.1  christos     gdb_breakpoint "end"
    266  1.1  christos     gdb_test "trace trace_me" "Tracepoint $::decimal at $::hex.*"
    267  1.1  christos     gdb_test_no_output "tstart"
    268  1.1  christos     gdb_continue_to_breakpoint "breakpoint at end"
    269  1.1  christos     gdb_test_no_output "tstop"
    270  1.1  christos     gdb_test "tfind" "Found trace frame 0, tracepoint $::decimal.*"
    271  1.1  christos     gdb_test_no_output "set \$v = \$trace_func"
    272  1.1  christos     gdb_test "tfind none" "No longer looking at any trace frame.*"
    273  1.1  christos     check_v_string "trace_me"
    274  1.1  christos }
    275  1.1  christos 
    276  1.1  christos test_setting
    277  1.1  christos test_python_value
    278  1.1  christos test_guile_value
    279  1.1  christos test_internal_var
    280