xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/mi/mi-symbol-cmds.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* MI Command Set - symbol commands.
2    Copyright (C) 2003-2023 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 = s->compunit ()->objfile ()->arch ();
54 
55   ui_out_emit_list list_emitter (uiout, "lines");
56   if (s->linetable () != NULL && s->linetable ()->nitems > 0)
57     for (i = 0; i < s->linetable ()->nitems; i++)
58       {
59 	ui_out_emit_tuple tuple_emitter (uiout, NULL);
60 	uiout->field_core_addr ("pc", gdbarch, s->linetable ()->item[i].pc);
61 	uiout->field_signed ("line", s->linetable ()->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 (sym->line () != 0)
78     uiout->field_unsigned ("line", sym->line ());
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 (sym->type (), "", &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 = msymbol.objfile->arch ();
100   ui_out_emit_tuple tuple_emitter (uiout, NULL);
101 
102   uiout->field_core_addr ("address", gdbarch,
103 			  msymbol.value_address ());
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 = symbols[i].symbol->symtab ();
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 		  && symbols[i].symbol->symtab () == 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 = first_result_symbol->symtab ();
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 == iter->second.symbol->symtab ());
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 }
495