xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/mi/mi-cmds.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* MI Command Set for GDB, the GNU debugger.
2    Copyright (C) 2000-2023 Free Software Foundation, Inc.
3 
4    Contributed by Cygnus Solutions (a Red Hat company).
5 
6    This file is part of GDB.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20 
21 #include "defs.h"
22 #include "top.h"
23 #include "mi-cmds.h"
24 #include "mi-main.h"
25 #include "mi-parse.h"
26 #include <map>
27 #include <string>
28 
29 /* MI command table (built at run time). */
30 
31 static std::map<std::string, mi_command_up> mi_cmd_table;
32 
33 /* MI command with a pure MI implementation.  */
34 
35 struct mi_command_mi : public mi_command
36 {
37   /* Constructor.  For NAME and SUPPRESS_NOTIFICATION see mi_command
38      constructor, FUNC is the function called from do_invoke, which
39      implements this MI command.  */
40   mi_command_mi (const char *name, mi_cmd_argv_ftype func,
41                  int *suppress_notification)
42     : mi_command (name, suppress_notification),
43       m_argv_function (func)
44   {
45     gdb_assert (func != nullptr);
46   }
47 
48   /* Called when this MI command has been invoked, calls m_argv_function
49      with arguments contained within PARSE.  */
50   void invoke (struct mi_parse *parse) const override
51   {
52     mi_parse_argv (parse->args, parse);
53 
54     if (parse->argv == nullptr)
55       error (_("Problem parsing arguments: %s %s"), parse->command,
56 	     parse->args);
57 
58     this->m_argv_function (parse->command, parse->argv, parse->argc);
59   }
60 
61 private:
62 
63   /* The function that implements this MI command.  */
64   mi_cmd_argv_ftype *m_argv_function;
65 };
66 
67 /* MI command implemented on top of a CLI command.  */
68 
69 struct mi_command_cli : public mi_command
70 {
71   /* Constructor.  For NAME and SUPPRESS_NOTIFICATION see mi_command
72      constructor, CLI_NAME is the name of a CLI command that should be
73      invoked to implement this MI command.  If ARGS_P is true then any
74      arguments from entered by the user as part of the MI command line are
75      forwarded to CLI_NAME as its argument string, otherwise, if ARGS_P is
76      false, nullptr is send to CLI_NAME as its argument string.  */
77   mi_command_cli (const char *name, const char *cli_name, bool args_p,
78                   int *suppress_notification)
79     : mi_command (name, suppress_notification),
80       m_cli_name (cli_name),
81       m_args_p (args_p)
82   { /* Nothing.  */ }
83 
84   /* Called when this MI command has been invoked, calls the m_cli_name
85      CLI function.  In m_args_p is true then the argument string from
86      within PARSE is passed through to the CLI function, otherwise nullptr
87      is passed through to the CLI function as its argument string.  */
88   void invoke (struct mi_parse *parse) const override
89   {
90     const char *args = m_args_p ? parse->args : nullptr;
91     mi_execute_cli_command (m_cli_name, m_args_p, args);
92   }
93 
94 private:
95 
96   /* The name of the CLI command to execute.  */
97   const char *m_cli_name;
98 
99   /* Should we be passing an argument string to the m_cli_name function?  */
100   bool m_args_p;
101 };
102 
103 /* See mi-cmds.h.  */
104 
105 bool
106 insert_mi_cmd_entry (mi_command_up command)
107 {
108   gdb_assert (command != nullptr);
109 
110   const std::string &name = command->name ();
111 
112   if (mi_cmd_table.find (name) != mi_cmd_table.end ())
113     return false;
114 
115   mi_cmd_table[name] = std::move (command);
116   return true;
117 }
118 
119 /* See mi-cmds.h.  */
120 
121 bool
122 remove_mi_cmd_entry (const std::string &name)
123 {
124   if (mi_cmd_table.find (name) == mi_cmd_table.end ())
125     return false;
126 
127   mi_cmd_table.erase (name);
128   return true;
129 }
130 
131 /* See mi-cmds.h.  */
132 
133 void
134 remove_mi_cmd_entries (remove_mi_cmd_entries_ftype callback)
135 {
136   for (auto it = mi_cmd_table.cbegin (); it != mi_cmd_table.cend (); )
137     {
138       if (callback (it->second.get ()))
139 	it = mi_cmd_table.erase (it);
140       else
141 	++it;
142     }
143 }
144 
145 /* Create and register a new MI command with an MI specific implementation.
146    NAME must name an MI command that does not already exist, otherwise an
147    assertion will trigger.  */
148 
149 static void
150 add_mi_cmd_mi (const char *name, mi_cmd_argv_ftype function,
151 	       int *suppress_notification = nullptr)
152 {
153   mi_command_up command (new mi_command_mi (name, function,
154 					    suppress_notification));
155 
156   bool success = insert_mi_cmd_entry (std::move (command));
157   gdb_assert (success);
158 }
159 
160 /* Create and register a new MI command implemented on top of a CLI
161    command.  NAME must name an MI command that does not already exist,
162    otherwise an assertion will trigger.  */
163 
164 static void
165 add_mi_cmd_cli (const char *name, const char *cli_name, int args_p,
166 		int *suppress_notification = nullptr)
167 {
168   mi_command_up command (new mi_command_cli (name, cli_name, args_p != 0,
169 					     suppress_notification));
170 
171   bool success = insert_mi_cmd_entry (std::move (command));
172   gdb_assert (success);
173 }
174 
175 /* See mi-cmds.h.  */
176 
177 mi_command::mi_command (const char *name, int *suppress_notification)
178   : m_name (name),
179     m_suppress_notification (suppress_notification)
180 {
181   gdb_assert (m_name != nullptr && m_name[0] != '\0');
182 }
183 
184 /* See mi-cmds.h.  */
185 
186 gdb::optional<scoped_restore_tmpl<int>>
187 mi_command::do_suppress_notification () const
188 {
189   if (m_suppress_notification != nullptr)
190     return scoped_restore_tmpl<int> (m_suppress_notification, 1);
191   else
192     return {};
193 }
194 
195 /* Initialize the available MI commands.  */
196 
197 static void
198 add_builtin_mi_commands ()
199 {
200   add_mi_cmd_mi ("ada-task-info", mi_cmd_ada_task_info);
201   add_mi_cmd_mi ("add-inferior", mi_cmd_add_inferior);
202   add_mi_cmd_cli ("break-after", "ignore", 1,
203 		  &mi_suppress_notification.breakpoint);
204   add_mi_cmd_mi ("break-condition",mi_cmd_break_condition,
205 		  &mi_suppress_notification.breakpoint);
206   add_mi_cmd_mi ("break-commands", mi_cmd_break_commands,
207 		 &mi_suppress_notification.breakpoint);
208   add_mi_cmd_cli ("break-delete", "delete breakpoint", 1,
209 		  &mi_suppress_notification.breakpoint);
210   add_mi_cmd_cli ("break-disable", "disable breakpoint", 1,
211 		  &mi_suppress_notification.breakpoint);
212   add_mi_cmd_cli ("break-enable", "enable breakpoint", 1,
213 		  &mi_suppress_notification.breakpoint);
214   add_mi_cmd_cli ("break-info", "info break", 1);
215   add_mi_cmd_mi ("break-insert", mi_cmd_break_insert,
216 		 &mi_suppress_notification.breakpoint);
217   add_mi_cmd_mi ("dprintf-insert", mi_cmd_dprintf_insert,
218 		 &mi_suppress_notification.breakpoint);
219   add_mi_cmd_cli ("break-list", "info break", 0);
220   add_mi_cmd_mi ("break-passcount", mi_cmd_break_passcount,
221 		 &mi_suppress_notification.breakpoint);
222   add_mi_cmd_mi ("break-watch", mi_cmd_break_watch,
223 		 &mi_suppress_notification.breakpoint);
224   add_mi_cmd_mi ("catch-assert", mi_cmd_catch_assert,
225 		 &mi_suppress_notification.breakpoint);
226   add_mi_cmd_mi ("catch-exception", mi_cmd_catch_exception,
227 		 &mi_suppress_notification.breakpoint);
228   add_mi_cmd_mi ("catch-handlers", mi_cmd_catch_handlers,
229 		 &mi_suppress_notification.breakpoint);
230   add_mi_cmd_mi ("catch-load", mi_cmd_catch_load,
231 		 &mi_suppress_notification.breakpoint);
232   add_mi_cmd_mi ("catch-unload", mi_cmd_catch_unload,
233 		 &mi_suppress_notification.breakpoint);
234   add_mi_cmd_mi ("catch-throw", mi_cmd_catch_throw,
235                  &mi_suppress_notification.breakpoint),
236   add_mi_cmd_mi ("catch-rethrow", mi_cmd_catch_rethrow,
237                  &mi_suppress_notification.breakpoint),
238   add_mi_cmd_mi ("catch-catch", mi_cmd_catch_catch,
239                  &mi_suppress_notification.breakpoint),
240   add_mi_cmd_mi ("complete", mi_cmd_complete);
241   add_mi_cmd_mi ("data-disassemble", mi_cmd_disassemble);
242   add_mi_cmd_mi ("data-evaluate-expression", mi_cmd_data_evaluate_expression);
243   add_mi_cmd_mi ("data-list-changed-registers",
244 		 mi_cmd_data_list_changed_registers);
245   add_mi_cmd_mi ("data-list-register-names", mi_cmd_data_list_register_names);
246   add_mi_cmd_mi ("data-list-register-values",
247 		 mi_cmd_data_list_register_values);
248   add_mi_cmd_mi ("data-read-memory", mi_cmd_data_read_memory);
249   add_mi_cmd_mi ("data-read-memory-bytes", mi_cmd_data_read_memory_bytes);
250   add_mi_cmd_mi ("data-write-memory", mi_cmd_data_write_memory,
251 		 &mi_suppress_notification.memory);
252   add_mi_cmd_mi ("data-write-memory-bytes", mi_cmd_data_write_memory_bytes,
253 		 &mi_suppress_notification.memory);
254   add_mi_cmd_mi ("data-write-register-values",
255 		 mi_cmd_data_write_register_values);
256   add_mi_cmd_mi ("enable-timings", mi_cmd_enable_timings);
257   add_mi_cmd_mi ("enable-pretty-printing", mi_cmd_enable_pretty_printing);
258   add_mi_cmd_mi ("enable-frame-filters", mi_cmd_enable_frame_filters);
259   add_mi_cmd_mi ("environment-cd", mi_cmd_env_cd);
260   add_mi_cmd_mi ("environment-directory", mi_cmd_env_dir);
261   add_mi_cmd_mi ("environment-path", mi_cmd_env_path);
262   add_mi_cmd_mi ("environment-pwd", mi_cmd_env_pwd);
263   add_mi_cmd_cli ("exec-arguments", "set args", 1,
264 		  &mi_suppress_notification.cmd_param_changed);
265   add_mi_cmd_mi ("exec-continue", mi_cmd_exec_continue);
266   add_mi_cmd_mi ("exec-finish", mi_cmd_exec_finish);
267   add_mi_cmd_mi ("exec-jump", mi_cmd_exec_jump);
268   add_mi_cmd_mi ("exec-interrupt", mi_cmd_exec_interrupt);
269   add_mi_cmd_mi ("exec-next", mi_cmd_exec_next);
270   add_mi_cmd_mi ("exec-next-instruction", mi_cmd_exec_next_instruction);
271   add_mi_cmd_mi ("exec-return", mi_cmd_exec_return);
272   add_mi_cmd_mi ("exec-run", mi_cmd_exec_run);
273   add_mi_cmd_mi ("exec-step", mi_cmd_exec_step);
274   add_mi_cmd_mi ("exec-step-instruction", mi_cmd_exec_step_instruction);
275   add_mi_cmd_cli ("exec-until", "until", 1);
276   add_mi_cmd_cli ("file-exec-and-symbols", "file", 1);
277   add_mi_cmd_cli ("file-exec-file", "exec-file", 1);
278   add_mi_cmd_mi ("file-list-exec-source-file",
279 		 mi_cmd_file_list_exec_source_file);
280   add_mi_cmd_mi ("file-list-exec-source-files",
281 		 mi_cmd_file_list_exec_source_files);
282   add_mi_cmd_mi ("file-list-shared-libraries",
283      mi_cmd_file_list_shared_libraries),
284   add_mi_cmd_cli ("file-symbol-file", "symbol-file", 1);
285   add_mi_cmd_mi ("fix-breakpoint-script-output",
286 		 mi_cmd_fix_breakpoint_script_output),
287   add_mi_cmd_mi ("fix-multi-location-breakpoint-output",
288 		 mi_cmd_fix_multi_location_breakpoint_output),
289   add_mi_cmd_mi ("gdb-exit", mi_cmd_gdb_exit);
290   add_mi_cmd_cli ("gdb-set", "set", 1,
291 		  &mi_suppress_notification.cmd_param_changed);
292   add_mi_cmd_cli ("gdb-show", "show", 1);
293   add_mi_cmd_cli ("gdb-version", "show version", 0);
294   add_mi_cmd_mi ("inferior-tty-set", mi_cmd_inferior_tty_set);
295   add_mi_cmd_mi ("inferior-tty-show", mi_cmd_inferior_tty_show);
296   add_mi_cmd_mi ("info-ada-exceptions", mi_cmd_info_ada_exceptions);
297   add_mi_cmd_mi ("info-gdb-mi-command", mi_cmd_info_gdb_mi_command);
298   add_mi_cmd_mi ("info-os", mi_cmd_info_os);
299   add_mi_cmd_mi ("interpreter-exec", mi_cmd_interpreter_exec);
300   add_mi_cmd_mi ("list-features", mi_cmd_list_features);
301   add_mi_cmd_mi ("list-target-features", mi_cmd_list_target_features);
302   add_mi_cmd_mi ("list-thread-groups", mi_cmd_list_thread_groups);
303   add_mi_cmd_mi ("remove-inferior", mi_cmd_remove_inferior);
304   add_mi_cmd_mi ("stack-info-depth", mi_cmd_stack_info_depth);
305   add_mi_cmd_mi ("stack-info-frame", mi_cmd_stack_info_frame);
306   add_mi_cmd_mi ("stack-list-arguments", mi_cmd_stack_list_args);
307   add_mi_cmd_mi ("stack-list-frames", mi_cmd_stack_list_frames);
308   add_mi_cmd_mi ("stack-list-locals", mi_cmd_stack_list_locals);
309   add_mi_cmd_mi ("stack-list-variables", mi_cmd_stack_list_variables);
310   add_mi_cmd_mi ("stack-select-frame", mi_cmd_stack_select_frame,
311 		 &mi_suppress_notification.user_selected_context);
312   add_mi_cmd_mi ("symbol-list-lines", mi_cmd_symbol_list_lines);
313   add_mi_cmd_mi ("symbol-info-functions", mi_cmd_symbol_info_functions);
314   add_mi_cmd_mi ("symbol-info-variables", mi_cmd_symbol_info_variables);
315   add_mi_cmd_mi ("symbol-info-types", mi_cmd_symbol_info_types);
316   add_mi_cmd_mi ("symbol-info-modules", mi_cmd_symbol_info_modules);
317   add_mi_cmd_mi ("symbol-info-module-functions",
318                  mi_cmd_symbol_info_module_functions);
319   add_mi_cmd_mi ("symbol-info-module-variables",
320                  mi_cmd_symbol_info_module_variables);
321   add_mi_cmd_cli ("target-attach", "attach", 1);
322   add_mi_cmd_mi ("target-detach", mi_cmd_target_detach);
323   add_mi_cmd_cli ("target-disconnect", "disconnect", 0);
324   add_mi_cmd_cli ("target-download", "load", 1);
325   add_mi_cmd_mi ("target-file-delete", mi_cmd_target_file_delete);
326   add_mi_cmd_mi ("target-file-get", mi_cmd_target_file_get);
327   add_mi_cmd_mi ("target-file-put", mi_cmd_target_file_put);
328   add_mi_cmd_mi ("target-flash-erase", mi_cmd_target_flash_erase);
329   add_mi_cmd_cli ("target-select", "target", 1);
330   add_mi_cmd_mi ("thread-info", mi_cmd_thread_info);
331   add_mi_cmd_mi ("thread-list-ids", mi_cmd_thread_list_ids);
332   add_mi_cmd_mi ("thread-select", mi_cmd_thread_select,
333 		 &mi_suppress_notification.user_selected_context);
334   add_mi_cmd_mi ("trace-define-variable", mi_cmd_trace_define_variable);
335   add_mi_cmd_mi ("trace-find", mi_cmd_trace_find,
336 		 &mi_suppress_notification.traceframe);
337   add_mi_cmd_mi ("trace-frame-collected", mi_cmd_trace_frame_collected);
338   add_mi_cmd_mi ("trace-list-variables", mi_cmd_trace_list_variables);
339   add_mi_cmd_mi ("trace-save", mi_cmd_trace_save);
340   add_mi_cmd_mi ("trace-start", mi_cmd_trace_start);
341   add_mi_cmd_mi ("trace-status", mi_cmd_trace_status);
342   add_mi_cmd_mi ("trace-stop", mi_cmd_trace_stop);
343   add_mi_cmd_mi ("var-assign", mi_cmd_var_assign);
344   add_mi_cmd_mi ("var-create", mi_cmd_var_create);
345   add_mi_cmd_mi ("var-delete", mi_cmd_var_delete);
346   add_mi_cmd_mi ("var-evaluate-expression", mi_cmd_var_evaluate_expression);
347   add_mi_cmd_mi ("var-info-path-expression", mi_cmd_var_info_path_expression);
348   add_mi_cmd_mi ("var-info-expression", mi_cmd_var_info_expression);
349   add_mi_cmd_mi ("var-info-num-children", mi_cmd_var_info_num_children);
350   add_mi_cmd_mi ("var-info-type", mi_cmd_var_info_type);
351   add_mi_cmd_mi ("var-list-children", mi_cmd_var_list_children);
352   add_mi_cmd_mi ("var-set-format", mi_cmd_var_set_format);
353   add_mi_cmd_mi ("var-set-frozen", mi_cmd_var_set_frozen);
354   add_mi_cmd_mi ("var-set-update-range", mi_cmd_var_set_update_range);
355   add_mi_cmd_mi ("var-set-visualizer", mi_cmd_var_set_visualizer);
356   add_mi_cmd_mi ("var-show-attributes", mi_cmd_var_show_attributes);
357   add_mi_cmd_mi ("var-show-format", mi_cmd_var_show_format);
358   add_mi_cmd_mi ("var-update", mi_cmd_var_update);
359 }
360 
361 /* See mi-cmds.h.  */
362 
363 mi_command *
364 mi_cmd_lookup (const char *command)
365 {
366   gdb_assert (command != nullptr);
367 
368   auto it = mi_cmd_table.find (command);
369   if (it == mi_cmd_table.end ())
370     return nullptr;
371   return it->second.get ();
372 }
373 
374 void _initialize_mi_cmds ();
375 void
376 _initialize_mi_cmds ()
377 {
378   add_builtin_mi_commands ();
379 }
380