f1d6db60f70d163fc7871977a1b85d28da3129cf
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.multi / tids.exp
1 # Copyright 2015-2021 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 thread ID parsing and display.
17
18 load_lib gdb-python.exp
19
20 standard_testfile
21
22 # Multiple inferiors are needed, therefore both native and extended
23 # gdbserver modes are supported. Only non-extended gdbserver is not
24 # supported.
25 if [use_gdb_stub] {
26 untested "using gdb stub"
27 return
28 }
29
30 if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {pthreads debug}] } {
31 return -1
32 }
33
34 clean_restart ${testfile}
35
36 if { ![runto_main] } then {
37 return -1
38 }
39
40 # Issue "thread apply TID_LIST p 1234" and expect EXP_TID_LIST (a list
41 # of thread ids) to be displayed.
42 proc thread_apply {tid_list exp_tid_list {message ""}} {
43 global decimal
44 set any "\[^\r\n\]*"
45 set expected [string_to_regexp $exp_tid_list]
46
47 set r ""
48 foreach tid $expected {
49 append r "\[\r\n\]+"
50 append r "Thread $tid $any:\r\n"
51 append r "\\$$decimal = 1234"
52 }
53
54 set cmd "thread apply $tid_list"
55 if {$message != ""} {
56 gdb_test "$cmd p 1234" $r $message
57 return
58 }
59
60 gdb_test "$cmd p 1234" $r
61 }
62
63 # Issue "info threads TID_LIST" and expect EXP_TID_LIST (a list of
64 # thread ids) to be displayed.
65 proc info_threads {tid_list exp_tid_list {message ""}} {
66 set any "\[^\r\n\]*"
67 set expected [string_to_regexp $exp_tid_list]
68 set r [join $expected " ${any}\r\n${any} "]
69 set r "${any} $r ${any}"
70 set cmd "info threads $tid_list"
71 if {$message != ""} {
72 gdb_test $cmd $r $message
73 return
74 }
75 gdb_test $cmd $r
76 }
77
78 # Issue "info threads TID_LIST" and expect INFO_THR output. Then
79 # issue "thread apply TID_LIST" and expect THR_APPLY output. If
80 # THR_APPLY is omitted, INFO_THR is expected instead.
81 proc thr_apply_info_thr {tid_list info_thr {thr_apply ""}} {
82 if {$thr_apply == ""} {
83 set thr_apply $info_thr
84 }
85
86 info_threads $tid_list $info_thr
87 thread_apply $tid_list $thr_apply
88 }
89
90 # Issue both "thread apply TID_LIST" and "info threads TID_LIST" and
91 # expect commands to error out with EXP_ERROR_APPLY and EXP_ERROR_INFO.
92 # If EXP_ERROR_INFO is missing, default to EXP_ERROR_APPLY.
93 proc thr_apply_info_thr_error {tid_list exp_error_apply {exp_error_info ""}} {
94 if { "$exp_error_info" == "" } {
95 set exp_error_info "$exp_error_apply"
96 }
97
98 gdb_test "info threads $tid_list" \
99 $exp_error_info
100
101 gdb_test "thread apply $tid_list" \
102 $exp_error_apply
103 }
104
105 # Issue both "info threads TID_LIST" and "thread apply TID_LIST" and
106 # expect the command to error out with "Invalid thread ID: $EXPECTED".
107 # EXPECTED is a literal string, not a regexp. If EXPECTED is omitted,
108 # TID_LIST is expected instead.
109 proc thr_apply_info_thr_invalid {tid_list {expected ""}} {
110 if {$expected == ""} {
111 set expected $tid_list
112 }
113 set expected [string_to_regexp $expected]
114 gdb_test "info threads $tid_list" \
115 "Invalid thread ID: $expected"
116
117 gdb_test "thread apply $tid_list p 1234" \
118 "Invalid thread ID: $expected p 1234" \
119 "thread apply $tid_list"
120 }
121
122 # "info threads" while there's only inferior 1 should show
123 # single-number thread IDs.
124 with_test_prefix "single inferior" {
125 info_threads "" "1"
126
127 gdb_test "thread" "Current thread is 1 .*"
128 }
129
130 # "info threads" while there are multiple inferiors should show
131 # qualified thread IDs.
132 with_test_prefix "two inferiors" {
133 # Add another inferior.
134 gdb_test "add-inferior" "Added inferior 2.*" "add empty inferior 2"
135
136 # Now that we've added another inferior, thread IDs now show the
137 # inferior number.
138 info_threads "" "1.1"
139
140 gdb_test "thread" "Current thread is 1\.1 .*"
141
142 gdb_test "inferior 2" "Switching to inferior 2 .*" "switch to inferior 2"
143 gdb_test "file ${binfile}" ".*" "load file in inferior 2"
144
145 runto_main
146
147 # Now that we've added another inferior, thread IDs now show the
148 # inferior number.
149 info_threads "" "1.1 2.1" \
150 "info threads show inferior numbers"
151
152 gdb_test "thread" "Current thread is 2\.1 .*" \
153 "switch to thread using extended thread ID"
154
155 gdb_breakpoint "thread_function1"
156
157 gdb_continue_to_breakpoint "once"
158 gdb_test "inferior 1" "Switching to inferior 1 .*"
159 gdb_continue_to_breakpoint "twice"
160
161 info_threads "" "1.1 1.2 2.1 2.2" \
162 "info threads again"
163
164 # Same, but show the global ID.
165 gdb_test "info threads -gid" \
166 [multi_line \
167 " 1\.1 +1 +.*" \
168 "\\* 1\.2 +4 +.* thread_function1 .* at .*$srcfile:.*" \
169 " 2\.1 +2 +.*" \
170 " 2\.2 +3 +.* thread_function1 .* at .*$srcfile:.*"]
171
172 # Confirm the convenience variables show the expected numbers.
173 gdb_test "p \$_thread == 2" " = 1"
174 gdb_test "p \$_gthread == 4" " = 1"
175
176 # Without an explicit inferior component, GDB defaults to the
177 # current inferior. Make sure we don't refer to a thread by
178 # global ID by mistake.
179 gdb_test "thread 4" "Unknown thread 1.4\\."
180
181 # Test thread ID list parsing. Test qualified and unqualified
182 # IDs; qualified and unqualified ranges; invalid IDs and invalid
183 # ranges.
184
185 # First spawn a couple more threads so ranges includes more than
186 # two threads.
187 with_test_prefix "more threads" {
188 gdb_breakpoint "thread_function2"
189
190 gdb_test "inferior 2" "Switching to inferior 2 .*"
191 gdb_continue_to_breakpoint "once"
192
193 gdb_test "inferior 1" "Switching to inferior 1 .*"
194 gdb_continue_to_breakpoint "twice"
195 }
196
197 thr_apply_info_thr "1" \
198 "1.1"
199
200 thr_apply_info_thr "1.1" \
201 "1.1"
202
203 thr_apply_info_thr "1 2 3" \
204 "1.1 1.2 1.3"
205
206 # Same, but with qualified thread IDs.
207 thr_apply_info_thr "1.1 1.2 1.3 2.1 2.2" \
208 "1.1 1.2 1.3 2.1 2.2"
209
210 # Test a thread number range.
211 thr_apply_info_thr "1-3" \
212 "1.1 1.2 1.3"
213
214 # Same, but using a qualified range.
215 thr_apply_info_thr "1.1-3" \
216 "1.1 1.2 1.3"
217
218 # A mix of qualified and unqualified thread IDs/ranges.
219 thr_apply_info_thr "1.1 2-3" \
220 "1.1 1.2 1.3"
221
222 thr_apply_info_thr "1 1.2-3" \
223 "1.1 1.2 1.3"
224
225 # Likewise, but mix inferiors too.
226 thr_apply_info_thr "2.1 2-3" \
227 "1.2 1.3 2.1" \
228 "2.1 1.2 1.3"
229
230 # Multiple ranges with mixed explicit inferiors.
231 thr_apply_info_thr "1.1-2 2.2-3" \
232 "1.1 1.2 2.2 2.3"
233
234 # All threads.
235 thread_apply "all" \
236 "2.3 2.2 2.1 1.3 1.2 1.1"
237 thread_apply "all -ascending" \
238 "1.1 1.2 1.3 2.1 2.2 2.3"
239
240 # Now test using GDB convenience variables.
241
242 gdb_test "p \$inf = 1" " = 1"
243 gdb_test "p \$thr_start = 2" " = 2"
244 gdb_test "p \$thr_end = 3" " = 3"
245
246 # Convenience variable for the inferior number, only.
247 thr_apply_info_thr "\$inf.2" \
248 "1.2"
249 thr_apply_info_thr "\$inf.2-3" \
250 "1.2 1.3"
251
252 # Convenience variables for thread numbers as well.
253 foreach prefix {"" "1." "\$inf."} {
254 thr_apply_info_thr "${prefix}\$thr_start" \
255 "1.2"
256 thr_apply_info_thr "${prefix}\$thr_start-\$thr_end" \
257 "1.2 1.3"
258 thr_apply_info_thr "${prefix}2-\$thr_end" \
259 "1.2 1.3"
260 thr_apply_info_thr "${prefix}\$thr_start-3" \
261 "1.2 1.3"
262
263 # Undefined convenience variable.
264 set prefix_re [string_to_regexp $prefix]
265 thr_apply_info_thr_error "${prefix}\$conv123" \
266 [multi_line \
267 "Convenience variable must have integer value\." \
268 "Invalid thread ID: ${prefix_re}\\\$conv123"]
269 }
270
271 # Convenience variables pointing at an inexisting thread and/or
272 # inferior.
273 gdb_test "p \$inf = 30" " = 30"
274 gdb_test "p \$thr = 20" " = 20"
275 # Try both the convenience variable and the literal number.
276 foreach thr {"\$thr" "20" "1.20" "\$inf.1" "30.1" } {
277 set expected [string_to_regexp $thr]
278 gdb_test "info threads $thr" "No threads match '${expected}'."
279 # "info threads" works like a filter. If there's any other
280 # valid thread in the list, there's no error.
281 info_threads "$thr 1.1" "1.1"
282 info_threads "1.1 $thr" "1.1"
283 }
284
285 gdb_test "thread apply \$thr p 1234" \
286 "warning: Unknown thread 1.20" \
287 "thread apply \$thr"
288
289 gdb_test "thread apply \$inf.1 p 1234" \
290 "warning: Unknown thread 30.1" \
291 "thread apply \$inf.1"
292
293 # Star ranges.
294
295 thr_apply_info_thr "1.*" \
296 "1.1 1.2 1.3"
297
298 thr_apply_info_thr "*" \
299 "1.1 1.2 1.3"
300
301 thr_apply_info_thr "1.* 2.1" \
302 "1.1 1.2 1.3 2.1"
303
304 thr_apply_info_thr "2.1 1.*" \
305 "1.1 1.2 1.3 2.1" \
306 "2.1 1.1 1.2 1.3"
307
308 thr_apply_info_thr "1.* 2.*" \
309 "1.1 1.2 1.3 2.1 2.2 2.3"
310
311 thr_apply_info_thr "2.* 1.*" \
312 "1.1 1.2 1.3 2.1 2.2 2.3" \
313 "2.1 2.2 2.3 1.1 1.2 1.3"
314
315 # There's no inferior 3, but "info threads" treats the thread list
316 # as a filter, so it's OK. "thread apply" complains about the
317 # unknown inferior through.
318 info_threads "1.1 3.*" \
319 "1.1"
320 gdb_test "thread apply 1.1 3.* p 1" \
321 "Thread 1.1.*warning: Unknown inferior 3"
322
323 # Now test a set of invalid thread IDs/ranges.
324
325 thr_apply_info_thr_invalid "1." \
326 "1."
327
328 thr_apply_info_thr_invalid "1-3 1." \
329 "1."
330
331 thr_apply_info_thr_invalid "1.1.1" \
332 "1.1.1"
333
334 thr_apply_info_thr_invalid "2 1.1.1" \
335 "1.1.1"
336
337 thr_apply_info_thr_invalid "1.1.1 2" \
338 "1.1.1 2"
339
340 thr_apply_info_thr_invalid "1-2.1" \
341 "1-2.1"
342
343 gdb_test "p \$zero = 0" " = 0"
344 gdb_test "p \$one = 1" " = 1"
345 gdb_test "p \$minus_one = -11" " = -11"
346 foreach prefix {"" "1." "$one."} {
347 set prefix_re [string_to_regexp $prefix]
348
349 thr_apply_info_thr_invalid "${prefix}foo"
350 thr_apply_info_thr_invalid "${prefix}1foo"
351 thr_apply_info_thr_invalid "${prefix}foo1"
352
353 thr_apply_info_thr_error "${prefix}1-0" "inverted range"
354 thr_apply_info_thr_error "${prefix}1-\$zero" "inverted range"
355 thr_apply_info_thr_error "${prefix}\$one-0" "inverted range"
356 thr_apply_info_thr_error "${prefix}\$one-\$zero" "inverted range"
357 thr_apply_info_thr_error "${prefix}1-" "inverted range"
358 thr_apply_info_thr_error "${prefix}2-1" "inverted range"
359 thr_apply_info_thr_error "${prefix}2-\$one" "inverted range"
360 if {$prefix == ""} {
361 thr_apply_info_thr_error "${prefix}-1" "Invalid thread ID: -1" \
362 "Unrecognized option at: -1"
363 thr_apply_info_thr_error "${prefix}-\$one" \
364 "Invalid thread ID: -\\\$one" "Unrecognized option at: -\\\$one"
365 } else {
366 thr_apply_info_thr_error "${prefix}-1" "negative value"
367 thr_apply_info_thr_error "${prefix}-\$one" "negative value"
368 }
369 thr_apply_info_thr_error "${prefix}\$minus_one" \
370 "negative value: ${prefix_re}\\\$minus_one"
371
372 thr_apply_info_thr_error "${prefix}1-*" "inverted range"
373 thr_apply_info_thr_invalid "${prefix}*1"
374 thr_apply_info_thr_invalid "${prefix}*foo"
375 thr_apply_info_thr_invalid "${prefix}foo*"
376 }
377
378 # Check that a valid thread ID list with a missing command errors
379 # out.
380 with_test_prefix "missing command" {
381 set output "Please specify a command following the thread ID list"
382 gdb_test "thread apply 1" $output
383 gdb_test "thread apply 1.1" $output
384 gdb_test "thread apply 1.1 1.2" $output
385 gdb_test "thread apply 1-2" $output
386 gdb_test "thread apply 1.1-2" $output
387 gdb_test "thread apply $thr" $output
388 gdb_test "thread apply 1.*" $output
389 }
390
391 # Check that thread ID list parsing stops at the non-number token
392 # "foo" in a corner case where the "foo" is followed by hyphens.
393 # In this corner case, GDB used to skip past "foo", and then parse
394 # "--1" as a tid range for the current inferior.
395 gdb_test "thread apply 1 foo --1" \
396 "Undefined command: \"foo\". Try \"help\"\\."
397
398 # Check that we do parse the inferior number and don't confuse it.
399 gdb_test "info threads 3.1" \
400 "No threads match '3.1'\."
401 }
402
403 if { ![skip_python_tests] } {
404 with_test_prefix "python" {
405 # Check that InferiorThread.num and InferiorThread.global_num
406 # return the expected numbers.
407 gdb_py_test_silent_cmd "python t0 = gdb.selected_thread ()" \
408 "test gdb.selected_thread" 1
409 gdb_test "python print ('result = %s' % t0.num)" " = 3" \
410 "test InferiorThread.num"
411 gdb_test "python print ('result = %s' % t0.global_num)" " = 6" \
412 "test InferiorThread.global_num"
413
414 # Breakpoint.thread expects global IDs. Confirm that that
415 # works as expected.
416 delete_breakpoints
417 gdb_breakpoint "thread_function1"
418
419 gdb_py_test_silent_cmd "python bp = gdb.breakpoints()\[0\]" \
420 "get python breakpoint" 0
421 gdb_test "python bp.thread = 6" "thread = 6" \
422 "make breakpoint thread-specific with python"
423 # Check that the inferior-qualified ID is correct.
424 gdb_test "info breakpoint" \
425 "stop only in thread 1.3\r\n.*" \
426 "thread specific breakpoint right thread"
427 }
428 }
429
430 # Remove the second inferior and confirm that GDB goes back to showing
431 # single-number thread IDs.
432 with_test_prefix "back to one inferior" {
433 gdb_test "kill inferior 2" "" "kill inferior 2" "Kill the program being debugged.*" "y"
434 gdb_test "thread 1.1" "Switching to thread 1\.1 .*"
435 gdb_test "remove-inferior 2" ".*" "remove inferior 2"
436
437 # "info threads" while there's only inferior 1 should show
438 # single-number thread IDs.
439 info_threads "" "1 2 3"
440
441 gdb_test "thread" "Current thread is 1 .*"
442 }
443
444 # Add another inferior and remove inferior 1. Since even though
445 # there's a single inferior, its number is not 1, GDB should show
446 # inferior-qualified thread IDs.
447 with_test_prefix "single-inferior but not initial" {
448 # Add another inferior.
449 gdb_test "add-inferior" "Added inferior 3.*" "add empty inferior"
450
451 # Now that we'd added another inferior, thread IDs should show the
452 # inferior number.
453 info_threads "" "1.1 1.2 1.3" \
454 "info threads with multiple inferiors"
455
456 gdb_test "thread" "Current thread is 1\.1 .*"
457
458 gdb_test "inferior 3" "Switching to inferior 3 .*" "switch to inferior 3"
459 gdb_test "file ${binfile}" ".*" "load file in inferior 3"
460
461 runto_main
462
463 gdb_test "remove-inferior 1" ".*" "remove inferior 1"
464
465 # Even though we have a single inferior, its number is > 1, so
466 # thread IDs should include the inferior number.
467 info_threads "" "3.1" \
468 "info threads with single inferior"
469
470 gdb_test "thread" "Current thread is 3\.1 .*" "thread again"
471 }
This page took 0.038411 seconds and 3 git commands to generate.