/* 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 "maint.h"
#include "gdbsupport/selftest.h"
#include "inferior.h"
+#include "gdbsupport/thread-pool.h"
#include "cli/cli-decode.h"
#include "cli/cli-utils.h"
#include "cli/cli-setshow.h"
#include "cli/cli-cmds.h"
-#if CXX_STD_THREAD
-#include "gdbsupport/thread-pool.h"
-#endif
-
static void maintenance_do_deprecate (const char *, int);
#ifndef _WIN32
static void
maintenance_demangle (const char *args, int from_tty)
{
- printf_filtered (_("This command has been moved to \"demangle\".\n"));
+ gdb_printf (_("This command has been moved to \"demangle\".\n"));
}
static void
maintenance_time_display (const char *args, int from_tty)
{
if (args == NULL || *args == '\0')
- printf_unfiltered (_("\"maintenance time\" takes a numeric argument.\n"));
+ gdb_printf (_("\"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");
+ gdb_printf ("\"maintenance space\" takes a numeric argument.\n");
else
set_per_command_space (strtol (args, NULL, 10));
}
for (const auto &f : bfd_flag_info)
{
if (flags & f.value)
- printf_filtered (" %s", f.name);
+ gdb_printf (" %s", f.name);
}
}
CORE_ADDR addr, CORE_ADDR endaddr,
unsigned long filepos, int addr_size)
{
- printf_filtered (" %s", hex_string_custom (addr, addr_size));
- printf_filtered ("->%s", hex_string_custom (endaddr, addr_size));
- printf_filtered (" at %s",
- hex_string_custom ((unsigned long) filepos, 8));
- printf_filtered (": %s", name);
+ gdb_printf (" %s", hex_string_custom (addr, addr_size));
+ gdb_printf ("->%s", hex_string_custom (endaddr, addr_size));
+ gdb_printf (" at %s",
+ hex_string_custom ((unsigned long) filepos, 8));
+ gdb_printf (": %s", name);
print_bfd_flags (flags);
- printf_filtered ("\n");
+ gdb_printf ("\n");
}
/* Return the number of digits required to display COUNT in decimal.
std::string result
= string_printf (" [%d] ", gdb_bfd_section_index (abfd, asect));
/* The '+ 4' for the leading and trailing characters. */
- printf_filtered ("%-*s", (index_digits + 4), result.c_str ());
+ gdb_printf ("%-*s", (index_digits + 4), result.c_str ());
}
/* Print information about ASECT from ABFD. The section will be printed using
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 (const char *header, bfd *abfd, objfile *objfile,
const char *arg)
{
- puts_filtered (header);
- wrap_here (" ");
- printf_filtered ("`%s', ", bfd_get_filename (abfd));
- wrap_here (" ");
- printf_filtered (_("file type %s.\n"), bfd_get_target (abfd));
+ gdb_puts (header);
+ gdb_stdout->wrap_here (8);
+ gdb_printf ("`%s', ", bfd_get_filename (abfd));
+ gdb_stdout->wrap_here (8);
+ gdb_printf (_("file type %s.\n"), bfd_get_target (abfd));
int section_count = gdb_bfd_count_sections (abfd);
int digits = index_digits (section_count);
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));
+ gdb_printf (_("From '%s', file type %s:\n"),
+ bfd_get_filename (abfd), bfd_get_target (abfd));
}
print_bfd_section_info (abfd,
sec.the_bfd_section,
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);
+ gdb_printf ("%*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);
}
}
{
const char *symbol_name = sym.minsym->print_name ();
const char *symbol_offset
- = pulongest (address - BMSYMBOL_VALUE_ADDRESS (sym));
+ = pulongest (address - sym.value_address ());
sect = sym.obj_section ();
if (sect != NULL)
obj_name = objfile_name (sect->objfile);
if (current_program_space->multi_objfile_p ())
- printf_filtered (_("%s + %s in section %s of %s\n"),
- symbol_name, symbol_offset,
- section_name, obj_name);
+ gdb_printf (_("%s + %s in section %s of %s\n"),
+ symbol_name, symbol_offset,
+ section_name, obj_name);
else
- printf_filtered (_("%s + %s in section %s\n"),
- symbol_name, symbol_offset, section_name);
+ gdb_printf (_("%s + %s in section %s\n"),
+ symbol_name, symbol_offset, section_name);
}
else
- printf_filtered (_("%s + %s\n"), symbol_name, symbol_offset);
+ gdb_printf (_("%s + %s\n"), symbol_name, symbol_offset);
}
else if (sect)
- printf_filtered (_("no symbol at %s:%s\n"),
- sect->the_bfd_section->name, hex_string (address));
+ gdb_printf (_("no symbol at %s:%s\n"),
+ sect->the_bfd_section->name, hex_string (address));
else
- printf_filtered (_("no symbol at %s\n"), hex_string (address));
+ gdb_printf (_("no symbol at %s\n"), hex_string (address));
return;
}
{
if (args == NULL || *args == '\0')
{
- printf_unfiltered (_("\"maintenance deprecate\" takes an argument,\n\
+ gdb_printf (_("\"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\
+ gdb_printf (_("\"maintenance undeprecate\" takes an argument, \n\
the command you want to undeprecate.\n"));
}
if (!lookup_cmd_composition (text, &alias, &prefix_cmd, &cmd))
{
- printf_filtered (_("Can't find command '%s' to deprecate.\n"), text);
+ gdb_printf (_("Can't find command '%s' to deprecate.\n"), text);
return;
}
show_maintenance_profile_p (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file, _("Internal profiling is %s.\n"), value);
+ gdb_printf (file, _("Internal profiling is %s.\n"), value);
}
#ifdef HAVE__ETEXT
}
EXTERN_C void monstartup (unsigned long, unsigned long);
-extern int main ();
+extern int main (int, char **);
static void
maintenance_set_profile_cmd (const char *args, int from_tty,
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)
+ {
+ gdb_printf (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
+ gdb_printf (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. */
for (compunit_symtab *cu : o->compunits ())
{
++nr_compunit_symtabs;
- nr_blocks += BLOCKVECTOR_NBLOCKS (COMPUNIT_BLOCKVECTOR (cu));
- nr_symtabs += std::distance (compunit_filetabs (cu).begin (),
- compunit_filetabs (cu).end ());
+ nr_blocks += cu->blockvector ()->num_blocks ();
+ nr_symtabs += std::distance (cu->filetabs ().begin (),
+ cu->filetabs ().end ());
}
}
}
/* Subtract time spend in prompt_for_continue from walltime. */
wall_time -= get_prompt_for_continue_wait_time ();
- printf_unfiltered (!m_msg_type
- ? _("Startup time: %.6f (cpu), %.6f (wall)\n")
- : _("Command execution time: %.6f (cpu), %.6f (wall)\n"),
- duration<double> (cmd_time).count (),
- duration<double> (wall_time).count ());
+ gdb_printf (gdb_stdlog,
+ !m_msg_type
+ ? _("Startup time: %.6f (cpu), %.6f (wall)\n")
+ : _("Command execution time: %.6f (cpu), %.6f (wall)\n"),
+ duration<double> (cmd_time).count (),
+ duration<double> (wall_time).count ());
}
if (m_space_enabled && per_command_space)
long space_now = lim - lim_at_start;
long space_diff = space_now - m_start_space;
- printf_unfiltered (!m_msg_type
- ? _("Space used: %ld (%s%ld during startup)\n")
- : _("Space used: %ld (%s%ld for this command)\n"),
- space_now,
- (space_diff >= 0 ? "+" : ""),
- space_diff);
+ gdb_printf (gdb_stdlog,
+ !m_msg_type
+ ? _("Space used: %ld (%s%ld during startup)\n")
+ : _("Space used: %ld (%s%ld for this command)\n"),
+ space_now,
+ (space_diff >= 0 ? "+" : ""),
+ space_diff);
#endif
}
int nr_symtabs, nr_compunit_symtabs, nr_blocks;
count_symtabs_and_blocks (&nr_symtabs, &nr_compunit_symtabs, &nr_blocks);
- printf_unfiltered (_("#symtabs: %d (+%d),"
- " #compunits: %d (+%d),"
- " #blocks: %d (+%d)\n"),
- nr_symtabs,
- nr_symtabs - m_start_nr_symtabs,
- nr_compunit_symtabs,
- (nr_compunit_symtabs
- - m_start_nr_compunit_symtabs),
- nr_blocks,
- nr_blocks - m_start_nr_blocks);
+ gdb_printf (gdb_stdlog,
+ _("#symtabs: %d (+%d),"
+ " #compunits: %d (+%d),"
+ " #blocks: %d (+%d)\n"),
+ nr_symtabs,
+ nr_symtabs - m_start_nr_symtabs,
+ nr_compunit_symtabs,
+ (nr_compunit_symtabs
+ - m_start_nr_compunit_symtabs),
+ nr_blocks,
+ nr_blocks - m_start_nr_blocks);
}
}
char out[100];
strftime (out, sizeof (out), "%F %H:%M:%S", &tm);
- printf_unfiltered ("%s.%03d - %s\n", out, (int) millis, msg);
+ gdb_printf (gdb_stdlog, "%s.%03d - %s\n", out, (int) millis, msg);
}
/* Handle unknown "mt set per-command" arguments.
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 (_("\
+ gdb_printf (_("\
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
+ for (const auto &test : selftests::all_selftests ())
+ {
+ if (startswith (test.name.c_str (), text))
+ tracker.add_completion (make_unique_xstrdup (test.name.c_str ()));
+ }
+#endif
+}
+
static void
maintenance_info_selftests (const char *arg, int from_tty)
{
#if GDB_SELF_TEST
- printf_filtered ("Registered selftests:\n");
- selftests::for_each_selftest ([] (const std::string &name) {
- printf_filtered (" - %s\n", name.c_str ());
- });
+ gdb_printf ("Registered selftests:\n");
+ for (const auto &test : selftests::all_selftests ())
+ gdb_printf (" - %s\n", test.name.c_str ());
#else
- printf_filtered (_("\
+ gdb_printf (_("\
Selftests have been disabled for this build.\n"));
#endif
}
{
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, 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, 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
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 ();
}