1 1.1.1.6 christos # Copyright 2016-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 # This test checks that the "thread", "select-frame", "frame" and "inferior" 17 1.1 christos # CLI commands, as well as the "-thread-select" and "-stack-select-frame" MI 18 1.1 christos # commands send the appropriate user-selection-change events to all UIs. 19 1.1 christos # 20 1.1 christos # This test considers the case where console and MI are two different UIs, 21 1.1 christos # and MI is created with the new-ui command. 22 1.1 christos # 23 1.1 christos # It also considers the case where the console commands are sent directly in 24 1.1 christos # the MI channel as described in PR 20487. 25 1.1 christos # 26 1.1 christos # It does so by starting 2 inferiors with 3 threads each. 27 1.1 christos # - Thread 1 of each inferior is the main thread, starting the others. 28 1.1 christos # - Thread 2 of each inferior is stopped at /* thread loop line */. 29 1.1 christos # - Thread 3 of each inferior is either stopped at /* thread loop line */, if we 30 1.1 christos # are using all-stop, or running, if we are using non-stop. 31 1.1 christos 32 1.1.1.4 christos # Do not run if gdb debug is enabled as it doesn't work for separate-mi-tty. 33 1.1.1.6 christos require !gdb_debug_enabled 34 1.1.1.4 christos 35 1.1 christos load_lib mi-support.exp 36 1.1 christos 37 1.1 christos standard_testfile 38 1.1 christos 39 1.1 christos # Multiple inferiors are needed, therefore only native gdb and extended 40 1.1 christos # gdbserver modes are supported. 41 1.1.1.6 christos require !use_gdb_stub 42 1.1 christos 43 1.1 christos set compile_options "debug pthreads" 44 1.1 christos if {[build_executable $testfile.exp $testfile ${srcfile} ${compile_options}] == -1} { 45 1.1.1.2 christos untested "failed to compile" 46 1.1 christos return -1 47 1.1 christos } 48 1.1 christos 49 1.1 christos set main_break_line [gdb_get_line_number "main break line"] 50 1.1 christos set thread_loop_line [gdb_get_line_number "thread loop line"] 51 1.1 christos set thread_caller_line [gdb_get_line_number "thread caller line"] 52 1.1 christos 53 1.1 christos # Return whether we expect thread THREAD to be running in mode MODE. 54 1.1 christos # 55 1.1 christos # MODE can be either "all-stop" or "non-stop". 56 1.1 christos # THREAD can be either a CLI thread id (e.g. 2.3) or an MI thread id (e.g. 6). 57 1.1 christos 58 1.1 christos proc thread_is_running { mode thread } { 59 1.1 christos if { $mode != "non-stop" } { 60 1.1 christos return 0 61 1.1 christos } 62 1.1 christos 63 1.1 christos return [expr { 64 1.1 christos $thread == 1.3 65 1.1 christos || $thread == 2.3 66 1.1 christos || $thread == 3 67 1.1 christos || $thread == 6 68 1.1 christos }] 69 1.1 christos } 70 1.1 christos 71 1.1 christos # Make a regular expression to match the various inferior/thread/frame selection 72 1.1 christos # events for CLI. 73 1.1 christos # 74 1.1 christos # MODE can be either "all-stop" or "non-stop", indicating which one is currently 75 1.1 christos # in use. 76 1.1 christos # INF is the inferior number we are expecting GDB to switch to, or -1 if we are 77 1.1 christos # not expecting GDB to announce an inferior switch. 78 1.1 christos # THREAD is the thread number we are expecting GDB to switch to, or -1 if we are 79 1.1 christos # not expecting GDB to announce a thread switch. 80 1.1 christos # FRAME is the frame number we are expecting GDB to switch to, or -1 if we are 81 1.1 christos # not expecting GDB to announce a frame switch. See the FRAME_RE variable for 82 1.1 christos # details. 83 1.1 christos 84 1.1 christos proc make_cli_re { mode inf thread frame } { 85 1.1 christos global srcfile 86 1.1 christos global thread_caller_line 87 1.1 christos global thread_loop_line 88 1.1 christos global main_break_line 89 1.1 christos global decimal 90 1.1 christos 91 1.1 christos set any "\[^\r\n\]*" 92 1.1 christos 93 1.1 christos set cli_re "" 94 1.1 christos 95 1.1 christos set inf_re "\\\[Switching to inferior $inf${any}\\\]" 96 1.1 christos set all_stop_thread_re "\\\[Switching to thread [string_to_regexp $thread]${any}\\\]" 97 1.1 christos 98 1.1 christos set frame_re(0) "#0${any}child_sub_function$any$srcfile:$thread_loop_line\r\n${any}thread loop line \\\*/" 99 1.1 christos set frame_re(1) "#1${any}child_function \\\(args=0x0\\\) at ${any}$srcfile:$thread_caller_line\r\n$thread_caller_line${any}/\\\* thread caller line \\\*/" 100 1.1 christos 101 1.1 christos # Special frame for main thread. 102 1.1 christos set frame_re(2) "#0${any}\r\n${main_break_line}${any}" 103 1.1 christos 104 1.1 christos if { $inf != -1 } { 105 1.1 christos append cli_re $inf_re 106 1.1 christos } 107 1.1 christos 108 1.1 christos if { $thread != -1 } { 109 1.1 christos if { $inf != -1 } { 110 1.1 christos append cli_re "\r\n" 111 1.1 christos } 112 1.1 christos set thread_re $all_stop_thread_re 113 1.1 christos 114 1.1 christos if [thread_is_running $mode $thread] { 115 1.1 christos set thread_re "$thread_re\\\(running\\\)" 116 1.1 christos } 117 1.1 christos 118 1.1 christos append cli_re $thread_re 119 1.1 christos } 120 1.1 christos 121 1.1 christos if { $frame != -1 } { 122 1.1 christos if { $thread != -1 } { 123 1.1 christos append cli_re "\r\n" 124 1.1 christos } 125 1.1 christos append cli_re $frame_re($frame) 126 1.1 christos } 127 1.1 christos 128 1.1 christos return $cli_re 129 1.1 christos } 130 1.1 christos 131 1.1 christos # Make a regular expression to match the various inferior/thread/frame selection 132 1.1 christos # events for MI. 133 1.1 christos # 134 1.1 christos # MODE can be either "all-stop" or "non-stop", indicating which one is currently 135 1.1 christos # in use. 136 1.1 christos # THREAD is the thread number we are expecting GDB to switch to, or -1 if we are 137 1.1 christos # not expecting GDB to announce a thread switch. 138 1.1 christos # If EVENT is 1, build a regex for an "=thread-selected" async event. 139 1.1 christos # Otherwise, build a regex for a response to a command. 140 1.1 christos # FRAME is the frame number we are expecting GDB to switch to, or -1 if we are 141 1.1 christos # not expecting GDB to announce a frame switch. See the FRAME_RE variable for 142 1.1 christos # details. 143 1.1 christos 144 1.1 christos proc make_mi_re { mode thread frame type } { 145 1.1 christos global srcfile 146 1.1 christos global hex 147 1.1 christos global decimal 148 1.1 christos global thread_loop_line 149 1.1 christos global main_break_line 150 1.1 christos global thread_caller_line 151 1.1 christos 152 1.1 christos set any "\[^\r\n\]*" 153 1.1 christos 154 1.1 christos set mi_re "" 155 1.1 christos 156 1.1 christos set thread_event_re "=thread-selected,id=\"$thread\"" 157 1.1 christos set thread_answer_re "\\^done,new-thread-id=\"$thread\"" 158 1.1 christos 159 1.1.1.3 christos set frame_re(0) ",frame=\{level=\"0\",addr=\"$hex\",func=\"child_sub_function\",args=\\\[\\\],file=\"${any}${srcfile}\",fullname=\"${any}${srcfile}\",line=\"$thread_loop_line\",arch=\"$any\"\}" 160 1.1.1.3 christos set frame_re(1) ",frame=\{level=\"1\",addr=\"$hex\",func=\"child_function\",args=\\\[\{name=\"args\",value=\"0x0\"\}\\\],file=\"${any}${srcfile}\",fullname=\"${any}${srcfile}\",line=\"$thread_caller_line\",arch=\"$any\"\}" 161 1.1 christos 162 1.1 christos # Special frame for main thread. 163 1.1.1.3 christos set frame_re(2) ",frame=\{level=\"0\",addr=\"$hex\",func=\"main\",args=\\\[\\\],file=\"${any}${srcfile}\",fullname=\"${any}${srcfile}\",line=\"${main_break_line}\",arch=\"$any\"\}" 164 1.1 christos 165 1.1 christos if { $thread != -1 } { 166 1.1 christos if { $type == "event" } { 167 1.1 christos append mi_re $thread_event_re 168 1.1 christos } elseif { $type == "response" } { 169 1.1 christos append mi_re $thread_answer_re 170 1.1 christos } else { 171 1.1 christos error "Invalid value for EVENT." 172 1.1 christos } 173 1.1 christos } 174 1.1 christos 175 1.1 christos if { $frame != -1 } { 176 1.1 christos append mi_re $frame_re($frame) 177 1.1 christos } 178 1.1 christos 179 1.1 christos if { $type == "event" } { 180 1.1 christos append mi_re "\r\n" 181 1.1 christos } 182 1.1 christos 183 1.1 christos return $mi_re 184 1.1 christos } 185 1.1 christos 186 1.1 christos # Make a regular expression to match the various inferior/thread/frame selection 187 1.1 christos # events when issuing CLI commands inside MI. 188 1.1 christos # 189 1.1 christos # COMMAND is the CLI command that was sent to GDB, which will be output in the 190 1.1 christos # console output stream. 191 1.1 christos # CLI_IN_MI_MODE indicates which method of CLI-in-MI command is used. It can be 192 1.1 christos # either "direct" of "interpreter-exec". 193 1.1 christos # MODE can be either "all-stop" or "non-stop", indicating which one is currently 194 1.1 christos # in use. 195 1.1 christos # If EVENT is 1, expect a =thread-select MI event. 196 1.1 christos # INF is the inferior number we are expecting GDB to switch to, or -1 if we are 197 1.1 christos # not expecting GDB to announce an inferior switch. 198 1.1 christos # CLI_THREAD is the thread number as seen in the CLI (inferior-qualified) we are 199 1.1 christos # expecting GDB to switch to, or -1 if we are not expecting GDB to announce a 200 1.1 christos # thread switch. 201 1.1 christos # MI_THREAD is the thread number as seen in the MI (global number) we are 202 1.1 christos # expecting GDB to switch to, or -1 if we are not expecting GDB to announce a 203 1.1 christos # thread switch. 204 1.1 christos # FRAME is the frame number we are expecting GDB to switch to, or -1 if we are 205 1.1 christos # not expecting GDB to announce a frame switch. See the FRAME_RE variable for 206 1.1 christos # details. 207 1.1 christos 208 1.1 christos proc make_cli_in_mi_re { command cli_in_mi_mode mode event inf cli_thread 209 1.1 christos mi_thread frame } { 210 1.1 christos global srcfile 211 1.1 christos global thread_loop_line 212 1.1 christos global main_break_line 213 1.1 christos global thread_caller_line 214 1.1 christos 215 1.1 christos set any "\[^\r\n\]*" 216 1.1 christos 217 1.1 christos set command_re [string_to_regexp $command] 218 1.1 christos set cli_in_mi_re "$command_re\r\n" 219 1.1 christos 220 1.1 christos if { $cli_in_mi_mode == "direct" } { 221 1.1 christos append cli_in_mi_re "&\"$command_re\\\\n\"\r\n" 222 1.1 christos } 223 1.1 christos 224 1.1 christos set frame_re(0) "~\"#0${any}child_sub_function${any}$srcfile:$thread_loop_line\\\\n\"\r\n~\"${thread_loop_line}${any}thread loop line \\\*/\\\\n\"\r\n" 225 1.1 christos set frame_re(1) "~\"#1${any}child_function \\\(args=0x0\\\) at ${any}$srcfile:$thread_caller_line\\\\n\"\r\n~\"$thread_caller_line${any}thread caller line \\\*/\\\\n\"\r\n" 226 1.1 christos 227 1.1 christos # Special frame for main thread. 228 1.1 christos set frame_re(2) "~\"#0${any}main${any}\\\\n\"\r\n~\"${main_break_line}${any}\"\r\n" 229 1.1 christos 230 1.1 christos if { $inf != -1 } { 231 1.1 christos append cli_in_mi_re "~\"" 232 1.1 christos append cli_in_mi_re [make_cli_re $mode $inf -1 -1] 233 1.1 christos append cli_in_mi_re "\\\\n\"\r\n" 234 1.1 christos } 235 1.1 christos 236 1.1 christos if { $cli_thread != "-1" } { 237 1.1 christos append cli_in_mi_re "~\"" 238 1.1 christos append cli_in_mi_re [make_cli_re $mode -1 $cli_thread -1] 239 1.1 christos append cli_in_mi_re "\\\\n\"\r\n" 240 1.1 christos } 241 1.1 christos 242 1.1 christos if { $frame != -1 } { 243 1.1 christos append cli_in_mi_re $frame_re($frame) 244 1.1 christos } 245 1.1 christos 246 1.1 christos if { $event == 1 } { 247 1.1 christos append cli_in_mi_re [make_mi_re $mode $mi_thread $frame event] 248 1.1 christos } 249 1.1 christos 250 1.1 christos append cli_in_mi_re "\\^done" 251 1.1 christos 252 1.1 christos return $cli_in_mi_re 253 1.1 christos } 254 1.1 christos 255 1.1 christos # Return the current value of the "scheduler-locking" parameter. 256 1.1 christos 257 1.1 christos proc show_scheduler_locking { } { 258 1.1 christos global gdb_prompt 259 1.1 christos global expect_out 260 1.1 christos 261 1.1 christos set any "\[^\r\n\]*" 262 1.1 christos 263 1.1 christos set test "show scheduler-locking" 264 1.1 christos gdb_test_multiple $test $test { 265 1.1 christos -re ".*Mode for locking scheduler during execution is \"(${any})\".\r\n$gdb_prompt " { 266 1.1 christos pass $test 267 1.1 christos return $expect_out(1,string) 268 1.1 christos } 269 1.1 christos } 270 1.1 christos 271 1.1 christos error "Couldn't get current scheduler-locking value." 272 1.1 christos } 273 1.1 christos 274 1.1 christos # Prepare inferior INF so it is in the state we expect (see comment at the top). 275 1.1 christos 276 1.1 christos proc test_continue_to_start { mode inf } { 277 1.1 christos global gdb_spawn_id 278 1.1 christos global mi_spawn_id 279 1.1 christos global gdb_main_spawn_id 280 1.1 christos global srcfile 281 1.1 christos global main_break_line 282 1.1 christos global thread_loop_line 283 1.1 christos global decimal 284 1.1 christos global gdb_prompt 285 1.1 christos 286 1.1 christos set any "\[^\r\n\]*" 287 1.1 christos 288 1.1 christos if { $gdb_spawn_id != $gdb_main_spawn_id } { 289 1.1 christos error "This should not happen." 290 1.1 christos } 291 1.1 christos 292 1.1 christos with_test_prefix "inferior $inf" { 293 1.1 christos with_spawn_id $gdb_main_spawn_id { 294 1.1 christos # Continue to the point where we know for sure the threads are 295 1.1 christos # started. 296 1.1 christos gdb_test "tbreak $srcfile:$main_break_line" \ 297 1.1 christos "Temporary breakpoint ${any}" \ 298 1.1 christos "set breakpoint in main" 299 1.1 christos 300 1.1 christos gdb_continue_to_breakpoint "main breakpoint" 301 1.1 christos 302 1.1 christos # Consume MI event output. 303 1.1 christos with_spawn_id $mi_spawn_id { 304 1.1.1.5 christos if { $inf == 1 } { 305 1.1.1.5 christos mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" \ 306 1.1.1.5 christos "$decimal" {"" "disp=\"del\""} "stop at breakpoint in main" 307 1.1.1.5 christos } else { 308 1.1.1.5 christos mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" \ 309 1.1.1.5 christos "$decimal" {"" "disp=\"del\"" "locno=\"[0-9]+\""} "stop at breakpoint in main" 310 1.1.1.5 christos } 311 1.1 christos } 312 1.1 christos 313 1.1 christos if { $mode == "all-stop" } { 314 1.1 christos set previous_schedlock_val [show_scheduler_locking] 315 1.1 christos 316 1.1 christos # Set scheduler-locking on, so that we can control threads 317 1.1 christos # independently. 318 1.1 christos gdb_test_no_output "set scheduler-locking on" 319 1.1 christos 320 1.1 christos # Continue each child thread to the point we want them to be. 321 1.1 christos foreach thread { 2 3 } { 322 1.1 christos gdb_test "thread $inf.$thread" ".*" "select child thread $inf.$thread" 323 1.1 christos 324 1.1 christos gdb_test "tbreak $srcfile:$thread_loop_line" \ 325 1.1 christos "Temporary breakpoint ${any}" \ 326 1.1 christos "set breakpoint for thread $inf.$thread" 327 1.1 christos 328 1.1 christos gdb_continue_to_breakpoint "continue thread $inf.$thread to infinite loop breakpoint" 329 1.1 christos 330 1.1 christos # Consume MI output. 331 1.1 christos with_spawn_id $mi_spawn_id { 332 1.1.1.5 christos if { $inf == 1} { 333 1.1.1.5 christos mi_expect_stop "breakpoint-hit" "child_sub_function" \ 334 1.1.1.5 christos "" "$srcfile" "$decimal" {"" "disp=\"del\""} \ 335 1.1.1.5 christos "thread $inf.$thread stops MI" 336 1.1.1.5 christos } else { 337 1.1.1.5 christos mi_expect_stop "breakpoint-hit" "child_sub_function" \ 338 1.1.1.5 christos "" "$srcfile" "$decimal" {"" "disp=\"del\"" "locno=\"[0-9]+\""} \ 339 1.1.1.5 christos "thread $inf.$thread stops MI" 340 1.1.1.5 christos } 341 1.1 christos } 342 1.1 christos } 343 1.1 christos 344 1.1 christos # Restore scheduler-locking to its original value. 345 1.1 christos gdb_test_no_output "set scheduler-locking $previous_schedlock_val" 346 1.1 christos } else { # $mode == "non-stop" 347 1.1 christos # Put a thread-specific breakpoint for thread 2 of the current 348 1.1 christos # inferior. We don't put a breakpoint for thread 3, since we 349 1.1 christos # want to let it run. 350 1.1 christos set test "set thread-specific breakpoint, thread $inf.2" 351 1.1 christos gdb_test_multiple "tbreak $srcfile:$thread_loop_line thread $inf.2" $test { 352 1.1 christos -re "Temporary breakpoint ${any}\r\n$gdb_prompt " { 353 1.1 christos pass $test 354 1.1 christos } 355 1.1 christos } 356 1.1 christos 357 1.1 christos # Confirm the stop of thread $inf.2. 358 1.1 christos set test "thread $inf.2 stops CLI" 359 1.1 christos gdb_test_multiple "" $test { 360 1.1 christos -re "Thread $inf.2 ${any} hit Temporary breakpoint ${any}\r\n$thread_loop_line${any}\r\n" { 361 1.1 christos pass $test 362 1.1 christos } 363 1.1 christos } 364 1.1 christos 365 1.1 christos # Consume MI output. 366 1.1 christos with_spawn_id $mi_spawn_id { 367 1.1.1.7 christos mi_expect_stop "breakpoint-hit" "child_sub_function" \ 368 1.1.1.7 christos "" "$srcfile" "$decimal" {"" "disp=\"del\""} \ 369 1.1.1.7 christos "thread $inf.2 stops MI" 370 1.1 christos } 371 1.1 christos } 372 1.1 christos } 373 1.1 christos } 374 1.1 christos } 375 1.1 christos 376 1.1 christos # Prepare the test environment. 377 1.1 christos # 378 1.1 christos # MODE can be either "all-stop" or "non-stop". 379 1.1 christos 380 1.1.1.2 christos proc_with_prefix test_setup { mode } { 381 1.1 christos global srcfile 382 1.1 christos global srcdir 383 1.1 christos global subdir 384 1.1 christos global gdb_main_spawn_id 385 1.1 christos global mi_spawn_id 386 1.1 christos global decimal 387 1.1 christos global binfile 388 1.1 christos global GDBFLAGS 389 1.1 christos global async 390 1.1 christos 391 1.1 christos set any "\[^\r\n\]*" 392 1.1 christos 393 1.1 christos save_vars { GDBFLAGS } { 394 1.1 christos if { $mode == "non-stop" } { 395 1.1 christos set GDBFLAGS [concat $GDBFLAGS " -ex \"set non-stop 1\""] 396 1.1 christos } 397 1.1 christos 398 1.1.1.6 christos if { [mi_clean_restart $binfile "separate-mi-tty"] != 0 } { 399 1.1.1.5 christos return -1 400 1.1 christos } 401 1.1 christos } 402 1.1 christos 403 1.1.1.5 christos if { [mi_runto_main] < 0 } { 404 1.1.1.5 christos return -1 405 1.1 christos } 406 1.1 christos 407 1.1 christos # When using mi_expect_stop, we don't expect a prompt after the *stopped 408 1.1 christos # event, since the blocking commands are done from the CLI. Setting async 409 1.1 christos # to 1 makes it not expect the prompt. 410 1.1 christos set async 1 411 1.1 christos 412 1.1 christos with_spawn_id $gdb_main_spawn_id { 413 1.1 christos # Add the second inferior now. While this is not mandatory, it allows 414 1.1 christos # us to assume that per-inferior thread numbering will be used, 415 1.1 christos # simplifying test_continue_to_start a bit (Thread 1.2 and not Thread 2). 416 1.1.1.4 christos gdb_test "add-inferior" "Added inferior 2 on connection .*" "add inferior 2" 417 1.1 christos 418 1.1 christos # Prepare the first inferior for the test. 419 1.1 christos test_continue_to_start $mode 1 420 1.1 christos 421 1.1 christos # Switch to and start the second inferior. 422 1.1 christos gdb_test "inferior 2" "\\\[Switching to inferior 2${any}\\\]" "switch to inferior 2" 423 1.1 christos gdb_load ${binfile} 424 1.1 christos 425 1.1 christos # Doing "start" on the CLI generates a ton of MI output. At some point, 426 1.1 christos # if we don't consume/match it, the buffer between GDB's MI channel and 427 1.1 christos # Expect will get full, GDB will block on a write system call and we'll 428 1.1 christos # deadlock, waiting for CLI output that will never arrive. And then 429 1.1 christos # we're sad. So instead of using gdb_test and expect CLI output, send 430 1.1 christos # the start command first, then consume MI output, and finally consume 431 1.1 christos # CLI output. 432 1.1 christos send_gdb "start\n" 433 1.1 christos 434 1.1 christos with_spawn_id $mi_spawn_id { 435 1.1 christos mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" "$decimal" \ 436 1.1.1.7 christos {"" "disp=\"del\""} "main stop" 437 1.1 christos } 438 1.1 christos 439 1.1 christos # Consume CLI output. 440 1.1 christos gdb_test "" "Temporary breakpoint.*Starting program.*" 441 1.1 christos 442 1.1 christos # Prepare the second inferior for the test. 443 1.1 christos test_continue_to_start $mode 2 444 1.1 christos } 445 1.1.1.5 christos 446 1.1.1.5 christos return 0 447 1.1 christos } 448 1.1 christos 449 1.1 christos # Reset the selection to frame #0 of thread THREAD. 450 1.1 christos 451 1.1 christos proc reset_selection { thread } { 452 1.1 christos global gdb_main_spawn_id 453 1.1 christos 454 1.1 christos set any "\[^\r\n\]*" 455 1.1 christos 456 1.1 christos with_spawn_id $gdb_main_spawn_id { 457 1.1 christos gdb_test "thread $thread" \ 458 1.1 christos "\\\[Switching to thread $thread ${any}\\\].*" \ 459 1.1 christos "reset selection to thread $thread" 460 1.1 christos gdb_test "frame 0" ".*" "reset selection to frame 0" 461 1.1 christos } 462 1.1 christos } 463 1.1 christos 464 1.1 christos # Flush Expect's internal buffers for both CLI and MI. 465 1.1 christos # 466 1.1 christos # The idea here is to send a command, and to consume all the characters that we 467 1.1 christos # expect that command to output, including the following prompt. Using gdb_test 468 1.1 christos # and mi_gdb_test should do that. 469 1.1 christos 470 1.1 christos proc flush_buffers { } { 471 1.1 christos global gdb_main_spawn_id mi_spawn_id 472 1.1 christos 473 1.1 christos with_spawn_id $gdb_main_spawn_id { 474 1.1 christos gdb_test "print 444" "= 444" "flush CLI" 475 1.1 christos } 476 1.1 christos 477 1.1 christos with_spawn_id $mi_spawn_id { 478 1.1 christos mi_gdb_test "555-data-evaluate-expression 666" ".*done,value=\"666\"" "flush MI" 479 1.1 christos } 480 1.1 christos } 481 1.1 christos 482 1.1 christos # Run a command on the current spawn id, to confirm that no output is pending 483 1.1 christos # in Expect's internal buffer. This is used to ensure that nothing was output 484 1.1 christos # on the spawn id since the call to gdb_test/mi_gdb_test/flush_buffers. 485 1.1 christos # 486 1.1 christos # The key here is that the regexes use start-of-buffer anchors (^), ensuring 487 1.1 christos # that they match the entire buffer, confirming that there was nothing in it 488 1.1 christos # before. 489 1.1 christos 490 1.1 christos proc ensure_no_output { test } { 491 1.1 christos global gdb_spawn_id gdb_main_spawn_id mi_spawn_id 492 1.1 christos global decimal 493 1.1 christos 494 1.1 christos if { $gdb_spawn_id == $gdb_main_spawn_id } { 495 1.1 christos # CLI 496 1.1 christos gdb_test "print 666" \ 497 1.1.1.6 christos "^\\\$$decimal = 666" \ 498 1.1 christos "$test, ensure no output CLI" 499 1.1 christos } elseif { $gdb_spawn_id == $mi_spawn_id } { 500 1.1 christos # MI 501 1.1 christos mi_gdb_test "777-data-evaluate-expression 888" \ 502 1.1 christos "^777-data-evaluate-expression 888\r\n777\\^done,value=\"888\"" \ 503 1.1 christos "$test, ensure no output MI" 504 1.1 christos } else { 505 1.1 christos error "Unexpected gdb_spawn_id value." 506 1.1 christos } 507 1.1 christos } 508 1.1 christos 509 1.1 christos # Match a regular expression, or ensure that there was no output. 510 1.1 christos # 511 1.1 christos # If RE is non-empty, try to match the content of the program output (using the 512 1.1 christos # current spawn_id) and pass/fail TEST accordingly. 513 1.1 christos # If RE is empty, ensure that the program did not output anything. 514 1.1 christos 515 1.1.1.5 christos proc match_re_or_ensure_no_output { re test } { 516 1.1 christos if { $re != "" } { 517 1.1 christos gdb_expect { 518 1.1 christos -re "$re" { 519 1.1 christos pass $test 520 1.1 christos } 521 1.1 christos 522 1.1 christos default { 523 1.1 christos fail $test 524 1.1 christos } 525 1.1 christos } 526 1.1 christos } else { 527 1.1 christos ensure_no_output $test 528 1.1 christos } 529 1.1 christos } 530 1.1 christos 531 1.1 christos # Test selecting an inferior from CLI. 532 1.1 christos 533 1.1.1.2 christos proc_with_prefix test_cli_inferior { mode } { 534 1.1 christos global gdb_main_spawn_id mi_spawn_id 535 1.1 christos 536 1.1 christos reset_selection "1.1" 537 1.1 christos 538 1.1 christos set mi_re [make_mi_re $mode 4 2 event] 539 1.1 christos set cli_re [make_cli_re $mode 2 2.1 2] 540 1.1 christos 541 1.1 christos flush_buffers 542 1.1 christos 543 1.1 christos # Do the 'inferior' command. 544 1.1 christos with_spawn_id $gdb_main_spawn_id { 545 1.1 christos gdb_test "inferior 2" $cli_re "CLI select inferior" 546 1.1 christos } 547 1.1 christos 548 1.1 christos with_spawn_id $mi_spawn_id { 549 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "event on MI" 550 1.1 christos } 551 1.1 christos 552 1.1 christos # Do the 'inferior' command on the currently selected inferior. For now, 553 1.1 christos # GDB naively re-outputs everything. 554 1.1 christos with_spawn_id $gdb_main_spawn_id { 555 1.1 christos gdb_test "inferior 2" $cli_re "CLI select inferior again" 556 1.1 christos } 557 1.1 christos 558 1.1 christos with_spawn_id $mi_spawn_id { 559 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "event on MI again" 560 1.1 christos } 561 1.1 christos } 562 1.1 christos 563 1.1 christos # Test thread selection from CLI. 564 1.1 christos 565 1.1.1.2 christos proc_with_prefix test_cli_thread { mode } { 566 1.1 christos global gdb_main_spawn_id 567 1.1 christos global mi_spawn_id 568 1.1 christos 569 1.1 christos set any "\[^\r\n\]*" 570 1.1 christos 571 1.1 christos reset_selection "1.1" 572 1.1 christos flush_buffers 573 1.1 christos 574 1.1 christos with_test_prefix "thread 1.2" { 575 1.1 christos # Do the 'thread' command to select a stopped thread. 576 1.1 christos 577 1.1 christos set mi_re [make_mi_re $mode 2 0 event] 578 1.1 christos set cli_re [make_cli_re $mode -1 1.2 0] 579 1.1 christos 580 1.1 christos with_spawn_id $gdb_main_spawn_id { 581 1.1 christos gdb_test "thread 1.2" $cli_re "select thread" 582 1.1 christos } 583 1.1 christos 584 1.1 christos with_spawn_id $mi_spawn_id { 585 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select thread, event on MI " 586 1.1 christos } 587 1.1 christos 588 1.1 christos # Do the 'thread' command to select the same thread. We shouldn't receive 589 1.1 christos # an event on MI, since we won't actually switch thread. 590 1.1 christos 591 1.1 christos set mi_re "" 592 1.1 christos 593 1.1 christos with_spawn_id $gdb_main_spawn_id { 594 1.1 christos gdb_test "thread 1.2" $cli_re "select thread again" 595 1.1 christos } 596 1.1 christos 597 1.1 christos with_spawn_id $mi_spawn_id { 598 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select thread, event on MI again" 599 1.1 christos } 600 1.1 christos 601 1.1 christos # Try the 'thread' command without arguments. 602 1.1 christos 603 1.1 christos set cli_re "\\\[Current thread is 1\\.2.*\\\]" 604 1.1 christos set mi_re "" 605 1.1 christos 606 1.1 christos with_spawn_id $gdb_main_spawn_id { 607 1.1 christos gdb_test "thread" $cli_re "thread without args" 608 1.1 christos } 609 1.1 christos 610 1.1 christos with_spawn_id $mi_spawn_id { 611 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "thread without args, event on MI" 612 1.1 christos } 613 1.1 christos } 614 1.1 christos 615 1.1 christos with_test_prefix "thread 1.3" { 616 1.1 christos # Do the 'thread' command to select the third thread, stopped on all-stop, 617 1.1 christos # running on non-stop. 618 1.1 christos 619 1.1 christos if { $mode == "all-stop" } { 620 1.1 christos set cli_re [make_cli_re $mode -1 1.3 0] 621 1.1 christos set mi_re [make_mi_re $mode 3 0 event] 622 1.1 christos } else { 623 1.1 christos set cli_re [make_cli_re $mode -1 1.3 -1] 624 1.1 christos set mi_re [make_mi_re $mode 3 -1 event] 625 1.1 christos } 626 1.1 christos 627 1.1 christos with_spawn_id $gdb_main_spawn_id { 628 1.1 christos gdb_test "thread 1.3" $cli_re "select thread" 629 1.1 christos } 630 1.1 christos 631 1.1 christos with_spawn_id $mi_spawn_id { 632 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select thread, event on MI" 633 1.1 christos } 634 1.1 christos 635 1.1 christos # Do the 'thread' command to select the third thread again. Again, we 636 1.1 christos # shouldn't receive an event on MI. 637 1.1 christos 638 1.1 christos set mi_re "" 639 1.1 christos 640 1.1 christos with_spawn_id $gdb_main_spawn_id { 641 1.1 christos gdb_test "thread 1.3" $cli_re "select thread again" 642 1.1 christos } 643 1.1 christos 644 1.1 christos with_spawn_id $mi_spawn_id { 645 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select thread again, event on MI" 646 1.1 christos } 647 1.1 christos 648 1.1 christos # Try the 'thread' command without arguments. 649 1.1 christos 650 1.1 christos set cli_re "\\\[Current thread is 1\\.3 ${any}\\\]" 651 1.1 christos set mi_re "" 652 1.1 christos 653 1.1 christos with_spawn_id $gdb_main_spawn_id { 654 1.1 christos gdb_test "thread" $cli_re "thread without args" 655 1.1 christos } 656 1.1 christos 657 1.1 christos with_spawn_id $mi_spawn_id { 658 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "thread without args, event on MI" 659 1.1 christos } 660 1.1 christos } 661 1.1 christos 662 1.1 christos # Idea for the future: selecting a thread in a different inferior. For now, 663 1.1 christos # GDB doesn't show an inferior switch, but if it did, it would be a nice 664 1.1 christos # place to test it. 665 1.1 christos } 666 1.1 christos 667 1.1 christos # Test frame selection from CLI. 668 1.1 christos 669 1.1.1.2 christos proc_with_prefix test_cli_frame { mode } { 670 1.1 christos global gdb_main_spawn_id mi_spawn_id 671 1.1 christos 672 1.1 christos with_test_prefix "thread 1.2" { 673 1.1 christos reset_selection "1.2" 674 1.1 christos flush_buffers 675 1.1 christos 676 1.1 christos # Do the 'frame' command to select frame 1. 677 1.1 christos 678 1.1 christos set mi_re [make_mi_re $mode 2 1 event] 679 1.1 christos set cli_re [make_cli_re $mode -1 -1 1] 680 1.1 christos 681 1.1 christos with_spawn_id $gdb_main_spawn_id { 682 1.1 christos gdb_test "frame 1" $cli_re "select frame 1" 683 1.1 christos } 684 1.1 christos 685 1.1 christos with_spawn_id $mi_spawn_id { 686 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1, event on MI" 687 1.1 christos } 688 1.1 christos 689 1.1 christos # Do the 'frame' command to select the same frame. This time we don't 690 1.1 christos # expect an event on MI, since we won't actually change frame. 691 1.1 christos 692 1.1 christos set mi_re "" 693 1.1 christos 694 1.1 christos with_spawn_id $gdb_main_spawn_id { 695 1.1 christos gdb_test "frame 1" $cli_re "select frame 1 again" 696 1.1 christos } 697 1.1 christos 698 1.1 christos with_spawn_id $mi_spawn_id { 699 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1 again, event on MI" 700 1.1 christos } 701 1.1 christos 702 1.1 christos # Do the 'frame' command without arguments. We shouldn't see anything on MI. 703 1.1 christos 704 1.1 christos with_spawn_id $gdb_main_spawn_id { 705 1.1 christos gdb_test "frame" $cli_re "frame without args" 706 1.1 christos } 707 1.1 christos 708 1.1 christos with_spawn_id $mi_spawn_id { 709 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "frame without args, event on MI" 710 1.1 christos } 711 1.1 christos } 712 1.1 christos 713 1.1 christos with_test_prefix "thread 1.3" { 714 1.1 christos # Now, try the 'frame' command on thread 3, which is running if we are in 715 1.1 christos # non-stop mode. 716 1.1 christos reset_selection "1.3" 717 1.1 christos flush_buffers 718 1.1 christos 719 1.1 christos if {$mode == "all-stop"} { 720 1.1 christos set mi_re [make_mi_re $mode 3 1 event] 721 1.1 christos set cli_re [make_cli_re $mode -1 -1 1] 722 1.1 christos } elseif {$mode == "non-stop"} { 723 1.1 christos set mi_re "" 724 1.1 christos set cli_re "Selected thread is running\\." 725 1.1 christos } 726 1.1 christos 727 1.1 christos with_spawn_id $gdb_main_spawn_id { 728 1.1 christos gdb_test "frame 1" $cli_re "select frame 1" 729 1.1 christos } 730 1.1 christos 731 1.1 christos with_spawn_id $mi_spawn_id { 732 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1, event on MI" 733 1.1 christos } 734 1.1 christos 735 1.1 christos # Do the 'frame' command without arguments. 736 1.1 christos 737 1.1 christos if { $mode == "non-stop" } { 738 1.1 christos set cli_re "No stack\\." 739 1.1 christos } 740 1.1 christos set mi_re "" 741 1.1 christos 742 1.1 christos with_spawn_id $gdb_main_spawn_id { 743 1.1 christos gdb_test "frame" $cli_re "frame without args" 744 1.1 christos } 745 1.1 christos 746 1.1 christos with_spawn_id $mi_spawn_id { 747 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "frame without args, event on MI" 748 1.1 christos } 749 1.1 christos } 750 1.1 christos } 751 1.1 christos 752 1.1 christos # Test frame selection from CLI with the select-frame command. 753 1.1 christos 754 1.1.1.2 christos proc_with_prefix test_cli_select_frame { mode } { 755 1.1 christos global gdb_main_spawn_id mi_spawn_id expect_out 756 1.1 christos 757 1.1 christos with_test_prefix "thread 1.2" { 758 1.1 christos reset_selection "1.2" 759 1.1 christos flush_buffers 760 1.1 christos 761 1.1 christos # Do the 'select-frame' command to select frame 1. 762 1.1 christos 763 1.1 christos set mi_re [make_mi_re $mode 2 1 event] 764 1.1 christos 765 1.1 christos with_spawn_id $gdb_main_spawn_id { 766 1.1 christos gdb_test_no_output "select-frame 1" "select frame 1" 767 1.1 christos } 768 1.1 christos 769 1.1 christos with_spawn_id $mi_spawn_id { 770 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1, event on MI" 771 1.1 christos } 772 1.1 christos 773 1.1 christos # Do the 'select-frame' command to select the same frame. This time we expect to 774 1.1 christos # event on MI, since we won't actually change frame. 775 1.1 christos 776 1.1 christos set mi_re "" 777 1.1 christos 778 1.1 christos with_spawn_id $gdb_main_spawn_id { 779 1.1 christos gdb_test_no_output "select-frame 1" "select frame 1 again" 780 1.1 christos } 781 1.1 christos 782 1.1 christos with_spawn_id $mi_spawn_id { 783 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1 again, event on MI" 784 1.1 christos } 785 1.1 christos } 786 1.1 christos 787 1.1 christos with_test_prefix "thread 1.3" { 788 1.1 christos # Now, try the 'select-frame' command on thread 3, which is running if we are in 789 1.1 christos # non-stop mode. 790 1.1 christos reset_selection "1.3" 791 1.1 christos flush_buffers 792 1.1 christos 793 1.1 christos if {$mode == "all-stop"} { 794 1.1 christos set mi_re [make_mi_re $mode 3 1 event] 795 1.1 christos } elseif {$mode == "non-stop"} { 796 1.1 christos set mi-re "" 797 1.1 christos set cli_re "Selected thread is running\\." 798 1.1 christos } 799 1.1 christos 800 1.1 christos with_spawn_id $gdb_main_spawn_id { 801 1.1 christos if { $mode == "all-stop" } { 802 1.1 christos gdb_test_no_output "select-frame 1" "select frame 1" 803 1.1 christos } else { 804 1.1 christos gdb_test "select-frame 1" $cli_re "select frame 1" 805 1.1 christos } 806 1.1 christos } 807 1.1 christos 808 1.1 christos with_spawn_id $mi_spawn_id { 809 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1, event on MI" 810 1.1 christos } 811 1.1 christos } 812 1.1 christos } 813 1.1 christos 814 1.1 christos # Test doing an up and then down command from CLI. 815 1.1 christos 816 1.1.1.2 christos proc_with_prefix test_cli_up_down { mode } { 817 1.1 christos global gdb_main_spawn_id mi_spawn_id 818 1.1 christos 819 1.1 christos reset_selection "1.2" 820 1.1 christos flush_buffers 821 1.1 christos 822 1.1 christos # Try doing an 'up'. 823 1.1 christos 824 1.1 christos set mi_re [make_mi_re $mode 2 1 event] 825 1.1 christos set cli_re [make_cli_re $mode -1 -1 1] 826 1.1 christos 827 1.1 christos with_spawn_id $gdb_main_spawn_id { 828 1.1 christos gdb_test "up" $cli_re "frame up" 829 1.1 christos } 830 1.1 christos 831 1.1 christos with_spawn_id $mi_spawn_id { 832 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "frame up, event on MI" 833 1.1 christos } 834 1.1 christos 835 1.1 christos # Try doing a 'down'. 836 1.1 christos 837 1.1 christos set mi_re [make_mi_re $mode 2 0 event] 838 1.1 christos set cli_re [make_cli_re $mode -1 -1 0] 839 1.1 christos 840 1.1 christos with_spawn_id $gdb_main_spawn_id { 841 1.1 christos gdb_test "down" $cli_re "frame down" 842 1.1 christos } 843 1.1 christos 844 1.1 christos with_spawn_id $mi_spawn_id { 845 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "frame down, event on MI" 846 1.1 christos } 847 1.1 christos } 848 1.1 christos 849 1.1 christos # Test selecting a thread from MI. 850 1.1 christos 851 1.1.1.2 christos proc_with_prefix test_mi_thread_select { mode } { 852 1.1 christos global gdb_main_spawn_id mi_spawn_id 853 1.1 christos 854 1.1 christos reset_selection "1.1" 855 1.1 christos flush_buffers 856 1.1 christos 857 1.1 christos with_test_prefix "thread 1.2" { 858 1.1 christos # Do the '-thread-select' command to select a stopped thread. 859 1.1 christos 860 1.1 christos set mi_re [make_mi_re $mode 2 0 response] 861 1.1 christos set cli_re [make_cli_re $mode -1 1.2 0] 862 1.1 christos 863 1.1 christos with_spawn_id $mi_spawn_id { 864 1.1 christos mi_gdb_test "-thread-select 2" $mi_re "-thread-select" 865 1.1 christos } 866 1.1 christos 867 1.1 christos with_spawn_id $gdb_main_spawn_id { 868 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-thread-select, event on CLI" 869 1.1 christos } 870 1.1 christos 871 1.1 christos # Do the '-thread-select' command to select the same thread. We 872 1.1 christos # shouldn't receive an event on CLI, since we won't actually switch 873 1.1 christos # thread. 874 1.1 christos 875 1.1 christos set cli_re "" 876 1.1 christos 877 1.1 christos with_spawn_id $mi_spawn_id { 878 1.1 christos mi_gdb_test "-thread-select 2" $mi_re "-thread-select again" 879 1.1 christos } 880 1.1 christos 881 1.1 christos with_spawn_id $gdb_main_spawn_id { 882 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "-thread-select again, event on CLI" 883 1.1 christos } 884 1.1 christos } 885 1.1 christos 886 1.1 christos with_test_prefix "thread 1.3" { 887 1.1 christos # Do the '-thread-select' command to select the third thread, stopped on all-stop, 888 1.1 christos # running on non-stop. 889 1.1 christos 890 1.1 christos if { $mode == "all-stop" } { 891 1.1 christos set mi_re [make_mi_re $mode 3 0 response] 892 1.1 christos set cli_re [make_cli_re $mode -1 1.3 0] 893 1.1 christos } else { 894 1.1 christos set mi_re [make_mi_re $mode 3 -1 response] 895 1.1 christos set cli_re [make_cli_re $mode -1 1.3 -1] 896 1.1 christos } 897 1.1 christos 898 1.1 christos with_spawn_id $mi_spawn_id { 899 1.1 christos mi_gdb_test "-thread-select 3" $mi_re "-thread-select" 900 1.1 christos } 901 1.1 christos 902 1.1 christos with_spawn_id $gdb_main_spawn_id { 903 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-thread-select, event on CLI" 904 1.1 christos } 905 1.1 christos 906 1.1 christos # Do the 'thread' command to select the third thread again. Again, we 907 1.1 christos # shouldn't receive an event on MI. 908 1.1 christos 909 1.1 christos set cli_re "" 910 1.1 christos 911 1.1 christos with_spawn_id $mi_spawn_id { 912 1.1 christos mi_gdb_test "-thread-select 3" $mi_re "-thread-select again" 913 1.1 christos } 914 1.1 christos 915 1.1 christos with_spawn_id $gdb_main_spawn_id { 916 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "-thread-select again, event on CLI" 917 1.1 christos } 918 1.1 christos } 919 1.1 christos 920 1.1.1.5 christos with_test_prefix "thread 1.2 with --thread 2" { 921 1.1 christos # Test selecting a thread from MI with a --thread option. This test 922 1.1.1.5 christos # verifies that even if the thread GDB would switch to is the same as 923 1.1 christos # the thread specified with --thread, an event is still sent to CLI. 924 1.1 christos # In this case this is thread 1.2 925 1.1 christos 926 1.1 christos set mi_re [make_mi_re $mode 2 0 response] 927 1.1 christos set cli_re [make_cli_re $mode -1 1.2 0] 928 1.1 christos 929 1.1 christos with_spawn_id $mi_spawn_id { 930 1.1 christos mi_gdb_test "-thread-select --thread 2 2" $mi_re "-thread-select" 931 1.1 christos } 932 1.1 christos 933 1.1 christos with_spawn_id $gdb_main_spawn_id { 934 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-thread-select, event on cli" 935 1.1.1.5 christos } 936 1.1.1.5 christos } 937 1.1.1.5 christos 938 1.1.1.5 christos with_test_prefix "thread 1.2 with --thread 3" { 939 1.1.1.5 christos # Test selecting a thread from MI with a --thread option. 940 1.1.1.5 christos # This test verifies that when different thread numbers are 941 1.1.1.5 christos # passed to the --thread option and the underlying 942 1.1.1.5 christos # -thread-select command, the correct thread is selected. 943 1.1.1.5 christos # In this case this is thread 1.2 944 1.1.1.5 christos 945 1.1.1.5 christos reset_selection "1.1" 946 1.1.1.5 christos 947 1.1.1.5 christos set mi_re [make_mi_re $mode 2 0 response] 948 1.1.1.5 christos set cli_re [make_cli_re $mode -1 1.2 0] 949 1.1.1.5 christos 950 1.1.1.5 christos with_spawn_id $mi_spawn_id { 951 1.1.1.5 christos mi_gdb_test "-thread-select --thread 3 2" $mi_re "-thread-select" 952 1.1.1.5 christos } 953 1.1.1.5 christos 954 1.1.1.5 christos with_spawn_id $gdb_main_spawn_id { 955 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-thread-select, event on cli" 956 1.1 christos } 957 1.1 christos } 958 1.1 christos 959 1.1 christos # Idea for the future: selecting a thread in a different inferior. For now, 960 1.1 christos # GDB doesn't show an inferior switch, but if it did, it would be a nice 961 1.1 christos # place to test it. 962 1.1 christos } 963 1.1 christos 964 1.1.1.2 christos proc_with_prefix test_mi_stack_select_frame { mode } { 965 1.1 christos global gdb_main_spawn_id mi_spawn_id 966 1.1 christos 967 1.1 christos with_test_prefix "thread 1.2" { 968 1.1 christos reset_selection "1.2" 969 1.1 christos flush_buffers 970 1.1 christos 971 1.1 christos # Do the '-stack-select-frame' command to select frame 1. 972 1.1 christos 973 1.1 christos set mi_re "\\^done" 974 1.1 christos set cli_re [make_cli_re $mode -1 -1 1] 975 1.1 christos 976 1.1 christos with_spawn_id $mi_spawn_id { 977 1.1 christos mi_gdb_test "-stack-select-frame 1" $mi_re "-stack-select-frame" 978 1.1 christos } 979 1.1 christos 980 1.1 christos with_spawn_id $gdb_main_spawn_id { 981 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-stack-select-frame, event on CLI" 982 1.1 christos } 983 1.1 christos 984 1.1 christos # Do the '-stack-select-frame' command to select the same frame. This time we don't 985 1.1 christos # expect an event on CLI, since we won't actually change frame. 986 1.1 christos 987 1.1 christos set cli_re "" 988 1.1 christos 989 1.1 christos with_spawn_id $mi_spawn_id { 990 1.1 christos mi_gdb_test "-stack-select-frame 1" $mi_re "-stack-select-frame again" 991 1.1 christos } 992 1.1 christos 993 1.1 christos with_spawn_id $gdb_main_spawn_id { 994 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "-stack-select-frame again, event on CLI" 995 1.1.1.5 christos } 996 1.1.1.5 christos 997 1.1.1.5 christos # Now use the '-stack-select-frame' command with the --frame 998 1.1.1.5 christos # option, this verifies that even when the frame GDB would 999 1.1.1.5 christos # swith to is the same as the frame specified with --frame, an 1000 1.1.1.5 christos # event is still sent to the CLI. 1001 1.1.1.5 christos 1002 1.1.1.5 christos set cli_re [make_cli_re $mode -1 -1 0] 1003 1.1.1.5 christos 1004 1.1.1.5 christos with_spawn_id $mi_spawn_id { 1005 1.1.1.5 christos mi_gdb_test "-stack-select-frame --thread 2 --frame 0 0" $mi_re 1006 1.1.1.5 christos } 1007 1.1.1.5 christos 1008 1.1.1.5 christos with_spawn_id $gdb_main_spawn_id { 1009 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-stack-select-frame with --frame 0, event on CLI" 1010 1.1.1.5 christos } 1011 1.1.1.5 christos 1012 1.1.1.5 christos # Now use the '-stack-select-frame' command with the --frame 1013 1.1.1.5 christos # option, this verifies that the correct event is sent to the 1014 1.1.1.5 christos # CLI when the frame specified with --frame is different to 1015 1.1.1.5 christos # the actual frame selected. 1016 1.1.1.5 christos 1017 1.1.1.5 christos set cli_re [make_cli_re $mode -1 -1 1] 1018 1.1.1.5 christos 1019 1.1.1.5 christos with_spawn_id $mi_spawn_id { 1020 1.1.1.5 christos mi_gdb_test "-stack-select-frame --thread 2 --frame 2 1" $mi_re 1021 1.1.1.5 christos } 1022 1.1.1.5 christos 1023 1.1.1.5 christos with_spawn_id $gdb_main_spawn_id { 1024 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-stack-select-frame with --frame 2, event on CLI" 1025 1.1 christos } 1026 1.1 christos } 1027 1.1 christos 1028 1.1 christos with_test_prefix "thread 1.3" { 1029 1.1 christos # Now, try the '-stack-select-frame' command on thread 3, which is 1030 1.1 christos # running if we are in non-stop mode. 1031 1.1 christos reset_selection "1.3" 1032 1.1 christos flush_buffers 1033 1.1 christos 1034 1.1 christos if {$mode == "all-stop"} { 1035 1.1 christos set mi_re "\\^done" 1036 1.1 christos set cli_re [make_cli_re $mode -1 -1 1] 1037 1.1 christos append cli_re "\r\n" 1038 1.1 christos } elseif {$mode == "non-stop"} { 1039 1.1 christos set cli_re "" 1040 1.1 christos set mi_re "\\^error,msg=\"Selected thread is running\\.\"" 1041 1.1 christos } 1042 1.1 christos 1043 1.1 christos with_spawn_id $mi_spawn_id { 1044 1.1 christos mi_gdb_test "-stack-select-frame 1" $mi_re "-stack-select-frame" 1045 1.1 christos } 1046 1.1 christos 1047 1.1 christos with_spawn_id $gdb_main_spawn_id { 1048 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "-stack-select-frame, event on CLI" 1049 1.1 christos } 1050 1.1 christos } 1051 1.1 christos } 1052 1.1 christos 1053 1.1 christos proc make_cli_in_mi_command { cli_in_mi_mode command } { 1054 1.1 christos if { $cli_in_mi_mode == "direct" } { 1055 1.1 christos return $command 1056 1.1 christos } elseif { $cli_in_mi_mode == "interpreter-exec" } { 1057 1.1 christos return "-interpreter-exec console \"$command\"" 1058 1.1 christos } else { 1059 1.1 christos error "Invalid value for CLI_IN_MI_MODE." 1060 1.1 christos } 1061 1.1 christos } 1062 1.1 christos 1063 1.1 christos # Test selecting the inferior using a CLI command in the MI channel. 1064 1.1 christos 1065 1.1.1.2 christos proc_with_prefix test_cli_in_mi_inferior { mode cli_in_mi_mode } { 1066 1.1 christos global gdb_main_spawn_id mi_spawn_id 1067 1.1 christos 1068 1.1 christos reset_selection "1.1" 1069 1.1 christos flush_buffers 1070 1.1 christos 1071 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "inferior 2"] 1072 1.1 christos 1073 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 2 2.1 4 2] 1074 1.1 christos set cli_re [make_cli_re $mode 2 "2.1" 2] 1075 1.1 christos 1076 1.1 christos with_spawn_id $mi_spawn_id { 1077 1.1 christos mi_gdb_test $command $mi_re "select inferior" 1078 1.1 christos } 1079 1.1 christos 1080 1.1 christos with_spawn_id $gdb_main_spawn_id { 1081 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "select inferior, event on CLI" 1082 1.1 christos } 1083 1.1 christos 1084 1.1 christos # Do the 'inferior' command on the currently selected inferior. For now, 1085 1.1 christos # GDB naively re-outputs everything. 1086 1.1 christos with_spawn_id $mi_spawn_id { 1087 1.1 christos mi_gdb_test $command $mi_re "select inferior again" 1088 1.1 christos } 1089 1.1 christos 1090 1.1 christos with_spawn_id $gdb_main_spawn_id { 1091 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "select inferior again, event on CLI" 1092 1.1 christos } 1093 1.1 christos } 1094 1.1 christos 1095 1.1 christos # Test selecting the thread using a CLI command in the MI channel. 1096 1.1 christos 1097 1.1.1.2 christos proc_with_prefix test_cli_in_mi_thread { mode cli_in_mi_mode } { 1098 1.1 christos global gdb_main_spawn_id mi_spawn_id 1099 1.1 christos 1100 1.1 christos reset_selection "1.1" 1101 1.1 christos flush_buffers 1102 1.1 christos 1103 1.1 christos with_test_prefix "thread 1.2" { 1104 1.1 christos # Do the 'thread' command to select a stopped thread. 1105 1.1 christos 1106 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "thread 1.2"] 1107 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 1.2 2 0] 1108 1.1 christos set cli_re [make_cli_re $mode -1 1.2 0] 1109 1.1 christos 1110 1.1 christos with_spawn_id $mi_spawn_id { 1111 1.1 christos mi_gdb_test $command $mi_re "select thread" 1112 1.1 christos } 1113 1.1 christos 1114 1.1 christos with_spawn_id $gdb_main_spawn_id { 1115 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "select thread, event on CLI" 1116 1.1 christos } 1117 1.1 christos 1118 1.1 christos # Do the 'thread' command to select the same thread. We shouldn't 1119 1.1 christos # receive an event on CLI, since we won't actually switch thread. 1120 1.1 christos 1121 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.2 2 0] 1122 1.1 christos set cli_re "" 1123 1.1 christos 1124 1.1 christos with_spawn_id $mi_spawn_id { 1125 1.1 christos mi_gdb_test $command $mi_re "select thread again" 1126 1.1 christos } 1127 1.1 christos 1128 1.1 christos with_spawn_id $gdb_main_spawn_id { 1129 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "select thread again, event on CLI" 1130 1.1 christos } 1131 1.1 christos 1132 1.1 christos # Try the 'thread' command without arguments. 1133 1.1 christos 1134 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "thread"] 1135 1.1 christos 1136 1.1 christos set mi_re "${command}.*~\"\\\[Current thread is 1\\.2.*\\\]\\\\n\".*\\^done" 1137 1.1 christos set cli_re "" 1138 1.1 christos 1139 1.1 christos with_spawn_id $mi_spawn_id { 1140 1.1 christos mi_gdb_test $command $mi_re "thread without args" 1141 1.1 christos } 1142 1.1 christos 1143 1.1 christos with_spawn_id $gdb_main_spawn_id { 1144 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "thread without args, event on CLI" 1145 1.1 christos } 1146 1.1 christos } 1147 1.1 christos 1148 1.1 christos with_test_prefix "thread 1.3" { 1149 1.1 christos # Do the 'thread' command to select the third thread, stopped on 1150 1.1 christos # all-stop, running on non-stop. 1151 1.1 christos 1152 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "thread 1.3"] 1153 1.1 christos if { $mode == "all-stop" } { 1154 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 1.3 3 0] 1155 1.1 christos set cli_re [make_cli_re $mode -1 "1.3" 0] 1156 1.1 christos } else { 1157 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 1.3 3 -1] 1158 1.1 christos set cli_re [make_cli_re $mode -1 "1.3" -1] 1159 1.1 christos } 1160 1.1 christos 1161 1.1 christos with_spawn_id $mi_spawn_id { 1162 1.1 christos mi_gdb_test $command $mi_re "select thread" 1163 1.1 christos } 1164 1.1 christos 1165 1.1 christos with_spawn_id $gdb_main_spawn_id { 1166 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "select thread, event on CLI" 1167 1.1 christos } 1168 1.1 christos 1169 1.1 christos # Do the 'thread' command to select the third thread again. Again, we 1170 1.1 christos # shouldn't receive an event on MI. 1171 1.1 christos 1172 1.1 christos if { $mode == "all-stop" } { 1173 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.3 3 0] 1174 1.1 christos } else { 1175 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.3 3 -1] 1176 1.1 christos } 1177 1.1 christos set cli_re "" 1178 1.1 christos 1179 1.1 christos with_spawn_id $mi_spawn_id { 1180 1.1 christos mi_gdb_test $command $mi_re "select thread again" 1181 1.1 christos } 1182 1.1 christos 1183 1.1 christos with_spawn_id $gdb_main_spawn_id { 1184 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "select thread again, event on CLI" 1185 1.1 christos } 1186 1.1 christos 1187 1.1 christos # Try the 'thread' command without arguments. 1188 1.1 christos 1189 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "thread"] 1190 1.1 christos 1191 1.1 christos set mi_re "${command}.*~\"\\\[Current thread is 1\\.3.*\\\]\\\\n\".*\\^done" 1192 1.1 christos set cli_re "" 1193 1.1 christos 1194 1.1 christos with_spawn_id $mi_spawn_id { 1195 1.1 christos mi_gdb_test $command $mi_re "thread without args" 1196 1.1 christos } 1197 1.1 christos 1198 1.1 christos with_spawn_id $gdb_main_spawn_id { 1199 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "thread without args, event on CLI" 1200 1.1 christos } 1201 1.1 christos } 1202 1.1 christos 1203 1.1 christos # Idea for the future: selecting a thread in a different inferior. For now, 1204 1.1 christos # GDB doesn't show an inferior switch, but if it did, it would be a nice 1205 1.1 christos # place to test it. 1206 1.1 christos } 1207 1.1 christos 1208 1.1 christos # Test selecting the frame using a CLI command in the MI channel. 1209 1.1 christos 1210 1.1.1.2 christos proc_with_prefix test_cli_in_mi_frame { mode cli_in_mi_mode } { 1211 1.1 christos global gdb_main_spawn_id mi_spawn_id 1212 1.1 christos 1213 1.1 christos with_test_prefix "thread 1.2" { 1214 1.1 christos reset_selection "1.2" 1215 1.1 christos flush_buffers 1216 1.1 christos 1217 1.1 christos # Do the 'frame' command to select frame 1. 1218 1.1 christos 1219 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "frame 1"] 1220 1.1 christos set cli_re [make_cli_re $mode -1 -1 1] 1221 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 -1 2 1] 1222 1.1 christos 1223 1.1 christos with_spawn_id $mi_spawn_id { 1224 1.1 christos mi_gdb_test $command $mi_re "select frame 1" 1225 1.1 christos } 1226 1.1 christos 1227 1.1 christos with_spawn_id $gdb_main_spawn_id { 1228 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "select frame 1, event on CLI" 1229 1.1 christos } 1230 1.1 christos 1231 1.1 christos # Do the 'frame' command to select the same frame. This time we don't 1232 1.1 christos # expect an event on MI, since we won't actually change frame. 1233 1.1 christos 1234 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 -1 2 1] 1235 1.1 christos set cli_re "" 1236 1.1 christos 1237 1.1 christos with_spawn_id $mi_spawn_id { 1238 1.1 christos mi_gdb_test $command $mi_re "select frame 1 again" 1239 1.1 christos } 1240 1.1 christos 1241 1.1 christos with_spawn_id $gdb_main_spawn_id { 1242 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "select frame 1 again, event on CLI" 1243 1.1 christos } 1244 1.1 christos 1245 1.1 christos # Do the 'frame' command without arguments. We shouldn't see anything on MI. 1246 1.1 christos 1247 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "frame"] 1248 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 -1 2 1] 1249 1.1 christos 1250 1.1 christos with_spawn_id $mi_spawn_id { 1251 1.1 christos mi_gdb_test $command $mi_re "frame without args" 1252 1.1 christos } 1253 1.1 christos 1254 1.1 christos with_spawn_id $gdb_main_spawn_id { 1255 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "frame without args, event on CLI" 1256 1.1 christos } 1257 1.1 christos } 1258 1.1 christos 1259 1.1 christos with_test_prefix "thread 1.3" { 1260 1.1 christos # Now, try the 'frame' command on thread 3, which is running if we are in 1261 1.1 christos # non-stop mode. 1262 1.1 christos reset_selection "1.3" 1263 1.1 christos flush_buffers 1264 1.1 christos 1265 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "frame 1"] 1266 1.1 christos if {$mode == "all-stop"} { 1267 1.1 christos set cli_re [make_cli_re $mode -1 -1 1] 1268 1.1 christos append cli_re "\r\n" 1269 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 -1 3 1] 1270 1.1 christos } elseif {$mode == "non-stop"} { 1271 1.1 christos set cli_re "" 1272 1.1 christos set mi_re "\\^error,msg=\"Selected thread is running\\.\".*" 1273 1.1 christos } 1274 1.1 christos 1275 1.1 christos with_spawn_id $mi_spawn_id { 1276 1.1 christos mi_gdb_test $command $mi_re "select frame 1" 1277 1.1 christos } 1278 1.1 christos 1279 1.1 christos with_spawn_id $gdb_main_spawn_id { 1280 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "select frame 1, event on CLI" 1281 1.1 christos } 1282 1.1 christos 1283 1.1 christos # Do the 'frame' command without arguments. 1284 1.1 christos 1285 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "frame"] 1286 1.1 christos if { $mode == "all-stop" } { 1287 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 -1 -1 1] 1288 1.1 christos } else { 1289 1.1 christos set mi_re "\\^error,msg=\"No stack\\.\"" 1290 1.1 christos } 1291 1.1 christos set cli_re "" 1292 1.1 christos 1293 1.1 christos with_spawn_id $mi_spawn_id { 1294 1.1 christos mi_gdb_test $command $mi_re "frame without args" 1295 1.1 christos } 1296 1.1 christos 1297 1.1 christos with_spawn_id $gdb_main_spawn_id { 1298 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "frame without args, event on CLI" 1299 1.1 christos } 1300 1.1 christos } 1301 1.1 christos } 1302 1.1 christos 1303 1.1 christos foreach_with_prefix mode { "all-stop" "non-stop" } { 1304 1.1.1.5 christos set test "setup done" 1305 1.1.1.5 christos if { [test_setup $mode] == -1 } { 1306 1.1.1.5 christos fail $test 1307 1.1.1.5 christos continue 1308 1.1.1.5 christos } 1309 1.1.1.5 christos pass $test 1310 1.1 christos 1311 1.1 christos # Test selecting inferior, thread and frame from CLI 1312 1.1 christos 1313 1.1.1.2 christos test_cli_inferior $mode 1314 1.1.1.2 christos test_cli_thread $mode 1315 1.1.1.2 christos test_cli_frame $mode 1316 1.1.1.2 christos test_cli_select_frame $mode 1317 1.1.1.2 christos test_cli_up_down $mode 1318 1.1 christos 1319 1.1 christos # Test selecting thread and frame from MI 1320 1.1 christos 1321 1.1.1.2 christos test_mi_thread_select $mode 1322 1.1.1.2 christos test_mi_stack_select_frame $mode 1323 1.1 christos 1324 1.1 christos # Test some CLI commands sent through MI, both with a "direct" command, 1325 1.1 christos # such as "thread 1", and with -interpreter-exec, such as 1326 1.1 christos # '-interpreter-exec console "thread 1"'. 1327 1.1 christos 1328 1.1 christos foreach_with_prefix exec_mode {"direct" "interpreter-exec"} { 1329 1.1.1.2 christos test_cli_in_mi_inferior $mode $exec_mode 1330 1.1.1.2 christos test_cli_in_mi_thread $mode $exec_mode 1331 1.1.1.2 christos test_cli_in_mi_frame $mode $exec_mode 1332 1.1 christos } 1333 1.1 christos } 1334