| /* MI Command Set - symbol commands. |
| Copyright (C) 2003-2019 Free Software Foundation, Inc. |
| |
| This file is part of GDB. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| |
| #include "defs.h" |
| #include "mi-cmds.h" |
| #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 |
| in ascending PC order. */ |
| |
| void |
| mi_cmd_symbol_list_lines (const char *command, char **argv, int argc) |
| { |
| struct gdbarch *gdbarch; |
| char *filename; |
| struct symtab *s; |
| int i; |
| struct ui_out *uiout = current_uiout; |
| |
| if (argc != 1) |
| error (_("-symbol-list-lines: Usage: SOURCE_FILENAME")); |
| |
| filename = argv[0]; |
| s = lookup_symtab (filename); |
| |
| if (s == NULL) |
| error (_("-symbol-list-lines: Unknown source file name.")); |
| |
| /* Now, dump the associated line table. The pc addresses are |
| already sorted by increasing values in the symbol table, so no |
| need to perform any other sorting. */ |
| |
| gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s)); |
| |
| ui_out_emit_list list_emitter (uiout, "lines"); |
| if (SYMTAB_LINETABLE (s) != NULL && SYMTAB_LINETABLE (s)->nitems > 0) |
| for (i = 0; i < SYMTAB_LINETABLE (s)->nitems; i++) |
| { |
| ui_out_emit_tuple tuple_emitter (uiout, NULL); |
| uiout->field_core_addr ("pc", gdbarch, SYMTAB_LINETABLE (s)->item[i].pc); |
| 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", SYMBOL_PRINT_NAME (sym)); |
| |
| 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.c_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_PRINT_NAME (msymbol.minsym)); |
| } |
| |
| /* This is the guts of the commands '-symbol-info-functions', |
| '-symbol-info-variables', and '-symbol-info-types'. It calls |
| search_symbols to find all matches and then prints the matching |
| [m]symbols in an MI structured format. This is similar to |
| symtab_symbol_info in symtab.c. All the arguments are used to |
| initialise a SEARCH_SYMBOLS_SPEC, see symtab.h for a description of |
| their meaning. */ |
| |
| static void |
| mi_symbol_info (enum search_domain kind, const char *regexp, |
| const char *t_regexp, bool exclude_minsyms) |
| { |
| /* Must make sure that if we're interrupted, symbols gets freed. */ |
| global_symbol_searcher sym_search (kind, regexp, t_regexp, 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... */ |
| while (i < symbols.size () |
| && symbols[i].msymbol.minsym == nullptr |
| && symbol_symtab (symbols[i].symbol) == symtab) |
| { |
| symbol_search &s = symbols[i]; |
| |
| output_debug_symbol(uiout, kind, s.symbol, s.block); |
| |
| i++; |
| } |
| } |
| } |
| |
| /* 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... */ |
| while (i < symbols.size ()) |
| { |
| gdb_assert (symbols[i].msymbol.minsym != nullptr); |
| |
| output_nondebug_symbol(uiout, symbols[i].msymbol); |
| |
| i++; |
| } |
| } |
| } |
| |
| /* 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 (1) |
| { |
| 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); |
| } |
| |