X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fmi%2Fmi-interp.c;h=556f446c2e19ef2f49725135f61ea9981dbe9809;hb=5b6d1e4fa4fc6827c7b3f0e99ff120dfa14d65d2;hp=6b6d8f06222865e3073e90a39eb077bd203f4b9a;hpb=56496dd4d6519c26bb375a78588bf56b28b13512;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index 6b6d8f0622..556f446c2e 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -1,6 +1,6 @@ /* MI Interpreter Definitions and Commands for GDB, the GNU debugger. - Copyright (C) 2002-2017 Free Software Foundation, Inc. + Copyright (C) 2002-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -18,6 +18,9 @@ along with this program. If not, see . */ #include "defs.h" + +#include "mi-interp.h" + #include "interps.h" #include "event-top.h" #include "event-loop.h" @@ -30,21 +33,22 @@ #include "mi-out.h" #include "mi-console.h" #include "mi-common.h" -#include "observer.h" +#include "observable.h" #include "gdbthread.h" #include "solist.h" -#include "gdb.h" #include "objfiles.h" #include "tracepoint.h" #include "cli-out.h" #include "thread-fsm.h" #include "cli/cli-interp.h" +#include "gdbsupport/scope-exit.h" /* These are the interpreter setup, etc. functions for the MI interpreter. */ static void mi_execute_command_wrapper (const char *cmd); -static void mi_execute_command_input_handler (char *cmd); +static void mi_execute_command_input_handler + (gdb::unique_xmalloc_ptr &&cmd); /* These are hooks that we put in place while doing interpreter_exec so we can report interesting things that happened "behind the MI's @@ -107,17 +111,13 @@ display_mi_prompt (struct mi_interp *mi) static struct mi_interp * as_mi_interp (struct interp *interp) { - if (interp_ui_out (interp)->is_mi_like_p ()) - return (struct mi_interp *) interp; - return NULL; + return dynamic_cast (interp); } void mi_interp::init (bool top_level) { mi_interp *mi = this; - const char *name; - int mi_version; /* Store the current output channel, so that we can create a console channel that encapsulates and prefixes all gdb_output-type bits @@ -131,22 +131,8 @@ mi_interp::init (bool top_level) mi->log = mi->err; mi->targ = new mi_console_file (mi->raw_stdout, "@", '"'); mi->event_channel = new mi_console_file (mi->raw_stdout, "=", 0); - - name = interp_name (this); - /* INTERP_MI selects the most recent released version. "mi2" was - released as part of GDB 6.0. */ - if (strcmp (name, INTERP_MI) == 0) - mi_version = 2; - else if (strcmp (name, INTERP_MI1) == 0) - mi_version = 1; - else if (strcmp (name, INTERP_MI2) == 0) - mi_version = 2; - else if (strcmp (name, INTERP_MI3) == 0) - mi_version = 3; - else - gdb_assert_not_reached ("unhandled MI version"); - - mi->mi_uiout = mi_out_new (mi_version); + mi->mi_uiout = mi_out_new (name ()); + gdb_assert (mi->mi_uiout != nullptr); mi->cli_uiout = cli_out_new (mi->out); if (top_level) @@ -198,7 +184,7 @@ gdb_exception mi_interp::exec (const char *command) { mi_execute_command_wrapper (command); - return exception_none; + return gdb_exception (); } void @@ -229,22 +215,18 @@ mi_cmd_interpreter_exec (const char *command, char **argv, int argc) /* Now run the code. */ - std::string mi_error_message; + SCOPE_EXIT + { + mi_remove_notify_hooks (); + }; + for (i = 1; i < argc; i++) { struct gdb_exception e = interp_exec (interp_to_use, argv[i]); if (e.reason < 0) - { - mi_error_message = e.message; - break; - } + error ("%s", e.what ()); } - - mi_remove_notify_hooks (); - - if (!mi_error_message.empty ()) - error ("%s", mi_error_message.c_str ()); } /* This inserts a number of hooks that are meant to produce @@ -285,7 +267,6 @@ mi_execute_command_wrapper (const char *cmd) static void mi_on_sync_execution_done (void) { - struct ui *ui = current_ui; struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); if (mi == NULL) @@ -300,14 +281,14 @@ mi_on_sync_execution_done (void) /* mi_execute_command_wrapper wrapper suitable for INPUT_HANDLER. */ static void -mi_execute_command_input_handler (char *cmd) +mi_execute_command_input_handler (gdb::unique_xmalloc_ptr &&cmd) { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); struct ui *ui = current_ui; ui->prompt_state = PROMPT_NEEDED; - mi_execute_command_wrapper (cmd); + mi_execute_command_wrapper (cmd.get ()); /* Print a prompt, indicating we're ready for further input, unless we just started a synchronous command. In that case, we're about @@ -334,27 +315,20 @@ mi_interp::pre_command_loop () static void mi_new_thread (struct thread_info *t) { - struct inferior *inf = find_inferior_ptid (t->ptid); - - gdb_assert (inf); - SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "thread-created,id=\"%d\",group-id=\"i%d\"", - t->global_num, inf->num); + t->global_num, t->inf->num); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -367,19 +341,16 @@ mi_thread_exit (struct thread_info *t, int silent) SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "thread-exited,id=\"%d\",group-id=\"i%d\"", t->global_num, t->inf->num); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -392,13 +363,12 @@ mi_record_changed (struct inferior *inferior, int started, const char *method, SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); if (started) { @@ -425,8 +395,6 @@ mi_record_changed (struct inferior *inferior, int started, const char *method, } gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -437,7 +405,6 @@ mi_inferior_added (struct inferior *inf) { struct interp *interp; struct mi_interp *mi; - struct cleanup *old_chain; /* We'll be called once for the initial inferior, before the top level interpreter is set. */ @@ -449,15 +416,13 @@ mi_inferior_added (struct inferior *inf) if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "thread-group-added,id=\"i%d\"", inf->num); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -467,19 +432,17 @@ mi_inferior_appeared (struct inferior *inf) SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "thread-group-started,id=\"i%d\",pid=\"%d\"", inf->num, inf->pid); gdb_flush (mi->event_channel); - do_cleanups (old_chain); } } @@ -489,13 +452,12 @@ mi_inferior_exit (struct inferior *inf) SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); if (inf->has_exit_code) fprintf_unfiltered (mi->event_channel, @@ -506,7 +468,6 @@ mi_inferior_exit (struct inferior *inf) "thread-group-exited,id=\"i%d\"", inf->num); gdb_flush (mi->event_channel); - do_cleanups (old_chain); } } @@ -516,20 +477,17 @@ mi_inferior_removed (struct inferior *inf) SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "thread-group-removed,id=\"i%d\"", inf->num); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -554,7 +512,7 @@ find_mi_interp (void) } /* Observers for several run control events that print why the - inferior has stopped to both the the MI event channel and to the MI + inferior has stopped to both the MI event channel and to the MI console. If the MI interpreter is not active, print nothing. */ /* Observer for the signal_received notification. */ @@ -648,7 +606,7 @@ mi_on_normal_stop_1 (struct bpstats *bs, int print_frame) /* Since this can be called when CLI command is executing, using cli interpreter, be sure to use MI uiout for output, not the current one. */ - struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); + struct ui_out *mi_uiout = top_level_interpreter ()->interp_ui_out (); struct mi_interp *mi = (struct mi_interp *) top_level_interpreter (); if (print_frame) @@ -660,32 +618,37 @@ mi_on_normal_stop_1 (struct bpstats *bs, int print_frame) tp = inferior_thread (); if (tp->thread_fsm != NULL - && thread_fsm_finished_p (tp->thread_fsm)) + && tp->thread_fsm->finished_p ()) { enum async_reply_reason reason; - reason = thread_fsm_async_reply_reason (tp->thread_fsm); + reason = tp->thread_fsm->async_reply_reason (); mi_uiout->field_string ("reason", async_reason_lookup (reason)); } - print_stop_event (mi_uiout); console_interp = interp_lookup (current_ui, INTERP_CONSOLE); - if (should_print_stop_to_console (console_interp, tp)) + /* We only want to print the displays once, and we want it to + look just how it would on the console, so we use this to + decide whether the MI stop should include them. */ + bool console_print = should_print_stop_to_console (console_interp, tp); + print_stop_event (mi_uiout, !console_print); + + if (console_print) print_stop_event (mi->cli_uiout); - mi_uiout->field_int ("thread-id", tp->global_num); + mi_uiout->field_signed ("thread-id", tp->global_num); if (non_stop) { ui_out_emit_list list_emitter (mi_uiout, "stopped-threads"); - mi_uiout->field_int (NULL, tp->global_num); + mi_uiout->field_signed (NULL, tp->global_num); } else mi_uiout->field_string ("stopped-threads", "all"); - core = target_core_of_thread (inferior_ptid); + core = target_core_of_thread (tp->ptid); if (core != -1) - mi_uiout->field_int ("core", core); + mi_uiout->field_signed ("core", core); } fputs_unfiltered ("*stopped", mi->raw_stdout); @@ -713,7 +676,7 @@ mi_about_to_proceed (void) { /* Suppress output while calling an inferior function. */ - if (!ptid_equal (inferior_ptid, null_ptid)) + if (inferior_ptid != null_ptid) { struct thread_info *tp = inferior_thread (); @@ -746,13 +709,12 @@ mi_traceframe_changed (int tfnum, int tpnum) SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); if (tfnum >= 0) fprintf_unfiltered (mi->event_channel, "traceframe-changed," @@ -762,8 +724,6 @@ mi_traceframe_changed (int tfnum, int tpnum) fprintf_unfiltered (mi->event_channel, "traceframe-changed,end"); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -775,21 +735,18 @@ mi_tsv_created (const struct trace_state_variable *tsv) SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "tsv-created," "name=\"%s\",initial=\"%s\"\n", - tsv->name, plongest (tsv->initial_value)); + tsv->name.c_str (), plongest (tsv->initial_value)); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -801,23 +758,20 @@ mi_tsv_deleted (const struct trace_state_variable *tsv) SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); if (tsv != NULL) fprintf_unfiltered (mi->event_channel, "tsv-deleted," - "name=\"%s\"\n", tsv->name); + "name=\"%s\"\n", tsv->name.c_str ()); else fprintf_unfiltered (mi->event_channel, "tsv-deleted\n"); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -830,15 +784,14 @@ mi_tsv_modified (const struct trace_state_variable *tsv) { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); struct ui_out *mi_uiout; - struct cleanup *old_chain; if (mi == NULL) continue; - mi_uiout = interp_ui_out (top_level_interpreter ()); + mi_uiout = top_level_interpreter ()->interp_ui_out (); - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "tsv-modified"); @@ -854,9 +807,38 @@ mi_tsv_modified (const struct trace_state_variable *tsv) mi_uiout->redirect (NULL); gdb_flush (mi->event_channel); + } +} + +/* Print breakpoint BP on MI's event channel. */ - do_cleanups (old_chain); +static void +mi_print_breakpoint_for_event (struct mi_interp *mi, breakpoint *bp) +{ + ui_out *mi_uiout = mi->interp_ui_out (); + + /* We want the output from print_breakpoint to go to + mi->event_channel. One approach would be to just call + print_breakpoint, and then use mi_out_put to send the current + content of mi_uiout into mi->event_channel. However, that will + break if anything is output to mi_uiout prior to calling the + breakpoint_created notifications. So, we use + ui_out_redirect. */ + mi_uiout->redirect (mi->event_channel); + + try + { + scoped_restore restore_uiout + = make_scoped_restore (¤t_uiout, mi_uiout); + + print_breakpoint (bp); } + catch (const gdb_exception &ex) + { + exception_print (gdb_stderr, ex); + } + + mi_uiout->redirect (NULL); } /* Emit notification about a created breakpoint. */ @@ -873,41 +855,18 @@ mi_breakpoint_created (struct breakpoint *b) SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct ui_out *mi_uiout; - struct cleanup *old_chain; if (mi == NULL) continue; - mi_uiout = interp_ui_out (top_level_interpreter ()); - - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "breakpoint-created"); - /* We want the output from gdb_breakpoint_query to go to - mi->event_channel. One approach would be to just call - gdb_breakpoint_query, and then use mi_out_put to send the current - content of mi_uiout into mi->event_channel. However, that will - break if anything is output to mi_uiout prior to calling the - breakpoint_created notifications. So, we use - ui_out_redirect. */ - mi_uiout->redirect (mi->event_channel); - TRY - { - gdb_breakpoint_query (mi_uiout, b->number, NULL); - } - CATCH (e, RETURN_MASK_ERROR) - { - } - END_CATCH - - mi_uiout->redirect (NULL); + mi_print_breakpoint_for_event (mi, b); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -925,20 +884,17 @@ mi_breakpoint_deleted (struct breakpoint *b) SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "breakpoint-deleted,id=\"%d\"", b->number); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -956,45 +912,23 @@ mi_breakpoint_modified (struct breakpoint *b) SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "breakpoint-modified"); - /* We want the output from gdb_breakpoint_query to go to - mi->event_channel. One approach would be to just call - gdb_breakpoint_query, and then use mi_out_put to send the current - content of mi_uiout into mi->event_channel. However, that will - break if anything is output to mi_uiout prior to calling the - breakpoint_created notifications. So, we use - ui_out_redirect. */ - mi->mi_uiout->redirect (mi->event_channel); - TRY - { - gdb_breakpoint_query (mi->mi_uiout, b->number, NULL); - } - CATCH (e, RETURN_MASK_ERROR) - { - } - END_CATCH - - mi->mi_uiout->redirect (NULL); + mi_print_breakpoint_for_event (mi, b); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } -static int -mi_output_running_pid (struct thread_info *info, void *arg) +static void +mi_output_running (struct thread_info *thread) { - ptid_t *ptid = (ptid_t *) arg; - SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); @@ -1002,29 +936,33 @@ mi_output_running_pid (struct thread_info *info, void *arg) if (mi == NULL) continue; - if (ptid_get_pid (*ptid) == ptid_get_pid (info->ptid)) - fprintf_unfiltered (mi->raw_stdout, - "*running,thread-id=\"%d\"\n", - info->global_num); + fprintf_unfiltered (mi->raw_stdout, + "*running,thread-id=\"%d\"\n", + thread->global_num); } - - return 0; } -static int -mi_inferior_count (struct inferior *inf, void *arg) +/* Return true if there are multiple inferiors loaded. This is used + for backwards compatibility -- if there's only one inferior, output + "all", otherwise, output each resumed thread individually. */ + +static bool +multiple_inferiors_p () { - if (inf->pid != 0) + int count = 0; + for (inferior *inf ATTRIBUTE_UNUSED : all_non_exited_inferiors ()) { - int *count_p = (int *) arg; - (*count_p)++; + count++; + if (count > 1) + return true; } - return 0; + return false; } static void -mi_on_resume_1 (struct mi_interp *mi, ptid_t ptid) +mi_on_resume_1 (struct mi_interp *mi, + process_stratum_target *targ, ptid_t ptid) { /* To cater for older frontends, emit ^running, but do it only once per each command. We do it here, since at this point we know @@ -1040,30 +978,15 @@ mi_on_resume_1 (struct mi_interp *mi, ptid_t ptid) current_token ? current_token : ""); } - if (ptid_get_pid (ptid) == -1) + /* Backwards compatibility. If doing a wildcard resume and there's + only one inferior, output "all", otherwise, output each resumed + thread individually. */ + if ((ptid == minus_one_ptid || ptid.is_pid ()) + && !multiple_inferiors_p ()) fprintf_unfiltered (mi->raw_stdout, "*running,thread-id=\"all\"\n"); - else if (ptid_is_pid (ptid)) - { - int count = 0; - - /* Backwards compatibility. If there's only one inferior, - output "all", otherwise, output each resumed thread - individually. */ - iterate_over_inferiors (mi_inferior_count, &count); - - if (count == 1) - fprintf_unfiltered (mi->raw_stdout, "*running,thread-id=\"all\"\n"); - else - iterate_over_threads (mi_output_running_pid, &ptid); - } else - { - struct thread_info *ti = find_thread_ptid (ptid); - - gdb_assert (ti); - fprintf_unfiltered (mi->raw_stdout, "*running,thread-id=\"%d\"\n", - ti->global_num); - } + for (thread_info *tp : all_non_exited_threads (targ, ptid)) + mi_output_running (tp); if (!running_result_record_printed && mi_proceeded) { @@ -1082,10 +1005,11 @@ mi_on_resume (ptid_t ptid) { struct thread_info *tp = NULL; - if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid)) + process_stratum_target *target = current_inferior ()->process_target (); + if (ptid == minus_one_ptid || ptid.is_pid ()) tp = inferior_thread (); else - tp = find_thread_ptid (ptid); + tp = find_thread_ptid (target, ptid); /* Suppress output while calling an inferior function. */ if (tp->control.in_infcall) @@ -1094,17 +1018,14 @@ mi_on_resume (ptid_t ptid) SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); - struct cleanup *old_chain; if (mi == NULL) continue; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); - - mi_on_resume_1 (mi, ptid); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); - do_cleanups (old_chain); + mi_on_resume_1 (mi, target, ptid); } } @@ -1118,7 +1039,7 @@ mi_output_solib_attribs (ui_out *uiout, struct so_list *solib) uiout->field_string ("id", solib->so_original_name); uiout->field_string ("target-name", solib->so_original_name); uiout->field_string ("host-name", solib->so_name); - uiout->field_int ("symbols-loaded", solib->symbols_loaded); + uiout->field_signed ("symbols-loaded", solib->symbols_loaded); if (!gdbarch_has_global_solist (target_gdbarch ())) uiout->field_fmt ("thread-group", "i%d", current_inferior ()->num); @@ -1138,15 +1059,14 @@ mi_solib_loaded (struct so_list *solib) { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); struct ui_out *uiout; - struct cleanup *old_chain; if (mi == NULL) continue; - uiout = interp_ui_out (top_level_interpreter ()); + uiout = top_level_interpreter ()->interp_ui_out (); - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "library-loaded"); @@ -1157,8 +1077,6 @@ mi_solib_loaded (struct so_list *solib) uiout->redirect (NULL); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -1169,15 +1087,14 @@ mi_solib_unloaded (struct so_list *solib) { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); struct ui_out *uiout; - struct cleanup *old_chain; if (mi == NULL) continue; - uiout = interp_ui_out (top_level_interpreter ()); + uiout = top_level_interpreter ()->interp_ui_out (); - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "library-unloaded"); @@ -1194,8 +1111,6 @@ mi_solib_unloaded (struct so_list *solib) uiout->redirect (NULL); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -1211,15 +1126,14 @@ mi_command_param_changed (const char *param, const char *value) { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); struct ui_out *mi_uiout; - struct cleanup *old_chain; if (mi == NULL) continue; - mi_uiout = interp_ui_out (top_level_interpreter ()); + mi_uiout = top_level_interpreter ()->interp_ui_out (); - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "cmd-param-changed"); @@ -1231,8 +1145,6 @@ mi_command_param_changed (const char *param, const char *value) mi_uiout->redirect (NULL); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -1250,15 +1162,14 @@ mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr, struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); struct ui_out *mi_uiout; struct obj_section *sec; - struct cleanup *old_chain; if (mi == NULL) continue; - mi_uiout = interp_ui_out (top_level_interpreter ()); + mi_uiout = top_level_interpreter ()->interp_ui_out (); - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "memory-changed"); @@ -1266,15 +1177,14 @@ mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr, mi_uiout->field_fmt ("thread-group", "i%d", inferior->num); mi_uiout->field_core_addr ("addr", target_gdbarch (), memaddr); - mi_uiout->field_fmt ("len", "%s", hex_string (len)); + mi_uiout->field_string ("len", hex_string (len)); /* Append 'type=code' into notification if MEMADDR falls in the range of sections contain code. */ sec = find_pc_section (memaddr); if (sec != NULL && sec->objfile != NULL) { - flagword flags = bfd_get_section_flags (sec->objfile->obfd, - sec->the_bfd_section); + flagword flags = bfd_section_flags (sec->the_bfd_section); if (flags & SEC_CODE) mi_uiout->field_string ("type", "code"); @@ -1283,8 +1193,6 @@ mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr, mi_uiout->redirect (NULL); gdb_flush (mi->event_channel); - - do_cleanups (old_chain); } } @@ -1300,25 +1208,26 @@ mi_user_selected_context_changed (user_selected_what selection) if (mi_suppress_notification.user_selected_context) return; - tp = find_thread_ptid (inferior_ptid); + if (inferior_ptid != null_ptid) + tp = inferior_thread (); + else + tp = NULL; SWITCH_THRU_ALL_UIS () { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); struct ui_out *mi_uiout; - struct cleanup *old_chain; if (mi == NULL) continue; - mi_uiout = interp_ui_out (top_level_interpreter ()); + mi_uiout = top_level_interpreter ()->interp_ui_out (); mi_uiout->redirect (mi->event_channel); + ui_out_redirect_pop redirect_popper (mi_uiout); - old_chain = make_cleanup_ui_out_redirect_pop (mi_uiout); - - make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); if (selection & USER_SELECTED_INFERIOR) print_selected_inferior (mi->cli_uiout); @@ -1341,7 +1250,6 @@ mi_user_selected_context_changed (user_selected_what selection) } gdb_flush (mi->event_channel); - do_cleanups (old_chain); } } @@ -1353,17 +1261,15 @@ report_initial_inferior (struct inferior *inf, void *closure) and top_level_interpreter_data is set, we cannot call it here. */ struct mi_interp *mi = (struct mi_interp *) closure; - struct cleanup *old_chain; - old_chain = make_cleanup_restore_target_terminal (); - target_terminal_ours_for_output (); + target_terminal::scoped_restore_terminal_state term_state; + target_terminal::ours_for_output (); fprintf_unfiltered (mi->event_channel, "thread-group-added,id=\"i%d\"", inf->num); gdb_flush (mi->event_channel); - do_cleanups (old_chain); return 0; } @@ -1377,25 +1283,43 @@ mi_interp::interp_ui_out () the consoles to use the supplied ui-file(s). */ void -mi_interp::set_logging (ui_file_up logfile, bool logging_redirect) +mi_interp::set_logging (ui_file_up logfile, bool logging_redirect, + bool debug_redirect) { struct mi_interp *mi = this; if (logfile != NULL) { mi->saved_raw_stdout = mi->raw_stdout; - mi->raw_stdout = make_logging_output (mi->raw_stdout, - std::move (logfile), - logging_redirect); + /* If something is being redirected, then grab logfile. */ + ui_file *logfile_p = nullptr; + if (logging_redirect || debug_redirect) + { + logfile_p = logfile.get (); + mi->saved_raw_file_to_delete = logfile_p; + } + + /* If something is not being redirected, then a tee containing both the + logfile and stdout. */ + ui_file *tee = nullptr; + if (!logging_redirect || !debug_redirect) + { + tee = new tee_file (mi->raw_stdout, std::move (logfile)); + mi->saved_raw_file_to_delete = tee; + } + + mi->raw_stdout = logging_redirect ? logfile_p : tee; + mi->raw_stdlog = debug_redirect ? logfile_p : tee; } else { - delete mi->raw_stdout; + delete mi->saved_raw_file_to_delete; mi->raw_stdout = mi->saved_raw_stdout; - mi->saved_raw_stdout = NULL; + mi->saved_raw_stdout = nullptr; + mi->saved_raw_file_to_delete = nullptr; } - + mi->out->set_raw (mi->raw_stdout); mi->err->set_raw (mi->raw_stdout); mi->log->set_raw (mi->raw_stdout); @@ -1411,8 +1335,6 @@ mi_interp_factory (const char *name) return new mi_interp (name); } -extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */ - void _initialize_mi_interp (void) { @@ -1422,33 +1344,33 @@ _initialize_mi_interp (void) interp_factory_register (INTERP_MI3, mi_interp_factory); interp_factory_register (INTERP_MI, mi_interp_factory); - observer_attach_signal_received (mi_on_signal_received); - observer_attach_end_stepping_range (mi_on_end_stepping_range); - observer_attach_signal_exited (mi_on_signal_exited); - observer_attach_exited (mi_on_exited); - observer_attach_no_history (mi_on_no_history); - observer_attach_new_thread (mi_new_thread); - observer_attach_thread_exit (mi_thread_exit); - observer_attach_inferior_added (mi_inferior_added); - observer_attach_inferior_appeared (mi_inferior_appeared); - observer_attach_inferior_exit (mi_inferior_exit); - observer_attach_inferior_removed (mi_inferior_removed); - observer_attach_record_changed (mi_record_changed); - observer_attach_normal_stop (mi_on_normal_stop); - observer_attach_target_resumed (mi_on_resume); - observer_attach_solib_loaded (mi_solib_loaded); - observer_attach_solib_unloaded (mi_solib_unloaded); - observer_attach_about_to_proceed (mi_about_to_proceed); - observer_attach_traceframe_changed (mi_traceframe_changed); - observer_attach_tsv_created (mi_tsv_created); - observer_attach_tsv_deleted (mi_tsv_deleted); - observer_attach_tsv_modified (mi_tsv_modified); - observer_attach_breakpoint_created (mi_breakpoint_created); - observer_attach_breakpoint_deleted (mi_breakpoint_deleted); - observer_attach_breakpoint_modified (mi_breakpoint_modified); - observer_attach_command_param_changed (mi_command_param_changed); - observer_attach_memory_changed (mi_memory_changed); - observer_attach_sync_execution_done (mi_on_sync_execution_done); - observer_attach_user_selected_context_changed + gdb::observers::signal_received.attach (mi_on_signal_received); + gdb::observers::end_stepping_range.attach (mi_on_end_stepping_range); + gdb::observers::signal_exited.attach (mi_on_signal_exited); + gdb::observers::exited.attach (mi_on_exited); + gdb::observers::no_history.attach (mi_on_no_history); + gdb::observers::new_thread.attach (mi_new_thread); + gdb::observers::thread_exit.attach (mi_thread_exit); + gdb::observers::inferior_added.attach (mi_inferior_added); + gdb::observers::inferior_appeared.attach (mi_inferior_appeared); + gdb::observers::inferior_exit.attach (mi_inferior_exit); + gdb::observers::inferior_removed.attach (mi_inferior_removed); + gdb::observers::record_changed.attach (mi_record_changed); + gdb::observers::normal_stop.attach (mi_on_normal_stop); + gdb::observers::target_resumed.attach (mi_on_resume); + gdb::observers::solib_loaded.attach (mi_solib_loaded); + gdb::observers::solib_unloaded.attach (mi_solib_unloaded); + gdb::observers::about_to_proceed.attach (mi_about_to_proceed); + gdb::observers::traceframe_changed.attach (mi_traceframe_changed); + gdb::observers::tsv_created.attach (mi_tsv_created); + gdb::observers::tsv_deleted.attach (mi_tsv_deleted); + gdb::observers::tsv_modified.attach (mi_tsv_modified); + gdb::observers::breakpoint_created.attach (mi_breakpoint_created); + gdb::observers::breakpoint_deleted.attach (mi_breakpoint_deleted); + gdb::observers::breakpoint_modified.attach (mi_breakpoint_modified); + gdb::observers::command_param_changed.attach (mi_command_param_changed); + gdb::observers::memory_changed.attach (mi_memory_changed); + gdb::observers::sync_execution_done.attach (mi_on_sync_execution_done); + gdb::observers::user_selected_context_changed.attach (mi_user_selected_context_changed); }