aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.server
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/testsuite/gdb.server')
-rw-r--r--gdb/testsuite/gdb.server/argument-errors.exp81
-rw-r--r--gdb/testsuite/gdb.server/bkpt-other-inferior.exp2
-rw-r--r--gdb/testsuite/gdb.server/build-id-seqno.exp6
-rw-r--r--gdb/testsuite/gdb.server/connect-stopped-target.exp2
-rw-r--r--gdb/testsuite/gdb.server/connect-with-no-symbol-file.exp2
-rw-r--r--gdb/testsuite/gdb.server/connect-without-multi-process.exp2
-rw-r--r--gdb/testsuite/gdb.server/exit-multiple-threads.exp9
-rw-r--r--gdb/testsuite/gdb.server/ext-attach.exp2
-rw-r--r--gdb/testsuite/gdb.server/ext-run.exp2
-rw-r--r--gdb/testsuite/gdb.server/extended-remote-restart.exp4
-rw-r--r--gdb/testsuite/gdb.server/fetch-exec-and-args.c34
-rw-r--r--gdb/testsuite/gdb.server/fetch-exec-and-args.exp307
-rw-r--r--gdb/testsuite/gdb.server/fileio-packets.exp66
-rw-r--r--gdb/testsuite/gdb.server/fileio-packets.py208
-rw-r--r--gdb/testsuite/gdb.server/inferior-args.c27
-rw-r--r--gdb/testsuite/gdb.server/inferior-args.exp156
-rw-r--r--gdb/testsuite/gdb.server/monitor-exit-quit.exp4
-rw-r--r--gdb/testsuite/gdb.server/no-thread-db.exp4
-rw-r--r--gdb/testsuite/gdb.server/non-existing-program.exp4
-rw-r--r--gdb/testsuite/gdb.server/pread-offset-size.S29
-rw-r--r--gdb/testsuite/gdb.server/pread-offset-size.exp49
-rw-r--r--gdb/testsuite/gdb.server/reconnect-ctrl-c.exp4
-rw-r--r--gdb/testsuite/gdb.server/server-empty-exec-name.exp93
-rw-r--r--gdb/testsuite/gdb.server/server-exec-info.exp2
-rw-r--r--gdb/testsuite/gdb.server/server-kill.exp13
-rw-r--r--gdb/testsuite/gdb.server/server-pipe.exp2
-rw-r--r--gdb/testsuite/gdb.server/server-run.exp2
-rw-r--r--gdb/testsuite/gdb.server/stop-reply-no-thread-multi.exp4
-rw-r--r--gdb/testsuite/gdb.server/stop-reply-no-thread.exp4
29 files changed, 1089 insertions, 35 deletions
diff --git a/gdb/testsuite/gdb.server/argument-errors.exp b/gdb/testsuite/gdb.server/argument-errors.exp
new file mode 100644
index 0000000..45037bf
--- /dev/null
+++ b/gdb/testsuite/gdb.server/argument-errors.exp
@@ -0,0 +1,81 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 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/>.
+
+# Test gdbserver prints a suitable message when argument values are
+# missing.
+
+load_lib gdbserver-support.exp
+
+standard_testfile
+
+require allow_gdbserver_tests
+
+set gdbserver [find_gdbserver]
+if { $gdbserver == "" } {
+ unsupported "could not find gdbserver"
+ return
+}
+
+# Start gdbserver using CMD_ARGS and a non-existent program name. We
+# expect to see an error message matching ERROR_RE from gdbserver.
+proc test_argument_error { cmd_args error_re } {
+ # Fire off gdbserver. gdbserver should give an error because
+ # --debug-file is missing its argument.
+ set spawn_id [remote_spawn target "$::gdbserver $cmd_args non-existing-program"]
+
+ set saw_expected_error false
+ set test "check gdbserver error: $cmd_args"
+ expect {
+ -i $spawn_id
+ -re $error_re {
+ set saw_expected_error true
+ exp_continue
+ }
+ eof {
+ gdb_assert $saw_expected_error $test
+ wait
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+ }
+
+ # expect defaults to spawn_id in many places. Avoid confusing any
+ # following code.
+ unset spawn_id
+}
+
+# Check that an argument that expects a value will not use a port, or
+# another argument, as its value.
+foreach arg { --debug-format --debug-file } {
+ test_argument_error "$arg stdio" \
+ "Missing argument value for: $arg"
+ test_argument_error "$arg :54321" \
+ "Missing argument value for: $arg"
+ test_argument_error "$arg -" \
+ "Missing argument value for: $arg"
+ test_argument_error "$arg --once -" \
+ "Missing argument value for: $arg"
+}
+
+# Test unknown argument handling.
+test_argument_error "--unknown -" \
+ "Unknown argument: --unknown"
+test_argument_error "-unknown -" \
+ "Unknown argument: -unknown"
+test_argument_error "--unknown=blah -" \
+ "Unknown argument: --unknown"
diff --git a/gdb/testsuite/gdb.server/bkpt-other-inferior.exp b/gdb/testsuite/gdb.server/bkpt-other-inferior.exp
index 893bd72..453be14 100644
--- a/gdb/testsuite/gdb.server/bkpt-other-inferior.exp
+++ b/gdb/testsuite/gdb.server/bkpt-other-inferior.exp
@@ -23,7 +23,7 @@ standard_testfile server.c
require allow_gdbserver_tests
-if { [prepare_for_testing "failed to prepare" ${binfile} "${srcfile}" \
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
{debug pthreads}] } {
return
}
diff --git a/gdb/testsuite/gdb.server/build-id-seqno.exp b/gdb/testsuite/gdb.server/build-id-seqno.exp
index a508a44..8475ccc 100644
--- a/gdb/testsuite/gdb.server/build-id-seqno.exp
+++ b/gdb/testsuite/gdb.server/build-id-seqno.exp
@@ -90,13 +90,13 @@ proc load_binfile_check_debug_is_found { debuginfo_file testname } {
with_test_prefix "$testname" {
with_timeout_factor 5 {
# Probing for .build-id based debug files on remote
- # targets uses the vFile:stat packet by default, though
+ # targets uses the vFile:lstat packet by default, though
# there is a work around that avoids this which can be
# used if GDB is connected to an older gdbserver without
# 'stat' support.
#
# Check the work around works by disabling use of the
- # vFile:stat packet.
+ # vFile:lstat packet.
foreach_with_prefix stat_pkt {auto off} {
clean_restart
@@ -105,7 +105,7 @@ proc load_binfile_check_debug_is_found { debuginfo_file testname } {
gdb_test_no_output "set sysroot target:"
- gdb_test "set remote hostio-stat-packet $stat_pkt"
+ gdb_test "set remote hostio-lstat-packet $stat_pkt"
# Make sure we're disconnected, in case we're testing with an
# extended-remote board, therefore already connected.
diff --git a/gdb/testsuite/gdb.server/connect-stopped-target.exp b/gdb/testsuite/gdb.server/connect-stopped-target.exp
index 021f063..603782c 100644
--- a/gdb/testsuite/gdb.server/connect-stopped-target.exp
+++ b/gdb/testsuite/gdb.server/connect-stopped-target.exp
@@ -34,7 +34,7 @@ proc do_test {nonstop} {
global gdb_prompt
global hex
- clean_restart $binfile
+ clean_restart $::testfile
# Make sure we're disconnected, in case we're testing with an
# extended-remote board, therefore already connected.
diff --git a/gdb/testsuite/gdb.server/connect-with-no-symbol-file.exp b/gdb/testsuite/gdb.server/connect-with-no-symbol-file.exp
index 4e5ee98..01d7e46 100644
--- a/gdb/testsuite/gdb.server/connect-with-no-symbol-file.exp
+++ b/gdb/testsuite/gdb.server/connect-with-no-symbol-file.exp
@@ -69,7 +69,7 @@ proc connect_no_symbol_file { sysroot action } {
} elseif { $action == "permission" } {
remote_exec target "chmod 000 $target_exec"
}
-
+
# Connect to GDBserver.
gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
}
diff --git a/gdb/testsuite/gdb.server/connect-without-multi-process.exp b/gdb/testsuite/gdb.server/connect-without-multi-process.exp
index 1a7246c..f47e57e 100644
--- a/gdb/testsuite/gdb.server/connect-without-multi-process.exp
+++ b/gdb/testsuite/gdb.server/connect-without-multi-process.exp
@@ -38,7 +38,7 @@ proc do_test {multiprocess} {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
diff --git a/gdb/testsuite/gdb.server/exit-multiple-threads.exp b/gdb/testsuite/gdb.server/exit-multiple-threads.exp
index 73e4c32..48bb10f 100644
--- a/gdb/testsuite/gdb.server/exit-multiple-threads.exp
+++ b/gdb/testsuite/gdb.server/exit-multiple-threads.exp
@@ -45,7 +45,8 @@ proc prepare_for_test { executable target_executable disable_multi_process } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart ${executable}
+ clean_restart
+ gdb_load $executable
}
# Make sure we're disconnected, in case we're testing with an
@@ -69,7 +70,7 @@ proc prepare_for_test { executable target_executable disable_multi_process } {
set gdbserver_protocol [lindex $res 0]
set gdbserver_gdbport [lindex $res 1]
set res [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
- if ![gdb_assert {$res == 0} "connect"] {
+ if { ![gdb_assert {$res == 0} "connect"] } {
return
}
@@ -137,8 +138,8 @@ foreach_with_prefix test { exit signal } {
set func "run_${test}_test"
set executable "$binfile-${test}"
- if [build_executable "failed to prepare" $executable $srcfile \
- [list debug pthreads additional_flags=-D${def}]] {
+ if {[build_executable "failed to prepare" $executable $srcfile \
+ [list debug pthreads additional_flags=-D${def}]]} {
return -1
}
diff --git a/gdb/testsuite/gdb.server/ext-attach.exp b/gdb/testsuite/gdb.server/ext-attach.exp
index bda3ae9..6af2ede 100644
--- a/gdb/testsuite/gdb.server/ext-attach.exp
+++ b/gdb/testsuite/gdb.server/ext-attach.exp
@@ -45,7 +45,7 @@ proc run_test { target_async target_non_stop to_disable } {
set ::GDBFLAGS "$::GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $::binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
diff --git a/gdb/testsuite/gdb.server/ext-run.exp b/gdb/testsuite/gdb.server/ext-run.exp
index 2286454..f4ff546 100644
--- a/gdb/testsuite/gdb.server/ext-run.exp
+++ b/gdb/testsuite/gdb.server/ext-run.exp
@@ -37,7 +37,7 @@ save_vars { GDBFLAGS } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
diff --git a/gdb/testsuite/gdb.server/extended-remote-restart.exp b/gdb/testsuite/gdb.server/extended-remote-restart.exp
index df722a1..a5ba53c 100644
--- a/gdb/testsuite/gdb.server/extended-remote-restart.exp
+++ b/gdb/testsuite/gdb.server/extended-remote-restart.exp
@@ -58,7 +58,7 @@ proc test_reload { do_kill_p follow_child_p } {
global decimal
global binfile
- clean_restart ${binfile}
+ clean_restart ${::testfile}
if {![runto_main]} {
return 0
@@ -70,7 +70,7 @@ proc test_reload { do_kill_p follow_child_p } {
set live_inf_ptn "process $decimal"
set dead_inf_ptn "<null>"
- if ${follow_child_p} {
+ if { $follow_child_p } {
gdb_test_no_output "set follow-fork child"
set parent_prefix " "
set child_prefix "\\*"
diff --git a/gdb/testsuite/gdb.server/fetch-exec-and-args.c b/gdb/testsuite/gdb.server/fetch-exec-and-args.c
new file mode 100644
index 0000000..3dc01a2
--- /dev/null
+++ b/gdb/testsuite/gdb.server/fetch-exec-and-args.c
@@ -0,0 +1,34 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023-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/>. */
+
+/* Simple test, do some work with the arguments so GDB has a chance to
+ break and check that the arguments are correct. */
+
+volatile int global_counter;
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+
+ global_counter = 0; /* Break here. */
+
+ for (i = 0; i < argc; ++i)
+ argv[i] = (char *) 0;
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.server/fetch-exec-and-args.exp b/gdb/testsuite/gdb.server/fetch-exec-and-args.exp
new file mode 100644
index 0000000..7c7750e
--- /dev/null
+++ b/gdb/testsuite/gdb.server/fetch-exec-and-args.exp
@@ -0,0 +1,307 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2023 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/>.
+
+# Test the qExecAndArgs packet, specifically, the argument fetching
+# component of the packet.
+
+# Skip test if target does not support argument passing.
+require {!target_info exists noargs}
+
+load_lib gdbserver-support.exp
+
+standard_testfile
+
+require allow_gdbserver_tests
+
+if {[build_executable "failed to build" $binfile $srcfile]} {
+ return
+}
+
+# Used as an override for extended_gdbserver_load_last_file in
+# configs/native-extended-gdbserver.exp, prevents the remote exec-file
+# from being set.
+proc do_nothing {} { return 0 }
+
+# Check the 'show args' output. If PACKET is 'on' then we expect to
+# see the arguments 'a b c', otherwise we don't expect to see any
+# arguments.
+proc check_show_args { packet } {
+ if { $packet } {
+ set args_re "a b c"
+ } else {
+ set args_re ""
+ }
+
+ gdb_test "show args" \
+ "Argument list to give program being debugged when it is started is \"$args_re\"\\."
+}
+
+# Check the 'show remote exec-file' output. PACKET is either 'on' or
+# 'off' and reflects whether the qExecAndArgs packet is turned on or
+# off. FILENAME is what we expect to see included in the output, and
+# is converted to a regexp by this function.
+proc check_remote_exec_file { packet filename } {
+ if { $filename eq "" } {
+ if { $packet } {
+ set remote_exec_re \
+ "The remote exec-file is unset, the remote has no default executable set\\."
+ } else {
+ set remote_exec_re \
+ "The remote exec-file is unset, the default remote executable will be used\\."
+ }
+ } else {
+ set remote_exec_re \
+ "The remote exec-file is \"[string_to_regexp $filename]\"\\."
+ }
+
+ gdb_test "show remote exec-file" $remote_exec_re
+}
+
+# Check the inferior has 4 arguments. Arg 0 will be the program name,
+# while 1, 2, and 3 should be a, b, and c respectively.
+proc check_full_args {} {
+ set exec_filename ""
+ gdb_test "print argc" " = 4"
+ gdb_test_multiple "print argv\[0\]" "" {
+ -re -wrap " = $::hex \"(.*/${::testfile})\"" {
+ set exec_filename $expect_out(1,string)
+ pass $gdb_test_name
+ }
+ }
+ gdb_test "print argv\[1\]" " = $::hex \"a\""
+ gdb_test "print argv\[2\]" " = $::hex \"b\""
+ gdb_test "print argv\[3\]" " = $::hex \"c\""
+
+ return $exec_filename
+}
+
+# Close and cleanup gdbserver process.
+proc cleanup_gdbserver {} {
+ catch {
+ close -i $server_spawn_id
+ wait -nowait -i $server_spawn_id
+ }
+}
+
+# Check that GDB can fetch the arguments from the remote using the
+# qExecAndArgs packet. When PACKET is 'on' we allow GDB to use the
+# packet, but when PACKET is 'off' we disable use of the qExecAndArgs
+# packet and ensure GDB falls back to the expected behaviour.
+proc_with_prefix test_exec_and_arg_fetch { packet } {
+ clean_restart $::testfile
+
+ # Make sure we're disconnected, in case we're testing with an
+ # extended-remote board, therefore already connected.
+ gdb_test "disconnect" ".*"
+
+ gdb_test "set remote fetch-exec-and-args ${packet}" \
+ "Support for the 'qExecAndArgs' packet on future remote targets is set to \"${packet}\"\\."
+
+ gdbserver_run "a b c"
+
+ gdb_breakpoint $::srcfile:[gdb_get_line_number "Break here"]
+ gdb_continue_to_breakpoint "run to breakpoint"
+
+ # Look in the inferior to check the arguments were passed
+ # correctly. We get back the name of the executable the inferior
+ # is running. If PACKET is 'on' then we expect GDB to have
+ # automatically fetched this executable name from the remote.
+ set exec_filename [check_full_args]
+ if { !$packet } {
+ set exec_filename ""
+ }
+
+ # Check 'show args' to ensure GDB sees the correct arguments.
+ check_show_args $packet
+
+ # Check 'show remote exec-file' to ensure GDB sees the correct
+ # filename.
+ check_remote_exec_file $packet $exec_filename
+
+ # Below this point we rely on restarting the inferior, which
+ # relies on the extended-remote protocol.
+ if {[target_info gdb_protocol] ne "extended-remote"} {
+ cleanup_gdbserver
+ return
+ }
+
+ with_test_prefix "rerun" {
+ # Don't restart GDB, but re-run the inferior.
+ gdb_run_cmd
+ gdb_test "" \
+ "Breakpoint $::decimal, main \\(\[^)\]+\\).*" \
+ "rerun until breakpoint in main"
+
+ # If the packet is enabled then we expect the arguments to
+ # still be correct, otherwise, we should have defaulted back
+ # to no additional arguments.
+ if { $packet } {
+ check_full_args
+ } else {
+ gdb_test "print argc" " = 1"
+ }
+
+ # Check 'show args' to ensure GDB sees the correct arguments.
+ check_show_args ${packet}
+
+ # Check 'show remote exec-file' to ensure GDB sees the correct
+ # filename.
+ check_remote_exec_file $packet $exec_filename
+ }
+
+ cleanup_gdbserver
+}
+
+# With the extended-remote target it is possible to start gdbserver
+# without specifying an inferior to run. In this case, gdbserver
+# should reply to the qExecAndArgs packet with a 'U' (for unset)
+# response. GDB should not override any currently set remote
+# executable or inferior arguments. The benefit of this is that a
+# user can set these values before connecting to gdbserver in this
+# case.
+proc_with_prefix test_exec_and_args_unset { packet } {
+ clean_restart
+
+ # Make sure we're disconnected, in case we're testing with an
+ # extended-remote board, therefore already connected.
+ gdb_test "disconnect" ".*"
+
+ # Enable or disable the qExecAndArgs packet.
+ gdb_test "set remote fetch-exec-and-args ${packet}" \
+ "Support for the 'qExecAndArgs' packet on future remote targets is set to \"${packet}\"\\."
+
+ # Setup a remote exec-file value, and some inferior arguments.
+ set fake_exec_name "/xxx/yyy/zzz"
+ set fake_args "1 2 3"
+ gdb_test_no_output "set remote exec-file $fake_exec_name"
+ gdb_test_no_output "set args $fake_args"
+
+ # Start gdbserver in extended-remote mode, don't specify an
+ # executable to start, or any inferior arguments.
+ set res [gdbserver_start "--multi" ""]
+ set gdbserver_protocol "extended-remote"
+ set gdbserver_gdbport [lindex $res 1]
+ gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
+
+ # Check within GDB that connecting to the extended-remote target
+ # didn't clobber the remote exec-file or inferior arguments.
+ gdb_test "show remote exec-file" \
+ "The remote exec-file is \"[string_to_regexp $fake_exec_name]\"\\."
+ gdb_test "show args" \
+ "Argument list to give program being debugged when it is started is \"${fake_args}\"\\."
+
+ cleanup_gdbserver
+}
+
+# Start GDB and set 'remote exec-file' to some random file. Then
+# start gdbserver with the name of the actual executable. Connect to
+# gdbserver from GDB and check that GDB gives a warning about the
+# remove exec-file value having changed.
+proc_with_prefix test_remote_exec_warning {} {
+ clean_restart
+
+ gdb_test "disconnect" ".*"
+
+ # Set the file GDB is going to debug. For extended-remote boards
+ # this also sets the remote exec-file.
+ gdb_file_cmd $::binfile
+
+ set invalid_remote_exec "/xxx/yyy/zzz"
+ gdb_test_no_output "set remote exec-file $invalid_remote_exec"
+ check_remote_exec_file on $invalid_remote_exec
+
+ # Start gdbserver.
+ set test "start gdbserver"
+ set target_exec [gdbserver_download_current_prog]
+ set target_exec_and_args "$target_exec a b c"
+ set catchres [catch {set res [gdbserver_start "" "$target_exec_and_args"]} errmsg]
+ if { $catchres != 0 } {
+ fail "$test: $errmsg"
+ } else {
+ pass "$test"
+ }
+
+ # And connect to gdbserver. Check for the warning GDB emits when
+ # the remote exec-file is updated.
+ set gdbserver_protocol [lindex $res 0]
+ set gdbserver_gdbport [lindex $res 1]
+ set test "connect to gdbserver"
+ set extra_re "warning: updating 'remote exec-file' to '[string_to_regexp $target_exec]' to match remote target"
+ set res [gdb_target_cmd_ext $gdbserver_protocol $gdbserver_gdbport $extra_re]
+ if { $res == 0 } {
+ pass $test
+ } elseif { $res == 1 } {
+ fail $test
+ } else {
+ unsupported $test
+ }
+
+ cleanup_gdbserver
+}
+
+# Start GDB. When PACKET is 'off' disable the qExecAndArgs packet,
+# otherwise, when PACKET is 'on' enable the packet.
+#
+# Start gdbserver in extended-remote mode, but don't provide a
+# filename when starting gdbserver.
+#
+# Connect to the remote server, and check 'show remote exec-file'.
+proc_with_prefix test_server_with_no_exec { packet set_remote_exec } {
+ clean_restart
+
+ gdb_test "disconnect" ".*"
+
+ gdb_file_cmd $::binfile
+
+ gdb_test "set remote fetch-exec-and-args ${packet}" \
+ "Support for the 'qExecAndArgs' packet on future remote targets is set to \"${packet}\"\\."
+
+ # Start gdbserver.
+ set target_exec [gdbserver_download_current_prog]
+
+ if { $set_remote_exec } {
+ gdb_test_no_output "set remote exec-file $target_exec" \
+ "set remote exec-file"
+ set expected_filename $target_exec
+ } else {
+ set expected_filename ""
+ }
+
+ gdbserver_start_extended
+
+ check_remote_exec_file $packet $expected_filename
+}
+
+# This override prevents the remote exec-file from being set when
+# using the extended-remote protocol. This is harmless when using
+# other boards.
+with_override extended_gdbserver_load_last_file do_nothing {
+ # This override stops GDB connecting to the gdbserver as soon as
+ # GDB is started when testing with the extended-remote protocol.
+ with_override gdbserver_start_multi do_nothing {
+ foreach_with_prefix packet { on off } {
+ test_exec_and_args_unset $packet
+ test_exec_and_arg_fetch $packet
+
+ foreach_with_prefix set_remote_exec { true false } {
+ test_server_with_no_exec $packet $set_remote_exec
+ }
+ }
+
+ test_remote_exec_warning
+ }
+}
diff --git a/gdb/testsuite/gdb.server/fileio-packets.exp b/gdb/testsuite/gdb.server/fileio-packets.exp
new file mode 100644
index 0000000..9435efd
--- /dev/null
+++ b/gdb/testsuite/gdb.server/fileio-packets.exp
@@ -0,0 +1,66 @@
+# Copyright 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/>.
+
+# Test some remote file I/O. The associated Python script uses the
+# Python API to create and send vFile:* packets to gdbserver to
+# perform actions like 'stat'. The same action is then performed
+# directly from Python (e.g. a 'stat' is performed), and the results,
+# from gdbserver, and from the local syscall, are compared.
+
+load_lib gdb-python.exp
+load_lib gdbserver-support.exp
+
+require allow_python_tests
+require allow_gdbserver_tests
+require {!is_remote host}
+require {!is_remote target}
+
+standard_testfile
+
+clean_restart
+
+# Make sure we're disconnected, in case we're testing with an
+# extended-remote board, therefore already connected.
+gdb_test "disconnect" ".*"
+
+set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
+gdb_test_no_output "source $pyfile" "source the script"
+
+# Start gdbserver, but always in extended-remote mode, and then
+# connect to it from GDB.
+set res [gdbserver_start "--multi --once" ""]
+set gdbserver_protocol "extended-remote"
+set gdbserver_gdbport [lindex $res 1]
+gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
+
+gdb_test_no_output "set python print-stack full"
+
+set test_file_1 [standard_output_file "test_file_1"]
+remote_exec host "touch $test_file_1"
+
+set test_file_2 [standard_output_file "test_file_2"]
+remote_exec host "ln -s $test_file_1 $test_file_2"
+
+gdb_test "python check_lstat(\"$test_file_1\")" "PASS" \
+ "check remote lstat works on a normal file"
+
+gdb_test "python check_lstat(\"$test_file_2\")" "PASS" \
+ "check remote lstat works on a symbolic link"
+
+gdb_test "python check_stat(\"$test_file_1\")" "PASS" \
+ "check remote stat works on a normal file"
+
+gdb_test "python check_stat(\"$test_file_2\")" "PASS" \
+ "check remote stat works on a symbolic link"
diff --git a/gdb/testsuite/gdb.server/fileio-packets.py b/gdb/testsuite/gdb.server/fileio-packets.py
new file mode 100644
index 0000000..f132e91
--- /dev/null
+++ b/gdb/testsuite/gdb.server/fileio-packets.py
@@ -0,0 +1,208 @@
+# Copyright (C) 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/>.
+
+import os
+import stat
+
+
+# Hex encode INPUT_STRING in the same way that GDB does. Each
+# character in INPUT_STRING is expanded to its two digit hex
+# representation in the returned string.
+#
+# Only ASCII characters may appear in INPUT_STRING, this is more
+# restrictive than GDB, but is good enough for testing.
+def hex_encode(input_string):
+ byte_string = input_string.encode("ascii")
+ hex_string = byte_string.hex()
+ return hex_string
+
+
+# Binary remote data packets can contain some escaped bytes. Decode
+# the packet now.
+def unescape_remote_data(buf):
+ escaped = False
+ res = bytearray()
+ for b in buf:
+ if escaped:
+ res.append(b ^ 0x20)
+ escaped = False
+ elif b == ord("}"):
+ escaped = True
+ else:
+ res.append(b)
+ res = bytes(res)
+ return res
+
+
+# Decode the results of a remote stat like command from BUF. Returns
+# None if BUF is not a valid stat result (e.g. if it indicates an
+# error, or the buffer is too short). If BUF is valid then the fields
+# are decoded according to the GDB remote protocol and placed into a
+# dictionary, this dictionary is then returned.
+def decode_stat_reply(buf, byteorder="big"):
+
+ buf = unescape_remote_data(buf)
+
+ if (
+ buf[0] != ord("F")
+ or buf[1] != ord("4")
+ or buf[2] != ord("0")
+ or buf[3] != ord(";")
+ or len(buf) != 68
+ ):
+ l = len(buf)
+ print(f"decode_stat_reply failed: {buf}\t(length = {l})")
+ return None
+
+ # Discard the 'F40;' prefix. The rest is the 64 bytes of data to
+ # be decoded.
+ buf = buf[4:]
+
+ st_dev = int.from_bytes(buf[0:4], byteorder=byteorder)
+ st_ino = int.from_bytes(buf[4:8], byteorder=byteorder)
+ st_mode = int.from_bytes(buf[8:12], byteorder=byteorder)
+ st_nlink = int.from_bytes(buf[12:16], byteorder=byteorder)
+ st_uid = int.from_bytes(buf[16:20], byteorder=byteorder)
+ st_gid = int.from_bytes(buf[20:24], byteorder=byteorder)
+ st_rdev = int.from_bytes(buf[24:28], byteorder=byteorder)
+ st_size = int.from_bytes(buf[28:36], byteorder=byteorder)
+ st_blksize = int.from_bytes(buf[36:44], byteorder=byteorder)
+ st_blocks = int.from_bytes(buf[44:52], byteorder=byteorder)
+ st_atime = int.from_bytes(buf[52:56], byteorder=byteorder)
+ st_mtime = int.from_bytes(buf[56:60], byteorder=byteorder)
+ st_ctime = int.from_bytes(buf[60:64], byteorder=byteorder)
+
+ return {
+ "st_dev": st_dev,
+ "st_ino": st_ino,
+ "st_mode": st_mode,
+ "st_nlink": st_nlink,
+ "st_uid": st_uid,
+ "st_gid": st_gid,
+ "st_rdev": st_rdev,
+ "st_size": st_size,
+ "st_blksize": st_blksize,
+ "st_blocks": st_blocks,
+ "st_atime": st_atime,
+ "st_mtime": st_mtime,
+ "st_ctime": st_ctime,
+ }
+
+
+# Perform an lstat of remote file FILENAME, and create a dictionary of
+# the results, the keys are the fields of the stat structure.
+def remote_lstat(filename):
+ conn = gdb.selected_inferior().connection
+ if not isinstance(conn, gdb.RemoteTargetConnection):
+ raise gdb.GdbError("connection is the wrong type")
+
+ filename_hex = hex_encode(filename)
+ reply = conn.send_packet("vFile:lstat:%s" % filename_hex)
+
+ stat = decode_stat_reply(reply)
+ return stat
+
+
+# Perform a stat of remote file FILENAME, and create a dictionary of
+# the results, the keys are the fields of the stat structure.
+def remote_stat(filename):
+ conn = gdb.selected_inferior().connection
+ if not isinstance(conn, gdb.RemoteTargetConnection):
+ raise gdb.GdbError("connection is the wrong type")
+
+ filename_hex = hex_encode(filename)
+ reply = conn.send_packet("vFile:stat:%s" % filename_hex)
+
+ stat = decode_stat_reply(reply)
+ return stat
+
+
+# Convert a stat_result object to a dictionary that should match the
+# dictionary built from the remote protocol reply.
+def stat_result_to_dict(res):
+ # GDB doesn't support the S_IFLNK flag for the remote protocol, so
+ # clear that flag in the local results.
+ if stat.S_ISLNK(res.st_mode):
+ st_mode = stat.S_IMODE(res.st_mode)
+ else:
+ st_mode = res.st_mode
+
+ # GDB returns an integer for these fields, while Python returns a
+ # floating point value. Convert back to an integer to match GDB.
+ st_atime = int(res.st_atime)
+ st_mtime = int(res.st_mtime)
+ st_ctime = int(res.st_ctime)
+
+ return {
+ "st_dev": res.st_dev,
+ "st_ino": res.st_ino,
+ "st_mode": st_mode,
+ "st_nlink": res.st_nlink,
+ "st_uid": res.st_uid,
+ "st_gid": res.st_gid,
+ "st_rdev": res.st_rdev,
+ "st_size": res.st_size,
+ "st_blksize": res.st_blksize,
+ "st_blocks": res.st_blocks,
+ "st_atime": st_atime,
+ "st_mtime": st_mtime,
+ "st_ctime": st_ctime,
+ }
+
+
+# Perform an lstat of local file FILENAME, and create a dictionary of
+# the results, the keys are the fields of the stat structure.
+def local_lstat(filename):
+ res = os.lstat(filename)
+ return stat_result_to_dict(res)
+
+
+# Perform an lstat of local file FILENAME, and create a dictionary of
+# the results, the keys are the fields of the stat structure.
+def local_stat(filename):
+ res = os.stat(filename)
+ return stat_result_to_dict(res)
+
+
+# Perform a remote lstat using GDB, and a local lstat using os.lstat.
+# Compare the results to check they are the same.
+#
+# For this test to work correctly, gdbserver, and GDB (where this
+# Python script is running), must see the same filesystem.
+def check_lstat(filename):
+ s1 = remote_lstat(filename)
+ s2 = local_lstat(filename)
+
+ print(f"remote = {s1}")
+ print(f"local = {s2}")
+
+ assert s1 == s2
+ print("PASS")
+
+
+# Perform a remote stat using GDB, and a local stat using os.stat.
+# Compare the results to check they are the same.
+#
+# For this test to work correctly, gdbserver, and GDB (where this
+# Python script is running), must see the same filesystem.
+def check_stat(filename):
+ s1 = remote_stat(filename)
+ s2 = local_stat(filename)
+
+ print(f"remote = {s1}")
+ print(f"local = {s2}")
+
+ assert s1 == s2
+ print("PASS")
diff --git a/gdb/testsuite/gdb.server/inferior-args.c b/gdb/testsuite/gdb.server/inferior-args.c
new file mode 100644
index 0000000..3bc3ff7
--- /dev/null
+++ b/gdb/testsuite/gdb.server/inferior-args.c
@@ -0,0 +1,27 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023-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/>. */
+
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ for (int i = 0; i < argc; i++)
+ printf ("[%d] %s\n", i, argv[i]);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.server/inferior-args.exp b/gdb/testsuite/gdb.server/inferior-args.exp
new file mode 100644
index 0000000..18ac5a3
--- /dev/null
+++ b/gdb/testsuite/gdb.server/inferior-args.exp
@@ -0,0 +1,156 @@
+# Copyright 2023-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/>.
+
+# Test passing inferior arguments on the gdbserver command line. Tests the
+# flags --no-startup-with-shell and --no-escape-args that change how GDB
+# interprets the arguments being passed.
+
+# This test relies on starting gdbserver using the pipe syntax. Not sure
+# how well this will run if part of this test is being run elsewhere.
+require {!is_remote target} {!is_remote host}
+
+load_lib gdbserver-support.exp
+
+standard_testfile
+
+require allow_gdbserver_tests
+
+set gdbserver [find_gdbserver]
+if { $gdbserver == "" } {
+ unsupported "could not find gdbserver"
+ return
+}
+
+standard_testfile
+if {[build_executable "failed to prepare" $testfile $srcfile]} {
+ return -1
+}
+
+# EXTENDED_P is a boolean, when true gdbserver is started with --multi, and
+# GDB connects using extended-remote protocol. Otherwise, no --multi flag
+# is passed, and GDB connects with the remote protocol.
+#
+# WITH_SHELL_P is a boolean, when true gdbserver starts the inferior using a
+# shell, when false gdbserver is passed the --no-startup-with-shell command
+# line option, and should not start the inferior through a shell.
+#
+# ESCAPE_P is a boolean, when true gdbserver applies escapes to the inferior
+# arguments, when false gdbserver is passed the --no-escape-args command
+# line option, and should not apply escaping to the inferior arguments.
+#
+# ARGLIST is a list of inferior arguments to add to the gdbserver command
+# line.
+#
+# RE_LIST is a list of patterns to match, one for each of ARGLIST. Once the
+# inferior is started we check that each argument matches its corresponding
+# entry in RE_LIST.
+proc do_test_inner { extended_p with_shell_p escape_p arglist re_list } {
+
+ clean_restart ${::testfile}
+
+ gdb_test_no_output "set sysroot"
+
+ # Make sure we're disconnected, in case we're testing with an
+ # extended-remote board, therefore already connected.
+ gdb_test "disconnect" ".*"
+
+ if { $extended_p } {
+ set protocol "extended-remote"
+ } else {
+ set protocol "remote"
+ }
+
+ if { $escape_p } {
+ set esc_opt ""
+ } else {
+ set esc_opt "--no-escape-args"
+ }
+
+ if { $with_shell_p } {
+ set shell_opt ""
+ } else {
+ set shell_opt "--no-startup-with-shell"
+ }
+
+ gdb_test "target ${protocol} | ${::gdbserver} --once ${esc_opt} ${shell_opt} - ${::binfile} ${arglist}" \
+ ".*" \
+ "start gdbserver over stdin"
+
+ gdb_breakpoint main
+ gdb_continue_to_breakpoint main
+
+ set expected_len [expr {1 + [llength $re_list]}]
+ gdb_test "print argc" \
+ "\\\$$::decimal = $expected_len" "check argc"
+
+ set i 1
+ foreach arg $re_list {
+ gdb_test "print argv\[$i\]" \
+ "\\\$$::decimal = $::hex \"$arg\"" \
+ "check argv\[$i\]"
+ incr i
+ }
+}
+
+# Wrapper around do_test_inner. NAME is the name of this test, used to make
+# the test names unique. ARGLIST is the list of inferior arguments to add
+# to the gdbserver command line.
+#
+# The optional RE_ESC_LIST is a list of patterns to match against the
+# inferior arguments once the inferior is started, one pattern for each
+# argument. If RE_ESC_LIST is not given then ARGLIST is reused, which
+# implies the arguments appear unmodified in the test output.
+#
+# The optional RE_NO_ESC_LIST is a list of patterns to match against the
+# inferior arguments when gdbserver is started with --no-escape-args or
+# --no-startup-with-shell. There should be one pattern for each argument.
+# If RE_NO_ESC_LIST is not given then RE_ESC_LIST is reused, which implies
+# there's no difference in how the arguments are printed.
+proc args_test { name arglist {re_esc_list {}} {re_no_esc_list {}} } {
+ if {[llength $re_esc_list] == 0} {
+ set re_esc_list $arglist
+ }
+
+ if {[llength $re_no_esc_list] == 0} {
+ set re_no_esc_list $re_esc_list
+ }
+
+ foreach_with_prefix extended_p { yes no } {
+ foreach_with_prefix startup_with_shell { on off } {
+ foreach_with_prefix escape_p { yes no } {
+ if { $escape_p || !$startup_with_shell } {
+ set re_list $re_esc_list
+ } else {
+ set re_list $re_no_esc_list
+ }
+
+ with_test_prefix "$name" {
+ do_test_inner $extended_p $startup_with_shell \
+ $escape_p $arglist $re_list
+ }
+ }
+ }
+ }
+}
+
+args_test "basic" {a b c}
+args_test "one empty" {1 "" 3}
+args_test "two empty" {1 "" "" 3}
+args_test "one with single quotes" {1 "''" 3}
+args_test "lone double quote" {"1" \" 3} {1 \\\\\" 3}
+save_vars { env(TEST) } {
+ set env(TEST) "ABCD"
+ args_test "shell variable" {\$TEST} {\\$TEST} {ABCD}
+}
diff --git a/gdb/testsuite/gdb.server/monitor-exit-quit.exp b/gdb/testsuite/gdb.server/monitor-exit-quit.exp
index ce63560..74842a0 100644
--- a/gdb/testsuite/gdb.server/monitor-exit-quit.exp
+++ b/gdb/testsuite/gdb.server/monitor-exit-quit.exp
@@ -34,7 +34,7 @@ save_vars { GDBFLAGS } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
@@ -70,7 +70,7 @@ gdb_test_multiple "quit" "" {
# Cleanup, as in default_gdb_exit.
if { $do_cleanup } {
- if ![is_remote host] {
+ if { ![is_remote host] } {
remote_close host
}
unset gdb_spawn_id
diff --git a/gdb/testsuite/gdb.server/no-thread-db.exp b/gdb/testsuite/gdb.server/no-thread-db.exp
index cc24708..9fd2090 100644
--- a/gdb/testsuite/gdb.server/no-thread-db.exp
+++ b/gdb/testsuite/gdb.server/no-thread-db.exp
@@ -57,6 +57,8 @@ gdb_breakpoint ${srcfile}:[gdb_get_line_number "after tls assignment"]
gdb_continue_to_breakpoint "after tls assignment"
# Printing a tls variable should fail gracefully without a libthread_db.
+# Alternately, the correct answer might be printed due GDB's internal
+# TLS support for some targets.
set re_exec "\[^\r\n\]*[file tail $binfile]"
gdb_test "print foo" \
- "Cannot find thread-local storage for Thread \[^,\]+, executable file $re_exec:\[\r\n\]+Remote target failed to process qGetTLSAddr request"
+ "= 1|(?:Cannot find thread-local storage for Thread \[^,\]+, executable file $re_exec:\[\r\n\]+Remote target failed to process qGetTLSAddr request)"
diff --git a/gdb/testsuite/gdb.server/non-existing-program.exp b/gdb/testsuite/gdb.server/non-existing-program.exp
index 7119723..ec9c044 100644
--- a/gdb/testsuite/gdb.server/non-existing-program.exp
+++ b/gdb/testsuite/gdb.server/non-existing-program.exp
@@ -34,6 +34,8 @@ if { $gdbserver == "" } {
# to spawn the program before opening the connection.
set spawn_id [remote_spawn target "$gdbserver stdio non-existing-program"]
+set eol {[\r\n]}
+
set msg "gdbserver exits cleanly"
set saw_exiting 0
expect {
@@ -51,7 +53,7 @@ expect {
exp_continue
}
# This is what we get on Windows.
- -re "Error creating process\r\n\r\nExiting\r\n" {
+ -re "Error creating process.*$eol+Exiting$eol+" {
set saw_exiting 1
exp_continue
}
diff --git a/gdb/testsuite/gdb.server/pread-offset-size.S b/gdb/testsuite/gdb.server/pread-offset-size.S
new file mode 100644
index 0000000..6ca8cf0
--- /dev/null
+++ b/gdb/testsuite/gdb.server/pread-offset-size.S
@@ -0,0 +1,29 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 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/>. */
+
+/* Here we are trying to create a large binary (> 2 GB),
+ 3742415472 bytes is about 3.5 gigabytes. */
+
+ .text
+ .globl _start
+_start:
+ .skip 3742415472
+ ret
+ .globl f
+ .type f, @function
+f:
+ ret
diff --git a/gdb/testsuite/gdb.server/pread-offset-size.exp b/gdb/testsuite/gdb.server/pread-offset-size.exp
new file mode 100644
index 0000000..54e67c5
--- /dev/null
+++ b/gdb/testsuite/gdb.server/pread-offset-size.exp
@@ -0,0 +1,49 @@
+# Copyright (C) 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/>.
+#
+# Check that GDBserver's vFile::pread implementation is able to access
+# large files (> 2GB).
+
+load_lib gdbserver-support.exp
+
+require allow_gdbserver_tests
+
+standard_testfile .S
+
+if { [prepare_for_testing ${testfile}.exp $testfile \
+ $srcfile {debug additional_flags=-nostdlib} ] } {
+ return -1
+}
+
+clean_restart
+
+gdb_test_no_output "set remote exec-file $binfile" \
+ "set remote exec-file"
+
+# Make sure we're disconnected, in case we're testing with an
+# extended-remote board, therefore already connected.
+gdb_test "disconnect" ".*"
+
+set res [gdbserver_spawn ""]
+set gdbserver_protocol [lindex $res 0]
+set gdbserver_gdbport [lindex $res 1]
+
+gdb_test "target $gdbserver_protocol $gdbserver_gdbport" \
+ "Remote debugging using .*" \
+ "target $gdbserver_protocol"
+
+# If loading the large binary was successful, we should be able to
+# place a breakpoint on f.
+gdb_test "break f" "Breakpoint 1.*"
diff --git a/gdb/testsuite/gdb.server/reconnect-ctrl-c.exp b/gdb/testsuite/gdb.server/reconnect-ctrl-c.exp
index 83869a3..61aaaea 100644
--- a/gdb/testsuite/gdb.server/reconnect-ctrl-c.exp
+++ b/gdb/testsuite/gdb.server/reconnect-ctrl-c.exp
@@ -32,7 +32,7 @@ save_vars { GDBFLAGS } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- if [prepare_for_testing "failed to prepare" $testfile $srcfile] {
+ if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} {
return -1
}
}
@@ -51,7 +51,7 @@ proc connect_continue_ctrl_c {} {
global gdbserver_protocol gdbserver_gdbport
set res [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
- if ![gdb_assert {$res == 0} "connect"] {
+ if { ![gdb_assert {$res == 0} "connect"] } {
return
}
diff --git a/gdb/testsuite/gdb.server/server-empty-exec-name.exp b/gdb/testsuite/gdb.server/server-empty-exec-name.exp
new file mode 100644
index 0000000..a9cb9ab
--- /dev/null
+++ b/gdb/testsuite/gdb.server/server-empty-exec-name.exp
@@ -0,0 +1,93 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 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/>.
+
+# Test what happens if we try to start gdbserver with an empty string
+# for the executable name. In theory we could choose to accept this
+# for the extended-remote case, indeed, in the extended-remote case
+# it's OK to start gdbserver with no program name or arguments.
+#
+# But actually specifying an empty executable name seems different,
+# and wrong, so for now at least, we don't allow this. If that
+# position changes in the future, then this test will need updating.
+
+# Skip test if target does not support argument passing.
+require {!target_info exists noargs}
+
+load_lib gdbserver-support.exp
+
+standard_testfile
+
+require allow_gdbserver_tests
+
+set gdbserver [find_gdbserver]
+if { $gdbserver == "" } {
+ unsupported "could not find gdbserver"
+ return
+}
+
+clean_restart
+
+# Try starting gdbserver in extended, and non-extended mode.
+foreach_with_prefix proto { extended-remote remote } {
+
+ if { $proto eq "extended-remote" } {
+ set server_flag "--multi"
+ } else {
+ set server_flag ""
+ }
+
+ # Try starting gdbserver with and without arguments.
+ foreach_with_prefix args { " a b c" "" } {
+ # Start gdbserver on its own. This makes it easier to check
+ # the error message that gdbserver emits. The program name is
+ # the empty string. gdbserver should exit.
+ set gdbserver_cmd \
+ "$gdbserver $server_flag --once - \"\"${args}"
+
+ set spawn_id [remote_spawn target $gdbserver_cmd]
+ set testname "start gdbserver"
+ expect {
+ -i $spawn_id
+
+ -re "No program to debug\r\nExiting" { pass $testname }
+
+ eof { fail $testname }
+ timeout { fail $testname }
+ }
+
+ catch {
+ close -i $spawn_id
+ wait -nowait -i $spawn_id
+ }
+
+ # Try connecting to gdbserver from GDB. The connection should
+ # immediately close as gdbserver exits. The inferior should
+ # be left with no connection.
+ gdb_test "disconnect" ".*" \
+ "disconnect before remote connection"
+
+ gdb_test "target $proto | ${::gdbserver} $server_flag --once - \"\"${args}" \
+ [multi_line \
+ "Remote debugging using \\| \[^\r\n\]+" \
+ "Remote communication error\\. Target disconnected: .*"] \
+ "start gdbserver over stdin"
+
+ gdb_test "info inferiors" \
+ "\\*\\s+1\\s+<null>\\s*" \
+ "check inferior 1 has no connection"
+ }
+}
diff --git a/gdb/testsuite/gdb.server/server-exec-info.exp b/gdb/testsuite/gdb.server/server-exec-info.exp
index fccf075..007290a 100644
--- a/gdb/testsuite/gdb.server/server-exec-info.exp
+++ b/gdb/testsuite/gdb.server/server-exec-info.exp
@@ -21,7 +21,7 @@ load_lib gdbserver-support.exp
require allow_gdbserver_tests allow_shlib_tests
standard_testfile server.c
-if [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] {
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
return -1
}
diff --git a/gdb/testsuite/gdb.server/server-kill.exp b/gdb/testsuite/gdb.server/server-kill.exp
index 0a759ae..f01f5e3 100644
--- a/gdb/testsuite/gdb.server/server-kill.exp
+++ b/gdb/testsuite/gdb.server/server-kill.exp
@@ -43,7 +43,7 @@ proc prepare {} {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
@@ -82,7 +82,7 @@ proc kill_server {} {
# Test issuing "tstatus" right after the connection is dropped.
proc_with_prefix test_tstatus {} {
- if ![prepare] {
+ if {![prepare]} {
return
}
@@ -97,14 +97,14 @@ proc_with_prefix test_tstatus {} {
# Force GDB to talk with GDBserver, so that we can get the
# "connection closed" error.
- gdb_test "tstatus" {Remote connection closed|Remote communication error\. Target disconnected: Connection reset by peer\.}
+ gdb_test "tstatus" {Remote connection closed|Remote communication error\. Target disconnected: error while reading: Connection reset by peer\.}
}
# Test unwinding with no debug/unwind info, right after the connection
# is dropped.
proc_with_prefix test_unwind_nosyms {} {
- if ![prepare] {
+ if {![prepare]} {
return
}
@@ -121,7 +121,7 @@ proc_with_prefix test_unwind_nosyms {} {
# dropped.
proc_with_prefix test_unwind_syms {} {
- if ![prepare] {
+ if {![prepare]} {
return
}
@@ -133,7 +133,7 @@ proc_with_prefix test_unwind_syms {} {
# Test performing a stepi right after the connection is dropped.
proc_with_prefix test_stepi {} {
- if ![prepare] {
+ if {![prepare]} {
return
}
@@ -152,4 +152,3 @@ test_tstatus
test_unwind_nosyms
test_unwind_syms
test_stepi
-
diff --git a/gdb/testsuite/gdb.server/server-pipe.exp b/gdb/testsuite/gdb.server/server-pipe.exp
index d786946..20ca0b0 100644
--- a/gdb/testsuite/gdb.server/server-pipe.exp
+++ b/gdb/testsuite/gdb.server/server-pipe.exp
@@ -50,7 +50,7 @@ if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
# the contents of the gdb.TargetConnection.details string.
proc do_test { target } {
global timeout
- clean_restart ${::binfile}
+ clean_restart ${::testfile}
# Make sure we're disconnected, in case we're testing with an
# extended-remote board, therefore already connected.
diff --git a/gdb/testsuite/gdb.server/server-run.exp b/gdb/testsuite/gdb.server/server-run.exp
index 6c9db98..53b3278 100644
--- a/gdb/testsuite/gdb.server/server-run.exp
+++ b/gdb/testsuite/gdb.server/server-run.exp
@@ -34,7 +34,7 @@ save_vars { GDBFLAGS } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart $binfile
+ clean_restart $::testfile
}
# Make sure we're disconnected, in case we're testing with an
diff --git a/gdb/testsuite/gdb.server/stop-reply-no-thread-multi.exp b/gdb/testsuite/gdb.server/stop-reply-no-thread-multi.exp
index 42608c4..f1c68a5 100644
--- a/gdb/testsuite/gdb.server/stop-reply-no-thread-multi.exp
+++ b/gdb/testsuite/gdb.server/stop-reply-no-thread-multi.exp
@@ -54,7 +54,7 @@ proc run_test { target_non_stop disable_feature } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
# Make sure we're disconnected, in case we're testing with an
@@ -78,7 +78,7 @@ proc run_test { target_non_stop disable_feature } {
"Support for the 'multiprocess-feature' packet on future remote targets is set to \"off\"."
set res [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
- if ![gdb_assert {$res == 0} "connect"] {
+ if { ![gdb_assert {$res == 0} "connect"] } {
return
}
diff --git a/gdb/testsuite/gdb.server/stop-reply-no-thread.exp b/gdb/testsuite/gdb.server/stop-reply-no-thread.exp
index 38402e8..aa77095 100644
--- a/gdb/testsuite/gdb.server/stop-reply-no-thread.exp
+++ b/gdb/testsuite/gdb.server/stop-reply-no-thread.exp
@@ -42,7 +42,7 @@ proc run_test { disable_feature target_nonstop } {
set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
}
- clean_restart ${binfile}
+ clean_restart ${::testfile}
}
# Make sure we're disconnected, in case we're testing with an
@@ -70,7 +70,7 @@ proc run_test { disable_feature target_nonstop } {
gdb_test_no_output "maint set target-non-stop ${target_nonstop}"
set res [gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport]
- if ![gdb_assert {$res == 0} "connect"] {
+ if { ![gdb_assert {$res == 0} "connect"] } {
return
}