]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/mi/mi-interp.c
gdb: rename struct shobj -> struct solib
[thirdparty/binutils-gdb.git] / gdb / mi / mi-interp.c
index e3cb159e0fa1d5ff5d21a8fe801a3ae97829cd85..38ae227690151ca9f4b30e15243e682356810422 100644 (file)
@@ -1,6 +1,6 @@
 /* MI Interpreter Definitions and Commands for GDB, the GNU debugger.
 
-   Copyright (C) 2002-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -60,34 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_on_signal_exited (enum gdb_signal siggnal);
-static void mi_on_exited (int exitstatus);
-static void mi_on_no_history (void);
-
-static void mi_new_thread (struct thread_info *t);
-static void mi_thread_exit (struct thread_info *t, int silent);
-static void mi_record_changed (struct inferior*, int, const char *,
-                              const char *);
-static void mi_inferior_added (struct inferior *inf);
-static void mi_inferior_appeared (struct inferior *inf);
-static void mi_inferior_exit (struct inferior *inf);
-static void mi_inferior_removed (struct inferior *inf);
-static void mi_on_resume (ptid_t ptid);
-static void mi_solib_loaded (struct so_list *solib);
-static void mi_solib_unloaded (struct so_list *solib);
-static void mi_about_to_proceed (void);
-static void mi_traceframe_changed (int tfnum, int tpnum);
-static void mi_tsv_created (const struct trace_state_variable *tsv);
-static void mi_tsv_deleted (const struct trace_state_variable *tsv);
-static void mi_tsv_modified (const struct trace_state_variable *tsv);
-static void mi_breakpoint_created (struct breakpoint *b);
-static void mi_breakpoint_deleted (struct breakpoint *b);
-static void mi_breakpoint_modified (struct breakpoint *b);
-static void mi_command_param_changed (const char *param, const char *value);
-static void mi_memory_changed (struct inferior *inf, CORE_ADDR memaddr,
-                              ssize_t len, const bfd_byte *myaddr);
-static void mi_on_sync_execution_done (void);
-
 /* Display the MI prompt.  */
 
 static void
@@ -100,23 +72,10 @@ display_mi_prompt (struct mi_interp *mi)
   ui->prompt_state = PROMPTED;
 }
 
-/* Returns the INTERP's data cast as mi_interp if INTERP is an MI, and
-   returns NULL otherwise.  */
-
-static struct mi_interp *
-as_mi_interp (struct interp *interp)
-{
-  return dynamic_cast<mi_interp *> (interp);
-}
-
-/* Observer for the command_error notification.  */
-
-static void
-mi_on_command_error ()
+void
+mi_interp::on_command_error ()
 {
-  mi_interp *mi = as_mi_interp (top_level_interpreter ());
-  if (mi != nullptr)
-    display_mi_prompt (mi);
+  display_mi_prompt (this);
 }
 
 void
@@ -136,7 +95,7 @@ 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);
-  mi->mi_uiout = mi_out_new (name ());
+  mi->mi_uiout = mi_out_new (name ()).release ();
   gdb_assert (mi->mi_uiout != nullptr);
   mi->cli_uiout = new cli_ui_out (mi->out);
 
@@ -148,20 +107,10 @@ mi_interp::init (bool top_level)
 
         This is also called when additional MI interpreters are added (using
         the new-ui command), when multiple inferiors possibly exist, so we need
-        to use iteration to report all the inferiors.  mi_inferior_added can't
-        be used, because it would print the event on all the other MI UIs.  */
+        to use iteration to report all the inferiors.  */
 
       for (inferior *inf : all_inferiors ())
-       {
-         target_terminal::scoped_restore_terminal_state term_state;
-         target_terminal::ours_for_output ();
-
-         gdb_printf (mi->event_channel,
-                     "thread-group-added,id=\"i%d\"",
-                     inf->num);
-
-         gdb_flush (mi->event_channel);
-       }
+       mi->on_inferior_added (inf);
   }
 }
 
