]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/mi/mi-cmds.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / mi / mi-cmds.c
1 /* MI Command Set for GDB, the GNU debugger.
2 Copyright (C) 2000-2024 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 parse->parse_argv ();
53
54 if (parse->argv == nullptr)
55 error (_("Problem parsing arguments: %s %s"), parse->command.get (),
56 parse->args ());
57
58 this->m_argv_function (parse->command.get (), 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 std::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 }