internal-string-values.exp revision 1.1 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