@@ -273,20 +222,13 @@ mi_execute_command_wrapper (const char *cmd)
   mi_execute_command (cmd, ui->instream == ui->stdin_stream);
 }
 
-/* Observer for the synchronous_command_done notification.  */
-
-static void
-mi_on_sync_execution_done (void)
+void
+mi_interp::on_sync_execution_done ()
 {
-  struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-  if (mi == NULL)
-    return;
-
   /* If MI is sync, then output the MI prompt now, indicating we're
      ready for further input.  */
   if (!mi_async_p ())
-    display_mi_prompt (mi);
+    display_mi_prompt (this);
 }
 
 /* mi_execute_command_wrapper wrapper suitable for INPUT_HANDLER.  */
@@ -323,200 +265,103 @@ mi_interp::pre_command_loop ()
   display_mi_prompt (mi);
 }
 
-static void
-mi_new_thread (struct thread_info *t)
+void
+mi_interp::on_new_thread (thread_info *t)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-       continue;
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
-
-      gdb_printf (mi->event_channel,
-                 "thread-created,id=\"%d\",group-id=\"i%d\"",
-                 t->global_num, t->inf->num);
-      gdb_flush (mi->event_channel);
-    }
+  gdb_printf (this->event_channel, "thread-created,id=\"%d\",group-id=\"i%d\"",
+             t->global_num, t->inf->num);
+  gdb_flush (this->event_channel);
 }
 
-static void
-mi_thread_exit (struct thread_info *t, int silent)
+void
+mi_interp::on_thread_exited (thread_info *t,
+                            std::optional<ULONGEST> /* exit_code */,
+                            int /* silent */)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-       continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
-      gdb_printf (mi->event_channel,
-                 "thread-exited,id=\"%d\",group-id=\"i%d\"",
-                 t->global_num, t->inf->num);
-      gdb_flush (mi->event_channel);
-    }
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
+  gdb_printf (this->event_channel, "thread-exited,id=\"%d\",group-id=\"i%d\"",
+             t->global_num, t->inf->num);
+  gdb_flush (this->event_channel);
 }
 
-/* Emit notification on changing the state of record.  */
-
-static void
-mi_record_changed (struct inferior *inferior, int started, const char *method,
-                  const char *format)
+void
+mi_interp::on_record_changed (inferior *inferior, int started,
+                             const char *method, const char *format)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      if (mi == NULL)
-       continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
-
-      if (started)
-       {
-         if (format != NULL)
-           {
-             gdb_printf (mi->event_channel,
-                         "record-started,thread-group=\"i%d\","
-                         "method=\"%s\",format=\"%s\"",
-                         inferior->num, method, format);
-           }
-         else
-           {
-             gdb_printf (mi->event_channel,
-                         "record-started,thread-group=\"i%d\","
-                         "method=\"%s\"",
-                         inferior->num, method);
-           }
-       }
+  if (started)
+    {
+      if (format != NULL)
+       gdb_printf (this->event_channel,
+                   "record-started,thread-group=\"i%d\","
+                   "method=\"%s\",format=\"%s\"",
+                   inferior->num, method, format);
       else
-       {
-         gdb_printf (mi->event_channel,
-                     "record-stopped,thread-group=\"i%d\"",
-                     inferior->num);
-       }
-
-      gdb_flush (mi->event_channel);
+       gdb_printf (this->event_channel,
+                   "record-started,thread-group=\"i%d\","
+                   "method=\"%s\"",
+                   inferior->num, method);
     }
