Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
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


  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