|  | # Copyright 2009-2025 Free Software Foundation, Inc. | 
|  |  | 
|  | # This program is free software; you can redistribute it and/or modify | 
|  | # it under the terms of the GNU General Public License as published by | 
|  | # the Free Software Foundation; either version 3 of the License, or | 
|  | # (at your option) any later version. | 
|  | # | 
|  | # This program is distributed in the hope that it will be useful, | 
|  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | # GNU General Public License for more details. | 
|  | # | 
|  | # You should have received a copy of the GNU General Public License | 
|  | # along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
|  |  | 
|  | # Generic subroutines for handling valgrind vgdb server. | 
|  |  | 
|  | # | 
|  | # Start a vgdb server, and connect gdb to it.  Return 0 on success, and -1 on | 
|  | # error. | 
|  | # | 
|  | proc vgdb_start { {active_at_startup 1} } { | 
|  | global binfile use_gdb_stub board testfile | 
|  | global valgrind_spawn_id gdb_spawn_id | 
|  | global decimal | 
|  |  | 
|  | set test "spawn valgrind" | 
|  | set cmd_list [list] | 
|  | lappend cmd_list "valgrind" | 
|  | if { $active_at_startup } { | 
|  | lappend cmd_list "--vgdb-error=0" | 
|  | } | 
|  | lappend cmd_list $binfile | 
|  | set cmd [join $cmd_list] | 
|  | set res [remote_spawn host $cmd] | 
|  | if { $res < 0 || $res == "" } { | 
|  | verbose -log "Spawning $cmd failed." | 
|  | unsupported $test | 
|  | return -1 | 
|  | } | 
|  | pass $test | 
|  | # Declare GDB now as running. | 
|  | set gdb_spawn_id $res | 
|  |  | 
|  | # GDB started by vgdb stops already after the startup is executed, like with | 
|  | # non-extended gdbserver.  It is also not correct to run/attach the inferior. | 
|  | set use_gdb_stub 1 | 
|  |  | 
|  | set test "valgrind started" | 
|  | # The trailing '.' differs for different memcheck versions. | 
|  | gdb_test_multiple "" $test { | 
|  | -re "==($decimal)== Memcheck, a memory error detector\\.?\r\n" { | 
|  | set vgdbpid $expect_out(1,string) | 
|  | pass $test | 
|  | } | 
|  | -re "valgrind: failed to start tool 'memcheck' for platform '.*': No such file or directory" { | 
|  | unsupported $test | 
|  | return -1 | 
|  | } | 
|  | -re "valgrind: wrong ELF executable class" { | 
|  | unsupported $test | 
|  | return -1 | 
|  | } | 
|  | -re "command not found" { | 
|  | # The spawn succeeded, but then valgrind was not found - e.g. if | 
|  | # we spawned SSH to a remote system. | 
|  | unsupported $test | 
|  | return -1 | 
|  | } | 
|  | -re "valgrind: Bad option.*--vgdb-error=0" { | 
|  | # valgrind is not >= 3.7.0. | 
|  | unsupported $test | 
|  | return -1 | 
|  | } | 
|  | } | 
|  |  | 
|  | # Do not kill valgrind. | 
|  | set valgrind_spawn_id [board_info host fileid] | 
|  | unset gdb_spawn_id | 
|  | set board [host_info name] | 
|  | unset_board_info fileid | 
|  |  | 
|  | clean_restart $testfile | 
|  |  | 
|  | set_remotetimeout 4 | 
|  |  | 
|  | # Make sure we're disconnected, in case we're testing with the | 
|  | # native-extended-gdbserver board, where gdb_start/gdb_load spawn | 
|  | # gdbserver and connect to it. | 
|  | gdb_test "disconnect" ".*" | 
|  |  | 
|  | set vgdbcmd "target remote | vgdb --wait=2 --max-invoke-ms=2500 --pid=$vgdbpid" | 
|  |  | 
|  | if { $active_at_startup } { | 
|  | set start_re1 " in \\.?_start " | 
|  | set start_re2 "\\.?_start \\(\\) at " | 
|  | set start_re3 "$::hex in \\?\\? \\(\\) from " | 
|  | gdb_test "$vgdbcmd" "($start_re1|$start_re2|$start_re3).*" \ | 
|  | "target remote for vgdb" | 
|  | } else { | 
|  | # Let $binfile run a bit before attaching.  This is a bit of a hack, | 
|  | # in that it lets test-case valgrind-infcall-2.exp run to the point of | 
|  | # nanosleep, which seems to be required to trigger the error condition. | 
|  | # So, without this, we hit | 
|  | # "UNSUPPORTED: gdb.base/valgrind-infcall-2.exp: do printf". | 
|  | exec sleep 1 | 
|  |  | 
|  | # Connect to vgdb.  Don't expect to be anywhere in particular. | 
|  | gdb_test "$vgdbcmd" "" "target remote for vgdb" | 
|  | } | 
|  |  | 
|  | gdb_test "monitor v.set gdb_output" "valgrind output will go to gdb.*" | 
|  | return 0 | 
|  | } | 
|  |  | 
|  | # | 
|  | # Stop vgdb server. | 
|  | # | 
|  | proc vgdb_stop { } { | 
|  | global valgrind_spawn_id | 
|  |  | 
|  | # Only if valgrind got stuck. | 
|  | kill_wait_spawned_process $valgrind_spawn_id | 
|  | } |