-}
-
-static void
-mi_inferior_added (struct inferior *inf)
-{
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct interp *interp;
-      struct mi_interp *mi;
-
-      /* We'll be called once for the initial inferior, before the top
-        level interpreter is set.  */
-      interp = top_level_interpreter ();
-      if (interp == NULL)
-       continue;
-
-      mi = as_mi_interp (interp);
-      if (mi == NULL)
-       continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  else
+    gdb_printf (this->event_channel,
+               "record-stopped,thread-group=\"i%d\"",
+               inferior->num);
 
-      gdb_printf (mi->event_channel,
-                 "thread-group-added,id=\"i%d\"",
-                 inf->num);
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
-static void
-mi_inferior_appeared (struct inferior *inf)
+void
+mi_interp::on_inferior_added (inferior *inf)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      if (mi == NULL)
-       continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
-
-      gdb_printf (mi->event_channel,
-                 "thread-group-started,id=\"i%d\",pid=\"%d\"",
-                 inf->num, inf->pid);
-      gdb_flush (mi->event_channel);
-    }
+  gdb_printf (this->event_channel, "thread-group-added,id=\"i%d\"", inf->num);
+  gdb_flush (this->event_channel);
 }
 
-static void
-mi_inferior_exit (struct inferior *inf)
+void
+mi_interp::on_inferior_appeared (inferior *inf)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      if (mi == NULL)
-       continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
-
-      if (inf->has_exit_code)
-       gdb_printf (mi->event_channel,
-                   "thread-group-exited,id=\"i%d\",exit-code=\"%s\"",
-                   inf->num, int_string (inf->exit_code, 8, 0, 0, 1));
-      else
-       gdb_printf (mi->event_channel,
-                   "thread-group-exited,id=\"i%d\"", inf->num);
-
-      gdb_flush (mi->event_channel);
-    }
+  gdb_printf (this->event_channel, "thread-group-started,id=\"i%d\",pid=\"%d\"",
+             inf->num, inf->pid);
+  gdb_flush (this->event_channel);
 }
 
-static void
-mi_inferior_removed (struct inferior *inf)
+void
+mi_interp::on_inferior_disappeared (inferior *inf)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-       continue;
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  if (inf->has_exit_code)
+    gdb_printf (this->event_channel,
+               "thread-group-exited,id=\"i%d\",exit-code=\"%s\"",
+               inf->num, int_string (inf->exit_code, 8, 0, 0, 1));
+  else
+    gdb_printf (this->event_channel,
+               "thread-group-exited,id=\"i%d\"", inf->num);
 
-      gdb_printf (mi->event_channel,
-                 "thread-group-removed,id=\"i%d\"",
-                 inf->num);
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
-/* Return the MI interpreter, if it is active -- either because it's
-   the top-level interpreter or the interpreter executing the current
-   command.  Returns NULL if the MI interpreter is not being used.  */
-
-static struct mi_interp *
-find_mi_interp (void)
+void
+mi_interp::on_inferior_removed (inferior *inf)
 {
-  struct mi_interp *mi;
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-  mi = as_mi_interp (top_level_interpreter ());
-  if (mi != NULL)
-    return mi;
-
-  mi = as_mi_interp (command_interp ());
-  if (mi != NULL)
-    return mi;
-
-  return NULL;
+  gdb_printf (this->event_channel, "thread-group-removed,id=\"i%d\"", inf->num);
+  gdb_flush (this->event_channel);
 }
 
 /* Observers for several run control events that print why the
@@ -530,55 +375,25 @@ mi_interp::on_signal_received (enum gdb_signal siggnal)
   print_signal_received_reason (this->cli_uiout, siggnal);
 }
 
-/* Observer for the signal_exited notification.  */
-
-static void
-mi_on_signal_exited (enum gdb_signal siggnal)
+void
+mi_interp::on_signal_exited (gdb_signal sig)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = find_mi_interp ();
-
-      if (mi == NULL)
-       continue;
-
-      print_signal_exited_reason (mi->mi_uiout, siggnal);
-      print_signal_exited_reason (mi->cli_uiout, siggnal);
-    }
+  print_signal_exited_reason (this->mi_uiout, sig);
+  print_signal_exited_reason (this->cli_uiout, sig);
 }
 
