gdb: add interp::on_user_selected_context_changed method
[binutils-gdb.git] / gdb / infrun.c
index ba56fe37a789be1bf813e000cc4d5b7cdba24a2c..d4334302a9963f6ffa6413c697f5334251fa68c9 100644 (file)
@@ -34,6 +34,7 @@
 #include "annotate.h"
 #include "symfile.h"
 #include "top.h"
+#include "ui.h"
 #include "inf-loop.h"
 #include "regcache.h"
 #include "value.h"
@@ -75,6 +76,7 @@
 #include "gdbsupport/buildargv.h"
 #include "extension.h"
 #include "disasm.h"
+#include "interps.h"
 
 /* Prototypes for local functions */
 
@@ -624,6 +626,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
   target_follow_fork (child_inf, child_ptid, fork_kind, follow_child,
                      detach_fork);
 
+  gdb::observers::inferior_forked.notify (parent_inf, child_inf, fork_kind);
+
   /* target_follow_fork must leave the parent as the current inferior.  If we
      want to follow the child, we make it the current one below.  */
   gdb_assert (current_inferior () == parent_inf);
@@ -947,14 +951,14 @@ follow_inferior_reset_breakpoints (void)
   if (tp->control.step_resume_breakpoint)
     {
       breakpoint_re_set_thread (tp->control.step_resume_breakpoint);
-      tp->control.step_resume_breakpoint->loc->enabled = 1;
+      tp->control.step_resume_breakpoint->first_loc ().enabled = 1;
     }
 
   /* Treat exception_resume breakpoints like step_resume breakpoints.  */
   if (tp->control.exception_resume_breakpoint)
     {
       breakpoint_re_set_thread (tp->control.exception_resume_breakpoint);
-      tp->control.exception_resume_breakpoint->loc->enabled = 1;
+      tp->control.exception_resume_breakpoint->first_loc ().enabled = 1;
     }
 
   /* Reinsert all breakpoints in the child.  The user may have set
@@ -1293,7 +1297,8 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
      previous incarnation of this process.  */
   no_shared_libraries (nullptr, 0);
 
-  struct inferior *inf = current_inferior ();
+  inferior *execing_inferior = current_inferior ();
+  inferior *following_inferior;
 
   if (follow_exec_mode_string == follow_exec_mode_new)
     {
@@ -1304,19 +1309,19 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
         inferior's pid.  Having two inferiors with the same pid would confuse
         find_inferior_p(t)id.  Transfer the terminal state and info from the
          old to the new inferior.  */
-      inferior *new_inferior = add_inferior_with_spaces ();
-
-      swap_terminal_info (new_inferior, inf);
-      exit_inferior_silent (inf);
+      following_inferior = add_inferior_with_spaces ();
 
-      new_inferior->pid = pid;
-      target_follow_exec (new_inferior, ptid, exec_file_target);
+      swap_terminal_info (following_inferior, execing_inferior);
+      exit_inferior_silent (execing_inferior);
 
-      /* We continue with the new inferior.  */
-      inf = new_inferior;
+      following_inferior->pid = pid;
     }
   else
     {
+      /* follow-exec-mode is "same", we continue execution in the execing
+        inferior.  */
+      following_inferior = execing_inferior;
+
       /* The old description may no longer be fit for the new image.
         E.g, a 64-bit process exec'ed a 32-bit process.  Clear the
         old description; we'll read a new one below.  No need to do
@@ -1324,18 +1329,20 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
         around (its description is later cleared/refetched on
         restart).  */
       target_clear_description ();
-      target_follow_exec (inf, ptid, exec_file_target);
     }
 
-  gdb_assert (current_inferior () == inf);
-  gdb_assert (current_program_space == inf->pspace);
+  target_follow_exec (following_inferior, ptid, exec_file_target);
+
+  gdb_assert (current_inferior () == following_inferior);
+  gdb_assert (current_program_space == following_inferior->pspace);
 
   /* Attempt to open the exec file.  SYMFILE_DEFER_BP_RESET is used
      because the proper displacement for a PIE (Position Independent
      Executable) main symbol file will only be computed by
      solib_create_inferior_hook below.  breakpoint_re_set would fail
      to insert the breakpoints with the zero displacement.  */
