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