From: Mohamed Bouhaouel <mohamed.bouhaouel@intel.com>
To: gdb-patches@sourceware.org
Cc: markus.t.metzger@intel.com, stephan.rohr@intel.com, eliz@gnu.org,
aburgess@redhat.com, pedro@palves.net
Subject: [PATCH v4 11/11] gdb, gdbserver: add AlwaysNonStop remote protocol extension
Date: Tue, 14 Jul 2026 11:21:28 +0200 [thread overview]
Message-ID: <20260714092128.12941-12-mohamed.bouhaouel@intel.com> (raw)
In-Reply-To: <20260714092128.12941-1-mohamed.bouhaouel@intel.com>
From: "Bouhaouel, Mohamed" <mohamed.bouhaouel@intel.com>
Add a new RSP extension allowing remote stubs to declare that a target
prefers to operate in non-stop mode.
When a stub advertises "AlwaysNonStop+" in its qSupported response:
* The stub automatically initializes to non-stop mode.
* GDB will operate the stub in non-stop mode (with default settings).
* The stub may reject QNonStop:0 requests with descriptive error
messages.
* GDB allows connection even if 'maint set target-non-stop off' is set,
but lets the stub decide whether to accept mode switches.
Additionally, gdbserver now accepts --enable-packet=PACKET to enable
specific remote protocol packets or extensions at startup. Currently
this supports the 'AlwaysNonStop' extension.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
---
gdb/NEWS | 13 +++
gdb/doc/gdb.texinfo | 46 ++++++++++-
gdb/remote.c | 21 +++++
.../gdb.server/enable-always-non-stop.exp | 56 +++++++++++++
gdbserver/server.cc | 79 +++++++++++++++++--
gdbserver/server.h | 2 +
gdbserver/target.cc | 6 ++
gdbserver/target.h | 6 ++
8 files changed, 223 insertions(+), 6 deletions(-)
create mode 100644 gdb/testsuite/gdb.server/enable-always-non-stop.exp
diff --git a/gdb/NEWS b/gdb/NEWS
index ec9b5a33787..4f75a55af5d 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -22,6 +22,10 @@
this flag is used gdbserver will not escape special shell characters
within the inferior arguments.
+* gdbserver now accepts --enable-packet=PACKET to enable specific remote
+ protocol packets or extensions at startup. Currently this supports
+ 'AlwaysNonStop' to force the target to always operate in non-stop mode.
+
* The add-inferior, clone-inferior, and MI -add-inferior commands will
now give a warning, and create the new inferior without a
connection, when the current inferior's connection, at the time the
@@ -116,6 +120,15 @@
intent to remove it in a future release.
The s390 64-bit target (s390x-*) remains supported.
+* New remote protocol extension 'AlwaysNonStop' allows gdbserver to
+ indicate that the target prefers to operate in non-stop mode. When a
+ remote stub advertises 'AlwaysNonStop+' in its qSupported reply, GDB
+ will operate the stub in non-stop mode (when 'maint set target-non-stop'
+ is 'auto', the default). If the user explicitly sets 'maint set
+ target-non-stop off', GDB will allow the connection but the stub may
+ reject attempts to switch to all-stop mode with a descriptive error
+ message.
+
* Configure changes
** --with-babeltrace has been removed. The babeltrace library was
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index a698b2b8451..3019cb915f2 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -42922,7 +42922,9 @@ does not indicate support.
@item maint set target-non-stop off
@value{GDBN} does not control the target in non-stop mode even if the
-target supports it.
+target supports it. Note: targets that prefer non-stop mode (via
+@samp{AlwaysNonStop+}) may reject attempts to switch to all-stop mode
+with a descriptive error message.
@end table
Here is how @code{set non-stop} and @code{maint set target-non-stop}
@@ -45094,6 +45096,12 @@ Reply:
@table @samp
@item OK
The request succeeded.
+
+@item @samp{E.@var{message}}
+The request failed. This may occur if the stub prefers non-stop mode
+and advertised @samp{AlwaysNonStop+} support, and @value{GDBN} attempted to
+switch to all-stop mode with @samp{QNonStop:0}. The stub returns a
+textual error message describing why the mode switch was rejected.
@end table
This packet is not probed by default; the remote stub must request it,
@@ -45511,6 +45519,22 @@ multiple-watchpoint-addresses-packet} command (@pxref{Remote
Configuration, set remote multiple-watchpoint-addresses-packet}).
@end table
+@item AlwaysNonStop
+This feature indicates that @value{GDBN} supports remote stubs that
+prefer non-stop mode operation. If the stub advertises
+@samp{AlwaysNonStop+}, it will run in non-stop mode, similar to
+the setting @code{maint set target-non-stop on}. If @value{GDBN}
+attempts to switch the target to all-stop mode, the stub may reject
+the request with a descriptive error message.
+
+Note: @samp{AlwaysNonStop+} requires @samp{QNonStop+} support.
+If a stub advertises @samp{AlwaysNonStop+} without @samp{QNonStop+},
+the @samp{AlwaysNonStop+} extension will be silently ignored by @value{GDBN}.
+
+Use of this feature is controlled by the @code{set remote
+always-non-stop-feature-packet} command (@pxref{Remote
+Configuration, set remote always-non-stop-feature-packet}).
+
Stubs should ignore any unknown values for
@var{gdbfeature}. Any @value{GDBN} which sends a @samp{qSupported}
packet supports receiving packets of unlimited length (earlier
@@ -45907,6 +45931,13 @@ packet (@pxref{qXfer fdpic loadmap read}).
The remote stub understands the @samp{QNonStop} packet
(@pxref{QNonStop}).
+@item AlwaysNonStop
+The remote stub prefers non-stop mode operation, may reject
+@samp{QNonStop:0} requests with a descriptive error message, and
+automatically initializes to non-stop mode. This feature must be
+advertised together with @samp{QNonStop+}; if advertised without it,
+the feature will be silently ignored by @value{GDBN}. @xref{QNonStop}.
+
@item QCatchSyscalls
The remote stub understands the @samp{QCatchSyscalls} packet
(@pxref{QCatchSyscalls}).
@@ -52204,6 +52235,19 @@ option special shell characters will not be escaped. When
@command{gdbserver} starts a new shell in order to invoke the
inferior, this new shell will expand any special shell characters.
+@item --enable-packet=@var{packet}@r{[},@var{packet}@dots{}@r{]}
+Enable specific remote protocol packets or extensions at startup.
+The @var{packet} argument can be one of the following:
+
+@table @code
+@item AlwaysNonStop
+Force the target to always operate in non-stop mode. When this
+extension is enabled, @command{gdbserver} will reject any attempts
+by @value{GDBN} to switch to all-stop mode with a descriptive error
+message. This is useful for targets that require non-stop mode
+for correct operation.
+@end table
+
@c --disable-packet is not documented for users.
@c --disable-randomization and --no-disable-randomization are superseded by
diff --git a/gdb/remote.c b/gdb/remote.c
index b1bc1283b9a..fc5fb6cd160 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -323,6 +323,9 @@ enum {
/* Support for the QNonStop packet. */
PACKET_QNonStop,
+ /* Support for AlwaysNonStop extension. */
+ PACKET_AlwaysNonStop_feature,
+
/* Support for the QThreadEvents packet. */
PACKET_QThreadEvents,
@@ -1442,6 +1445,8 @@ class remote_target : public process_stratum_target
void check_binary_download (CORE_ADDR addr);
+ bool always_non_stop_p () override;
+
target_xfer_status remote_write_bytes_aux (const char *header,
CORE_ADDR memaddr,
const gdb_byte *myaddr,
@@ -6133,6 +6138,8 @@ static const struct protocol_feature remote_protocol_features[] = {
{ "multiprocess", PACKET_DISABLE, remote_supported_packet,
PACKET_multiprocess_feature },
{ "QNonStop", PACKET_DISABLE, remote_supported_packet, PACKET_QNonStop },
+ { "AlwaysNonStop", PACKET_DISABLE, remote_supported_packet,
+ PACKET_AlwaysNonStop_feature },
{ "qXfer:siginfo:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_siginfo_read },
{ "qXfer:siginfo:write", PACKET_DISABLE, remote_supported_packet,
@@ -9817,6 +9824,18 @@ remote_target::check_binary_download (CORE_ADDR addr)
}
}
+/* Determine whether the remote target operates in non-stop mode.
+ Returns true if the target advertises AlwaysNonStop, and supports
+ QNonStop for asynchronous execution and stop notifications. */
+
+bool
+remote_target::always_non_stop_p ()
+{
+ return ((m_features.packet_support (PACKET_QNonStop) == PACKET_ENABLE)
+ && (m_features.packet_support (PACKET_AlwaysNonStop_feature)
+ == PACKET_ENABLE));
+}
+
/* Helper function to resize the payload in order to try to get a good
alignment. We try to write an amount of data such that the next write will
start on an address aligned on REMOTE_ALIGN_WRITES. */
@@ -17073,6 +17092,8 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (PACKET_multi_wp_addr,
"multi-wp-addr", "multiple-watchpoint-addresses", 0);
+ add_packet_config_cmd (PACKET_AlwaysNonStop_feature,
+ "AlwaysNonStop", "always-non-stop-feature", 0);
/* Assert that we've registered "set remote foo-packet" commands
for all packet configs. */
diff --git a/gdb/testsuite/gdb.server/enable-always-non-stop.exp b/gdb/testsuite/gdb.server/enable-always-non-stop.exp
new file mode 100644
index 00000000000..c05f58847bb
--- /dev/null
+++ b/gdb/testsuite/gdb.server/enable-always-non-stop.exp
@@ -0,0 +1,56 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2026 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 that the --enable-packet=AlwaysNonStop gdbserver command line option
+# causes GDB to operate gdbserver with target-non-stop mode enabled.
+
+load_lib gdbserver-support.exp
+
+require allow_gdbserver_tests
+
+standard_testfile server.c
+
+if { [build_executable "failed to prepare" $testfile $srcfile] == -1 } {
+ return
+}
+set target_binfile [gdb_remote_download target $binfile]
+
+save_vars { ::GDBFLAGS } {
+ if { ![is_remote host] && ![is_remote target] } {
+ set ::GDBFLAGS "$::GDBFLAGS -ex \"set sysroot\""
+ }
+ clean_restart $::testfile
+}
+gdb_test "disconnect" ".*"
+
+# Start gdbserver with --enable-packet=AlwaysNonStop
+set res [gdbserver_start "--enable-packet=AlwaysNonStop" $::target_binfile]
+set protocol [lindex $res 0]
+set port [lindex $res 1]
+
+set res [gdb_target_cmd $protocol $port]
+if { ![gdb_assert {$res == 0} "connect"] } {
+ return
+}
+
+# Check that target-non-stop is on
+gdb_test "maint show target-non-stop" \
+ "Whether the target is always in non-stop mode is auto \\(currently on\\)\\." \
+ "verify target-non-stop is on"
+
+# continue to end
+gdb_continue_to_end
diff --git a/gdbserver/server.cc b/gdbserver/server.cc
index 4a727c465f0..614e807271f 100644
--- a/gdbserver/server.cc
+++ b/gdbserver/server.cc
@@ -147,6 +147,9 @@ bool disable_packet_qC;
bool disable_packet_qfThreadInfo;
bool disable_packet_T;
+/* Set if you want to enable optional packets or extensions via CLI. */
+bool enable_always_non_stop;
+
static unsigned char *mem_buf;
/* A sub-class of 'struct notif_event' for stop, holding information
@@ -838,10 +841,19 @@ handle_general_set (char *own_buf)
}
req_str = req ? "non-stop" : "all-stop";
- if (the_target->start_non_stop (req == 1) != 0)
+
+ try
{
- fprintf (stderr, "Setting %s mode failed\n", req_str);
- write_enn (own_buf);
+ if (the_target->start_non_stop (req == 1) != 0)
+ {
+ sprintf (own_buf, "E.Setting %s mode failed.", req_str);
+ return;
+ }
+ }
+ catch (const gdb_exception_error &exception)
+ {
+ /* The target rejected the setting, forward the error message. */
+ sprintf (own_buf, "E.%s", exception.what ());
return;
}
@@ -2812,7 +2824,11 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
strcat (own_buf, ";exec-events+");
if (target_supports_non_stop ())
- strcat (own_buf, ";QNonStop+");
+ {
+ strcat (own_buf, ";QNonStop+");
+ if (target_always_non_stop ())
+ strcat (own_buf, ";AlwaysNonStop+");
+ }
if (target_supports_disable_randomization ())
strcat (own_buf, ";QDisableRandomization+");
@@ -2876,6 +2892,19 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (cs.single_inferior_argument)
strcat (own_buf, ";single-inf-arg+");
+ /* If the target requires non-stop mode, initialize it now rather
+ than waiting for GDB to request it via QNonStop:1. */
+ if (target_supports_non_stop () && target_always_non_stop ())
+ {
+ if (the_target->start_non_stop (true) != 0)
+ error ("Cannot initialize target: requires non-stop mode but "
+ "non-stop mode initialization failed.");
+
+ non_stop = true;
+ remote_debug_printf ("Target requires non-stop mode: "
+ "enabled at startup.\n");
+ }
+
/* Reinitialize components as needed for the new connection. */
hostio_handle_new_gdb_connection ();
target_handle_new_gdb_connection ();
@@ -3931,6 +3960,10 @@ gdbserver_usage (FILE *stream)
" Options:\n"
" vCont, vConts, T, Tthread, qC, qfThreadInfo and\n"
" threads (disable all threading packets).\n"
+ " --enable-packet=OPT1[,OPT2,...]\n"
+ " Enable support for RSP packets or extensions.\n"
+ " Options:\n"
+ " AlwaysNonStop.\n"
"\n"
"For more information, consult the GDB manual (available as on-line \n"
"info or a printed manual).\n");
@@ -3951,6 +3984,13 @@ gdbserver_show_disableable (FILE *stream)
" T \tAll 'T' packets\n");
}
+static void
+gdbserver_show_enableable (FILE *stream)
+{
+ fprintf (stream, "Enableable packets:\n"
+ " AlwaysNonStop\tForce AlwaysNonStop extension\n");
+}
+
/* Start up the event loop. This is the entry point to the event
loop. */
@@ -4186,7 +4226,7 @@ captured_main (int argc, char *argv[])
enum opts { OPT_VERSION = 1, OPT_HELP, OPT_ATTACH, OPT_MULTI, OPT_WRAPPER,
OPT_DEBUG, OPT_DEBUG_FILE, OPT_DEBUG_FORMAT, OPT_DISABLE_PACKET,
- OPT_DISABLE_RANDOMIZATION, OPT_NO_DISABLE_RANDOMIZATION,
+ OPT_ENABLE_PACKET, OPT_DISABLE_RANDOMIZATION, OPT_NO_DISABLE_RANDOMIZATION,
OPT_STARTUP_WITH_SHELL, OPT_NO_STARTUP_WITH_SHELL, OPT_ONCE,
OPT_SELFTEST, OPT_NO_ESCAPE
};
@@ -4204,6 +4244,9 @@ captured_main (int argc, char *argv[])
/* --disable-packet is optional_argument only so that we can print a
better help list when the argument is missing. */
{"disable-packet", optional_argument, nullptr, OPT_DISABLE_PACKET},
+ /* --enable-packet is optional_argument only so that we can print a
+ better help list when the argument is missing. */
+ {"enable-packet", optional_argument, nullptr, OPT_ENABLE_PACKET},
{"disable-randomization", no_argument, nullptr,
OPT_DISABLE_RANDOMIZATION},
{"no-disable-randomization", no_argument, nullptr,
@@ -4411,6 +4454,32 @@ captured_main (int argc, char *argv[])
}
break;
+ case OPT_ENABLE_PACKET:
+ {
+ char *packets = optarg;
+ if (packets == nullptr)
+ {
+ gdbserver_show_enableable (stdout);
+ exit (1);
+ }
+ char *saveptr;
+ for (char *tok = strtok_r (packets, ",", &saveptr);
+ tok != nullptr;
+ tok = strtok_r (nullptr, ",", &saveptr))
+ {
+ if (streq ("AlwaysNonStop", tok))
+ enable_always_non_stop = true;
+ else
+ {
+ fprintf (stderr, "Don't know how to enable \"%s\".\n\n",
+ tok);
+ gdbserver_show_enableable (stderr);
+ exit (1);
+ }
+ }
+ }
+ break;
+
case OPT_DISABLE_RANDOMIZATION:
cs.disable_randomization = 1;
break;
diff --git a/gdbserver/server.h b/gdbserver/server.h
index bbba3650de7..4238882dfc7 100644
--- a/gdbserver/server.h
+++ b/gdbserver/server.h
@@ -74,6 +74,8 @@ extern bool disable_packet_qC;
extern bool disable_packet_qfThreadInfo;
extern bool disable_packet_T;
+extern bool enable_always_non_stop;
+
extern bool run_once;
extern bool non_stop;
diff --git a/gdbserver/target.cc b/gdbserver/target.cc
index 43ef421df74..6ce584c8aba 100644
--- a/gdbserver/target.cc
+++ b/gdbserver/target.cc
@@ -498,6 +498,12 @@ process_stratum_target::supports_non_stop ()
return false;
}
+bool
+process_stratum_target::always_non_stop ()
+{
+ return enable_always_non_stop;
+}
+
bool
process_stratum_target::async (bool enable)
{
diff --git a/gdbserver/target.h b/gdbserver/target.h
index 82eab9d1243..cdd1e26f2d6 100644
--- a/gdbserver/target.h
+++ b/gdbserver/target.h
@@ -260,6 +260,9 @@ class process_stratum_target
/* Return true if non-stop mode is supported. */
virtual bool supports_non_stop ();
+ /* Return true if target must run in non-stop mode. */
+ virtual bool always_non_stop ();
+
/* Enables async target events. Returns the previous enable
state. */
virtual bool async (bool enable);
@@ -583,6 +586,9 @@ int kill_inferior (process_info *proc);
#define target_supports_non_stop() \
the_target->supports_non_stop ()
+#define target_always_non_stop() \
+ the_target->always_non_stop ()
+
#define target_async(enable) \
the_target->async (enable)
--
2.43.0
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
next prev parent reply other threads:[~2026-07-14 9:26 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-14 9:21 [PATCH v4 00/11] Add " Mohamed Bouhaouel
2026-07-14 9:21 ` [PATCH v4 01/11] gdb, record: fix assertion when remote target is set to non-stop Mohamed Bouhaouel
2026-07-14 9:21 ` [PATCH v4 02/11] gdb, remote: fix assertion on reconnect to non-stop target Mohamed Bouhaouel
2026-07-14 9:21 ` [PATCH v4 03/11] gdb, remote: fix async handler " Mohamed Bouhaouel
2026-07-14 9:21 ` [PATCH v4 04/11] gdb, remote: fix "info program" after " Mohamed Bouhaouel
2026-07-14 9:21 ` [PATCH v4 05/11] gdb, remote: fix crash when accessing removed events Mohamed Bouhaouel
2026-07-14 9:21 ` [PATCH v4 06/11] gdb, remote: fix ptid matching for process-wide stop events Mohamed Bouhaouel
2026-07-14 9:21 ` [PATCH v4 07/11] gdb, dap: fix DAP events if no thread is selected Mohamed Bouhaouel
2026-07-14 9:21 ` [PATCH v4 08/11] gdb, testsuite: handle async close in monitor-exit-quit.exp Mohamed Bouhaouel
2026-07-14 9:21 ` [PATCH v4 09/11] gdb, testsuite: update attach-deleted-exec.exp to handle async messages Mohamed Bouhaouel
2026-07-14 9:21 ` [PATCH v4 10/11] gdb, testsuite: add kfails for step-over-process-exit.exp Mohamed Bouhaouel
2026-07-14 9:21 ` Mohamed Bouhaouel [this message]
2026-07-14 12:07 ` [PATCH v4 11/11] gdb, gdbserver: add AlwaysNonStop remote protocol extension Eli Zaretskii
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=20260714092128.12941-12-mohamed.bouhaouel@intel.com \
--to=mohamed.bouhaouel@intel.com \
--cc=aburgess@redhat.com \
--cc=eliz@gnu.org \
--cc=gdb-patches@sourceware.org \
--cc=markus.t.metzger@intel.com \
--cc=pedro@palves.net \
--cc=stephan.rohr@intel.com \
/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