]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/mi/mi-interp.c
Handle "info symbol" in Rust language mode
[thirdparty/binutils-gdb.git] / gdb / mi / mi-interp.c
1 /* MI Interpreter Definitions and Commands for GDB, the GNU debugger.
2
3 Copyright (C) 2002-2024 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20
21 #include "mi-interp.h"
22
23 #include "exceptions.h"
24 #include "interps.h"
25 #include "event-top.h"
26 #include "gdbsupport/event-loop.h"
27 #include "inferior.h"
28 #include "infrun.h"
29 #include "ui-out.h"
30 #include "ui.h"
31 #include "mi-main.h"
32 #include "mi-cmds.h"
33 #include "mi-out.h"
34 #include "mi-console.h"
35 #include "mi-common.h"
36 #include "observable.h"
37 #include "gdbthread.h"
38 #include "solist.h"
39 #include "objfiles.h"
40 #include "tracepoint.h"
41 #include "cli-out.h"
42 #include "thread-fsm.h"
43 #include "cli/cli-interp.h"
44 #include "gdbsupport/scope-exit.h"
45
46 /* These are the interpreter setup, etc. functions for the MI
47 interpreter. */
48
49 static void mi_execute_command_wrapper (const char *cmd);
50 static void mi_execute_command_input_handler
51 (gdb::unique_xmalloc_ptr<char> &&cmd);
52
53 /* These are hooks that we put in place while doing interpreter_exec
54 so we can report interesting things that happened "behind the MI's
55 back" in this command. */
56
57 static int mi_interp_query_hook (const char *ctlstr, va_list ap)
58 ATTRIBUTE_PRINTF (1, 0);
59
60 static void mi_insert_notify_hooks (void);
61 static void mi_remove_notify_hooks (void);
62
63 /* Display the MI prompt. */
64
65 static void
66 display_mi_prompt (struct mi_interp *mi)
67 {
68 struct ui *ui = current_ui;
69
70 gdb_puts ("(gdb) \n", mi->raw_stdout);
71 gdb_flush (mi->raw_stdout);
72 ui->prompt_state = PROMPTED;
73 }
74
75 void
76 mi_interp::on_command_error ()
77 {
78 display_mi_prompt (this);
79 }
80
81 void
82 mi_interp::init (bool top_level)
83 {
84 mi_interp *mi = this;
85
86 /* Store the current output channel, so that we can create a console
87 channel that encapsulates and prefixes all gdb_output-type bits
88 coming from the rest of the debugger. */
89 mi->raw_stdout = gdb_stdout;
90
91 /* Create MI console channels, each with a different prefix so they
92 can be distinguished. */
93 mi->out = new mi_console_file (mi->raw_stdout, "~", '"');
94 mi->err = new mi_console_file (mi->raw_stdout, "&", '"');
95 mi->log = mi->err;
96 mi->targ = new mi_console_file (mi->raw_stdout, "@", '"');
97 mi->event_channel = new mi_console_file (mi->raw_stdout, "=", 0);
98 mi->mi_uiout = mi_out_new (name ()).release ();
99 gdb_assert (mi->mi_uiout != nullptr);
100 mi->cli_uiout = new cli_ui_out (mi->out);
101
102 if (top_level)
103 {
104 /* The initial inferior is created before this function is called, so we
105 need to report it explicitly when initializing the top-level MI
106 interpreter.
107
108 This is also called when additional MI interpreters are added (using
109 the new-ui command), when multiple inferiors possibly exist, so we need
110 to use iteration to report all the inferiors. */
111
112 for (inferior *inf : all_inferiors ())
113 mi->on_inferior_added (inf);
114 }
115 }
116
117 void
118 mi_interp::resume ()
119 {
120 struct mi_interp *mi = this;
121 struct ui *ui = current_ui;
122
123 /* As per hack note in mi_interpreter_init, swap in the output
124 channels... */
125 gdb_setup_readline (0);
126
127 ui->call_readline = gdb_readline_no_editing_callback;
128 ui->input_handler = mi_execute_command_input_handler;
129
130 gdb_stdout = mi->out;
131 /* Route error and log output through the MI. */
132 gdb_stderr = mi->err;
133 gdb_stdlog = mi->log;
134 /* Route target output through the MI. */
135 gdb_stdtarg = mi->targ;
136
137 deprecated_show_load_progress = mi_load_progress;
138 }
139
140 void
141 mi_interp::suspend ()
142 {
143 gdb_disable_readline ();
144 }
145
146 void
147 mi_interp::exec (const char *command)
148 {
149 mi_execute_command_wrapper (command);
150 }
151
152 void
153 mi_cmd_interpreter_exec (const char *command, const char *const *argv,
154 int argc)
155 {
156 struct interp *interp_to_use;
157 int i;
158
159 if (argc < 2)
160 error (_("-interpreter-exec: "
161 "Usage: -interpreter-exec interp command"));
162
163 interp_to_use = interp_lookup (current_ui, argv[0]);
164 if (interp_to_use == NULL)
165 error (_("-interpreter-exec: could not find interpreter \"%s\""),
166 argv[0]);
167
168 /* Note that unlike the CLI version of this command, we don't
169 actually set INTERP_TO_USE as the current interpreter, as we
170 still want gdb_stdout, etc. to point at MI streams. */
171
172 /* Insert the MI out hooks, making sure to also call the
173 interpreter's hooks if it has any. */
174 /* KRS: We shouldn't need this... Events should be installed and
175 they should just ALWAYS fire something out down the MI
176 channel. */
177 mi_insert_notify_hooks ();
178
179 /* Now run the code. */
180
181 SCOPE_EXIT
182 {
183 mi_remove_notify_hooks ();
184 };
185
186 for (i = 1; i < argc; i++)
187 interp_exec (interp_to_use, argv[i]);
188 }
189
190 /* This inserts a number of hooks that are meant to produce
191 async-notify ("=") MI messages while running commands in another
192 interpreter using mi_interpreter_exec. The canonical use for this
193 is to allow access to the gdb CLI interpreter from within the MI,
194 while still producing MI style output when actions in the CLI
195 command change GDB's state. */
196
197 static void
198 mi_insert_notify_hooks (void)
199 {
200 deprecated_query_hook = mi_interp_query_hook;
201 }
202
203 static void
204 mi_remove_notify_hooks (void)
205 {
206 deprecated_query_hook = NULL;
207 }
208
209 static int
210 mi_interp_query_hook (const char *ctlstr, va_list ap)
211 {
212 return 1;
213 }
214
215 static void
216 mi_execute_command_wrapper (const char *cmd)
217 {
218 struct ui *ui = current_ui;
219
220 mi_execute_command (cmd, ui->instream == ui->stdin_stream);
221 }
222
223 void
224 mi_interp::on_sync_execution_done ()
225 {
226 /* If MI is sync, then output the MI prompt now, indicating we're
227 ready for further input. */
228 if (!mi_async_p ())
229 display_mi_prompt (this);
230 }
231
232 /* mi_execute_command_wrapper wrapper suitable for INPUT_HANDLER. */
233
234 static void
235 mi_execute_command_input_handler (gdb::unique_xmalloc_ptr<char> &&cmd)
236 {
237 struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
238 struct ui *ui = current_ui;
239
240 ui->prompt_state = PROMPT_NEEDED;
241
242 mi_execute_command_wrapper (cmd.get ());
243
244 /* Print a prompt, indicating we're ready for further input, unless
245 we just started a synchronous command. In that case, we're about
246 to go back to the event loop and will output the prompt in the
247 'synchronous_command_done' observer when the target next
248 stops. */
249 if (ui->prompt_state == PROMPT_NEEDED)
250 display_mi_prompt (mi);
251 }
252
253 void
254 mi_interp::pre_command_loop ()
255 {
256 struct mi_interp *mi = this;
257
258 /* Turn off 8 bit strings in quoted output. Any character with the
259 high bit set is printed using C's octal format. */
260 sevenbit_strings = 1;
261
262 /* Tell the world that we're alive. */
263 display_mi_prompt (mi);
264 }
265
266 void
267 mi_interp::on_new_thread (thread_info *t)
268 {
269 target_terminal::scoped_restore_terminal_state term_state;
270 target_terminal::ours_for_output ();
271
272 gdb_printf (this->event_channel, "thread-created,id=\"%d\",group-id=\"i%d\"",
273 t->global_num, t->inf->num);
274 gdb_flush (this->event_channel);
275 }
276
277 void
278 mi_interp::on_thread_exited (thread_info *t,
279 std::optional<ULONGEST> /* exit_code */,
280 int /* silent */)
281 {
282 target_terminal::scoped_restore_terminal_state term_state;
283 target_terminal::ours_for_output ();
284 gdb_printf (this->event_channel, "thread-exited,id=\"%d\",group-id=\"i%d\"",
285 t->global_num, t->inf->num);
286 gdb_flush (this->event_channel);
287 }
288
289 void
290 mi_interp::on_record_changed (inferior *inferior, int started,
291 const char *method, const char *format)
292 {
293 target_terminal::scoped_restore_terminal_state term_state;
294 target_terminal::ours_for_output ();
295
296 if (started)
297 {
298 if (format != NULL)
299 gdb_printf (this->event_channel,
300 "record-started,thread-group=\"i%d\","
301 "method=\"%s\",format=\"%s\"",
302 inferior->num, method, format);
303 else
304 gdb_printf (this->event_channel,
305 "record-started,thread-group=\"i%d\","
306 "method=\"%s\"",
307 inferior->num, method);
308 }
309 else
310 gdb_printf (this->event_channel,
311 "record-stopped,thread-group=\"i%d\"",
312 inferior->num);
313
314 gdb_flush (this->event_channel);
315 }
316
317 void
318 mi_interp::on_inferior_added (inferior *inf)
319 {
320 target_terminal::scoped_restore_terminal_state term_state;
321 target_terminal::ours_for_output ();
322
323 gdb_printf (this->event_channel, "thread-group-added,id=\"i%d\"", inf->num);
324 gdb_flush (this->event_channel);
325 }
326
327 void
328 mi_interp::on_inferior_appeared (inferior *inf)
329 {
330 target_terminal::scoped_restore_terminal_state term_state;
331 target_terminal::ours_for_output ();
332
333 gdb_printf (this->event_channel, "thread-group-started,id=\"i%d\",pid=\"%d\"",
334 inf->num, inf->pid);
335 gdb_flush (this->event_channel);
336 }
337
338 void
339 mi_interp::on_inferior_disappeared (inferior *inf)
340 {
341 target_terminal::scoped_restore_terminal_state term_state;
342 target_terminal::ours_for_output ();
343
344 if (inf->has_exit_code)
345 gdb_printf (this->event_channel,
346 "thread-group-exited,id=\"i%d\",exit-code=\"%s\"",
347 inf->num, int_string (inf->exit_code, 8, 0, 0, 1));
348 else
349 gdb_printf (this->event_channel,
350 "thread-group-exited,id=\"i%d\"", inf->num);
351
352 gdb_flush (this->event_channel);
353 }
354
355 void
356 mi_interp::on_inferior_removed (inferior *inf)
357 {
358 target_terminal::scoped_restore_terminal_state term_state;
359 target_terminal::ours_for_output ();
360
361 gdb_printf (this->event_channel, "thread-group-removed,id=\"i%d\"", inf->num);
362 gdb_flush (this->event_channel);
363 }
364
365 /* Observers for several run control events that print why the
366 inferior has stopped to both the MI event channel and to the MI
367 console. If the MI interpreter is not active, print nothing. */
368
369 void
370 mi_interp::on_signal_received (enum gdb_signal siggnal)
371 {
372 print_signal_received_reason (this->mi_uiout, siggnal);
373 print_signal_received_reason (this->cli_uiout, siggnal);
374 }
375
376 void
377 mi_interp::on_signal_exited (gdb_signal sig)
378 {
379 print_signal_exited_reason (this->mi_uiout, sig);
380 print_signal_exited_reason (this->cli_uiout, sig);
381 }
382
383 void
384 mi_interp::on_exited (int status)
385 {
386 print_exited_reason (this->mi_uiout, status);
387 print_exited_reason (this->cli_uiout, status);
388 }
389
390 void
391 mi_interp::on_no_history ()
392 {
393 print_no_history_reason (this->mi_uiout);
394 print_no_history_reason (this->cli_uiout);
395 }
396
397 void
398 mi_interp::on_normal_stop (struct bpstat *bs, int print_frame)
399 {
400 /* Since this can be called when CLI command is executing,
401 using cli interpreter, be sure to use MI uiout for output,
402 not the current one. */
403 ui_out *mi_uiout = this->interp_ui_out ();
404
405 if (print_frame)
406 {
407 thread_info *tp = inferior_thread ();
408
409 if (tp->thread_fsm () != nullptr
410 && tp->thread_fsm ()->finished_p ())
411 {
412 async_reply_reason reason
413 = tp->thread_fsm ()->async_reply_reason ();
414 mi_uiout->field_string ("reason", async_reason_lookup (reason));
415 }
416
417 interp *console_interp = interp_lookup (current_ui, INTERP_CONSOLE);
418
419 /* We only want to print the displays once, and we want it to
420 look just how it would on the console, so we use this to
421 decide whether the MI stop should include them. */
422 bool console_print = should_print_stop_to_console (console_interp, tp);
423 print_stop_event (mi_uiout, !console_print);
424
425 if (console_print)
426 print_stop_event (this->cli_uiout);
427
428 mi_uiout->field_signed ("thread-id", tp->global_num);
429 if (non_stop)
430 {
431 ui_out_emit_list list_emitter (mi_uiout, "stopped-threads");
432
433 mi_uiout->field_signed (NULL, tp->global_num);
434 }
435 else
436 mi_uiout->field_string ("stopped-threads", "all");
437
438 int core = target_core_of_thread (tp->ptid);
439 if (core != -1)
440 mi_uiout->field_signed ("core", core);
441 }
442
443 gdb_puts ("*stopped", this->raw_stdout);
444 mi_out_put (mi_uiout, this->raw_stdout);
445 mi_out_rewind (mi_uiout);
446 mi_print_timing_maybe (this->raw_stdout);
447 gdb_puts ("\n", this->raw_stdout);
448 gdb_flush (this->raw_stdout);
449 }
450
451 void
452 mi_interp::on_about_to_proceed ()
453 {
454 /* Suppress output while calling an inferior function. */
455
456 if (inferior_ptid != null_ptid)
457 {
458 struct thread_info *tp = inferior_thread ();
459
460 if (tp->control.in_infcall)
461 return;
462 }
463
464 this->mi_proceeded = 1;
465 }
466
467 /* When the element is non-zero, no MI notifications will be emitted in
468 response to the corresponding observers. */
469
470 struct mi_suppress_notification mi_suppress_notification =
471 {
472 0,
473 0,
474 0,
475 0,
476 };
477
478 void
479 mi_interp::on_traceframe_changed (int tfnum, int tpnum)
480 {
481 if (mi_suppress_notification.traceframe)
482 return;
483
484 target_terminal::scoped_restore_terminal_state term_state;
485 target_terminal::ours_for_output ();
486
487 if (tfnum >= 0)
488 gdb_printf (this->event_channel, "traceframe-changed,"
489 "num=\"%d\",tracepoint=\"%d\"",
490 tfnum, tpnum);
491 else
492 gdb_printf (this->event_channel, "traceframe-changed,end");
493
494 gdb_flush (this->event_channel);
495 }
496
497 void
498 mi_interp::on_tsv_created (const trace_state_variable *tsv)
499 {
500 target_terminal::scoped_restore_terminal_state term_state;
501 target_terminal::ours_for_output ();
502
503 gdb_printf (this->event_channel, "tsv-created,"
504 "name=\"%s\",initial=\"%s\"",
505 tsv->name.c_str (), plongest (tsv->initial_value));
506
507 gdb_flush (this->event_channel);
508 }
509
510 void
511 mi_interp::on_tsv_deleted (const trace_state_variable *tsv)
512 {
513 target_terminal::scoped_restore_terminal_state term_state;
514 target_terminal::ours_for_output ();
515
516 if (tsv != nullptr)
517 gdb_printf (this->event_channel, "tsv-deleted,name=\"%s\"",
518 tsv->name.c_str ());
519 else
520 gdb_printf (this->event_channel, "tsv-deleted");
521
522 gdb_flush (this->event_channel);
523 }
524
525 void
526 mi_interp::on_tsv_modified (const trace_state_variable *tsv)
527 {
528 ui_out *mi_uiout = this->interp_ui_out ();
529
530 target_terminal::scoped_restore_terminal_state term_state;
531 target_terminal::ours_for_output ();
532
533 gdb_printf (this->event_channel,
534 "tsv-modified");
535
536 ui_out_redirect_pop redir (mi_uiout, this->event_channel);
537
538 mi_uiout->field_string ("name", tsv->name);
539 mi_uiout->field_string ("initial",
540 plongest (tsv->initial_value));
541 if (tsv->value_known)
542 mi_uiout->field_string ("current", plongest (tsv->value));
543
544 gdb_flush (this->event_channel);
545 }
546
547 /* Print breakpoint BP on MI's event channel. */
548
549 static void
550 mi_print_breakpoint_for_event (struct mi_interp *mi, breakpoint *bp)
551 {
552 ui_out *mi_uiout = mi->interp_ui_out ();
553
554 /* We want the output from print_breakpoint to go to
555 mi->event_channel. One approach would be to just call
556 print_breakpoint, and then use mi_out_put to send the current
557 content of mi_uiout into mi->event_channel. However, that will
558 break if anything is output to mi_uiout prior to calling the
559 breakpoint_created notifications. So, we use
560 ui_out_redirect. */
561 ui_out_redirect_pop redir (mi_uiout, mi->event_channel);
562
563 try
564 {
565 scoped_restore restore_uiout
566 = make_scoped_restore (&current_uiout, mi_uiout);
567
568 print_breakpoint (bp);
569 }
570 catch (const gdb_exception_error &ex)
571 {
572 exception_print (gdb_stderr, ex);
573 }
574 }
575
576 void
577 mi_interp::on_breakpoint_created (breakpoint *b)
578 {
579 if (mi_suppress_notification.breakpoint)
580 return;
581
582 if (b->number <= 0)
583 return;
584
585 target_terminal::scoped_restore_terminal_state term_state;
586 target_terminal::ours_for_output ();
587
588 gdb_printf (this->event_channel, "breakpoint-created");
589 mi_print_breakpoint_for_event (this, b);
590
591 gdb_flush (this->event_channel);
592 }
593
594 void
595 mi_interp::on_breakpoint_deleted (breakpoint *b)
596 {
597 if (mi_suppress_notification.breakpoint)
598 return;
599
600 if (b->number <= 0)
601 return;
602
603 target_terminal::scoped_restore_terminal_state term_state;
604 target_terminal::ours_for_output ();
605
606 gdb_printf (this->event_channel, "breakpoint-deleted,id=\"%d\"", b->number);
607 gdb_flush (this->event_channel);
608 }
609
610 void
611 mi_interp::on_breakpoint_modified (breakpoint *b)
612 {
613 if (mi_suppress_notification.breakpoint)
614 return;
615
616 if (b->number <= 0)
617 return;
618
619 target_terminal::scoped_restore_terminal_state term_state;
620 target_terminal::ours_for_output ();
621 gdb_printf (this->event_channel, "breakpoint-modified");
622 mi_print_breakpoint_for_event (this, b);
623
624 gdb_flush (this->event_channel);
625 }
626
627 static void
628 mi_output_running (struct thread_info *thread)
629 {
630 SWITCH_THRU_ALL_UIS ()
631 {
632 struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
633
634 if (mi == NULL)
635 continue;
636
637 gdb_printf (mi->raw_stdout,
638 "*running,thread-id=\"%d\"\n",
639 thread->global_num);
640 }
641 }
642
643 /* Return true if there are multiple inferiors loaded. This is used
644 for backwards compatibility -- if there's only one inferior, output
645 "all", otherwise, output each resumed thread individually. */
646
647 static bool
648 multiple_inferiors_p ()
649 {
650 int count = 0;
651 for (inferior *inf ATTRIBUTE_UNUSED : all_non_exited_inferiors ())
652 {
653 count++;
654 if (count > 1)
655 return true;
656 }
657
658 return false;
659 }
660
661 static void
662 mi_on_resume_1 (struct mi_interp *mi,
663 process_stratum_target *targ, ptid_t ptid)
664 {
665 /* To cater for older frontends, emit ^running, but do it only once
666 per each command. We do it here, since at this point we know
667 that the target was successfully resumed, and in non-async mode,
668 we won't return back to MI interpreter code until the target
669 is done running, so delaying the output of "^running" until then
670 will make it impossible for frontend to know what's going on.
671
672 In future (MI3), we'll be outputting "^done" here. */
673 if (!mi->running_result_record_printed && mi->mi_proceeded)
674 {
675 gdb_printf (mi->raw_stdout, "%s^running\n",
676 mi->current_token ? mi->current_token : "");
677 }
678
679 /* Backwards compatibility. If doing a wildcard resume and there's
680 only one inferior, output "all", otherwise, output each resumed
681 thread individually. */
682 if ((ptid == minus_one_ptid || ptid.is_pid ())
683 && !multiple_inferiors_p ())
684 gdb_printf (mi->raw_stdout, "*running,thread-id=\"all\"\n");
685 else
686 for (thread_info *tp : all_non_exited_threads (targ, ptid))
687 mi_output_running (tp);
688
689 if (!mi->running_result_record_printed && mi->mi_proceeded)
690 {
691 mi->running_result_record_printed = 1;
692 /* This is what gdb used to do historically -- printing prompt
693 even if it cannot actually accept any input. This will be
694 surely removed for MI3, and may be removed even earlier. */
695 if (current_ui->prompt_state == PROMPT_BLOCKED)
696 gdb_puts ("(gdb) \n", mi->raw_stdout);
697 }
698 gdb_flush (mi->raw_stdout);
699 }
700
701 void
702 mi_interp::on_target_resumed (ptid_t ptid)
703 {
704 struct thread_info *tp = NULL;
705
706 process_stratum_target *target = current_inferior ()->process_target ();
707 if (ptid == minus_one_ptid || ptid.is_pid ())
708 tp = inferior_thread ();
709 else
710 tp = target->find_thread (ptid);
711
712 /* Suppress output while calling an inferior function. */
713 if (tp->control.in_infcall)
714 return;
715
716 target_terminal::scoped_restore_terminal_state term_state;
717 target_terminal::ours_for_output ();
718
719 mi_on_resume_1 (this, target, ptid);
720 }
721
722 /* See mi-interp.h. */
723
724 void
725 mi_output_solib_attribs (ui_out *uiout, const solib &solib)
726 {
727 gdbarch *gdbarch = current_inferior ()->arch ();
728
729 uiout->field_string ("id", solib.so_original_name);
730 uiout->field_string ("target-name", solib.so_original_name);
731 uiout->field_string ("host-name", solib.so_name);
732 uiout->field_signed ("symbols-loaded", solib.symbols_loaded);
733 if (!gdbarch_has_global_solist (current_inferior ()->arch ()))
734 uiout->field_fmt ("thread-group", "i%d", current_inferior ()->num);
735
736 ui_out_emit_list list_emitter (uiout, "ranges");
737 ui_out_emit_tuple tuple_emitter (uiout, NULL);
738 if (solib.addr_high != 0)
739 {
740 uiout->field_core_addr ("from", gdbarch, solib.addr_low);
741 uiout->field_core_addr ("to", gdbarch, solib.addr_high);
742 }
743 }
744
745 void
746 mi_interp::on_solib_loaded (const solib &solib)
747 {
748 ui_out *uiout = this->interp_ui_out ();
749
750 target_terminal::scoped_restore_terminal_state term_state;
751 target_terminal::ours_for_output ();
752
753 gdb_printf (this->event_channel, "library-loaded");
754
755 ui_out_redirect_pop redir (uiout, this->event_channel);
756
757 mi_output_solib_attribs (uiout, solib);
758
759 gdb_flush (this->event_channel);
760 }
761
762 void
763 mi_interp::on_solib_unloaded (const solib &solib)
764 {
765 ui_out *uiout = this->interp_ui_out ();
766
767 target_terminal::scoped_restore_terminal_state term_state;
768 target_terminal::ours_for_output ();
769
770 gdb_printf (this->event_channel, "library-unloaded");
771
772 ui_out_redirect_pop redir (uiout, this->event_channel);
773
774 uiout->field_string ("id", solib.so_original_name);
775 uiout->field_string ("target-name", solib.so_original_name);
776 uiout->field_string ("host-name", solib.so_name);
777 if (!gdbarch_has_global_solist (current_inferior ()->arch ()))
778 uiout->field_fmt ("thread-group", "i%d", current_inferior ()->num);
779
780 gdb_flush (this->event_channel);
781 }
782
783 void
784 mi_interp::on_param_changed (const char *param, const char *value)
785 {
786 if (mi_suppress_notification.cmd_param_changed)
787 return;
788
789 ui_out *mi_uiout = this->interp_ui_out ();
790
791 target_terminal::scoped_restore_terminal_state term_state;
792 target_terminal::ours_for_output ();
793
794 gdb_printf (this->event_channel, "cmd-param-changed");
795
796 ui_out_redirect_pop redir (mi_uiout, this->event_channel);
797
798 mi_uiout->field_string ("param", param);
799 mi_uiout->field_string ("value", value);
800
801 gdb_flush (this->event_channel);
802 }
803
804 void
805 mi_interp::on_memory_changed (inferior *inferior, CORE_ADDR memaddr,
806 ssize_t len, const bfd_byte *myaddr)
807 {
808 if (mi_suppress_notification.memory)
809 return;
810
811
812 ui_out *mi_uiout = this->interp_ui_out ();
813
814 target_terminal::scoped_restore_terminal_state term_state;
815 target_terminal::ours_for_output ();
816
817 gdb_printf (this->event_channel, "memory-changed");
818
819 ui_out_redirect_pop redir (mi_uiout, this->event_channel);
820
821 mi_uiout->field_fmt ("thread-group", "i%d", inferior->num);
822 mi_uiout->field_core_addr ("addr", current_inferior ()->arch (), memaddr);
823 mi_uiout->field_string ("len", hex_string (len));
824
825 /* Append 'type=code' into notification if MEMADDR falls in the range of
826 sections contain code. */
827 obj_section *sec = find_pc_section (memaddr);
828 if (sec != nullptr && sec->objfile != nullptr)
829 {
830 flagword flags = bfd_section_flags (sec->the_bfd_section);
831
832 if (flags & SEC_CODE)
833 mi_uiout->field_string ("type", "code");
834 }
835
836 gdb_flush (this->event_channel);
837 }
838
839 void
840 mi_interp::on_user_selected_context_changed (user_selected_what selection)
841 {
842 /* Don't send an event if we're responding to an MI command. */
843 if (mi_suppress_notification.user_selected_context)
844 return;
845
846 thread_info *tp = inferior_ptid != null_ptid ? inferior_thread () : nullptr;
847 ui_out *mi_uiout = this->interp_ui_out ();
848 ui_out_redirect_pop redirect_popper (mi_uiout, this->event_channel);
849
850 target_terminal::scoped_restore_terminal_state term_state;
851 target_terminal::ours_for_output ();
852
853 if (selection & USER_SELECTED_INFERIOR)
854 print_selected_inferior (this->cli_uiout);
855
856 if (tp != NULL
857 && (selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME)))
858 {
859 print_selected_thread_frame (this->cli_uiout, selection);
860
861 gdb_printf (this->event_channel, "thread-selected,id=\"%d\"",
862 tp->global_num);
863
864 if (tp->state != THREAD_RUNNING)
865 {
866 if (has_stack_frames ())
867 print_stack_frame_to_uiout (mi_uiout, get_selected_frame (NULL),
868 1, SRC_AND_LOC, 1);
869 }
870 }
871
872 gdb_flush (this->event_channel);
873 }
874
875 ui_out *
876 mi_interp::interp_ui_out ()
877 {
878 return this->mi_uiout;
879 }
880
881 /* Do MI-specific logging actions; save raw_stdout, and change all
882 the consoles to use the supplied ui-file(s). */
883
884 void
885 mi_interp::set_logging (ui_file_up logfile, bool logging_redirect,
886 bool debug_redirect)
887 {
888 struct mi_interp *mi = this;
889
890 if (logfile != NULL)
891 {
892 mi->saved_raw_stdout = mi->raw_stdout;
893
894 ui_file *logfile_p = logfile.get ();
895 mi->logfile_holder = std::move (logfile);
896
897 /* If something is not being redirected, then a tee containing both the
898 logfile and stdout. */
899 ui_file *tee = nullptr;
900 if (!logging_redirect || !debug_redirect)
901 {
902 tee = new tee_file (mi->raw_stdout, logfile_p);
903 mi->stdout_holder.reset (tee);
904 }
905
906 mi->raw_stdout = logging_redirect ? logfile_p : tee;
907 }
908 else
909 {
910 mi->logfile_holder.reset ();
911 mi->stdout_holder.reset ();
912 mi->raw_stdout = mi->saved_raw_stdout;
913 mi->saved_raw_stdout = nullptr;
914 }
915
916 mi->out->set_raw (mi->raw_stdout);
917 mi->err->set_raw (mi->raw_stdout);
918 mi->log->set_raw (mi->raw_stdout);
919 mi->targ->set_raw (mi->raw_stdout);
920 mi->event_channel->set_raw (mi->raw_stdout);
921 }
922
923 /* Factory for MI interpreters. */
924
925 static struct interp *
926 mi_interp_factory (const char *name)
927 {
928 return new mi_interp (name);
929 }
930
931 void _initialize_mi_interp ();
932 void
933 _initialize_mi_interp ()
934 {
935 /* The various interpreter levels. */
936 interp_factory_register (INTERP_MI2, mi_interp_factory);
937 interp_factory_register (INTERP_MI3, mi_interp_factory);
938 interp_factory_register (INTERP_MI4, mi_interp_factory);
939 interp_factory_register (INTERP_MI, mi_interp_factory);
940 }