-/* Observer for the exited notification.  */
-
-static void
-mi_on_exited (int exitstatus)
+void
+mi_interp::on_exited (int status)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = find_mi_interp ();
-
-      if (mi == NULL)
-       continue;
-
-      print_exited_reason (mi->mi_uiout, exitstatus);
-      print_exited_reason (mi->cli_uiout, exitstatus);
-    }
+  print_exited_reason (this->mi_uiout, status);
+  print_exited_reason (this->cli_uiout, status);
 }
 
-/* Observer for the no_history notification.  */
-
-static void
-mi_on_no_history (void)
+void
+mi_interp::on_no_history ()
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = find_mi_interp ();
-
-      if (mi == NULL)
-       continue;
-
-      print_no_history_reason (mi->mi_uiout);
-      print_no_history_reason (mi->cli_uiout);
-    }
+  print_no_history_reason (this->mi_uiout);
+  print_no_history_reason (this->cli_uiout);
 }
 
 void
@@ -635,8 +450,8 @@ mi_interp::on_normal_stop (struct bpstat *bs, int print_frame)
   gdb_flush (this->raw_stdout);
 }
 
-static void
-mi_about_to_proceed (void)
+void
+mi_interp::on_about_to_proceed ()
 {
   /* Suppress output while calling an inferior function.  */
 
@@ -648,12 +463,7 @@ mi_about_to_proceed (void)
        return;
     }
 
-  mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-  if (mi == nullptr)
-    return;
-
-  mi->mi_proceeded = 1;
+  this->mi_proceeded = 1;
 }
 
 /* When the element is non-zero, no MI notifications will be emitted in
@@ -667,114 +477,73 @@ struct mi_suppress_notification mi_suppress_notification =
     0,
   };
 
-/* Emit notification on changing a traceframe.  */
-
-static void
-mi_traceframe_changed (int tfnum, int tpnum)
+void
+mi_interp::on_traceframe_changed (int tfnum, int tpnum)
 {
   if (mi_suppress_notification.traceframe)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-       continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      if (tfnum >= 0)
-       gdb_printf (mi->event_channel, "traceframe-changed,"
-                   "num=\"%d\",tracepoint=\"%d\"",
-                   tfnum, tpnum);
-      else
-       gdb_printf (mi->event_channel, "traceframe-changed,end");
+  if (tfnum >= 0)
+    gdb_printf (this->event_channel, "traceframe-changed,"
+               "num=\"%d\",tracepoint=\"%d\"",
+               tfnum, tpnum);
+  else
+    gdb_printf (this->event_channel, "traceframe-changed,end");
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
-/* Emit notification on creating a trace state variable.  */
-
-static void
-mi_tsv_created (const struct trace_state_variable *tsv)
+void
+mi_interp::on_tsv_created (const trace_state_variable *tsv)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      if (mi == NULL)
-       continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
-
-      gdb_printf (mi->event_channel, "tsv-created,"
-                 "name=\"%s\",initial=\"%s\"",
-                 tsv->name.c_str (), plongest (tsv->initial_value));
+  gdb_printf (this->event_channel, "tsv-created,"
+             "name=\"%s\",initial=\"%s\"",
+             tsv->name.c_str (), plongest (tsv->initial_value));
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
-/* Emit notification on deleting a trace state variable.  */
-
-static void
-mi_tsv_deleted (const struct trace_state_variable *tsv)
+void
+mi_interp::on_tsv_deleted (const trace_state_variable *tsv)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-       continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      if (tsv != NULL)
-       gdb_printf (mi->event_channel, "tsv-deleted,"
-                   "name=\"%s\"", tsv->name.c_str ());
-      else
-       gdb_printf (mi->event_channel, "tsv-deleted");
+  if (tsv != nullptr)
+    gdb_printf (this->event_channel, "tsv-deleted,name=\"%s\"",
+               tsv->name.c_str ());
+  else
+    gdb_printf (this->event_channel, "tsv-deleted");
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
-/* Emit notification on modifying a trace state variable.  */
-
-static void
-mi_tsv_modified (const struct trace_state_variable *tsv)
+void
+mi_interp::on_tsv_modified (const trace_state_variable *tsv)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct ui_out *mi_uiout;
-
-      if (mi == NULL)
-       continue;
-
-      mi_uiout = top_level_interpreter ()->interp_ui_out ();
+  ui_out *mi_uiout = this->interp_ui_out ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel,
-                 "tsv-modified");
+  gdb_printf (this->event_channel,
+             "tsv-modified");
 
