From 7dc42066097ca6188ecd2c505d865e68d84998ee Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Tue, 24 Sep 2019 23:35:47 +0100 Subject: gdb/mi: Add new commands -symbol-info-{functions,variables,types} Add new MI commands -symbol-info-functions, -symbol-info-variables, and -symbol-info-types which correspond to the CLI commands 'info functions', 'info variables', and 'info types' respectively. gdb/ChangeLog: * mi/mi-cmds.c (mi_cmds): Add '-symbol-info-functions', '-symbol-info-types', and '-symbol-info-variables'. * mi/mi-cmds.h (mi_cmd_symbol_info_functions): Declare. (mi_cmd_symbol_info_types): Declare. (mi_cmd_symbol_info_variables): Declare. * mi/mi-symbol-cmds.c: Add 'source.h' and 'mi-getopt.h' includes. (output_debug_symbol): New function. (output_nondebug_symbol): New function. (mi_symbol_info): New function. (mi_info_functions_or_variables): New function. (mi_cmd_symbol_info_functions): New function. (mi_cmd_symbol_info_types): New function. (mi_cmd_symbol_info_variables): New function. * NEWS: Mention new commands. gdb/testsuite/ChangeLog: * gdb.mi/mi-sym-info-1.c: New file. * gdb.mi/mi-sym-info-2.c: New file. * gdb.mi/mi-sym-info.exp: New file. gdb/doc/ChangeLog: * doc/gdb.texinfo (GDB/MI Symbol Query): Document new MI command -symbol-info-functions, -symbol-info-types, and -symbol-info-variables. Change-Id: Ic2fc6a6750bbce91cdde2344791014e5ef45642d --- gdb/mi/mi-cmds.c | 3 + gdb/mi/mi-cmds.h | 3 + gdb/mi/mi-symbol-cmds.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+) (limited to 'gdb/mi') diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index 37eab01..df9f25f 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -151,6 +151,9 @@ static struct mi_cmd mi_cmds[] = DEF_MI_CMD_MI_1 ("stack-select-frame", mi_cmd_stack_select_frame, &mi_suppress_notification.user_selected_context), DEF_MI_CMD_MI ("symbol-list-lines", mi_cmd_symbol_list_lines), + DEF_MI_CMD_MI ("symbol-info-functions", mi_cmd_symbol_info_functions), + 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_CLI ("target-attach", "attach", 1), DEF_MI_CMD_MI ("target-detach", mi_cmd_target_detach), DEF_MI_CMD_CLI ("target-disconnect", "disconnect", 0), diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 91ce4cd..c2fd7d3 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -94,6 +94,9 @@ extern mi_cmd_argv_ftype mi_cmd_stack_list_locals; extern mi_cmd_argv_ftype mi_cmd_stack_list_variables; 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_types; +extern mi_cmd_argv_ftype mi_cmd_symbol_info_variables; extern mi_cmd_argv_ftype mi_cmd_target_detach; extern mi_cmd_argv_ftype mi_cmd_target_file_get; extern mi_cmd_argv_ftype mi_cmd_target_file_put; diff --git a/gdb/mi/mi-symbol-cmds.c b/gdb/mi/mi-symbol-cmds.c index 63142e8..f674dcf 100644 --- a/gdb/mi/mi-symbol-cmds.c +++ b/gdb/mi/mi-symbol-cmds.c @@ -21,6 +21,8 @@ #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 @@ -59,3 +61,210 @@ mi_cmd_symbol_list_lines (const char *command, char **argv, int argc) 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 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); +} + +/* 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-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); +} -- cgit v1.1