-  try_open_exec_file (exec_file_host.get (), inf, SYMFILE_DEFER_BP_RESET);
+  try_open_exec_file (exec_file_host.get (), following_inferior,
+                     SYMFILE_DEFER_BP_RESET);
 
   /* If the target can specify a description, read it.  Must do this
      after flipping to the new executable (because the target supplied
@@ -1345,7 +1352,7 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
      registers.  */
   target_find_description ();
 
-  gdb::observers::inferior_execd.notify (inf);
+  gdb::observers::inferior_execd.notify (execing_inferior, following_inferior);
 
   breakpoint_re_set ();
 
@@ -1622,15 +1629,15 @@ infrun_inferior_exit (struct inferior *inf)
 }
 
 static void
-infrun_inferior_execd (inferior *inf)
+infrun_inferior_execd (inferior *exec_inf, inferior *follow_inf)
 {
   /* If some threads where was doing a displaced step in this inferior at the
      moment of the exec, they no longer exist.  Even if the exec'ing thread
      doing a displaced step, we don't want to to any fixup nor restore displaced
      stepping buffer bytes.  */
-  inf->displaced_step_state.reset ();
+  follow_inf->displaced_step_state.reset ();
 
-  for (thread_info *thread : inf->threads ())
+  for (thread_info *thread : follow_inf->threads ())
     thread->displaced_step_state.reset ();
 
   /* Since an in-line step is done with everything else stopped, if there was
@@ -1638,7 +1645,7 @@ infrun_inferior_execd (inferior *inf)
      thread.  */
   clear_step_over_info ();
 
-  inf->thread_waiting_for_vfork_done = nullptr;
+  follow_inf->thread_waiting_for_vfork_done = nullptr;
 }
 
 /* If ON, and the architecture supports it, GDB will use displaced
@@ -2545,7 +2552,8 @@ resume_1 (enum gdb_signal sig)
                 user breakpoints at PC to trigger (again) when this
                 hits.  */
              insert_hp_step_resume_breakpoint_at_frame (get_current_frame ());
-             gdb_assert (tp->control.step_resume_breakpoint->loc->permanent);
+             gdb_assert (tp->control.step_resume_breakpoint->first_loc ()
+                         .permanent);
 
              tp->step_after_step_resume_breakpoint = step;
            }
@@ -4199,7 +4207,7 @@ check_curr_ui_sync_execution_done (void)
       && !gdb_in_secondary_prompt_p (ui))
     {
       target_terminal::ours ();
-      gdb::observers::sync_execution_done.notify ();
+      top_level_interpreter ()->on_sync_execution_done ();
       ui->register_file_handler ();
     }
 }
@@ -4353,9 +4361,13 @@ fetch_inferior_event ()
 
     gdb_assert (ecs.ws.kind () != TARGET_WAITKIND_IGNORE);
 
-    /* Switch to the target that generated the event, so we can do
-       target calls.  */
-    switch_to_target_no_thread (ecs.target);
+    /* Switch to the inferior that generated the event, so we can do
+       target calls.  If the event was not associated to a ptid,  */
+    if (ecs.ptid != null_ptid
+       && ecs.ptid != minus_one_ptid)
+      switch_to_inferior_no_thread (find_inferior_ptid (ecs.target, ecs.ptid));
+    else
+      switch_to_target_no_thread (ecs.target);
 
     if (debug_infrun)
       print_target_wait_results (minus_one_ptid, ecs.ptid, ecs.ws);
@@ -5716,7 +5728,7 @@ handle_inferior_event (struct execution_control_state *ecs)
          /* Support the --return-child-result option.  */
          return_child_result_value = ecs->ws.exit_status ();
 
-         gdb::observers::exited.notify (ecs->ws.exit_status ());
+         interps_notify_exited (ecs->ws.exit_status ());
        }
       else
        {
@@ -5743,7 +5755,7 @@ handle_inferior_event (struct execution_control_state *ecs)
                                   "signal number.");
            }
 
-         gdb::observers::signal_exited.notify (ecs->ws.sig ());
+         interps_notify_signal_exited (ecs->ws.sig ());
        }
 
       gdb_flush (gdb_stdout);
@@ -5800,7 +5812,7 @@ handle_inferior_event (struct execution_control_state *ecs)
               list yet at this point.  */
 
            child_regcache
