/* MI Command Set - symbol commands.
- Copyright (C) 2003-2017 Free Software Foundation, Inc.
+ Copyright (C) 2003-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "symtab.h"
#include "objfiles.h"
#include "ui-out.h"
+#include "source.h"
+#include "mi-getopt.h"
/* Print the list of all pc addresses and lines of code for the
provided (full or base) source file name. The entries are sorted
{
ui_out_emit_tuple tuple_emitter (uiout, NULL);
uiout->field_core_addr ("pc", gdbarch, SYMTAB_LINETABLE (s)->item[i].pc);
- uiout->field_int ("line", SYMTAB_LINETABLE (s)->item[i].line);
+ uiout->field_signed ("line", SYMTAB_LINETABLE (s)->item[i].line);
}
}
+
+/* Used by the -symbol-info-* and -symbol-info-module-* commands to print
+ information about the symbol SYM in a block of index BLOCK (either
+ GLOBAL_BLOCK or STATIC_BLOCK). KIND is the kind of symbol we searched
+ for in order to find SYM, which impact which fields are displayed in the
+ results. */
+
+static void
+output_debug_symbol (ui_out *uiout, enum search_domain kind,
+ struct symbol *sym, int block)
+{
+ ui_out_emit_tuple tuple_emitter (uiout, NULL);
+
+ if (SYMBOL_LINE (sym) != 0)
+ uiout->field_unsigned ("line", SYMBOL_LINE (sym));
+ uiout->field_string ("name", sym->print_name ());
+
+ if (kind == FUNCTIONS_DOMAIN || kind == VARIABLES_DOMAIN)
+ {
+ string_file tmp_stream;
+ type_print (SYMBOL_TYPE (sym), "", &tmp_stream, -1);
+ uiout->field_string ("type", tmp_stream.string ());
+
+ std::string str = symbol_to_info_string (sym, block, kind);
+ uiout->field_string ("description", str);
+ }
+}
+
+/* Actually output one nondebug symbol, puts a tuple emitter in place
+ and then outputs the fields for this msymbol. */
+
+static void
+output_nondebug_symbol (ui_out *uiout,
+ const struct bound_minimal_symbol &msymbol)
+{
+ struct gdbarch *gdbarch = get_objfile_arch (msymbol.objfile);
+ ui_out_emit_tuple tuple_emitter (uiout, NULL);
+
+ uiout->field_core_addr ("address", gdbarch,
+ BMSYMBOL_VALUE_ADDRESS (msymbol));
+ uiout->field_string ("name", msymbol.minsym->print_name ());
+}
+
+/* This is the guts of the commands '-symbol-info-functions',
+ '-symbol-info-variables', and '-symbol-info-types'. It searches for
+ symbols matching KING, NAME_REGEXP, TYPE_REGEXP, and EXCLUDE_MINSYMS,
+ and then prints the matching [m]symbols in an MI structured format. */
+
+static void
+mi_symbol_info (enum search_domain kind, const char *name_regexp,
+ const char *type_regexp, bool exclude_minsyms)
+{
+ global_symbol_searcher sym_search (kind, name_regexp);
+ sym_search.set_symbol_type_regexp (type_regexp);
+ sym_search.set_exclude_minsyms (exclude_minsyms);
+ std::vector<symbol_search> symbols = sym_search.search ();
+ ui_out *uiout = current_uiout;
+ int i = 0;
+
+ ui_out_emit_tuple outer_symbols_emitter (uiout, "symbols");
+
+ /* Debug symbols are placed first. */
+ if (i < symbols.size () && symbols[i].msymbol.minsym == nullptr)
+ {
+ ui_out_emit_list debug_symbols_list_emitter (uiout, "debug");
+
+ /* As long as we have debug symbols... */
+ while (i < symbols.size () && symbols[i].msymbol.minsym == nullptr)
+ {
+ symtab *symtab = symbol_symtab (symbols[i].symbol);
+ ui_out_emit_tuple symtab_tuple_emitter (uiout, nullptr);
+
+ uiout->field_string ("filename",
+ symtab_to_filename_for_display (symtab));
+ uiout->field_string ("fullname", symtab_to_fullname (symtab));
+
+ ui_out_emit_list symbols_list_emitter (uiout, "symbols");
+
+ /* As long as we have debug symbols from this symtab... */
+ for (; (i < symbols.size ()
+ && symbols[i].msymbol.minsym == nullptr
+ && symbol_symtab (symbols[i].symbol) == symtab);
+ ++i)
+ {
+ symbol_search &s = symbols[i];
+
+ output_debug_symbol (uiout, kind, s.symbol, s.block);
+ }
+ }
+ }
+
+ /* Non-debug symbols are placed after. */
+ if (i < symbols.size ())
+ {
+ ui_out_emit_list nondebug_symbols_list_emitter (uiout, "nondebug");
+
+ /* As long as we have nondebug symbols... */
+ for (; i < symbols.size (); i++)
+ {
+ gdb_assert (symbols[i].msymbol.minsym != nullptr);
+ output_nondebug_symbol (uiout, symbols[i].msymbol);
+ }
+ }
+}
+
+/* Helper for mi_cmd_symbol_info_{functions,variables} - depending on KIND.
+ Processes command line options from ARGV and ARGC. */
+
+static void
+mi_info_functions_or_variables (enum search_domain kind, char **argv, int argc)
+{
+ const char *regexp = nullptr;
+ const char *t_regexp = nullptr;
+ bool exclude_minsyms = true;
+
+ enum opt
+ {
+ INCLUDE_NONDEBUG_OPT, TYPE_REGEXP_OPT, NAME_REGEXP_OPT
+ };
+ static const struct mi_opt opts[] =
+ {
+ {"-include-nondebug" , INCLUDE_NONDEBUG_OPT, 0},
+ {"-type", TYPE_REGEXP_OPT, 1},
+ {"-name", NAME_REGEXP_OPT, 1},
+ { 0, 0, 0 }
+ };
+
+ int oind = 0;
+ char *oarg = nullptr;
+
+ while (1)
+ {
+ const char *cmd_string
+ = ((kind == FUNCTIONS_DOMAIN)
+ ? "-symbol-info-functions" : "-symbol-info-variables");
+ int opt = mi_getopt (cmd_string, argc, argv, opts, &oind, &oarg);
+ if (opt < 0)
+ break;
+ switch ((enum opt) opt)
+ {
+ case INCLUDE_NONDEBUG_OPT:
+ exclude_minsyms = false;
+ break;
+ case TYPE_REGEXP_OPT:
+ t_regexp = oarg;
+ break;
+ case NAME_REGEXP_OPT:
+ regexp = oarg;
+ break;
+ }
+ }
+
+ mi_symbol_info (kind, regexp, t_regexp, exclude_minsyms);
+}
+
+/* Type for an iterator over a vector of module_symbol_search results. */
+typedef std::vector<module_symbol_search>::const_iterator
+ module_symbol_search_iterator;
+
+/* Helper for mi_info_module_functions_or_variables. Display the results
+ from ITER up to END or until we find a symbol that is in a different
+ module, or in a different symtab than the first symbol we print. Update
+ and return the new value for ITER. */
+static module_symbol_search_iterator
+output_module_symbols_in_single_module_and_file
+ (struct ui_out *uiout, module_symbol_search_iterator iter,
+ const module_symbol_search_iterator end, enum search_domain kind)
+{
+ /* The symbol for the module in which the first result resides. */
+ const symbol *first_module_symbol = iter->first.symbol;
+
+ /* The symbol for the first result, and the symtab in which it resides. */
+ const symbol *first_result_symbol = iter->second.symbol;
+ symtab *first_symbtab = symbol_symtab (first_result_symbol);
+
+ /* Formatted output. */
+ ui_out_emit_tuple current_file (uiout, nullptr);
+ uiout->field_string ("filename",
+ symtab_to_filename_for_display (first_symbtab));
+ uiout->field_string ("fullname", symtab_to_fullname (first_symbtab));
+ ui_out_emit_list item_list (uiout, "symbols");
+
+ /* Repeatedly output result symbols until either we run out of symbols,
+ we change module, or we change symtab. */
+ for (; (iter != end
+ && first_module_symbol == iter->first.symbol
+ && first_symbtab == symbol_symtab (iter->second.symbol));
+ ++iter)
+ output_debug_symbol (uiout, kind, iter->second.symbol,
+ iter->second.block);
+
+ return iter;
+}
+
+/* Helper for mi_info_module_functions_or_variables. Display the results
+ from ITER up to END or until we find a symbol that is in a different
+ module than the first symbol we print. Update and return the new value
+ for ITER. */
+static module_symbol_search_iterator
+output_module_symbols_in_single_module
+ (struct ui_out *uiout, module_symbol_search_iterator iter,
+ const module_symbol_search_iterator end, enum search_domain kind)
+{
+ gdb_assert (iter->first.symbol != nullptr);
+ gdb_assert (iter->second.symbol != nullptr);
+
+ /* The symbol for the module in which the first result resides. */
+ const symbol *first_module_symbol = iter->first.symbol;
+
+ /* Create output formatting. */
+ ui_out_emit_tuple module_tuple (uiout, nullptr);
+ uiout->field_string ("module", first_module_symbol->print_name ());
+ ui_out_emit_list files_list (uiout, "files");
+
+ /* The results are sorted so that symbols within the same file are next
+ to each other in the list. Calling the output function once will
+ print all results within a single file. We keep calling the output
+ function until we change module. */
+ while (iter != end && first_module_symbol == iter->first.symbol)
+ iter = output_module_symbols_in_single_module_and_file (uiout, iter,
+ end, kind);
+ return iter;
+}
+
+/* Core of -symbol-info-module-functions and -symbol-info-module-variables.
+ KIND indicates what we are searching for, and ARGV and ARGC are the
+ command line options passed to the MI command. */
+
+static void
+mi_info_module_functions_or_variables (enum search_domain kind,
+ char **argv, int argc)
+{
+ const char *module_regexp = nullptr;
+ const char *regexp = nullptr;
+ const char *type_regexp = nullptr;
+
+ /* Process the command line options. */
+
+ enum opt
+ {
+ MODULE_REGEXP_OPT, TYPE_REGEXP_OPT, NAME_REGEXP_OPT
+ };
+ static const struct mi_opt opts[] =
+ {
+ {"-module", MODULE_REGEXP_OPT, 1},
+ {"-type", TYPE_REGEXP_OPT, 1},
+ {"-name", NAME_REGEXP_OPT, 1},
+ { 0, 0, 0 }
+ };
+
+ int oind = 0;
+ char *oarg = nullptr;
+
+ while (1)
+ {
+ const char *cmd_string
+ = ((kind == FUNCTIONS_DOMAIN)
+ ? "-symbol-info-module-functions"
+ : "-symbol-info-module-variables");
+ int opt = mi_getopt (cmd_string, argc, argv, opts, &oind, &oarg);
+ if (opt < 0)
+ break;
+ switch ((enum opt) opt)
+ {
+ case MODULE_REGEXP_OPT:
+ module_regexp = oarg;
+ break;
+ case TYPE_REGEXP_OPT:
+ type_regexp = oarg;
+ break;
+ case NAME_REGEXP_OPT:
+ regexp = oarg;
+ break;
+ }
+ }
+
+ std::vector<module_symbol_search> module_symbols
+ = search_module_symbols (module_regexp, regexp, type_regexp, kind);
+
+ struct ui_out *uiout = current_uiout;
+ ui_out_emit_list all_matching_symbols (uiout, "symbols");
+
+ /* The results in the module_symbols list are ordered so symbols in the
+ same module are next to each other. Repeatedly call the output
+ function to print sequences of symbols that are in the same module
+ until we have no symbols left to print. */
+ module_symbol_search_iterator iter = module_symbols.begin ();
+ const module_symbol_search_iterator end = module_symbols.end ();
+ while (iter != end)
+ iter = output_module_symbols_in_single_module (uiout, iter, end, kind);
+}
+
+/* Implement -symbol-info-functions command. */
+
+void
+mi_cmd_symbol_info_functions (const char *command, char **argv, int argc)
+{
+ mi_info_functions_or_variables (FUNCTIONS_DOMAIN, argv, argc);
+}
+
+/* Implement -symbol-info-module-functions command. */
+
+void
+mi_cmd_symbol_info_module_functions (const char *command, char **argv,
+ int argc)
+{
+ mi_info_module_functions_or_variables (FUNCTIONS_DOMAIN, argv, argc);
+}
+
+/* Implement -symbol-info-module-variables command. */
+
+void
+mi_cmd_symbol_info_module_variables (const char *command, char **argv,
+ int argc)
+{
+ mi_info_module_functions_or_variables (VARIABLES_DOMAIN, argv, argc);
+}
+
+/* Implement -symbol-inf-modules command. */
+
+void
+mi_cmd_symbol_info_modules (const char *command, char **argv, int argc)
+{
+ const char *regexp = nullptr;
+
+ enum opt
+ {
+ NAME_REGEXP_OPT
+ };
+ static const struct mi_opt opts[] =
+ {
+ {"-name", NAME_REGEXP_OPT, 1},
+ { 0, 0, 0 }
+ };
+
+ int oind = 0;
+ char *oarg = nullptr;
+
+ while (1)
+ {
+ int opt = mi_getopt ("-symbol-info-modules", argc, argv, opts,
+ &oind, &oarg);
+ if (opt < 0)
+ break;
+ switch ((enum opt) opt)
+ {
+ case NAME_REGEXP_OPT:
+ regexp = oarg;
+ break;
+ }
+ }
+
+ mi_symbol_info (MODULES_DOMAIN, regexp, nullptr, true);
+}
+
+/* Implement -symbol-info-types command. */
+
+void
+mi_cmd_symbol_info_types (const char *command, char **argv, int argc)
+{
+ const char *regexp = nullptr;
+
+ enum opt
+ {
+ NAME_REGEXP_OPT
+ };
+ static const struct mi_opt opts[] =
+ {
+ {"-name", NAME_REGEXP_OPT, 1},
+ { 0, 0, 0 }
+ };
+
+ int oind = 0;
+ char *oarg = nullptr;
+
+ while (true)
+ {
+ int opt = mi_getopt ("-symbol-info-types", argc, argv, opts,
+ &oind, &oarg);
+ if (opt < 0)
+ break;
+ switch ((enum opt) opt)
+ {
+ case NAME_REGEXP_OPT:
+ regexp = oarg;
+ break;
+ }
+ }
+
+ mi_symbol_info (TYPES_DOMAIN, regexp, nullptr, true);
+}
+
+/* Implement -symbol-info-variables command. */
+
+void
+mi_cmd_symbol_info_variables (const char *command, char **argv, int argc)
+{
+ mi_info_functions_or_variables (VARIABLES_DOMAIN, argv, argc);
+}