| 1 | /* MI Command Set - symbol commands. |
| 2 | Copyright (C) 2003-2019 Free Software Foundation, Inc. |
| 3 | |
| 4 | This file is part of GDB. |
| 5 | |
| 6 | This program is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation; either version 3 of the License, or |
| 9 | (at your option) any later version. |
| 10 | |
| 11 | This program is distributed in the hope that it will be useful, |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | GNU General Public License for more details. |
| 15 | |
| 16 | You should have received a copy of the GNU General Public License |
| 17 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| 18 | |
| 19 | #include "defs.h" |
| 20 | #include "mi-cmds.h" |
| 21 | #include "symtab.h" |
| 22 | #include "objfiles.h" |
| 23 | #include "ui-out.h" |
| 24 | #include "source.h" |
| 25 | #include "mi-getopt.h" |
| 26 | |
| 27 | /* Print the list of all pc addresses and lines of code for the |
| 28 | provided (full or base) source file name. The entries are sorted |
| 29 | in ascending PC order. */ |
| 30 | |
| 31 | void |
| 32 | mi_cmd_symbol_list_lines (const char *command, char **argv, int argc) |
| 33 | { |
| 34 | struct gdbarch *gdbarch; |
| 35 | char *filename; |
| 36 | struct symtab *s; |
| 37 | int i; |
| 38 | struct ui_out *uiout = current_uiout; |
| 39 | |
| 40 | if (argc != 1) |
| 41 | error (_("-symbol-list-lines: Usage: SOURCE_FILENAME")); |
| 42 | |
| 43 | filename = argv[0]; |
| 44 | s = lookup_symtab (filename); |
| 45 | |
| 46 | if (s == NULL) |
| 47 | error (_("-symbol-list-lines: Unknown source file name.")); |
| 48 | |
| 49 | /* Now, dump the associated line table. The pc addresses are |
| 50 | already sorted by increasing values in the symbol table, so no |
| 51 | need to perform any other sorting. */ |
| 52 | |
| 53 | gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s)); |
| 54 | |
| 55 | ui_out_emit_list list_emitter (uiout, "lines"); |
| 56 | if (SYMTAB_LINETABLE (s) != NULL && SYMTAB_LINETABLE (s)->nitems > 0) |
| 57 | for (i = 0; i < SYMTAB_LINETABLE (s)->nitems; i++) |
| 58 | { |
| 59 | ui_out_emit_tuple tuple_emitter (uiout, NULL); |
| 60 | uiout->field_core_addr ("pc", gdbarch, SYMTAB_LINETABLE (s)->item[i].pc); |
| 61 | uiout->field_signed ("line", SYMTAB_LINETABLE (s)->item[i].line); |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | /* Used by the -symbol-info-* and -symbol-info-module-* commands to print |
| 66 | information about the symbol SYM in a block of index BLOCK (either |
| 67 | GLOBAL_BLOCK or STATIC_BLOCK). KIND is the kind of symbol we searched |
| 68 | for in order to find SYM, which impact which fields are displayed in the |
| 69 | results. */ |
| 70 | |
| 71 | static void |
| 72 | output_debug_symbol (ui_out *uiout, enum search_domain kind, |
| 73 | struct symbol *sym, int block) |
| 74 | { |
| 75 | ui_out_emit_tuple tuple_emitter (uiout, NULL); |
| 76 | |
| 77 | if (SYMBOL_LINE (sym) != 0) |
| 78 | uiout->field_unsigned ("line", SYMBOL_LINE (sym)); |
| 79 | uiout->field_string ("name", sym->print_name ()); |
| 80 | |
| 81 | if (kind == FUNCTIONS_DOMAIN || kind == VARIABLES_DOMAIN) |
| 82 | { |
| 83 | string_file tmp_stream; |
| 84 | type_print (SYMBOL_TYPE (sym), "", &tmp_stream, -1); |
| 85 | uiout->field_string ("type", tmp_stream.string ()); |
| 86 | |
| 87 | std::string str = symbol_to_info_string (sym, block, kind); |
| 88 | uiout->field_string ("description", str); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | /* Actually output one nondebug symbol, puts a tuple emitter in place |
| 93 | and then outputs the fields for this msymbol. */ |
| 94 | |
| 95 | static void |
| 96 | output_nondebug_symbol (ui_out *uiout, |
| 97 | const struct bound_minimal_symbol &msymbol) |
| 98 | { |
| 99 | struct gdbarch *gdbarch = get_objfile_arch (msymbol.objfile); |
| 100 | ui_out_emit_tuple tuple_emitter (uiout, NULL); |
| 101 | |
| 102 | uiout->field_core_addr ("address", gdbarch, |
| 103 | BMSYMBOL_VALUE_ADDRESS (msymbol)); |
| 104 | uiout->field_string ("name", msymbol.minsym->print_name ()); |
| 105 | } |
| 106 | |
| 107 | /* This is the guts of the commands '-symbol-info-functions', |
| 108 | '-symbol-info-variables', and '-symbol-info-types'. It searches for |
| 109 | symbols matching KING, NAME_REGEXP, TYPE_REGEXP, and EXCLUDE_MINSYMS, |
| 110 | and then prints the matching [m]symbols in an MI structured format. */ |
| 111 | |
| 112 | static void |
| 113 | mi_symbol_info (enum search_domain kind, const char *name_regexp, |
| 114 | const char *type_regexp, bool exclude_minsyms, |
| 115 | size_t max_results) |
| 116 | { |
| 117 | global_symbol_searcher sym_search (kind, name_regexp); |
| 118 | sym_search.set_symbol_type_regexp (type_regexp); |
| 119 | sym_search.set_exclude_minsyms (exclude_minsyms); |
| 120 | sym_search.set_max_search_results (max_results); |
| 121 | std::vector<symbol_search> symbols = sym_search.search (); |
| 122 | ui_out *uiout = current_uiout; |
| 123 | int i = 0; |
| 124 | |
| 125 | ui_out_emit_tuple outer_symbols_emitter (uiout, "symbols"); |
| 126 | |
| 127 | /* Debug symbols are placed first. */ |
| 128 | if (i < symbols.size () && symbols[i].msymbol.minsym == nullptr) |
| 129 | { |
| 130 | ui_out_emit_list debug_symbols_list_emitter (uiout, "debug"); |
| 131 | |
| 132 | /* As long as we have debug symbols... */ |
| 133 | while (i < symbols.size () && symbols[i].msymbol.minsym == nullptr) |
| 134 | { |
| 135 | symtab *symtab = symbol_symtab (symbols[i].symbol); |
| 136 | ui_out_emit_tuple symtab_tuple_emitter (uiout, nullptr); |
| 137 | |
| 138 | uiout->field_string ("filename", |
| 139 | symtab_to_filename_for_display (symtab)); |
| 140 | uiout->field_string ("fullname", symtab_to_fullname (symtab)); |
| 141 | |
| 142 | ui_out_emit_list symbols_list_emitter (uiout, "symbols"); |
| 143 | |
| 144 | /* As long as we have debug symbols from this symtab... */ |
| 145 | for (; (i < symbols.size () |
| 146 | && symbols[i].msymbol.minsym == nullptr |
| 147 | && symbol_symtab (symbols[i].symbol) == symtab); |
| 148 | ++i) |
| 149 | { |
| 150 | symbol_search &s = symbols[i]; |
| 151 | |
| 152 | output_debug_symbol (uiout, kind, s.symbol, s.block); |
| 153 | } |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | /* Non-debug symbols are placed after. */ |
| 158 | if (i < symbols.size ()) |
| 159 | { |
| 160 | ui_out_emit_list nondebug_symbols_list_emitter (uiout, "nondebug"); |
| 161 | |
| 162 | /* As long as we have nondebug symbols... */ |
| 163 | for (; i < symbols.size (); i++) |
| 164 | { |
| 165 | gdb_assert (symbols[i].msymbol.minsym != nullptr); |
| 166 | output_nondebug_symbol (uiout, symbols[i].msymbol); |
| 167 | } |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | /* Helper to parse the option text from an -max-results argument and return |
| 172 | the parsed value. If the text can't be parsed then an error is thrown. */ |
| 173 | |
| 174 | static size_t |
| 175 | parse_max_results_option (char *arg) |
| 176 | { |
| 177 | char *ptr = arg; |
| 178 | long long val = strtoll (arg, &ptr, 10); |
| 179 | if (arg == ptr || *ptr != '\0' || val > SIZE_MAX || val < 0) |
| 180 | error (_("invalid value for --max-results argument")); |
| 181 | size_t max_results = (size_t) val; |
| 182 | |
| 183 | return max_results; |
| 184 | } |
| 185 | |
| 186 | /* Helper for mi_cmd_symbol_info_{functions,variables} - depending on KIND. |
| 187 | Processes command line options from ARGV and ARGC. */ |
| 188 | |
| 189 | static void |
| 190 | mi_info_functions_or_variables (enum search_domain kind, char **argv, int argc) |
| 191 | { |
| 192 | size_t max_results = SIZE_MAX; |
| 193 | const char *regexp = nullptr; |
| 194 | const char *t_regexp = nullptr; |
| 195 | bool exclude_minsyms = true; |
| 196 | |
| 197 | enum opt |
| 198 | { |
| 199 | INCLUDE_NONDEBUG_OPT, TYPE_REGEXP_OPT, NAME_REGEXP_OPT, MAX_RESULTS_OPT |
| 200 | }; |
| 201 | static const struct mi_opt opts[] = |
| 202 | { |
| 203 | {"-include-nondebug" , INCLUDE_NONDEBUG_OPT, 0}, |
| 204 | {"-type", TYPE_REGEXP_OPT, 1}, |
| 205 | {"-name", NAME_REGEXP_OPT, 1}, |
| 206 | {"-max-results", MAX_RESULTS_OPT, 1}, |
| 207 | { 0, 0, 0 } |
| 208 | }; |
| 209 | |
| 210 | int oind = 0; |
| 211 | char *oarg = nullptr; |
| 212 | |
| 213 | while (1) |
| 214 | { |
| 215 | const char *cmd_string |
| 216 | = ((kind == FUNCTIONS_DOMAIN) |
| 217 | ? "-symbol-info-functions" : "-symbol-info-variables"); |
| 218 | int opt = mi_getopt (cmd_string, argc, argv, opts, &oind, &oarg); |
| 219 | if (opt < 0) |
| 220 | break; |
| 221 | switch ((enum opt) opt) |
| 222 | { |
| 223 | case INCLUDE_NONDEBUG_OPT: |
| 224 | exclude_minsyms = false; |
| 225 | break; |
| 226 | case TYPE_REGEXP_OPT: |
| 227 | t_regexp = oarg; |
| 228 | break; |
| 229 | case NAME_REGEXP_OPT: |
| 230 | regexp = oarg; |
| 231 | break; |
| 232 | case MAX_RESULTS_OPT: |
| 233 | max_results = parse_max_results_option (oarg); |
| 234 | break; |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | mi_symbol_info (kind, regexp, t_regexp, exclude_minsyms, max_results); |
| 239 | } |
| 240 | |
| 241 | /* Type for an iterator over a vector of module_symbol_search results. */ |
| 242 | typedef std::vector<module_symbol_search>::const_iterator |
| 243 | module_symbol_search_iterator; |
| 244 | |
| 245 | /* Helper for mi_info_module_functions_or_variables. Display the results |
| 246 | from ITER up to END or until we find a symbol that is in a different |
| 247 | module, or in a different symtab than the first symbol we print. Update |
| 248 | and return the new value for ITER. */ |
| 249 | static module_symbol_search_iterator |
| 250 | output_module_symbols_in_single_module_and_file |
| 251 | (struct ui_out *uiout, module_symbol_search_iterator iter, |
| 252 | const module_symbol_search_iterator end, enum search_domain kind) |
| 253 | { |
| 254 | /* The symbol for the module in which the first result resides. */ |
| 255 | const symbol *first_module_symbol = iter->first.symbol; |
| 256 | |
| 257 | /* The symbol for the first result, and the symtab in which it resides. */ |
| 258 | const symbol *first_result_symbol = iter->second.symbol; |
| 259 | symtab *first_symbtab = symbol_symtab (first_result_symbol); |
| 260 | |
| 261 | /* Formatted output. */ |
| 262 | ui_out_emit_tuple current_file (uiout, nullptr); |
| 263 | uiout->field_string ("filename", |
| 264 | symtab_to_filename_for_display (first_symbtab)); |
| 265 | uiout->field_string ("fullname", symtab_to_fullname (first_symbtab)); |
| 266 | ui_out_emit_list item_list (uiout, "symbols"); |
| 267 | |
| 268 | /* Repeatedly output result symbols until either we run out of symbols, |
| 269 | we change module, or we change symtab. */ |
| 270 | for (; (iter != end |
| 271 | && first_module_symbol == iter->first.symbol |
| 272 | && first_symbtab == symbol_symtab (iter->second.symbol)); |
| 273 | ++iter) |
| 274 | output_debug_symbol (uiout, kind, iter->second.symbol, |
| 275 | iter->second.block); |
| 276 | |
| 277 | return iter; |
| 278 | } |
| 279 | |
| 280 | /* Helper for mi_info_module_functions_or_variables. Display the results |
| 281 | from ITER up to END or until we find a symbol that is in a different |
| 282 | module than the first symbol we print. Update and return the new value |
| 283 | for ITER. */ |
| 284 | static module_symbol_search_iterator |
| 285 | output_module_symbols_in_single_module |
| 286 | (struct ui_out *uiout, module_symbol_search_iterator iter, |
| 287 | const module_symbol_search_iterator end, enum search_domain kind) |
| 288 | { |
| 289 | gdb_assert (iter->first.symbol != nullptr); |
| 290 | gdb_assert (iter->second.symbol != nullptr); |
| 291 | |
| 292 | /* The symbol for the module in which the first result resides. */ |
| 293 | const symbol *first_module_symbol = iter->first.symbol; |
| 294 | |
| 295 | /* Create output formatting. */ |
| 296 | ui_out_emit_tuple module_tuple (uiout, nullptr); |
| 297 | uiout->field_string ("module", first_module_symbol->print_name ()); |
| 298 | ui_out_emit_list files_list (uiout, "files"); |
| 299 | |
| 300 | /* The results are sorted so that symbols within the same file are next |
| 301 | to each other in the list. Calling the output function once will |
| 302 | print all results within a single file. We keep calling the output |
| 303 | function until we change module. */ |
| 304 | while (iter != end && first_module_symbol == iter->first.symbol) |
| 305 | iter = output_module_symbols_in_single_module_and_file (uiout, iter, |
| 306 | end, kind); |
| 307 | return iter; |
| 308 | } |
| 309 | |
| 310 | /* Core of -symbol-info-module-functions and -symbol-info-module-variables. |
| 311 | KIND indicates what we are searching for, and ARGV and ARGC are the |
| 312 | command line options passed to the MI command. */ |
| 313 | |
| 314 | static void |
| 315 | mi_info_module_functions_or_variables (enum search_domain kind, |
| 316 | char **argv, int argc) |
| 317 | { |
| 318 | const char *module_regexp = nullptr; |
| 319 | const char *regexp = nullptr; |
| 320 | const char *type_regexp = nullptr; |
| 321 | |
| 322 | /* Process the command line options. */ |
| 323 | |
| 324 | enum opt |
| 325 | { |
| 326 | MODULE_REGEXP_OPT, TYPE_REGEXP_OPT, NAME_REGEXP_OPT |
| 327 | }; |
| 328 | static const struct mi_opt opts[] = |
| 329 | { |
| 330 | {"-module", MODULE_REGEXP_OPT, 1}, |
| 331 | {"-type", TYPE_REGEXP_OPT, 1}, |
| 332 | {"-name", NAME_REGEXP_OPT, 1}, |
| 333 | { 0, 0, 0 } |
| 334 | }; |
| 335 | |
| 336 | int oind = 0; |
| 337 | char *oarg = nullptr; |
| 338 | |
| 339 | while (1) |
| 340 | { |
| 341 | const char *cmd_string |
| 342 | = ((kind == FUNCTIONS_DOMAIN) |
| 343 | ? "-symbol-info-module-functions" |
| 344 | : "-symbol-info-module-variables"); |
| 345 | int opt = mi_getopt (cmd_string, argc, argv, opts, &oind, &oarg); |
| 346 | if (opt < 0) |
| 347 | break; |
| 348 | switch ((enum opt) opt) |
| 349 | { |
| 350 | case MODULE_REGEXP_OPT: |
| 351 | module_regexp = oarg; |
| 352 | break; |
| 353 | case TYPE_REGEXP_OPT: |
| 354 | type_regexp = oarg; |
| 355 | break; |
| 356 | case NAME_REGEXP_OPT: |
| 357 | regexp = oarg; |
| 358 | break; |
| 359 | } |
| 360 | } |
| 361 | |
| 362 | std::vector<module_symbol_search> module_symbols |
| 363 | = search_module_symbols (module_regexp, regexp, type_regexp, kind); |
| 364 | |
| 365 | struct ui_out *uiout = current_uiout; |
| 366 | ui_out_emit_list all_matching_symbols (uiout, "symbols"); |
| 367 | |
| 368 | /* The results in the module_symbols list are ordered so symbols in the |
| 369 | same module are next to each other. Repeatedly call the output |
| 370 | function to print sequences of symbols that are in the same module |
| 371 | until we have no symbols left to print. */ |
| 372 | module_symbol_search_iterator iter = module_symbols.begin (); |
| 373 | const module_symbol_search_iterator end = module_symbols.end (); |
| 374 | while (iter != end) |
| 375 | iter = output_module_symbols_in_single_module (uiout, iter, end, kind); |
| 376 | } |
| 377 | |
| 378 | /* Implement -symbol-info-functions command. */ |
| 379 | |
| 380 | void |
| 381 | mi_cmd_symbol_info_functions (const char *command, char **argv, int argc) |
| 382 | { |
| 383 | mi_info_functions_or_variables (FUNCTIONS_DOMAIN, argv, argc); |
| 384 | } |
| 385 | |
| 386 | /* Implement -symbol-info-module-functions command. */ |
| 387 | |
| 388 | void |
| 389 | mi_cmd_symbol_info_module_functions (const char *command, char **argv, |
| 390 | int argc) |
| 391 | { |
| 392 | mi_info_module_functions_or_variables (FUNCTIONS_DOMAIN, argv, argc); |
| 393 | } |
| 394 | |
| 395 | /* Implement -symbol-info-module-variables command. */ |
| 396 | |
| 397 | void |
| 398 | mi_cmd_symbol_info_module_variables (const char *command, char **argv, |
| 399 | int argc) |
| 400 | { |
| 401 | mi_info_module_functions_or_variables (VARIABLES_DOMAIN, argv, argc); |
| 402 | } |
| 403 | |
| 404 | /* Implement -symbol-inf-modules command. */ |
| 405 | |
| 406 | void |
| 407 | mi_cmd_symbol_info_modules (const char *command, char **argv, int argc) |
| 408 | { |
| 409 | size_t max_results = SIZE_MAX; |
| 410 | const char *regexp = nullptr; |
| 411 | |
| 412 | enum opt |
| 413 | { |
| 414 | NAME_REGEXP_OPT, MAX_RESULTS_OPT |
| 415 | }; |
| 416 | static const struct mi_opt opts[] = |
| 417 | { |
| 418 | {"-name", NAME_REGEXP_OPT, 1}, |
| 419 | {"-max-results", MAX_RESULTS_OPT, 1}, |
| 420 | { 0, 0, 0 } |
| 421 | }; |
| 422 | |
| 423 | int oind = 0; |
| 424 | char *oarg = nullptr; |
| 425 | |
| 426 | while (1) |
| 427 | { |
| 428 | int opt = mi_getopt ("-symbol-info-modules", argc, argv, opts, |
| 429 | &oind, &oarg); |
| 430 | if (opt < 0) |
| 431 | break; |
| 432 | switch ((enum opt) opt) |
| 433 | { |
| 434 | case NAME_REGEXP_OPT: |
| 435 | regexp = oarg; |
| 436 | break; |
| 437 | case MAX_RESULTS_OPT: |
| 438 | max_results = parse_max_results_option (oarg); |
| 439 | break; |
| 440 | } |
| 441 | } |
| 442 | |
| 443 | mi_symbol_info (MODULES_DOMAIN, regexp, nullptr, true, max_results); |
| 444 | } |
| 445 | |
| 446 | /* Implement -symbol-info-types command. */ |
| 447 | |
| 448 | void |
| 449 | mi_cmd_symbol_info_types (const char *command, char **argv, int argc) |
| 450 | { |
| 451 | size_t max_results = SIZE_MAX; |
| 452 | const char *regexp = nullptr; |
| 453 | |
| 454 | enum opt |
| 455 | { |
| 456 | NAME_REGEXP_OPT, MAX_RESULTS_OPT |
| 457 | }; |
| 458 | static const struct mi_opt opts[] = |
| 459 | { |
| 460 | {"-name", NAME_REGEXP_OPT, 1}, |
| 461 | {"-max-results", MAX_RESULTS_OPT, 1}, |
| 462 | { 0, 0, 0 } |
| 463 | }; |
| 464 | |
| 465 | int oind = 0; |
| 466 | char *oarg = nullptr; |
| 467 | |
| 468 | while (true) |
| 469 | { |
| 470 | int opt = mi_getopt ("-symbol-info-types", argc, argv, opts, |
| 471 | &oind, &oarg); |
| 472 | if (opt < 0) |
| 473 | break; |
| 474 | switch ((enum opt) opt) |
| 475 | { |
| 476 | case NAME_REGEXP_OPT: |
| 477 | regexp = oarg; |
| 478 | break; |
| 479 | case MAX_RESULTS_OPT: |
| 480 | max_results = parse_max_results_option (oarg); |
| 481 | break; |
| 482 | } |
| 483 | } |
| 484 | |
| 485 | mi_symbol_info (TYPES_DOMAIN, regexp, nullptr, true, max_results); |
| 486 | } |
| 487 | |
| 488 | /* Implement -symbol-info-variables command. */ |
| 489 | |
| 490 | void |
| 491 | mi_cmd_symbol_info_variables (const char *command, char **argv, int argc) |
| 492 | { |
| 493 | mi_info_functions_or_variables (VARIABLES_DOMAIN, argv, argc); |
| 494 | } |