-             = get_thread_arch_aspace_regcache (parent_inf->process_target (),
+             = get_thread_arch_aspace_regcache (parent_inf,
                                                 ecs->ws.child_ptid (),
                                                 gdbarch,
                                                 parent_inf->aspace);
@@ -6027,7 +6039,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       if (handle_stop_requested (ecs))
        return;
 
-      gdb::observers::no_history.notify ();
+      interps_notify_no_history ();
       stop_waiting (ecs);
       return;
     }
@@ -6253,6 +6265,32 @@ finish_step_over (struct execution_control_state *ecs)
   return 0;
 }
 
+/* See infrun.h.  */
+
+void
+notify_signal_received (gdb_signal sig)
+{
+  interps_notify_signal_received (sig);
+  gdb::observers::signal_received.notify (sig);
+}
+
+/* See infrun.h.  */
+
+void
+notify_normal_stop (bpstat *bs, int print_frame)
+{
+  interps_notify_normal_stop (bs, print_frame);
+  gdb::observers::normal_stop.notify (bs, print_frame);
+}
+
+/* See infrun.h.  */
+
+void notify_user_selected_context_changed (user_selected_what selection)
+{
+  interps_notify_user_selected_context_changed (selection);
+  gdb::observers::user_selected_context_changed.notify (selection);
+}
+
 /* Come here when the program has stopped with a signal.  */
 
 static void
@@ -6676,7 +6714,7 @@ handle_signal_stop (struct execution_control_state *ecs)
        {
          /* The signal table tells us to print about this signal.  */
          target_terminal::ours_for_output ();
-         gdb::observers::signal_received.notify (ecs->event_thread->stop_signal ());
+         notify_signal_received (ecs->event_thread->stop_signal ());
          target_terminal::inferior ();
        }
 
@@ -6998,9 +7036,9 @@ process_event_stop_test (struct execution_control_state *ecs)
        = ecs->event_thread->control.step_resume_breakpoint;
 
       if (sr_bp != nullptr
-         && sr_bp->loc->permanent
+         && sr_bp->first_loc ().permanent
          && sr_bp->type == bp_hp_step_resume
-         && sr_bp->loc->address == ecs->event_thread->prev_pc)
+         && sr_bp->first_loc ().address == ecs->event_thread->prev_pc)
        {
          infrun_debug_printf ("stepped permanent breakpoint, stopped in handler");
          delete_step_resume_breakpoint (ecs->event_thread);
@@ -8489,18 +8527,6 @@ end_stepping_range (struct execution_control_state *ecs)
    the interpreters, through observers.  Interpreters then call these
    with whatever uiout is right.  */
 
-void
-print_end_stepping_range_reason (struct ui_out *uiout)
-{
-  /* For CLI-like interpreters, print nothing.  */
-
-  if (uiout->is_mi_like_p ())
-    {
-      uiout->field_string ("reason",
-                          async_reason_lookup (EXEC_ASYNC_END_STEPPING_RANGE));
-    }
-}
-
 void
 print_signal_exited_reason (struct ui_out *uiout, enum gdb_signal siggnal)
 {
@@ -8830,7 +8856,7 @@ normal_stop ()
   update_thread_list ();
 
   if (last.kind () == TARGET_WAITKIND_STOPPED && stopped_by_random_signal)
-    gdb::observers::signal_received.notify (inferior_thread ()->stop_signal ());
+    notify_signal_received (inferior_thread ()->stop_signal ());
 
   /* As with the notification of thread events, we want to delay
      notifying the user that we've switched thread context until
@@ -8947,12 +8973,10 @@ normal_stop ()
 
   /* Notify observers about the stop.  This is where the interpreters
      print the stop event.  */
-  if (inferior_ptid != null_ptid)
-    gdb::observers::normal_stop.notify (inferior_thread ()->control.stop_bpstat,
-                                       stop_print_frame);
-  else
-    gdb::observers::normal_stop.notify (nullptr, stop_print_frame);
-
+  notify_normal_stop ((inferior_ptid != null_ptid
+                      ? inferior_thread ()->control.stop_bpstat
+                      : nullptr),
+                     stop_print_frame);
   annotate_stopped ();
 
   if (target_has_execution ())