1 # This testcase is part of GDB, the GNU debugger. 2 # 3 # Copyright 2021-2024 Free Software Foundation, Inc. 4 # 5 # This program is free software; you can redistribute it and/or modify 6 # it under the terms of the GNU General Public License as published by 7 # the Free Software Foundation; either version 3 of the License, or 8 # (at your option) any later version. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public License 16 # along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 # Test how GDB handles the case where a target either doesn't use 'T' 19 # packets at all or doesn't include a thread-id in a 'T' packet, AND, 20 # where the test program contains multiple threads. 21 # 22 # In general if multiple threads are executing and the target doesn't 23 # include a thread-id in its stop response then GDB will not be able 24 # to correctly figure out which thread the stop applies to. 25 # 26 # However, this test covers a very specific case, there are multiple 27 # threads but only a single thread is actually executing. So, when 28 # the stop comes from the target, without a thread-id, GDB should be 29 # able to correctly figure out which thread has stopped. 30 31 load_lib gdbserver-support.exp 32 33 require allow_gdbserver_tests 34 35 standard_testfile 36 if { [build_executable "failed to prepare" $testfile $srcfile {debug pthreads}] == -1 } { 37 return -1 38 } 39 40 set target_binfile [gdb_remote_download target $binfile] 41 42 # Run the tests with different features of GDBserver disabled. 43 # TARGET_NON_STOP is passed to "maint set target-non-stop". 44 proc run_test { target_non_stop disable_feature } { 45 global binfile gdb_prompt decimal hex tdlabel_re 46 global GDBFLAGS 47 48 save_vars { GDBFLAGS } { 49 append GDBFLAGS " -ex \"maint set target-non-stop $target_non_stop\"" 50 51 # If GDB and GDBserver are both running locally, set the sysroot to avoid 52 # reading files via the remote protocol. 53 if { ![is_remote host] && ![is_remote target] } { 54 set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\"" 55 } 56 57 clean_restart ${binfile} 58 } 59 60 # Make sure we're disconnected, in case we're testing with an 61 # extended-remote board, therefore already connected. 62 gdb_test "disconnect" ".*" 63 64 set packet_arg "" 65 if { $disable_feature != "" } { 66 set packet_arg "--disable-packet=${disable_feature}" 67 } 68 set res [gdbserver_start $packet_arg $::target_binfile] 69 set gdbserver_protocol [lindex $res 0] 70 set gdbserver_gdbport [lindex $res 1] 71 72 # Disable XML-based thread listing, and multi-process extensions. 73 gdb_test \ 74 "set remote threads-packet off" \ 75 "Support for the 'qXfer:threads:read' packet on future remote targets is set to \"off\"." 76 gdb_test \ 77 "set remote multiprocess-feature-packet off" \ 78 "Support for the 'multiprocess-feature' packet on future remote targets is set to \"off\"." 79 80 set res [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport] 81 if ![gdb_assert {$res == 0} "connect"] { 82 return 83 } 84 85 # There should be only one thread listed at this point. 86 gdb_test_multiple "info threads" "" { 87 -re "2 ${tdlabel_re}.*$gdb_prompt $" { 88 fail $gdb_test_name 89 } 90 -re "has terminated.*$gdb_prompt $" { 91 fail $gdb_test_name 92 } 93 -re "\\\* 1\[\t \]*${tdlabel_re}\[^\r\n\]*\r\n$gdb_prompt $" { 94 pass $gdb_test_name 95 } 96 } 97 98 gdb_breakpoint "unlock_worker" 99 gdb_continue_to_breakpoint "run to unlock_worker" 100 101 # There should be two threads at this point with thread 1 selected. 102 gdb_test "info threads" \ 103 "\\\* 1\[\t \]*${tdlabel_re}\[^\r\n\]*\r\n 2\[\t \]*${tdlabel_re}\[^\r\n\]*" \ 104 "second thread should now exist" 105 106 # Switch threads. 107 gdb_test "thread 2" ".*" "switch to second thread" 108 109 # Now turn on scheduler-locking so that when we step thread 2 only 110 # that one thread will be set running. 111 gdb_test_no_output "set scheduler-locking on" 112 113 # Single step thread 2. Only the one thread will step. When the 114 # thread stops, if the stop packet doesn't include a thread-id 115 # then GDB should still understand which thread stopped. 116 gdb_test_multiple "stepi" "" { 117 -re -wrap "Thread 1 received signal SIGTRAP.*" { 118 fail $gdb_test_name 119 } 120 -re -wrap "$hex.*$decimal.*while \\(worker_blocked\\).*" { 121 pass $gdb_test_name 122 } 123 } 124 125 # Check that thread 2 is still selected. 126 gdb_test "info threads" \ 127 " 1\[\t \]*${tdlabel_re}\[^\r\n\]*\r\n\\\* 2\[\t \]*${tdlabel_re}\[^\r\n\]*" \ 128 "second thread should still be selected after stepi" 129 130 # Turn scheduler locking off again so that when we continue all 131 # threads will be set running. 132 gdb_test_no_output "set scheduler-locking off" 133 134 # Continue until exit. The server sends a 'W' with no PID. 135 # Bad GDB gave an error like below when target is nonstop: 136 # (gdb) c 137 # Continuing. 138 # No process or thread specified in stop reply: W00 139 gdb_continue_to_end "" continue 1 140 } 141 142 # Disable different features within gdbserver: 143 # 144 # Tthread: Start GDBserver, with ";thread:NNN" in T stop replies disabled, 145 # emulating old gdbservers when debugging single-threaded programs. 146 # 147 # T: Start GDBserver with the entire 'T' stop reply packet disabled, 148 # GDBserver will instead send the 'S' stop reply. 149 # 150 # Also test both all-stop and non-stop variants of the remote 151 # protocol. 152 foreach_with_prefix target-non-stop {"off" "on"} { 153 foreach_with_prefix to_disable { "" Tthread T } { 154 run_test ${target-non-stop} $to_disable 155 } 156 } 157