+2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * mi/mi-cmds.c (mi_cmds): Add -symbol-info-module-functions and
+ -symbol-info-module-variables entries.
+ * mi/mi-cmds.h (mi_cmd_symbol_info_module_functions): Declare.
+ (mi_cmd_symbol_info_module_variables): Declare.
+ * mi/mi-symbol-cmds.c
+ (module_symbol_search_iterator): New typedef.
+ (output_module_symbols_in_single_module_and_file): New function.
+ (output_module_symbols_in_single_module): New function.
+ (mi_info_module_functions_or_variables): New function.
+ (mi_cmd_symbol_info_module_functions): New function.
+ (mi_cmd_symbol_info_module_variables): New function.
+ * NEWS: Mention new MI command.
+
2019-12-03 Christian Biesinger <cbiesinger@google.com>
* bcache.c (hash): Remove.
-symbol-info-modules, this is the MI equivalent of the CLI 'info
modules' command.
+-symbol-info-module-functions and -symbol-info-module-variables.
+ These commands are the MI equivalent of the CLI commands 'info
+ module functions' and 'info module variables'.
+
* Other MI changes
** The default version of the MI interpreter is now 3 (-i=mi3).
+2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * doc/gdb.texinfo (GDB/MI Symbol Query): Document new MI command
+ -symbol-info-module-functions and -symbol-info-module-variables.
+
2019-12-01 Tom Tromey <tom@tromey.com>
* gdb.texinfo (TUI Configuration): Mention TUI border styles.
@end group
@end smallexample
+@subheading The @code{-symbol-info-module-functions} Command
+@findex -symbol-info-module-functions
+@anchor{-symbol-info-module-functions}
+
+@subsubheading Synopsis
+
+@smallexample
+ -symbol-info-module-functions [--module @var{module_regexp}]
+ [--name @var{name_regexp}]
+ [--type @var{type_regexp}]
+@end smallexample
+
+@noindent
+Return a list containing the names of all known functions within all
+know Fortran modules. The functions are grouped by source file and
+containing module, and shown with the line number on which each
+function is defined.
+
+The option @code{--module} only returns results for modules matching
+@var{module_regexp}. The option @code{--name} only returns functions
+whose name matches @var{name_regexp}, and @code{--type} only returns
+functions whose type matches @var{type_regexp}.
+
+@subsubheading @value{GDBN} Command
+
+The corresponding @value{GDBN} command is @samp{info module functions}.
+
+@subsubheading Example
+
+@smallexample
+@group
+(gdb)
+-symbol-info-module-functions
+^done,symbols=
+ [@{module="mod1",
+ files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90",
+ fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90",
+ symbols=[@{line="21",name="mod1::check_all",type="void (void)",
+ description="void mod1::check_all(void);"@}]@}]@},
+ @{module="mod2",
+ files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90",
+ fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90",
+ symbols=[@{line="30",name="mod2::check_var_i",type="void (void)",
+ description="void mod2::check_var_i(void);"@}]@}]@},
+ @{module="mod3",
+ files=[@{filename="/projec/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ fullname="/projec/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ symbols=[@{line="21",name="mod3::check_all",type="void (void)",
+ description="void mod3::check_all(void);"@},
+ @{line="27",name="mod3::check_mod2",type="void (void)",
+ description="void mod3::check_mod2(void);"@}]@}]@},
+ @{module="modmany",
+ files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ symbols=[@{line="35",name="modmany::check_some",type="void (void)",
+ description="void modmany::check_some(void);"@}]@}]@},
+ @{module="moduse",
+ files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ symbols=[@{line="44",name="moduse::check_all",type="void (void)",
+ description="void moduse::check_all(void);"@},
+ @{line="49",name="moduse::check_var_x",type="void (void)",
+ description="void moduse::check_var_x(void);"@}]@}]@}]
+@end group
+@end smallexample
+
+@subheading The @code{-symbol-info-module-variables} Command
+@findex -symbol-info-module-variables
+@anchor{-symbol-info-module-variables}
+
+@subsubheading Synopsis
+
+@smallexample
+ -symbol-info-module-variables [--module @var{module_regexp}]
+ [--name @var{name_regexp}]
+ [--type @var{type_regexp}]
+@end smallexample
+
+@noindent
+Return a list containing the names of all known variables within all
+know Fortran modules. The variables are grouped by source file and
+containing module, and shown with the line number on which each
+variable is defined.
+
+The option @code{--module} only returns results for modules matching
+@var{module_regexp}. The option @code{--name} only returns variables
+whose name matches @var{name_regexp}, and @code{--type} only returns
+variables whose type matches @var{type_regexp}.
+
+@subsubheading @value{GDBN} Command
+
+The corresponding @value{GDBN} command is @samp{info module variables}.
+
+@subsubheading Example
+
+@smallexample
+@group
+(gdb)
+-symbol-info-module-variables
+^done,symbols=
+ [@{module="mod1",
+ files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90",
+ fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90",
+ symbols=[@{line="18",name="mod1::var_const",type="integer(kind=4)",
+ description="integer(kind=4) mod1::var_const;"@},
+ @{line="17",name="mod1::var_i",type="integer(kind=4)",
+ description="integer(kind=4) mod1::var_i;"@}]@}]@},
+ @{module="mod2",
+ files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90",
+ fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90",
+ symbols=[@{line="28",name="mod2::var_i",type="integer(kind=4)",
+ description="integer(kind=4) mod2::var_i;"@}]@}]@},
+ @{module="mod3",
+ files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ symbols=[@{line="18",name="mod3::mod1",type="integer(kind=4)",
+ description="integer(kind=4) mod3::mod1;"@},
+ @{line="17",name="mod3::mod2",type="integer(kind=4)",
+ description="integer(kind=4) mod3::mod2;"@},
+ @{line="19",name="mod3::var_i",type="integer(kind=4)",
+ description="integer(kind=4) mod3::var_i;"@}]@}]@},
+ @{module="modmany",
+ files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ symbols=[@{line="33",name="modmany::var_a",type="integer(kind=4)",
+ description="integer(kind=4) modmany::var_a;"@},
+ @{line="33",name="modmany::var_b",type="integer(kind=4)",
+ description="integer(kind=4) modmany::var_b;"@},
+ @{line="33",name="modmany::var_c",type="integer(kind=4)",
+ description="integer(kind=4) modmany::var_c;"@},
+ @{line="33",name="modmany::var_i",type="integer(kind=4)",
+ description="integer(kind=4) modmany::var_i;"@}]@}]@},
+ @{module="moduse",
+ files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90",
+ symbols=[@{line="42",name="moduse::var_x",type="integer(kind=4)",
+ description="integer(kind=4) moduse::var_x;"@},
+ @{line="42",name="moduse::var_y",type="integer(kind=4)",
+ description="integer(kind=4) moduse::var_y;"@}]@}]@}]
+@end group
+@end smallexample
+
@subheading The @code{-symbol-info-modules} Command
@findex -symbol-info-modules
@anchor{-symbol-info-modules}
DEF_MI_CMD_MI ("symbol-info-variables", mi_cmd_symbol_info_variables),
DEF_MI_CMD_MI ("symbol-info-types", mi_cmd_symbol_info_types),
DEF_MI_CMD_MI ("symbol-info-modules", mi_cmd_symbol_info_modules),
+ DEF_MI_CMD_MI ("symbol-info-module-functions",
+ mi_cmd_symbol_info_module_functions),
+ DEF_MI_CMD_MI ("symbol-info-module-variables",
+ mi_cmd_symbol_info_module_variables),
DEF_MI_CMD_CLI ("target-attach", "attach", 1),
DEF_MI_CMD_MI ("target-detach", mi_cmd_target_detach),
DEF_MI_CMD_CLI ("target-disconnect", "disconnect", 0),
extern mi_cmd_argv_ftype mi_cmd_stack_select_frame;
extern mi_cmd_argv_ftype mi_cmd_symbol_list_lines;
extern mi_cmd_argv_ftype mi_cmd_symbol_info_functions;
+extern mi_cmd_argv_ftype mi_cmd_symbol_info_module_functions;
+extern mi_cmd_argv_ftype mi_cmd_symbol_info_module_variables;
extern mi_cmd_argv_ftype mi_cmd_symbol_info_modules;
extern mi_cmd_argv_ftype mi_cmd_symbol_info_types;
extern mi_cmd_argv_ftype mi_cmd_symbol_info_variables;
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_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
+2019-12-04 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * gdb.mi/mi-fortran-modules.exp: Add additional tests for
+ -symbol-info-module-functions and -symbol-info-module-variables.
+
2019-12-01 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.fortran/array-slices.exp: Add test for dynamic strings.
"103\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"41\",name=\"moduse\"\}\\\]\}\\\]\}" \
"-symbol-info-modules --name moduse"
-
+mi_gdb_test "104-symbol-info-module-functions" \
+ [join \
+ [list \
+ "104\\^done,symbols=\\\[\{module=\"mod1\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"21\",name=\"mod1::check_all\",type=\"void \\(void\\)\",description=\"void mod1::check_all\\(void\\);\"\}\\\]\}\\\]\},\{module=\"mod2\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"30\",name=\"mod2::check_var_i\",type=\"void \\(void\\)\",description=\"void mod2::check_var_i\\(void\\);\"\}\\\]\}\\\]\},\{module=\"mod3\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"21\",name=\"mod3::check_all\",type=\"void \\(void\\)\",description=\"void mod3::check_all\\(void\\);\"\},\{line=\"27\",name=\"mod3::check_mod2\",type=\"void \\(void\\)\",description=\"void mod3::check_mod2\\(void\\);\"\}\\\]\}\\\]\}," \
+ "\{module=\"modmany\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"35\",name=\"modmany::check_some\",type=\"void \\(void\\)\",description=\"void modmany::check_some\\(void\\);\"\}\\\]\}\\\]\},\{module=\"moduse\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"44\",name=\"moduse::check_all\",type=\"void \\(void\\)\",description=\"void moduse::check_all\\(void\\);\"\},\{line=\"49\",name=\"moduse::check_var_x\",type=\"void \\(void\\)\",description=\"void moduse::check_var_x\\(void\\);\"\}\\\]\}\\\]\}\\\]" ] "" ] \
+ "-symbol-info-module-functions"
+
+mi_gdb_test "105-symbol-info-module-functions --name _all" \
+ "105\\^done,symbols=\\\[\{module=\"mod1\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"21\",name=\"mod1::check_all\",type=\"void \\(void\\)\",description=\"void mod1::check_all\\(void\\);\"\}\\\]\}\\\]\},\{module=\"mod3\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"21\",name=\"mod3::check_all\",type=\"void \\(void\\)\",description=\"void mod3::check_all\\(void\\);\"\}\\\]\}\\\]\},\{module=\"moduse\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"44\",name=\"moduse::check_all\",type=\"void \\(void\\)\",description=\"void moduse::check_all\\(void\\);\"\}\\\]\}\\\]\}\\\]" \
+ "-symbol-info-module-functions --name _all"
+
+mi_gdb_test "106-symbol-info-module-functions --module mod\[123\]" \
+ "106\\^done,symbols=\\\[\{module=\"mod1\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"21\",name=\"mod1::check_all\",type=\"void \\(void\\)\",description=\"void mod1::check_all\\(void\\);\"\}\\\]\}\\\]\},\{module=\"mod2\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"30\",name=\"mod2::check_var_i\",type=\"void \\(void\\)\",description=\"void mod2::check_var_i\\(void\\);\"\}\\\]\}\\\]\},\{module=\"mod3\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"21\",name=\"mod3::check_all\",type=\"void \\(void\\)\",description=\"void mod3::check_all\\(void\\);\"\},\{line=\"27\",name=\"mod3::check_mod2\",type=\"void \\(void\\)\",description=\"void mod3::check_mod2\\(void\\);\"\}\\\]\}\\\]\}\\\]" \
+ "-symbol-info-module-functions --module mod\[123\]"
+
+set int4 [fortran_int4]
+
+mi_gdb_test "107-symbol-info-module-variables" \
+ [join \
+ [list \
+ "107\\^done,symbols=\\\[\{module=\"mod1\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"18\",name=\"mod1::var_const\",type=\"$int4\",description=\"$int4 mod1::var_const;\"\},\{line=\"17\",name=\"mod1::var_i\",type=\"$int4\",description=\"$int4 mod1::var_i;\"\}\\\]\}\\\]\},\{module=\"mod2\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"28\",name=\"mod2::var_i\",type=\"$int4\",description=\"$int4 mod2::var_i;\"\}\\\]\}\\\]\}," \
+ "\{module=\"mod3\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"18\",name=\"mod3::mod1\",type=\"$int4\",description=\"$int4 mod3::mod1;\"\},\{line=\"17\",name=\"mod3::mod2\",type=\"$int4\",description=\"$int4 mod3::mod2;\"\},\{line=\"19\",name=\"mod3::var_i\",type=\"$int4\",description=\"$int4 mod3::var_i;\"\}\\\]\}\\\]\},\{module=\"modmany\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"33\",name=\"modmany::var_a\",type=\"$int4\",description=\"$int4 modmany::var_a;\"\}," \
+ "\{line=\"33\",name=\"modmany::var_b\",type=\"$int4\",description=\"$int4 modmany::var_b;\"\},\{line=\"33\",name=\"modmany::var_c\",type=\"$int4\",description=\"$int4 modmany::var_c;\"\},\{line=\"33\",name=\"modmany::var_i\",type=\"$int4\",description=\"$int4 modmany::var_i;\"\}\\\]\}\\\]\},\{module=\"moduse\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"42\",name=\"moduse::var_x\",type=\"$int4\",description=\"$int4 moduse::var_x;\"\},\{line=\"42\",name=\"moduse::var_y\",type=\"$int4\",description=\"$int4 moduse::var_y;\"\}\\\]\}\\\]\}\\\]" ] "" ] \
+ "-symbol-info-module-variables"