-      ui_out_redirect_pop redir (mi_uiout, mi->event_channel);
+  ui_out_redirect_pop redir (mi_uiout, this->event_channel);
 
-      mi_uiout->field_string ("name", tsv->name);
-      mi_uiout->field_string ("initial",
-                             plongest (tsv->initial_value));
-      if (tsv->value_known)
-       mi_uiout->field_string ("current", plongest (tsv->value));
+  mi_uiout->field_string ("name", tsv->name);
+  mi_uiout->field_string ("initial",
+                         plongest (tsv->initial_value));
+  if (tsv->value_known)
+    mi_uiout->field_string ("current", plongest (tsv->value));
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 /* Print breakpoint BP on MI's event channel.  */
@@ -806,10 +575,8 @@ mi_print_breakpoint_for_event (struct mi_interp *mi, breakpoint *bp)
     }
 }
 
-/* Emit notification about a created breakpoint.  */
-
-static void
-mi_breakpoint_created (struct breakpoint *b)
+void
+mi_interp::on_breakpoint_created (breakpoint *b)
 {
   if (mi_suppress_notification.breakpoint)
     return;
@@ -817,28 +584,17 @@ mi_breakpoint_created (struct breakpoint *b)
   if (b->number <= 0)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-       continue;
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  gdb_printf (this->event_channel, "breakpoint-created");
+  mi_print_breakpoint_for_event (this, b);
 
-      gdb_printf (mi->event_channel,
-                 "breakpoint-created");
-      mi_print_breakpoint_for_event (mi, b);
-
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
-/* Emit notification about deleted breakpoint.  */
-
-static void
-mi_breakpoint_deleted (struct breakpoint *b)
+void
+mi_interp::on_breakpoint_deleted (breakpoint *b)
 {
   if (mi_suppress_notification.breakpoint)
     return;
@@ -846,27 +602,15 @@ mi_breakpoint_deleted (struct breakpoint *b)
   if (b->number <= 0)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-       continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel, "breakpoint-deleted,id=\"%d\"",
-                 b->number);
-
-      gdb_flush (mi->event_channel);
-    }
+  gdb_printf (this->event_channel, "breakpoint-deleted,id=\"%d\"", b->number);
+  gdb_flush (this->event_channel);
 }
 
-/* Emit notification about modified breakpoint.  */
-
-static void
-mi_breakpoint_modified (struct breakpoint *b)
+void
+mi_interp::on_breakpoint_modified (breakpoint *b)
 {
   if (mi_suppress_notification.breakpoint)
     return;
@@ -874,21 +618,12 @@ mi_breakpoint_modified (struct breakpoint *b)
   if (b->number <= 0)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-       continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
-      gdb_printf (mi->event_channel,
-                 "breakpoint-modified");
-      mi_print_breakpoint_for_event (mi, b);
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
+  gdb_printf (this->event_channel, "breakpoint-modified");
+  mi_print_breakpoint_for_event (this, b);
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 static void
@@ -940,7 +675,7 @@ mi_on_resume_1 (struct mi_interp *mi,
   if (!mi->running_result_record_printed && mi->mi_proceeded)
     {
       gdb_printf (mi->raw_stdout, "%s^running\n",
-                 current_token ? current_token : "");
+                 mi->current_token ? mi->current_token : "");
     }
 
   /* Backwards compatibility.  If doing a wildcard resume and there's
@@ -965,8 +700,8 @@ mi_on_resume_1 (struct mi_interp *mi,
   gdb_flush (mi->raw_stdout);
 }
 
-static void
-mi_on_resume (ptid_t ptid)
+void
+mi_interp::on_target_resumed (ptid_t ptid)
 {
   struct thread_info *tp = NULL;
 
@@ -980,233 +715,163 @@ mi_on_resume (ptid_t ptid)
   if (tp->control.in_infcall)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-       continue;
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
-
-      mi_on_resume_1 (mi, target, ptid);
-    }
+  mi_on_resume_1 (this, target, ptid);
 }
 
 /* See mi-interp.h.  */
 
 void
-mi_output_solib_attribs (ui_out *uiout, struct so_list *solib)
+mi_output_solib_attribs (ui_out *uiout, const solib &solib)
 {
-  struct gdbarch *gdbarch = target_gdbarch ();
+  gdbarch *gdbarch = current_inferior ()->arch ();
 
-  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_signed ("symbols-loaded", solib->symbols_loaded);
-  if (!gdbarch_has_global_solist (target_gdbarch ()))
+  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_signed ("symbols-loaded", solib.symbols_loaded);
+  if (!gdbarch_has_global_solist (current_inferior ()->arch ()))
       uiout->field_fmt ("thread-group", "i%d", current_inferior ()->num);
 
   ui_out_emit_list list_emitter (uiout, "ranges");
   ui_out_emit_tuple tuple_emitter (uiout, NULL);
-  if (solib->addr_high != 0)
+  if (solib.addr_high != 0)
     {
-      uiout->field_core_addr ("from", gdbarch, solib->addr_low);
-      uiout->field_core_addr ("to", gdbarch, solib->addr_high);
+      uiout->field_core_addr ("from", gdbarch, solib.addr_low);
+      uiout->field_core_addr ("to", gdbarch, solib.addr_high);
     }
 }
 
-static void
-mi_solib_loaded (struct so_list *solib)
+void
+mi_interp::on_solib_loaded (const solib &solib)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct ui_out *uiout;
-
-      if (mi == NULL)
-       continue;
+  ui_out *uiout = this->interp_ui_out ();
 
-      uiout = top_level_interpreter ()->interp_ui_out ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  gdb_printf (this->event_channel, "library-loaded");
 
-      gdb_printf (mi->event_channel, "library-loaded");
+  ui_out_redirect_pop redir (uiout, this->event_channel);
 
-      ui_out_redirect_pop redir (uiout, mi->event_channel);
+  mi_output_solib_attribs (uiout, solib);
 
-      mi_output_solib_attribs (uiout, solib);
-
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
-static void
-mi_solib_unloaded (struct so_list *solib)
+void
+mi_interp::on_solib_unloaded (const solib &solib)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct ui_out *uiout;
-
-      if (mi == NULL)
-       continue;
+  ui_out *uiout = this->interp_ui_out ();
 
-      uiout = top_level_interpreter ()->interp_ui_out ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  gdb_printf (this->event_channel, "library-unloaded");
 
-      gdb_printf (mi->event_channel, "library-unloaded");
+  ui_out_redirect_pop redir (uiout, this->event_channel);
 
-      ui_out_redirect_pop redir (uiout, mi->event_channel);
+  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);
+  if (!gdbarch_has_global_solist (current_inferior ()->arch ()))
+    uiout->field_fmt ("thread-group", "i%d", current_inferior ()->num);
 
-      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);
-      if (!gdbarch_has_global_solist (target_gdbarch ()))
-       {
-         uiout->field_fmt ("thread-group", "i%d", current_inferior ()->num);
-       }
-
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
-/* Emit notification about the command parameter change.  */
-
-static void
-mi_command_param_changed (const char *param, const char *value)
+void
+mi_interp::on_param_changed (const char *param, const char *value)
 {
   if (mi_suppress_notification.cmd_param_changed)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct ui_out *mi_uiout;
-
-      if (mi == NULL)
-       continue;
-
-      mi_uiout = top_level_interpreter ()->interp_ui_out ();
+  ui_out *mi_uiout = this->interp_ui_out ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel, "cmd-param-changed");
+  gdb_printf (this->event_channel, "cmd-param-changed");
 
-      ui_out_redirect_pop redir (mi_uiout, mi->event_channel);
+  ui_out_redirect_pop redir (mi_uiout, this->event_channel);
 
-      mi_uiout->field_string ("param", param);
-      mi_uiout->field_string ("value", value);
+  mi_uiout->field_string ("param", param);
+  mi_uiout->field_string ("value", value);
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
-/* Emit notification about the target memory change.  */
-
-static void
-mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr,
-                  ssize_t len, const bfd_byte *myaddr)
+void
+mi_interp::on_memory_changed (inferior *inferior, CORE_ADDR memaddr,
+                             ssize_t len, const bfd_byte *myaddr)
 {
   if (mi_suppress_notification.memory)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct ui_out *mi_uiout;
-      struct obj_section *sec;
 
-      if (mi == NULL)
-       continue;
-
-      mi_uiout = top_level_interpreter ()->interp_ui_out ();
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  ui_out *mi_uiout = this->interp_ui_out ();
 
-      gdb_printf (mi->event_channel, "memory-changed");
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      ui_out_redirect_pop redir (mi_uiout, mi->event_channel);
+  gdb_printf (this->event_channel, "memory-changed");
 
-      mi_uiout->field_fmt ("thread-group", "i%d", inferior->num);
-      mi_uiout->field_core_addr ("addr", target_gdbarch (), memaddr);
-      mi_uiout->field_string ("len", hex_string (len));
+  ui_out_redirect_pop redir (mi_uiout, this->event_channel);
 
-      /* 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_section_flags (sec->the_bfd_section);
+  mi_uiout->field_fmt ("thread-group", "i%d", inferior->num);
+  mi_uiout->field_core_addr ("addr", current_inferior ()->arch (), memaddr);
+  mi_uiout->field_string ("len", hex_string (len));
 
-         if (flags & SEC_CODE)
-           mi_uiout->field_string ("type", "code");
-       }
+  /* Append 'type=code' into notification if MEMADDR falls in the range of
+     sections contain code.  */
+  obj_section *sec = find_pc_section (memaddr);
+  if (sec != nullptr && sec->objfile != nullptr)
+    {
+      flagword flags = bfd_section_flags (sec->the_bfd_section);
 
-      gdb_flush (mi->event_channel);
+      if (flags & SEC_CODE)
+       mi_uiout->field_string ("type", "code");
     }
-}
 
-/* Emit an event when the selection context (inferior, thread, frame)
-   changed.  */
+  gdb_flush (this->event_channel);
+}
 
