aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/NEWS10
-rw-r--r--gdb/doc/gdb.texinfo70
-rw-r--r--gdbserver/server.cc158
3 files changed, 216 insertions, 22 deletions
diff --git a/gdb/NEWS b/gdb/NEWS
index 1073e38..94d1fd8 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -38,6 +38,16 @@ set remote thread-options-packet
show remote thread-options-packet
Set/show the use of the thread options packet.
+* New features in the GDB remote stub, GDBserver
+
+ ** The --remote-debug and --event-loop-debug command line options
+ have been removed.
+
+ ** The --debug command line option now takes an optional comma
+ separated list of components to emit debug for. The currently
+ supported components are: all, threads, event-loop, and remote.
+ If no components are given then threads is assumed.
+
* Python API
** New function gdb.notify_mi(NAME, DATA), that emits custom
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index d2428ef..6d20e4c 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -23674,11 +23674,42 @@ program. For more information,
@pxref{--multi Option in Types of Remote Connnections}.
@cindex @option{--debug}, @code{gdbserver} option
-The @option{--debug} option tells @code{gdbserver} to display extra
-status information about the debugging process.
-@cindex @option{--remote-debug}, @code{gdbserver} option
-The @option{--remote-debug} option tells @code{gdbserver} to display
-remote protocol debug output.
+The @option{--debug[=option1,option2,@dots{}]} option tells
+@code{gdbserver} to display extra diagnostic information about the
+debugging process. The options (@var{option1}, @var{option2}, etc)
+control for which areas of @code{gdbserver} additional information
+will be displayed, possible values are:
+
+@table @code
+@item all
+This enables all available diagnostic output.
+@item threads
+This enables diagnostic output related to threading. Currently other
+general diagnostic output is included in this category, but this could
+change in future releases of @code{gdbserver}.
+@item event-loop
+This enables event-loop specific diagnostic output.
+@item remote
+This enables diagnostic output related to the transfer of remote
+protocol packets too and from the debugger.
+@end table
+
+@noindent
+If no options are passed to @option{--debug} then this is treated as
+equivalent to @option{--debug=threads}. This could change in future
+releases of @code{gdbserver}. The options passed to @option{--debug}
+are processed left to right, and individual options can be prefixed
+with the @kbd{-} (minus) character to disable diagnostic output from
+this area, so it is possible to use:
+
+@smallexample
+ target> gdbserver --debug=all,-event-loop
+@end smallexample
+
+@noindent
+In order to enable all diagnostic output except that for the
+event-loop.
+
@cindex @option{--debug-file}, @code{gdbserver} option
@cindex @code{gdbserver}, send all debug output to a single file
The @option{--debug-file=@var{filename}} option tells @code{gdbserver} to
@@ -50671,16 +50702,27 @@ the program you want to debug. The syntax is:
target> gdbserver --multi @var{comm}
@end smallexample
-@item --debug
-Instruct @code{gdbserver} to display extra status information about the debugging
-process.
-This option is intended for @code{gdbserver} development and for bug reports to
-the developers.
+@item --debug@r{[}=option1,option2,@dots{}@r{]}
+Instruct @code{gdbserver} to display extra status information about
+the debugging process. This option is intended for @code{gdbserver}
+development and for bug reports to the developers.
-@item --remote-debug
-Instruct @code{gdbserver} to display remote protocol debug output.
-This option is intended for @code{gdbserver} development and for bug reports to
-the developers.
+Each @var{option} is the name of a component for which debugging
+should be enabled. The list of possible options is @option{all},
+@option{threads}, @option{event-loop}, @option{remote}. The special
+option @option{all} enables all components. The option list is
+processed left to right, and an option can be prefixed with the
+@kbd{-} character to disable output for that component, so you could write:
+
+@smallexample
+target> gdbserver --debug=all,-event-loop
+@end smallexample
+
+@noindent
+to turn on debug output for all components except @option{event-loop}.
+If no options are passed to @option{--debug} then this is treated as
+equivalent to @option{--debug=threads}. This could change in future
+releases of @code{gdbserver}.
@item --debug-file=@var{filename}
Instruct @code{gdbserver} to send any debug output to the given @var{filename}.
diff --git a/gdbserver/server.cc b/gdbserver/server.cc
index d73d637..ea5d28c 100644
--- a/gdbserver/server.cc
+++ b/gdbserver/server.cc
@@ -1457,6 +1457,124 @@ parse_debug_format_options (const char *arg, int is_monitor)
return std::string ();
}
+/* A wrapper to enable, or disable a debug flag. These are debug flags
+ that control the debug output from gdbserver, that developers might
+ want, this is not something most end users will need. */
+
+struct debug_opt
+{
+ /* NAME is the name of this debug option, this should be a simple string
+ containing no whitespace, starting with a letter from isalpha(), and
+ contain only isalnum() characters and '_' underscore and '-' hyphen.
+
+ SETTER is a callback function used to set the debug variable. This
+ callback will be passed true to enable the debug setting, or false to
+ disable the debug setting. */
+ debug_opt (const char *name, std::function<void (bool)> setter)
+ : m_name (name),
+ m_setter (setter)
+ {
+ gdb_assert (isalpha (*name));
+ }
+
+ /* Called to enable or disable the debug setting. */
+ void set (bool enable) const
+ {
+ m_setter (enable);
+ }
+
+ /* Return the name of this debug option. */
+ const char *name () const
+ { return m_name; }
+
+private:
+ /* The name of this debug option. */
+ const char *m_name;
+
+ /* The callback to update the debug setting. */
+ std::function<void (bool)> m_setter;
+};
+
+/* The set of all debug options that gdbserver supports. These are the
+ options that can be passed to the command line '--debug=...' flag, or to
+ the monitor command 'monitor set debug ...'. */
+
+static std::vector<debug_opt> all_debug_opt {
+ {"threads", [] (bool enable)
+ {
+ debug_threads = enable;
+ }},
+ {"remote", [] (bool enable)
+ {
+ remote_debug = enable;
+ }},
+ {"event-loop", [] (bool enable)
+ {
+ debug_event_loop = (enable ? debug_event_loop_kind::ALL
+ : debug_event_loop_kind::OFF);
+ }}
+};
+
+/* Parse the options to --debug=...
+
+ OPTIONS is the string of debug components which should be enabled (or
+ disabled), and must not be nullptr. An empty OPTIONS string is valid,
+ in which case a default set of debug components will be enabled.
+
+ An unknown, or otherwise invalid debug component will result in an
+ exception being thrown.
+
+ OPTIONS can consist of multiple debug component names separated by a
+ comma. Debugging for each component will be turned on. The special
+ component 'all' can be used to enable debugging for all components.
+
+ A component can also be prefixed with '-' to disable debugging of that
+ component, so a user might use: '--debug=all,-remote', to enable all
+ debugging, except for the remote (protocol) component. Components are
+ processed left to write in the OPTIONS list. */
+
+static void
+parse_debug_options (const char *options)
+{
+ gdb_assert (options != nullptr);
+
+ /* Empty options means the "default" set. This exists mostly for
+ backwards compatibility with gdbserver's legacy behaviour. */
+ if (*options == '\0')
+ options = "+threads";
+
+ while (*options != '\0')
+ {
+ const char *end = strchrnul (options, ',');
+
+ bool enable = *options != '-';
+ if (*options == '-' || *options == '+')
+ ++options;
+
+ std::string opt (options, end - options);
+
+ if (opt.size () == 0)
+ error ("invalid empty debug option");
+
+ bool is_opt_all = opt == "all";
+
+ bool found = false;
+ for (const auto &debug_opt : all_debug_opt)
+ if (is_opt_all || opt == debug_opt.name ())
+ {
+ debug_opt.set (enable);
+ found = true;
+ if (!is_opt_all)
+ break;
+ }
+
+ if (!found)
+ error ("unknown debug option '%s'", opt.c_str ());
+
+ options = (*end == ',') ? end + 1 : end;
+ }
+}
+
/* Handle monitor commands not handled by target-specific handlers. */
static void
@@ -3583,15 +3701,19 @@ gdbserver_usage (FILE *stream)
"\n"
"Debug options:\n"
"\n"
- " --debug Enable general debugging output.\n"
+ " --debug[=OPT1,OPT2,...]\n"
+ " Enable debugging output.\n"
+ " Options:\n"
+ " all, threads, event-loop, remote\n"
+ " With no options, 'threads' is assumed.\n"
+ " Prefix an option with '-' to disable\n"
+ " debugging of that component.\n"
" --debug-format=OPT1[,OPT2,...]\n"
" Specify extra content in debugging output.\n"
" Options:\n"
" all\n"
" none\n"
" timestamp\n"
- " --remote-debug Enable remote protocol debugging output.\n"
- " --event-loop-debug Enable event loop debugging output.\n"
" --disable-packet=OPT1[,OPT2,...]\n"
" Disable support for RSP packets or features.\n"
" Options:\n"
@@ -3870,8 +3992,32 @@ captured_main (int argc, char *argv[])
/* Consume the "--". */
*next_arg = NULL;
}
+ else if (startswith (*next_arg, "--debug="))
+ {
+ try
+ {
+ parse_debug_options ((*next_arg) + sizeof ("--debug=") - 1);
+ }
+ catch (const gdb_exception_error &exception)
+ {
+ fflush (stdout);
+ fprintf (stderr, "gdbserver: %s\n", exception.what ());
+ exit (1);
+ }
+ }
else if (strcmp (*next_arg, "--debug") == 0)
- debug_threads = true;
+ {
+ try
+ {
+ parse_debug_options ("");
+ }
+ catch (const gdb_exception_error &exception)
+ {
+ fflush (stdout);
+ fprintf (stderr, "gdbserver: %s\n", exception.what ());
+ exit (1);
+ }
+ }
else if (startswith (*next_arg, "--debug-format="))
{
std::string error_msg
@@ -3884,10 +4030,6 @@ captured_main (int argc, char *argv[])
exit (1);
}
}
- else if (strcmp (*next_arg, "--remote-debug") == 0)
- remote_debug = true;
- else if (strcmp (*next_arg, "--event-loop-debug") == 0)
- debug_event_loop = debug_event_loop_kind::ALL;
else if (startswith (*next_arg, "--debug-file="))
debug_set_output ((*next_arg) + sizeof ("--debug-file=") -1);
else if (strcmp (*next_arg, "--disable-packet") == 0)