/* Support for GDB maintenance commands.
- Copyright (C) 1992-2021 Free Software Foundation, Inc.
+ Copyright (C) 1992-2022 Free Software Foundation, Inc.
Written by Fred Fish at Cygnus Support.
#include "top.h"
#include "maint.h"
#include "gdbsupport/selftest.h"
+#include "inferior.h"
#include "cli/cli-decode.h"
#include "cli/cli-utils.h"
maintenance_time_display (const char *args, int from_tty)
{
if (args == NULL || *args == '\0')
- printf_unfiltered (_("\"maintenance time\" takes a numeric argument.\n"));
+ printf_filtered (_("\"maintenance time\" takes a numeric argument.\n"));
else
set_per_command_time (strtol (args, NULL, 10));
}
maintenance_space_display (const char *args, int from_tty)
{
if (args == NULL || *args == '\0')
- printf_unfiltered ("\"maintenance space\" takes a numeric argument.\n");
+ printf_filtered ("\"maintenance space\" takes a numeric argument.\n");
else
set_per_command_space (strtol (args, NULL, 10));
}
print_section_index (abfd, asect->the_bfd_section, index_digits);
maint_print_section_info (name, flags,
- obj_section_addr (asect),
- obj_section_endaddr (asect),
+ asect->addr (), asect->endaddr (),
asect->the_bfd_section->filepos,
addr_size);
}
from ABFD. It might be that no such wrapper exists (for example debug
sections don't have such wrappers) in which case nullptr is returned. */
-static obj_section *
+obj_section *
maint_obj_section_from_bfd_section (bfd *abfd,
asection *asection,
objfile *ofile)
maint_print_all_sections (_("Core file: "), core_bfd, nullptr, arg);
}
+/* Implement the "maintenance info target-sections" command. */
+
+static void
+maintenance_info_target_sections (const char *arg, int from_tty)
+{
+ bfd *abfd = nullptr;
+ int digits = 0;
+ const target_section_table *table
+ = target_get_section_table (current_inferior ()->top_target ());
+ if (table == nullptr)
+ return;
+
+ for (const target_section &sec : *table)
+ {
+ if (abfd == nullptr || sec.the_bfd_section->owner != abfd)
+ {
+ abfd = sec.the_bfd_section->owner;
+ digits = std::max (index_digits (gdb_bfd_count_sections (abfd)),
+ digits);
+ }
+ }
+
+ struct gdbarch *gdbarch = nullptr;
+ int addr_size = 0;
+ abfd = nullptr;
+ for (const target_section &sec : *table)
+ {
+ if (sec.the_bfd_section->owner != abfd)
+ {
+ abfd = sec.the_bfd_section->owner;
+ gdbarch = gdbarch_from_bfd (abfd);
+ addr_size = gdbarch_addr_bit (gdbarch) / 8;
+
+ printf_filtered (_("From '%s', file type %s:\n"),
+ bfd_get_filename (abfd), bfd_get_target (abfd));
+ }
+ print_bfd_section_info (abfd,
+ sec.the_bfd_section,
+ nullptr,
+ digits);
+ /* The magic '8 + digits' here ensures that the 'Start' is aligned
+ with the output of print_bfd_section_info. */
+ printf_filtered ("%*sStart: %s, End: %s, Owner token: %p\n",
+ (8 + digits), "",
+ hex_string_custom (sec.addr, addr_size),
+ hex_string_custom (sec.endaddr, addr_size),
+ sec.owner);
+ }
+}
+
static void
maintenance_print_statistics (const char *args, int from_tty)
{
print_objfile_statistics ();
- print_symbol_bcache_statistics ();
}
static void
{
if (args == NULL || *args == '\0')
{
- printf_unfiltered (_("\"maintenance deprecate\" takes an argument,\n\
+ printf_filtered (_("\"maintenance deprecate\" takes an argument,\n\
the command you want to deprecate, and optionally the replacement command\n\
enclosed in quotes.\n"));
}
{
if (args == NULL || *args == '\0')
{
- printf_unfiltered (_("\"maintenance undeprecate\" takes an argument, \n\
+ printf_filtered (_("\"maintenance undeprecate\" takes an argument, \n\
the command you want to undeprecate.\n"));
}
update_thread_pool_size ();
}
+static void
+maintenance_show_worker_threads (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+#if CXX_STD_THREAD
+ if (n_worker_threads == -1)
+ {
+ fprintf_filtered (file, _("The number of worker threads GDB "
+ "can use is unlimited (currently %zu).\n"),
+ gdb::thread_pool::g_thread_pool->thread_count ());
+ return;
+ }
+#endif
+
+ int report_threads = 0;
+#if CXX_STD_THREAD
+ report_threads = n_worker_threads;
+#endif
+ fprintf_filtered (file, _("The number of worker threads GDB "
+ "can use is %d.\n"),
+ report_threads);
+}
+
\f
/* If true, display time usage both at startup and for each command. */
error (_("Bad value for 'mt set per-command no'."));
for (list = per_command_setlist; list != NULL; list = list->next)
- if (list->var_type == var_boolean)
+ if (list->var->type () == var_boolean)
{
gdb_assert (list->type == set_cmd);
do_set_command (args, from_tty, list);
}
}
-\f
+/* Options affecting the "maintenance selftest" command. */
+
+struct maintenance_selftest_options
+{
+ bool verbose = false;
+} user_maintenance_selftest_options;
+
+static const gdb::option::option_def maintenance_selftest_option_defs[] = {
+ gdb::option::boolean_option_def<maintenance_selftest_options> {
+ "verbose",
+ [] (maintenance_selftest_options *opt) { return &opt->verbose; },
+ nullptr,
+ N_("Set whether selftests run in verbose mode."),
+ N_("Show whether selftests run in verbose mode."),
+ N_("\
+When on, selftests may print verbose information."),
+ },
+};
+
+/* Make option groups for the "maintenance selftest" command. */
+
+static std::array<gdb::option::option_def_group, 1>
+make_maintenance_selftest_option_group (maintenance_selftest_options *opts)
+{
+ return {{
+ {{maintenance_selftest_option_defs}, opts},
+ }};
+}
/* The "maintenance selftest" command. */
maintenance_selftest (const char *args, int from_tty)
{
#if GDB_SELF_TEST
- gdb_argv argv (args);
- selftests::run_tests (argv.as_array_view ());
+ maintenance_selftest_options opts = user_maintenance_selftest_options;
+ auto grp = make_maintenance_selftest_option_group (&opts);
+ gdb::option::process_options
+ (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp);
+ const gdb_argv argv (args);
+ selftests::run_tests (argv.as_array_view (), opts.verbose);
#else
printf_filtered (_("\
Selftests have been disabled for this build.\n"));
#endif
}
+/* Completer for the "maintenance selftest" command. */
+
+static void
+maintenance_selftest_completer (cmd_list_element *cmd,
+ completion_tracker &tracker,
+ const char *text,
+ const char *word)
+{
+ auto grp = make_maintenance_selftest_option_group (nullptr);
+
+ if (gdb::option::complete_options
+ (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp))
+ return;
+
+#if GDB_SELF_TEST
+ selftests::for_each_selftest ([&tracker, text] (const std::string &name)
+ {
+ if (startswith (name.c_str (), text))
+ tracker.add_completion (make_unique_xstrdup (name.c_str ()));
+ });
+#endif
+}
+
static void
maintenance_info_selftests (const char *arg, int from_tty)
{
{
struct cmd_list_element *cmd;
- add_basic_prefix_cmd ("maintenance", class_maintenance, _("\
+ cmd_list_element *maintenance_cmd
+ = add_basic_prefix_cmd ("maintenance", class_maintenance, _("\
Commands for use by GDB maintainers.\n\
Includes commands to dump specific internal GDB structures in\n\
a human readable form, to cause GDB to deliberately dump core, etc."),
- &maintenancelist, "maintenance ", 0,
- &cmdlist);
+ &maintenancelist, 0,
+ &cmdlist);
- add_com_alias ("mt", "maintenance", class_maintenance, 1);
+ add_com_alias ("mt", maintenance_cmd, class_maintenance, 1);
- add_basic_prefix_cmd ("info", class_maintenance, _("\
+ cmd_list_element *maintenance_info_cmd
+ = add_basic_prefix_cmd ("info", class_maintenance, _("\
Commands for showing internal info about the program being debugged."),
- &maintenanceinfolist, "maintenance info ", 0,
- &maintenancelist);
- add_alias_cmd ("i", "info", class_maintenance, 1, &maintenancelist);
+ &maintenanceinfolist, 0,
+ &maintenancelist);
+ add_alias_cmd ("i", maintenance_info_cmd, class_maintenance, 1,
+ &maintenancelist);
const auto opts = make_maint_info_sections_options_def_group (nullptr);
static std::string maint_info_sections_command_help
&maintenanceinfolist);
set_cmd_completer_handle_brkchars (cmd, maint_info_sections_completer);
+ add_cmd ("target-sections", class_maintenance,
+ maintenance_info_target_sections, _("\
+List GDB's internal section table.\n\
+\n\
+Print the current targets section list. This is a sub-set of all\n\
+sections, from all objects currently loaded. Usually the ALLOC\n\
+sectoins."),
+ &maintenanceinfolist);
+
add_basic_prefix_cmd ("print", class_maintenance,
_("Maintenance command for printing GDB internal state."),
- &maintenanceprintlist, "maintenance print ", 0,
+ &maintenanceprintlist, 0,
&maintenancelist);
add_basic_prefix_cmd ("flush", class_maintenance,
_("Maintenance command for flushing GDB internal caches."),
- &maintenanceflushlist, "maintenance flush ", 0,
+ &maintenanceflushlist, 0,
&maintenancelist);
add_basic_prefix_cmd ("set", class_maintenance, _("\
Set GDB internal variables used by the GDB maintainer.\n\
Configure variables internal to GDB that aid in GDB's maintenance"),
- &maintenance_set_cmdlist, "maintenance set ",
+ &maintenance_set_cmdlist,
0/*allow-unknown*/,
&maintenancelist);
add_show_prefix_cmd ("show", class_maintenance, _("\
Show GDB internal variables used by the GDB maintainer.\n\
Configure variables internal to GDB that aid in GDB's maintenance"),
- &maintenance_show_cmdlist, "maintenance show ",
+ &maintenance_show_cmdlist,
0/*allow-unknown*/,
&maintenancelist);
add_prefix_cmd ("per-command", class_maintenance, set_per_command_cmd, _("\
Per-command statistics settings."),
- &per_command_setlist, "maintenance set per-command ",
+ &per_command_setlist,
1/*allow-unknown*/, &maintenance_set_cmdlist);
add_show_prefix_cmd ("per-command", class_maintenance, _("\
Show per-command statistics settings."),
- &per_command_showlist, "maintenance show per-command ",
+ &per_command_showlist,
0/*allow-unknown*/, &maintenance_show_cmdlist);
add_setshow_boolean_cmd ("time", class_maintenance,
add_basic_prefix_cmd ("check", class_maintenance, _("\
Commands for checking internal gdb state."),
- &maintenancechecklist, "maintenance check ", 0,
+ &maintenancechecklist, 0,
&maintenancelist);
add_cmd ("translate-address", class_maintenance,
You probably shouldn't use this."),
&maintenancelist);
- add_cmd ("selftest", class_maintenance, maintenance_selftest, _("\
+ cmd_list_element *maintenance_selftest_cmd
+ = add_cmd ("selftest", class_maintenance, maintenance_selftest, _("\
Run gdb's unit tests.\n\
Usage: maintenance selftest [FILTER]\n\
This will run any unit tests that were built in to gdb.\n\
If a filter is given, only the tests with that value in their name will ran."),
- &maintenancelist);
+ &maintenancelist);
+ set_cmd_completer_handle_brkchars (maintenance_selftest_cmd,
+ maintenance_selftest_completer);
add_cmd ("selftests", class_maintenance, maintenance_info_selftests,
_("List the registered selftests."), &maintenanceinfolist);
Show the number of worker threads GDB can use."), _("\
GDB may use multiple threads to speed up certain CPU-intensive operations,\n\
such as demangling symbol names."),
- maintenance_set_worker_threads, NULL,
+ maintenance_set_worker_threads,
+ maintenance_show_worker_threads,
&maintenance_set_cmdlist,
&maintenance_show_cmdlist);
+ /* Add the "maint set/show selftest" commands. */
+ static cmd_list_element *set_selftest_cmdlist = nullptr;
+ static cmd_list_element *show_selftest_cmdlist = nullptr;
+
+ add_setshow_prefix_cmd ("selftest", class_maintenance,
+ _("Self tests-related settings."),
+ _("Self tests-related settings."),
+ &set_selftest_cmdlist, &show_selftest_cmdlist,
+ &maintenance_set_cmdlist, &maintenance_show_cmdlist);
+
+ /* Add setting commands matching "maintenance selftest" options. */
+ gdb::option::add_setshow_cmds_for_options (class_maintenance,
+ &user_maintenance_selftest_options,
+ maintenance_selftest_option_defs,
+ &set_selftest_cmdlist,
+ &show_selftest_cmdlist);
+
update_thread_pool_size ();
}