-static void
-mi_user_selected_context_changed (user_selected_what selection)
+void
+mi_interp::on_user_selected_context_changed (user_selected_what selection)
 {
-  struct thread_info *tp;
-
   /* Don't send an event if we're responding to an MI command.  */
   if (mi_suppress_notification.user_selected_context)
     return;
 
-  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;
-
-      if (mi == NULL)
-       continue;
+  thread_info *tp = inferior_ptid != null_ptid ? inferior_thread () : nullptr;
+  ui_out *mi_uiout = this->interp_ui_out ();
+  ui_out_redirect_pop redirect_popper (mi_uiout, this->event_channel);
 
-      mi_uiout = top_level_interpreter ()->interp_ui_out ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      ui_out_redirect_pop redirect_popper (mi_uiout, mi->event_channel);
+  if (selection & USER_SELECTED_INFERIOR)
+    print_selected_inferior (this->cli_uiout);
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  if (tp != NULL
+      && (selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME)))
+    {
+      print_selected_thread_frame (this->cli_uiout, selection);
 
-      if (selection & USER_SELECTED_INFERIOR)
-       print_selected_inferior (mi->cli_uiout);
+      gdb_printf (this->event_channel, "thread-selected,id=\"%d\"",
+                 tp->global_num);
 
-      if (tp != NULL
-         && (selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME)))
+      if (tp->state != THREAD_RUNNING)
        {
-         print_selected_thread_frame (mi->cli_uiout, selection);
-
-         gdb_printf (mi->event_channel,
-                     "thread-selected,id=\"%d\"",
-                     tp->global_num);
-
-         if (tp->state != THREAD_RUNNING)
-           {
-             if (has_stack_frames ())
-               print_stack_frame_to_uiout (mi_uiout, get_selected_frame (NULL),
-                                           1, SRC_AND_LOC, 1);
-           }
+         if (has_stack_frames ())
+           print_stack_frame_to_uiout (mi_uiout, get_selected_frame (NULL),
+                                       1, SRC_AND_LOC, 1);
        }
-
-      gdb_flush (mi->event_channel);
     }
+
+  gdb_flush (this->event_channel);
 }
 
 ui_out *
@@ -1274,38 +939,4 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI3, mi_interp_factory);
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
-
-  gdb::observers::signal_exited.attach (mi_on_signal_exited, "mi-interp");
-  gdb::observers::exited.attach (mi_on_exited, "mi-interp");
-  gdb::observers::no_history.attach (mi_on_no_history, "mi-interp");
-  gdb::observers::new_thread.attach (mi_new_thread, "mi-interp");
-  gdb::observers::thread_exit.attach (mi_thread_exit, "mi-interp");
-  gdb::observers::inferior_added.attach (mi_inferior_added, "mi-interp");
-  gdb::observers::inferior_appeared.attach (mi_inferior_appeared, "mi-interp");
-  gdb::observers::inferior_exit.attach (mi_inferior_exit, "mi-interp");
-  gdb::observers::inferior_removed.attach (mi_inferior_removed, "mi-interp");
-  gdb::observers::record_changed.attach (mi_record_changed, "mi-interp");
-  gdb::observers::target_resumed.attach (mi_on_resume, "mi-interp");
-  gdb::observers::solib_loaded.attach (mi_solib_loaded, "mi-interp");
-  gdb::observers::solib_unloaded.attach (mi_solib_unloaded, "mi-interp");
-  gdb::observers::about_to_proceed.attach (mi_about_to_proceed, "mi-interp");
-  gdb::observers::traceframe_changed.attach (mi_traceframe_changed,
-                                            "mi-interp");
-  gdb::observers::tsv_created.attach (mi_tsv_created, "mi-interp");
-  gdb::observers::tsv_deleted.attach (mi_tsv_deleted, "mi-interp");
-  gdb::observers::tsv_modified.attach (mi_tsv_modified, "mi-interp");
-  gdb::observers::breakpoint_created.attach (mi_breakpoint_created,
-                                            "mi-interp");
-  gdb::observers::breakpoint_deleted.attach (mi_breakpoint_deleted,
-                                            "mi-interp");
-  gdb::observers::breakpoint_modified.attach (mi_breakpoint_modified,
-                                             "mi-interp");
-  gdb::observers::command_param_changed.attach (mi_command_param_changed,
-                                               "mi-interp");
-  gdb::observers::command_error.attach (mi_on_command_error, "mi-interp");
-  gdb::observers::memory_changed.attach (mi_memory_changed, "mi-interp");
-  gdb::observers::sync_execution_done.attach (mi_on_sync_execution_done,
-                                             "mi-interp");
-  gdb::observers::user_selected_context_changed.attach
-    (mi_user_selected_context_changed, "mi-interp");
 }