From: Andrew Burgess <aburgess@redhat.com>
To: gdb-patches@sourceware.org
Cc: Andrew Burgess <aburgess@redhat.com>
Subject: [PATCH] gdbserver: reset single_inferior_argument feature on a new connection
Date: Wed, 28 Oct 2026 13:34:54 +0000 [thread overview]
Message-ID: <4797c01ed0887b34fcdf765baa3714fbc7a230bc.1793194469.git.aburgess@redhat.com> (raw)
In commit:
commit 8e28eef6cdcbd86ad61325ce1e6bd563b0fad1e1
Date: Thu Nov 23 18:46:54 2023 +0000
gdb/gdbserver: pass inferior arguments as a single string
the new single_inferior_argument feature was added to gdbserver.
There was a mistake in that commit though, the new connection flag was
not reset at the point that a new connection was established as other
flags are.
This means that the flag value will carry over from one connection to
the next, which in turn means that connecting with a GDB that supports
the single-inferior-argument feature will latch the feature on in
gdbserver. Reconnecting with a GDB that doesn't support this feature
will then mean that GDB is unable to start a new inferior with more
than a single argument.
I have a test that exposes the issue by switching off the
single-inferior-argument feature in GDB.
This bug was introduced in the GDB 18 release, so the fix should
probably be backported to the gdb-18-branch too. However, I'm not
massively worried about this bug. In order to run into the problem
users would need to have a single gdbserver session to which they
first connect GDB 18, then to the *same* session they connect an older
version of GDB. This seems an unlikely use case.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34908
---
gdb/testsuite/gdb.server/inferior-args.exp | 101 +++++++++++++++++++++
gdbserver/server.cc | 1 +
2 files changed, 102 insertions(+)
diff --git a/gdb/testsuite/gdb.server/inferior-args.exp b/gdb/testsuite/gdb.server/inferior-args.exp
index f6ad3e69b40..4fb31ba2fd7 100644
--- a/gdb/testsuite/gdb.server/inferior-args.exp
+++ b/gdb/testsuite/gdb.server/inferior-args.exp
@@ -145,6 +145,105 @@ proc args_test { name arglist {re_esc_list {}} {re_no_esc_list {}} } {
}
}
+# Start gdbserver in --multi mode, connect and start an inferior.
+# Then switch off the single-inferior-argument-feature-packet and
+# reconnect to the SAME gdbserver. Then try to start a new inferior
+# passing multiple command line arguments.
+#
+# This checks that gdbserver correctly clears the feature flag for the
+# single inferior argument feature. If it doesn't then the second
+# connection will fail to start an inferior as there will be a
+# disagreement between GDB and gdbserver about how the argument packet
+# should be formatted.
+proc reconnection_and_single_inf_args {} {
+ global GDBFLAGS gdbserver_reconnect_p use_gdb_stub
+
+ save_vars { GDBFLAGS } {
+ # If GDB and GDBserver are both running locally, set the sysroot to avoid
+ # reading files via the remote protocol (the `is_remote target` check is
+ # already done above).
+ if { ![is_remote host] } {
+ set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\""
+ }
+ clean_restart $::testfile
+
+ # Make sure we're disconnected, in case we're testing with an
+ # extended-remote board, therefore already connected.
+ gdb_test "disconnect" ".*"
+ }
+
+ save_vars { gdbserver_reconnect_p use_gdb_stub } {
+ # Setting this flag prevents gdbserver being started with the
+ # --once option; this is required so that we can reconnect.
+ set gdbserver_reconnect_p 1
+
+ # This test always starts gdbserver in --multi mode, so clear
+ # the use_gdb_stub global to allow gdb_start_cmd to work.
+ set use_gdb_stub 0
+
+ # Start gdbserver in extended-remote mode.
+ set res [gdbserver_start "--multi" "$::binfile"]
+ set gdbserver_protocol "extended-remote"
+ set gdbserver_gdbport [lindex $res 1]
+ gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
+
+ # Start an inferior passing multiple arguments. By default
+ # this will make use of the single-inferior-argument remote
+ # feature, passing these arguments as a single string.
+ if { [gdb_start_cmd "a b c"] < 0 } {
+ fail "start command"
+ return -1
+ }
+
+ # gdb_start_cmd doesn't consume the prompt. Collect it now.
+ gdb_test "" "" \
+ "wait for prompt after starting the inferior"
+
+ # Check the inferior saw the correct argument count; the
+ # executable name and three arguments: 'a', 'b', and 'c'.
+ gdb_test "print argc" " = 4" \
+ "print argc after initial start"
+
+ # Turn off the single-inferior-argument feature and reconnect.
+ # With the new connection gdbserver should reset its feature
+ # flags and renegotiate, so the new connection should end up
+ # not using this feature.
+ gdb_test "set remote single-inferior-argument-feature-packet off" \
+ "Support for the 'single-inferior-argument-feature' packet on the current remote target is set to \"off\"\\."
+
+ gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport
+
+ # Now start a new inferior, in the newly connected session.
+ # GDB will split these arguments and send them as 3 separate
+ # strings. If gdbserver messed up its feature flags then it
+ # will only be expecting a single string, in which case it
+ # will reject this request and not start the inferior.
+ if { [gdb_start_cmd "a b c"] < 0 } {
+ fail "second start command"
+ return -1
+ }
+
+ # This time we check for the 'remote target failed' message,
+ # this is the bug that was fixed when this test was added.
+ set saw_run_failure false
+ gdb_test_multiple "" "start inferior after reconnecting" -lbl {
+ -re "\r\nRunning \"\[^\r\n\]+/$::testfile\" on the remote target failed(?=\r\n)" {
+ set saw_run_failure true
+ exp_continue
+ }
+
+ -re "\r\n$::gdb_prompt " {
+ gdb_assert { !$saw_run_failure } $gdb_test_name
+ }
+ }
+
+ # Print the argc value as a double check. This confirms that
+ # the inferior started, and saw the correct number of args.
+ gdb_test "print argc" " = 4" \
+ "print argc after reconnecting"
+ }
+}
+
args_test "basic" {a b c}
args_test "one empty" {1 "" 3}
args_test "two empty" {1 "" "" 3}
@@ -154,3 +253,5 @@ save_vars { env(TEST) } {
set env(TEST) "ABCD"
args_test "shell variable" {\$TEST} {\\$TEST} {ABCD}
}
+
+reconnection_and_single_inf_args
diff --git a/gdbserver/server.cc b/gdbserver/server.cc
index 74774fcde7c..a7d966ce7e3 100644
--- a/gdbserver/server.cc
+++ b/gdbserver/server.cc
@@ -4629,6 +4629,7 @@ captured_main (int argc, char *argv[])
cs.vCont_supported = 0;
cs.memory_tagging_feature = false;
cs.error_message_supported = false;
+ cs.single_inferior_argument = false;
cs.multiple_wp_addr_feature = false;
remote_open (port);
base-commit: b2fe3a449cb5d130ea2fec65bb214601826cdeff
--
2.25.4
reply other threads:[~2026-10-28 13:35 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4797c01ed0887b34fcdf765baa3714fbc7a230bc.1793194469.git.aburgess@redhat.com \
--to=aburgess@redhat.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox