]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/infcmd.c
PR31796, Internal error in write_function_pdata at obj-coff-seh
[thirdparty/binutils-gdb.git] / gdb / infcmd.c
index b9fb121dbbe62015f88e78878ec5ac02bb28357a..02f6f0b3683fe83ff506e57fb2d84cc1cbef6dcf 100644 (file)
@@ -1,6 +1,6 @@
 /* Memory-access and commands for "inferior" process, for GDB.
 
-   Copyright (C) 1986-2022 Free Software Foundation, Inc.
+   Copyright (C) 1986-2024 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -17,7 +17,6 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#include "defs.h"
 #include "arch-utils.h"
 #include "symtab.h"
 #include "gdbtypes.h"
@@ -26,7 +25,7 @@
 #include "infrun.h"
 #include "gdbsupport/environ.h"
 #include "value.h"
-#include "gdbcmd.h"
+#include "cli/cli-cmds.h"
 #include "symfile.h"
 #include "gdbcore.h"
 #include "target.h"
 #include "inf-loop.h"
 #include "linespec.h"
 #include "thread-fsm.h"
-#include "top.h"
+#include "ui.h"
 #include "interps.h"
 #include "skip.h"
-#include "gdbsupport/gdb_optional.h"
+#include <optional>
 #include "source.h"
 #include "cli/cli-style.h"
 
@@ -65,23 +64,6 @@ static void step_1 (int, int, const char *);
 #define ERROR_NO_INFERIOR \
    if (!target_has_execution ()) error (_("The program is not being run."));
 
-/* Scratch area where string containing arguments to give to the
-   program will be stored by 'set args'.  As soon as anything is
-   stored, notice_args_set will move it into per-inferior storage.
-   Arguments are separated by spaces.  Empty string (pointer to '\0')
-   means no args.  */
-
-static std::string inferior_args_scratch;
-
-/* Scratch area where the new cwd will be stored by 'set cwd'.  */
-
-static std::string inferior_cwd_scratch;
-
-/* Scratch area where 'set inferior-tty' will store user-provided value.
-   We'll immediate copy it into per-inferior storage.  */
-
-static std::string inferior_io_terminal_scratch;
-
 /* Pid of our debugged inferior, or 0 if no inferior now.
    Since various parts of infrun.c test this to see whether there is a program
    being debugged it should be nonzero (currently 3 is used) for remote
@@ -98,17 +80,31 @@ enum stop_stack_kind stop_stack_dummy;
 
 int stopped_by_random_signal;
 
+
+/* Whether "finish" should print the value.  */
+
+static bool finish_print = true;
+
 \f
 
+/* Store the new value passed to 'set inferior-tty'.  */
+
 static void
-set_inferior_tty_command (const char *args, int from_tty,
-                         struct cmd_list_element *c)
+set_tty_value (const std::string &tty)
 {
-  /* CLI has assigned the user-provided value to inferior_io_terminal_scratch.
-     Now route it to current inferior.  */
-  current_inferior ()->set_tty (inferior_io_terminal_scratch);
+  current_inferior ()->set_tty (tty);
 }
 
+/* Get the current 'inferior-tty' value.  */
+
+static const std::string &
+get_tty_value ()
+{
+  return current_inferior ()->tty ();
+}
+
+/* Implement 'show inferior-tty' command.  */
+
 static void
 show_inferior_tty_command (struct ui_file *file, int from_tty,
                           struct cmd_list_element *c, const char *value)
@@ -117,39 +113,38 @@ show_inferior_tty_command (struct ui_file *file, int from_tty,
      directly.  */
   const std::string &inferior_tty = current_inferior ()->tty ();
 
-  fprintf_filtered (file,
-                   _("Terminal for future runs of program being debugged "
-                     "is \"%s\".\n"), inferior_tty.c_str ());
+  gdb_printf (file,
+             _("Terminal for future runs of program being debugged "
+               "is \"%s\".\n"), inferior_tty.c_str ());
 }
 
-void
-set_inferior_args_vector (int argc, char **argv)
+/* Store the new value passed to 'set args'.  */
+
+static void
+set_args_value (const std::string &args)
 {
-  gdb::array_view<char * const> args (argv, argc);
-  std::string n = construct_inferior_arguments (args);
-  current_inferior ()->set_args (std::move (n));
+  current_inferior ()->set_args (args);
 }
 
-/* Notice when `set args' is run.  */
+/* Return the value for 'show args' to display.  */
 
-static void
-set_args_command (const char *args, int from_tty, struct cmd_list_element *c)
+static const std::string &
+get_args_value ()
 {
-  /* CLI has assigned the user-provided value to inferior_args_scratch.
-     Now route it to current inferior.  */
-  current_inferior ()->set_args (inferior_args_scratch);
+  return current_inferior ()->args ();
 }
 
-/* Notice when `show args' is run.  */
+/* Callback to implement 'show args' command.  */
 
 static void
 show_args_command (struct ui_file *file, int from_tty,
                   struct cmd_list_element *c, const char *value)
 {
-  /* Note that we ignore the passed-in value in favor of computing it
-     directly.  */
-  deprecated_show_value_hack (file, from_tty, c,
-                             current_inferior ()->args ().c_str ());
+  /* Ignore the passed in value, pull the argument directly from the
+     inferior.  However, these should always be the same.  */
+  gdb_printf (file, _("\
+Argument list to give program being debugged when it is started is \"%s\".\n"),
+             current_inferior ()->args ().c_str ());
 }
 
 /* See gdbsupport/common-inferior.h.  */
@@ -160,12 +155,12 @@ get_inferior_cwd ()
   return current_inferior ()->cwd ();
 }
 
-/* Handle the 'set cwd' command.  */
+/* Store the new value passed to 'set cwd'.  */
 
 static void
-set_cwd_command (const char *args, int from_tty, struct cmd_list_element *c)
+set_cwd_value (const std::string &args)
 {
-  current_inferior ()->set_cwd (inferior_cwd_scratch);
+  current_inferior ()->set_cwd (args);
 }
 
 /* Handle the 'show cwd' command.  */
@@ -177,16 +172,16 @@ show_cwd_command (struct ui_file *file, int from_tty,
   const std::string &cwd = current_inferior ()->cwd ();
 
   if (cwd.empty ())
-    fprintf_filtered (file,
-                     _("\
+    gdb_printf (file,
+               _("\
 You have not set the inferior's current working directory.\n\
 The inferior will inherit GDB's cwd if native debugging, or the remote\n\
 server's cwd if remote debugging.\n"));
   else
-    fprintf_filtered (file,
-                     _("Current working directory that will be used "
-                       "when starting the inferior is \"%s\".\n"),
-                     cwd.c_str ());
+    gdb_printf (file,
+               _("Current working directory that will be used "
+                 "when starting the inferior is \"%s\".\n"),
+               cwd.c_str ());
 }
 
 
@@ -202,10 +197,10 @@ strip_bg_char (const char *args, int *bg_char_p)
 {
   const char *p;
 
-  if (args == NULL || *args == '\0')
+  if (args == nullptr || *args == '\0')
     {
       *bg_char_p = 0;
-      return NULL;
+      return nullptr;
     }
 
   p = args + strlen (args);
@@ -238,6 +233,9 @@ post_create_inferior (int from_tty)
   /* Be sure we own the terminal in case write operations are performed.  */ 
   target_terminal::ours_for_output ();
 
+  infrun_debug_show_threads ("threads in the newly created inferior",
+                            current_inferior ()->non_exited_threads ());
+
   /* If the target hasn't taken care of this already, do it now.
      Targets which need to access registers during to_open,
      to_create_inferior, or to_attach should do it earlier; but many
@@ -287,8 +285,8 @@ post_create_inferior (int from_tty)
 
          /* If the solist is global across processes, there's no need to
             refetch it here.  */
-         if (!gdbarch_has_global_solist (target_gdbarch ()))
-           solib_add (NULL, 0, auto_solib_add);
+         if (!gdbarch_has_global_solist (current_inferior ()->arch ()))
+           solib_add (nullptr, 0, auto_solib_add);
        }
     }
 
@@ -415,7 +413,11 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
   /* Insert temporary breakpoint in main function if requested.  */
   if (run_how == RUN_STOP_AT_MAIN)
     {
-      std::string arg = string_printf ("-qualified %s", main_name ());
+      /* To avoid other inferiors hitting this breakpoint, make it
+        inferior-specific.  */
+      std::string arg = string_printf ("-qualified %s inferior %d",
+                                      main_name (),
+                                      current_inferior ()->num);
       tbreak_command (arg.c_str (), 0);
     }
 
@@ -430,15 +432,16 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
      want them to go away (PR 2207).  This is probably reasonable.  */
 
   /* If there were other args, beside '&', process them.  */
-  if (args != NULL)
+  if (args != nullptr)
     current_inferior ()->set_args (args);
 
   if (from_tty)
     {
-      uiout->field_string (NULL, "Starting program");
+      uiout->field_string (nullptr, "Starting program");
       uiout->text (": ");
       if (exec_file)
-       uiout->field_string ("execfile", exec_file);
+       uiout->field_string ("execfile", exec_file,
+                            file_name_style.style ());
       uiout->spaces (1);
       uiout->field_string ("infargs", current_inferior ()->args ());
       uiout->text ("\n");
@@ -451,7 +454,10 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
                               from_tty);
   /* to_create_inferior should push the target, so after this point we
      shouldn't refer to run_target again.  */
-  run_target = NULL;
+  run_target = nullptr;
+
+  infrun_debug_show_threads ("immediately after create_process",
+                            current_inferior ()->non_exited_threads ());
 
   /* We're starting off a new process.  When we get out of here, in
      non-stop mode, finish the state of all threads of that process,
@@ -488,7 +494,8 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
 
   /* Start the target running.  Do not use -1 continuation as it would skip
      breakpoint right at the entry point.  */
-  proceed (regcache_read_pc (get_current_regcache ()), GDB_SIGNAL_0);
+  proceed (regcache_read_pc (get_thread_regcache (inferior_thread ())),
+          GDB_SIGNAL_0);
 
   /* Since there was no error, there's no need to finish the thread
      states here.  */
@@ -606,7 +613,7 @@ continue_1 (int all_threads)
       scoped_disable_commit_resumed disable_commit_resumed
        ("continue all threads in non-stop");
 
-      iterate_over_threads (proceed_thread_callback, NULL);
+      iterate_over_threads (proceed_thread_callback, nullptr);
 
       if (current_ui->prompt_state == PROMPT_BLOCKED)
        {
@@ -651,27 +658,27 @@ continue_command (const char *args, int from_tty)
   gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec);
   args = stripped.get ();
 
-  if (args != NULL)
+  if (args != nullptr)
     {
       if (startswith (args, "-a"))
        {
          all_threads_p = true;
          args += sizeof ("-a") - 1;
          if (*args == '\0')
-           args = NULL;
+           args = nullptr;
        }
     }
 
   if (!non_stop && all_threads_p)
     error (_("`-a' is meaningless in all-stop mode."));
 
-  if (args != NULL && all_threads_p)
+  if (args != nullptr && all_threads_p)
     error (_("Can't resume all threads and specify "
             "proceed count simultaneously."));
 
   /* If we have an argument left, set proceed count of breakpoint we
      stopped at.  */
-  if (args != NULL)
+  if (args != nullptr)
     {
       bpstat *bs = nullptr;
       int num, stat;
@@ -686,9 +693,9 @@ continue_command (const char *args, int from_tty)
          ptid_t last_ptid;
 
          get_last_target_status (&last_target, &last_ptid, nullptr);
-         tp = find_thread_ptid (last_target, last_ptid);
+         tp = last_target->find_thread (last_ptid);
        }
-      if (tp != NULL)
+      if (tp != nullptr)
        bs = tp->control.stop_bpstat;
 
       while ((stat = bpstat_num (&bs, &num)) != 0)
@@ -700,18 +707,17 @@ continue_command (const char *args, int from_tty)
            /* set_ignore_count prints a message ending with a period.
               So print two spaces before "Continuing.".  */
            if (from_tty)
-             printf_filtered ("  ");
+             gdb_printf ("  ");
            stopped = 1;
          }
 
       if (!stopped && from_tty)
        {
-         printf_filtered
+         gdb_printf
            ("Not stopped at any breakpoint; argument ignored.\n");
        }
     }
 
-  ERROR_NO_INFERIOR;
   ensure_not_tfind_mode ();
 
   if (!non_stop || !all_threads_p)
@@ -723,7 +729,7 @@ continue_command (const char *args, int from_tty)
   prepare_execution_command (current_inferior ()->top_target (), async_exec);
 
   if (from_tty)
-    printf_filtered (_("Continuing.\n"));
+    gdb_printf (_("Continuing.\n"));
 
   continue_1 (all_threads_p);
 }
@@ -737,7 +743,7 @@ set_step_frame (thread_info *tp)
      inferior_ptid value.  */
   gdb_assert (inferior_ptid == tp->ptid);
 
-  frame_info *frame = get_current_frame ();
+  frame_info_ptr frame = get_current_frame ();
 
   symtab_and_line sal = find_frame_sal (frame);
   set_step_info (tp, frame, sal);
@@ -848,7 +854,7 @@ step_1 (int skip_subroutines, int single_inst, const char *count_string)
      steps.  */
   thr = inferior_thread ();
   step_sm = new step_command_fsm (command_interp ());
-  thr->thread_fsm = step_sm;
+  thr->set_thread_fsm (std::unique_ptr<thread_fsm> (step_sm));
 
   step_command_fsm_prepare (step_sm, skip_subroutines,
                            single_inst, count, thr);
@@ -861,12 +867,10 @@ step_1 (int skip_subroutines, int single_inst, const char *count_string)
     proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
   else
     {
-      int proceeded;
-
       /* Stepped into an inline frame.  Pretend that we've
         stopped.  */
-      thr->thread_fsm->clean_up (thr);
-      proceeded = normal_stop ();
+      thr->thread_fsm ()->clean_up (thr);
+      bool proceeded = normal_stop ();
       if (!proceeded)
        inferior_event_handler (INF_EXEC_COMPLETE);
       all_uis_check_sync_execution_done ();
@@ -927,7 +931,7 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
 
   if (sm->count > 0)
     {
-      struct frame_info *frame = get_current_frame ();
+      frame_info_ptr frame = get_current_frame ();
 
       set_step_frame (tp);
 
@@ -940,7 +944,7 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
              && inline_skipped_frames (tp))
            {
              ptid_t resume_ptid;
-             const char *fn = NULL;
+             const char *fn = nullptr;
              symtab_and_line sal;
              struct symbol *sym;
 
@@ -954,7 +958,7 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
              sal = find_frame_sal (frame);
              sym = get_frame_function (frame);
 
-             if (sym != NULL)
+             if (sym != nullptr)
                fn = sym->print_name ();
 
              if (sal.line == 0
@@ -970,6 +974,19 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
                                 &tp->control.step_range_start,
                                 &tp->control.step_range_end);
 
+         if (execution_direction == EXEC_REVERSE)
+           {
+             symtab_and_line sal = find_pc_line (pc, 0);
+             symtab_and_line sal_start
+               = find_pc_line (tp->control.step_range_start, 0);
+
+             if (sal.line == sal_start.line)
+               /* Executing in reverse, the step_range_start address is in
+                  the same line.  We want to stop in the previous line so
+                  move step_range_start before the current line.  */
+               tp->control.step_range_start--;
+           }
+
          /* There's a problem in gcc (PR gcc/98780) that causes missing line
             table entries, which results in a too large stepping range.
             Use inlined_subroutine info to make the range more narrow.  */
@@ -978,9 +995,9 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
              symbol *sym = inline_skipped_symbol (tp);
              if (sym->aclass () == LOC_BLOCK)
                {
-                 const block *block = SYMBOL_BLOCK_VALUE (sym);
-                 if (BLOCK_END (block) < tp->control.step_range_end)
-                   tp->control.step_range_end = BLOCK_END (block);
+                 const block *block = sym->value_block ();
+                 if (block->end () < tp->control.step_range_end)
+                   tp->control.step_range_end = block->end ();
                }
            }
 
@@ -1002,9 +1019,9 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
                error (_("Cannot find bounds of current function"));
 
              target_terminal::ours_for_output ();
-             printf_filtered (_("Single stepping until exit from function %s,"
-                                "\nwhich has no line number information.\n"),
-                              name);
+             gdb_printf (_("Single stepping until exit from function %s,"
+                           "\nwhich has no line number information.\n"),
+                         name);
            }
        }
       else
@@ -1056,9 +1073,21 @@ jump_command (const char *arg, int from_tty)
     error_no_arg (_("starting address"));
 
   std::vector<symtab_and_line> sals
-    = decode_line_with_last_displayed (arg, DECODE_LINE_FUNFIRSTLINE);
+    = decode_line_with_current_source (arg, DECODE_LINE_FUNFIRSTLINE);
   if (sals.size () != 1)
-    error (_("Unreasonable jump request"));
+    {
+      /* If multiple sal-objects were found, try dropping those that aren't
+        from the current symtab.  */
+      struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+      sals.erase (std::remove_if (sals.begin (), sals.end (),
+                 [&] (const symtab_and_line &sal)
+                   {
+                     return sal.symtab != cursal.symtab;
+                   }), sals.end ());
+      if (sals.size () != 1)
+       error (_("Jump request is ambiguous: "
+                "does not resolve to a single address"));
+    }
 
   symtab_and_line &sal = sals[0];
 
@@ -1069,8 +1098,9 @@ jump_command (const char *arg, int from_tty)
 
   /* See if we are trying to jump to another function.  */
   fn = get_frame_function (get_current_frame ());
-  sfn = find_pc_function (sal.pc);
-  if (fn != NULL && sfn != fn)
+  sfn = find_pc_sect_containing_function (sal.pc,
+                                         find_pc_mapped_section (sal.pc));
+  if (fn != nullptr && sfn != fn)
     {
       if (!query (_("Line %d is not in `%s'.  Jump anyway? "), sal.line,
                  fn->print_name ()))
@@ -1080,12 +1110,11 @@ jump_command (const char *arg, int from_tty)
        }
     }
 
-  if (sfn != NULL)
+  if (sfn != nullptr)
     {
       struct obj_section *section;
 
-      fixup_symbol_section (sfn, 0);
-      section = sfn->obj_section (symbol_objfile (sfn));
+      section = sfn->obj_section (sfn->objfile ());
       if (section_is_overlay (section)
          && !section_is_mapped (section))
        {
@@ -1102,9 +1131,9 @@ jump_command (const char *arg, int from_tty)
 
   if (from_tty)
     {
-      printf_filtered (_("Continuing at "));
-      puts_filtered (paddress (gdbarch, addr));
-      printf_filtered (".\n");
+      gdb_printf (_("Continuing at "));
+      gdb_puts (paddress (gdbarch, addr));
+      gdb_printf (".\n");
     }
 
   clear_proceed_status (0);
@@ -1178,11 +1207,11 @@ signal_command (const char *signum_exp, int from_tty)
              && signal_pass_state (tp->stop_signal ()))
            {
              if (!must_confirm)
-               printf_unfiltered (_("Note:\n"));
-             printf_unfiltered (_("  Thread %s previously stopped with signal %s, %s.\n"),
-                                print_thread_id (tp),
-                                gdb_signal_to_name (tp->stop_signal ()),
-                                gdb_signal_to_string (tp->stop_signal ()));
+               gdb_printf (_("Note:\n"));
+             gdb_printf (_("  Thread %s previously stopped with signal %s, %s.\n"),
+                         print_thread_id (tp),
+                         gdb_signal_to_name (tp->stop_signal ()),
+                         gdb_signal_to_string (tp->stop_signal ()));
              must_confirm = 1;
            }
        }
@@ -1198,10 +1227,10 @@ signal_command (const char *signum_exp, int from_tty)
   if (from_tty)
     {
       if (oursig == GDB_SIGNAL_0)
-       printf_filtered (_("Continuing with no signal.\n"));
+       gdb_printf (_("Continuing with no signal.\n"));
       else
-       printf_filtered (_("Continuing with signal %s.\n"),
-                        gdb_signal_to_name (oursig));
+       gdb_printf (_("Continuing with signal %s.\n"),
+                   gdb_signal_to_name (oursig));
     }
 
   clear_proceed_status (0);
@@ -1221,7 +1250,7 @@ queue_signal_command (const char *signum_exp, int from_tty)
   ensure_valid_thread ();
   ensure_not_running ();
 
-  if (signum_exp == NULL)
+  if (signum_exp == nullptr)
     error_no_arg (_("signal number"));
 
   /* It would be even slicker to make signal names be valid expressions,
@@ -1308,7 +1337,7 @@ until_next_fsm::do_async_reply_reason ()
 static void
 until_next_command (int from_tty)
 {
-  struct frame_info *frame;
+  frame_info_ptr frame;
   CORE_ADDR pc;
   struct symbol *func;
   struct symtab_and_line sal;
@@ -1332,10 +1361,10 @@ until_next_command (int from_tty)
     {
       struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc);
 
-      if (msymbol.minsym == NULL)
+      if (msymbol.minsym == nullptr)
        error (_("Execution is not within a known function."));
 
-      tp->control.step_range_start = BMSYMBOL_VALUE_ADDRESS (msymbol);
+      tp->control.step_range_start = msymbol.value_address ();
       /* The upper-bound of step_range is exclusive.  In order to make PC
         within the range, set the step_range_end with PC + 1.  */
       tp->control.step_range_end = pc + 1;
@@ -1344,7 +1373,7 @@ until_next_command (int from_tty)
     {
       sal = find_pc_line (pc, 0);
 
-      tp->control.step_range_start = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (func));
+      tp->control.step_range_start = func->value_block ()->entry_pc ();
       tp->control.step_range_end = sal.end;
     }
   tp->control.may_range_step = 1;
@@ -1355,7 +1384,7 @@ until_next_command (int from_tty)
   delete_longjmp_breakpoint_cleanup lj_deleter (thread);
 
   sm = new until_next_fsm (command_interp (), tp->global_num);
-  tp->thread_fsm = sm;
+  tp->set_thread_fsm (std::unique_ptr<thread_fsm> (sm));
   lj_deleter.release ();
 
   proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
@@ -1393,7 +1422,7 @@ advance_command (const char *arg, int from_tty)
   ensure_valid_thread ();
   ensure_not_running ();
 
-  if (arg == NULL)
+  if (arg == nullptr)
     error_no_arg (_("a location"));
 
   /* Find out whether we must run in the background.  */
@@ -1405,20 +1434,28 @@ advance_command (const char *arg, int from_tty)
   until_break_command (arg, from_tty, 1);
 }
 \f
-/* Return the value of the result of a function at the end of a 'finish'
-   command/BP.  DTOR_DATA (if not NULL) can represent inferior registers
-   right after an inferior call has finished.  */
+/* See inferior.h.  */
 
 struct value *
-get_return_value (struct value *function, struct type *value_type)
+get_return_value (struct symbol *func_symbol, struct value *function)
 {
-  regcache *stop_regs = get_current_regcache ();
+  regcache *stop_regs = get_thread_regcache (inferior_thread ());
   struct gdbarch *gdbarch = stop_regs->arch ();
   struct value *value;
 
-  value_type = check_typedef (value_type);
+  struct type *value_type
+    = check_typedef (func_symbol->type ()->target_type ());
   gdb_assert (value_type->code () != TYPE_CODE_VOID);
 
+  if (is_nocall_function (check_typedef (function->type ())))
+    {
+      warning (_("Function '%s' does not follow the target calling "
+                "convention, cannot determine its returned value."),
+              func_symbol->print_name ());
+
+      return nullptr;
+    }
+
   /* FIXME: 2003-09-27: When returning from a nested inferior function
      call, it's possible (with no help from the architecture vector)
      to locate and return/print a "struct return" value.  This is just
@@ -1426,61 +1463,43 @@ get_return_value (struct value *function, struct type *value_type)
      inferior function call code.  In fact, when inferior function
      calls are made async, this will likely be made the norm.  */
 
-  switch (gdbarch_return_value (gdbarch, function, value_type,
-                               NULL, NULL, NULL))
+  switch (gdbarch_return_value_as_value (gdbarch, function, value_type,
+                                        nullptr, nullptr, nullptr))
     {
     case RETURN_VALUE_REGISTER_CONVENTION:
     case RETURN_VALUE_ABI_RETURNS_ADDRESS:
     case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
-      value = allocate_value (value_type);
-      gdbarch_return_value (gdbarch, function, value_type, stop_regs,
-                           value_contents_raw (value).data (), NULL);
+      gdbarch_return_value_as_value (gdbarch, function, value_type, stop_regs,
+                                    &value, nullptr);
       break;
     case RETURN_VALUE_STRUCT_CONVENTION:
-      value = NULL;
+      value = nullptr;
       break;
     default:
-      internal_error (__FILE__, __LINE__, _("bad switch"));
+      internal_error (_("bad switch"));
     }
 
   return value;
 }
 
-/* The captured function return value/type and its position in the
-   value history.  */
-
-struct return_value_info
-{
-  /* The captured return value.  May be NULL if we weren't able to
-     retrieve it.  See get_return_value.  */
-  struct value *value;
-
-  /* The return type.  In some cases, we'll not be able extract the
-     return value, but we always know the type.  */
-  struct type *type;
-
-  /* If we captured a value, this is the value history index.  */
-  int value_history_index;
-};
-
 /* Helper for print_return_value.  */
 
 static void
 print_return_value_1 (struct ui_out *uiout, struct return_value_info *rv)
 {
-  if (rv->value != NULL)
+  if (rv->value != nullptr)
     {
-      struct value_print_options opts;
-
       /* Print it.  */
       uiout->text ("Value returned is ");
       uiout->field_fmt ("gdb-result-var", "$%d",
                         rv->value_history_index);
       uiout->text (" = ");
-      get_user_print_options (&opts);
 
-      if (opts.finish_print)
+      if (finish_print)
        {
+         struct value_print_options opts;
+         get_user_print_options (&opts);
+
          string_file stb;
          value_print (rv->value, &stb, &opts);
          uiout->field_stream ("return-value", stb);
@@ -1507,7 +1526,7 @@ print_return_value_1 (struct ui_out *uiout, struct return_value_info *rv)
 void
 print_return_value (struct ui_out *uiout, struct return_value_info *rv)
 {
-  if (rv->type == NULL
+  if (rv->type == nullptr
       || check_typedef (rv->type)->code () == TYPE_CODE_VOID)
     return;
 
@@ -1518,7 +1537,7 @@ print_return_value (struct ui_out *uiout, struct return_value_info *rv)
         delete the breakpoint.  */
       print_return_value_1 (uiout, rv);
     }
-  catch (const gdb_exception &ex)
+  catch (const gdb_exception_error &ex)
     {
       exception_print (gdb_stdout, ex);
     }
@@ -1539,6 +1558,12 @@ struct finish_command_fsm : public thread_fsm
      return value.  */
   struct return_value_info return_value_info {};
 
+  /* If the current function uses the "struct return convention",
+     this holds the address at which the value being returned will
+     be stored, or zero if that address could not be determined or
+     the "struct return convention" is not being used.  */
+  CORE_ADDR return_buf;
+
   explicit finish_command_fsm (struct interp *cmd_interp)
     : thread_fsm (cmd_interp)
   {
@@ -1560,26 +1585,31 @@ finish_command_fsm::should_stop (struct thread_info *tp)
 {
   struct return_value_info *rv = &return_value_info;
 
-  if (function != NULL
+  if (function != nullptr
       && bpstat_find_breakpoint (tp->control.stop_bpstat,
-                                breakpoint.get ()) != NULL)
+                                breakpoint.get ()) != nullptr)
     {
       /* We're done.  */
       set_finished ();
 
-      rv->type = TYPE_TARGET_TYPE (function->type ());
-      if (rv->type == NULL)
-       internal_error (__FILE__, __LINE__,
-                       _("finish_command: function has no target type"));
+      rv->type = function->type ()->target_type ();
+      if (rv->type == nullptr)
+       internal_error (_("finish_command: function has no target type"));
 
       if (check_typedef (rv->type)->code () != TYPE_CODE_VOID)
        {
          struct value *func;
 
-         func = read_var_value (function, NULL, get_current_frame ());
-         rv->value = get_return_value (func, rv->type);
-         if (rv->value != NULL)
-           rv->value_history_index = record_latest_value (rv->value);
+         func = read_var_value (function, nullptr, get_current_frame ());
+
+         if (return_buf != 0)
+           /* Retrieve return value from the buffer where it was saved.  */
+             rv->value = value_at (rv->type, return_buf);
+         else
+             rv->value = get_return_value (function, func);
+
+         if (rv->value != nullptr)
+           rv->value_history_index = rv->value->record_latest ();
        }
     }
   else if (tp->control.stop_step)
@@ -1632,13 +1662,28 @@ finish_backward (struct finish_command_fsm *sm)
   struct thread_info *tp = inferior_thread ();
   CORE_ADDR pc;
   CORE_ADDR func_addr;
+  CORE_ADDR alt_entry_point;
+  CORE_ADDR entry_point;
+  frame_info_ptr frame = get_selected_frame (nullptr);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
 
   pc = get_frame_pc (get_current_frame ());
 
-  if (find_pc_partial_function (pc, NULL, &func_addr, NULL) == 0)
+  if (find_pc_partial_function (pc, nullptr, &func_addr, nullptr) == 0)
     error (_("Cannot find bounds of current function"));
 
   sal = find_pc_line (func_addr, 0);
+  alt_entry_point = sal.pc;
+  entry_point = alt_entry_point;
+
+  if (gdbarch_skip_entrypoint_p (gdbarch))
+    /* Some architectures, like PowerPC use local and global entry points.
+       There is only one Entry Point (GEP = LEP) for other architectures.
+       The GEP is an alternate entry point.  The LEP is the normal entry point.
+       The value of entry_point was initialized to the alternate entry point
+       (GEP).  It will be adjusted to the normal entry point if the function
+       has two entry points.  */
+    entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
 
   tp->control.proceed_to_finish = 1;
   /* Special case: if we're sitting at the function entry point,
@@ -1650,15 +1695,12 @@ finish_backward (struct finish_command_fsm *sm)
      no way that a function up the stack can have a return address
      that's equal to its entry point.  */
 
-  if (sal.pc != pc)
+  if ((pc < alt_entry_point) || (pc > entry_point))
     {
-      struct frame_info *frame = get_selected_frame (NULL);
-      struct gdbarch *gdbarch = get_frame_arch (frame);
-
-      /* Set a step-resume at the function's entry point.  Once that's
-        hit, we'll do one more step backwards.  */
+      /* We are in the body of the function.  Set a breakpoint to go back to
+        the normal entry point.  */
       symtab_and_line sr_sal;
-      sr_sal.pc = sal.pc;
+      sr_sal.pc = entry_point;
       sr_sal.pspace = get_frame_program_space (frame);
       insert_step_resume_breakpoint_at_sal (gdbarch,
                                            sr_sal, null_frame_id);
@@ -1667,8 +1709,12 @@ finish_backward (struct finish_command_fsm *sm)
     }
   else
     {
-      /* We're almost there -- we just need to back up by one more
-        single-step.  */
+      /* We are either at one of the entry points or between the entry points.
+        If we are not at the alt_entry point, go back to the alt_entry_point
+        If we at the normal entry point step back one instruction, when we
+        stop we will determine if we entered via the entry point or the
+        alternate entry point.  If we are at the alternate entry point,
+        single step back to the function call.  */
       tp->control.step_range_start = tp->control.step_range_end = 1;
       proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
     }
@@ -1678,7 +1724,7 @@ finish_backward (struct finish_command_fsm *sm)
    frame that called the function we're about to step out of.  */
 
 static void
-finish_forward (struct finish_command_fsm *sm, struct frame_info *frame)
+finish_forward (struct finish_command_fsm *sm, const frame_info_ptr &frame)
 {
   struct frame_id frame_id = get_frame_id (frame);
   struct gdbarch *gdbarch = get_frame_arch (frame);
@@ -1692,9 +1738,6 @@ finish_forward (struct finish_command_fsm *sm, struct frame_info *frame)
                                             get_stack_frame_id (frame),
                                             bp_finish);
 
-  /* set_momentary_breakpoint invalidates FRAME.  */
-  frame = NULL;
-
   set_longjmp_breakpoint (tp, frame_id);
 
   /* We want to print return value, please...  */
@@ -1705,21 +1748,22 @@ finish_forward (struct finish_command_fsm *sm, struct frame_info *frame)
 
 /* Skip frames for "finish".  */
 
-static struct frame_info *
-skip_finish_frames (struct frame_info *frame)
+static frame_info_ptr
+skip_finish_frames (const frame_info_ptr &initial_frame)
 {
-  struct frame_info *start;
+  frame_info_ptr start;
+  frame_info_ptr frame = initial_frame;
 
   do
     {
       start = frame;
 
       frame = skip_tailcall_frames (frame);
-      if (frame == NULL)
+      if (frame == nullptr)
        break;
 
       frame = skip_unwritable_frames (frame);
-      if (frame == NULL)
+      if (frame == nullptr)
        break;
     }
   while (start != frame);
@@ -1733,7 +1777,7 @@ skip_finish_frames (struct frame_info *frame)
 static void
 finish_command (const char *arg, int from_tty)
 {
-  struct frame_info *frame;
+  frame_info_ptr frame;
   int async_exec;
   struct finish_command_fsm *sm;
   struct thread_info *tp;
@@ -1762,7 +1806,7 @@ finish_command (const char *arg, int from_tty)
 
   sm = new finish_command_fsm (command_interp ());
 
-  tp->thread_fsm = sm;
+  tp->set_thread_fsm (std::unique_ptr<thread_fsm> (sm));
 
   /* Finishing from an inline frame is completely different.  We don't
      try to show the "return value" - no way to locate it.  */
@@ -1783,8 +1827,8 @@ finish_command (const char *arg, int from_tty)
         source.  */
       if (from_tty)
        {
-         printf_filtered (_("Run till exit from "));
-         print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
+         gdb_printf (_("Run till exit from "));
+         print_stack_frame (get_selected_frame (nullptr), 1, LOCATION, 0);
        }
 
       proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
@@ -1792,26 +1836,49 @@ finish_command (const char *arg, int from_tty)
     }
 
   /* Find the function we will return from.  */
+  frame_info_ptr callee_frame = get_selected_frame (nullptr);
+  sm->function = find_pc_function (get_frame_pc (callee_frame));
+  sm->return_buf = 0;    /* Initialize buffer address is not available.  */
 
-  sm->function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
+  /* Determine the return convention.  If it is RETURN_VALUE_STRUCT_CONVENTION,
+     attempt to determine the address of the return buffer.  */
+  if (sm->function != nullptr)
+    {
+      enum return_value_convention return_value;
+      struct gdbarch *gdbarch = get_frame_arch (callee_frame);
+
+      struct type * val_type
+       = check_typedef (sm->function->type ()->target_type ());
+
+      return_value
+       = gdbarch_return_value_as_value (gdbarch,
+                                        read_var_value (sm->function, nullptr,
+                                                        callee_frame),
+                                        val_type, nullptr, nullptr, nullptr);
+
+      if (return_value == RETURN_VALUE_STRUCT_CONVENTION
+         && val_type->code () != TYPE_CODE_VOID)
+       sm->return_buf = gdbarch_get_return_buf_addr (gdbarch, val_type,
+                                                     callee_frame);
+    }
 
   /* Print info on the selected frame, including level number but not
      source.  */
   if (from_tty)
     {
       if (execution_direction == EXEC_REVERSE)
-       printf_filtered (_("Run back to call of "));
+       gdb_printf (_("Run back to call of "));
       else
        {
-         if (sm->function != NULL && TYPE_NO_RETURN (sm->function->type ())
+         if (sm->function != nullptr && TYPE_NO_RETURN (sm->function->type ())
              && !query (_("warning: Function %s does not return normally.\n"
                           "Try to finish anyway? "),
                         sm->function->print_name ()))
            error (_("Not confirmed."));
-         printf_filtered (_("Run till exit from "));
+         gdb_printf (_("Run till exit from "));
        }
 
-      print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
+      print_stack_frame (callee_frame, 1, LOCATION, 0);
     }
 
   if (execution_direction == EXEC_REVERSE)
@@ -1820,7 +1887,7 @@ finish_command (const char *arg, int from_tty)
     {
       frame = skip_finish_frames (frame);
 
-      if (frame == NULL)
+      if (frame == nullptr)
        error (_("Cannot find the caller frame."));
 
       finish_forward (sm, frame);
@@ -1831,43 +1898,80 @@ finish_command (const char *arg, int from_tty)
 static void
 info_program_command (const char *args, int from_tty)
 {
-  bpstat *bs;
-  int num, stat;
-  ptid_t ptid;
-  process_stratum_target *proc_target;
+  scoped_restore_current_thread restore_thread;
 
-  if (!target_has_execution ())
-    {
-      printf_filtered (_("The program being debugged is not being run.\n"));
-      return;
-    }
+  thread_info *tp;
+
+  /* In non-stop, since every thread is controlled individually, we'll
+     show execution info about the current thread.  In all-stop, we'll
+     show execution info about the last stop.  */
 
   if (non_stop)
     {
-      ptid = inferior_ptid;
-      proc_target = current_inferior ()->process_target ();
+      if (!target_has_execution ())
+       {
+         gdb_printf (_("The program being debugged is not being run.\n"));
+         return;
+       }
+
+      if (inferior_ptid == null_ptid)
+       error (_("No selected thread."));
+
+      tp = inferior_thread ();
+
+      gdb_printf (_("Selected thread %s (%s).\n"),
+                 print_thread_id (tp),
+                 target_pid_to_str (tp->ptid).c_str ());
+
+      if (tp->state == THREAD_EXITED)
+       {
+         gdb_printf (_("Selected thread has exited.\n"));
+         return;
+       }
+      else if (tp->state == THREAD_RUNNING)
+       {
+         gdb_printf (_("Selected thread is running.\n"));
+         return;
+       }
     }
   else
-    get_last_target_status (&proc_target, &ptid, nullptr);
+    {
+      tp = get_previous_thread ();
+
+      if (tp == nullptr)
+       {
+         gdb_printf (_("The program being debugged is not being run.\n"));
+         return;
+       }
+
+      switch_to_thread (tp);
 
-  if (ptid == null_ptid || ptid == minus_one_ptid)
-    error (_("No selected thread."));
+      gdb_printf (_("Last stopped for thread %s (%s).\n"),
+                 print_thread_id (tp),
+                 target_pid_to_str (tp->ptid).c_str ());
 
-  thread_info *tp = find_thread_ptid (proc_target, ptid);
+      if (tp->state == THREAD_EXITED)
+       {
+         gdb_printf (_("Thread has since exited.\n"));
+         return;
+       }
 
-  if (tp->state == THREAD_EXITED)
-    error (_("Invalid selected thread."));
-  else if (tp->state == THREAD_RUNNING)
-    error (_("Selected thread is running."));
+      if (tp->state == THREAD_RUNNING)
+       {
+         gdb_printf (_("Thread is now running.\n"));
+         return;
+       }
+    }
 
-  bs = tp->control.stop_bpstat;
-  stat = bpstat_num (&bs, &num);
+  int num;
+  bpstat *bs = tp->control.stop_bpstat;
+  int stat = bpstat_num (&bs, &num);
 
   target_files_info ();
-  printf_filtered (_("Program stopped at %s.\n"),
-                  paddress (target_gdbarch (), tp->stop_pc ()));
+  gdb_printf (_("Program stopped at %s.\n"),
+             paddress (current_inferior ()->arch (), tp->stop_pc ()));
   if (tp->control.stop_step)
-    printf_filtered (_("It stopped after being stepped.\n"));
+    gdb_printf (_("It stopped after being stepped.\n"));
   else if (stat != 0)
     {
       /* There may be several breakpoints in the same place, so this
@@ -1876,25 +1980,25 @@ info_program_command (const char *args, int from_tty)
        {
          if (stat < 0)
            {
-             printf_filtered (_("It stopped at a breakpoint "
-                                "that has since been deleted.\n"));
+             gdb_printf (_("It stopped at a breakpoint "
+                           "that has since been deleted.\n"));
            }
          else
-           printf_filtered (_("It stopped at breakpoint %d.\n"), num);
+           gdb_printf (_("It stopped at breakpoint %d.\n"), num);
          stat = bpstat_num (&bs, &num);
        }
     }
   else if (tp->stop_signal () != GDB_SIGNAL_0)
     {
-      printf_filtered (_("It stopped with signal %s, %s.\n"),
-                      gdb_signal_to_name (tp->stop_signal ()),
-                      gdb_signal_to_string (tp->stop_signal ()));
+      gdb_printf (_("It stopped with signal %s, %s.\n"),
+                 gdb_signal_to_name (tp->stop_signal ()),
+                 gdb_signal_to_string (tp->stop_signal ()));
     }
 
   if (from_tty)
     {
-      printf_filtered (_("Type \"info stack\" or \"info "
-                        "registers\" for more information.\n"));
+      gdb_printf (_("Type \"info stack\" or \"info "
+                   "registers\" for more information.\n"));
     }
 }
 \f
@@ -1907,26 +2011,26 @@ environment_info (const char *var, int from_tty)
 
       if (val)
        {
-         puts_filtered (var);
-         puts_filtered (" = ");
-         puts_filtered (val);
-         puts_filtered ("\n");
+         gdb_puts (var);
+         gdb_puts (" = ");
+         gdb_puts (val);
+         gdb_puts ("\n");
        }
       else
        {
-         puts_filtered ("Environment variable \"");
-         puts_filtered (var);
-         puts_filtered ("\" not defined.\n");
+         gdb_puts ("Environment variable \"");
+         gdb_puts (var);
+         gdb_puts ("\" not defined.\n");
        }
     }
   else
     {
       char **envp = current_inferior ()->environment.envp ();
 
-      for (int idx = 0; envp[idx] != NULL; ++idx)
+      for (int idx = 0; envp[idx] != nullptr; ++idx)
        {
-         puts_filtered (envp[idx]);
-         puts_filtered ("\n");
+         gdb_puts (envp[idx]);
+         gdb_puts ("\n");
        }
     }
 }
@@ -1984,9 +2088,9 @@ set_environment_command (const char *arg, int from_tty)
   std::string var (arg, p - arg);
   if (nullset)
     {
-      printf_filtered (_("Setting environment variable "
-                        "\"%s\" to null value.\n"),
-                      var.c_str ());
+      gdb_printf (_("Setting environment variable "
+                   "\"%s\" to null value.\n"),
+                 var.c_str ());
       current_inferior ()->environment.set (var.c_str (), "");
     }
   else
@@ -2014,9 +2118,9 @@ static const char path_var_name[] = "PATH";
 static void
 path_info (const char *args, int from_tty)
 {
-  puts_filtered ("Executable and object file path: ");
-  puts_filtered (current_inferior ()->environment.get (path_var_name));
-  puts_filtered ("\n");
+  gdb_puts ("Executable and object file path: ");
+  gdb_puts (current_inferior ()->environment.get (path_var_name));
+  gdb_puts ("\n");
 }
 
 /* Add zero or more directories to the front of the execution path.  */
@@ -2035,7 +2139,7 @@ path_command (const char *dirname, int from_tty)
   mod_path (dirname, exec_path);
   current_inferior ()->environment.set (path_var_name, exec_path.c_str ());
   if (from_tty)
-    path_info (NULL, from_tty);
+    path_info (nullptr, from_tty);
 }
 \f
 
@@ -2057,7 +2161,7 @@ default_print_one_register_info (struct ui_file *file,
                                 const char *name,
                                 struct value *val)
 {
-  struct type *regtype = value_type (val);
+  struct type *regtype = val->type ();
   int print_raw_format;
   string_file format_stream;
   enum tab_stops
@@ -2071,8 +2175,8 @@ default_print_one_register_info (struct ui_file *file,
   format_stream.puts (name);
   pad_to_column (format_stream, value_column_1);
 
-  print_raw_format = (value_entirely_available (val)
-                     && !value_optimized_out (val));
+  print_raw_format = (val->entirely_available ()
+                     && !val->optimized_out ());
 
   /* If virtual format is floating, print it that way, and in raw
      hex.  */
@@ -2080,11 +2184,11 @@ default_print_one_register_info (struct ui_file *file,
       || regtype->code () == TYPE_CODE_DECFLOAT)
     {
       struct value_print_options opts;
-      const gdb_byte *valaddr = value_contents_for_printing (val).data ();
+      const gdb_byte *valaddr = val->contents_for_printing ().data ();
       enum bfd_endian byte_order = type_byte_order (regtype);
 
       get_user_print_options (&opts);
-      opts.deref_ref = 1;
+      opts.deref_ref = true;
 
       common_val_print (val, &format_stream, 0, &opts, current_language);
 
@@ -2092,7 +2196,7 @@ default_print_one_register_info (struct ui_file *file,
        {
          pad_to_column (format_stream, value_column_2);
          format_stream.puts ("(raw ");
-         print_hex_chars (&format_stream, valaddr, TYPE_LENGTH (regtype),
+         print_hex_chars (&format_stream, valaddr, regtype->length (),
                           byte_order, true);
          format_stream.putc (')');
        }
@@ -2103,7 +2207,7 @@ default_print_one_register_info (struct ui_file *file,
 
       /* Print the register in hex.  */
       get_formatted_print_options (&opts, 'x');
-      opts.deref_ref = 1;
+      opts.deref_ref = true;
       common_val_print (val, &format_stream, 0, &opts, current_language);
       /* If not a vector register, print it also according to its
         natural format.  */
@@ -2111,13 +2215,13 @@ default_print_one_register_info (struct ui_file *file,
        {
          pad_to_column (format_stream, value_column_2);
          get_user_print_options (&opts);
-         opts.deref_ref = 1;
+         opts.deref_ref = true;
          common_val_print (val, &format_stream, 0, &opts, current_language);
        }
     }
 
-  fputs_filtered (format_stream.c_str (), file);
-  fprintf_filtered (file, "\n");
+  gdb_puts (format_stream.c_str (), file);
+  gdb_printf (file, "\n");
 }
 
 /* Print out the machine register regnum.  If regnum is -1, print all
@@ -2134,7 +2238,7 @@ default_print_one_register_info (struct ui_file *file,
 void
 default_print_registers_info (struct gdbarch *gdbarch,
                              struct ui_file *file,
-                             struct frame_info *frame,
+                             const frame_info_ptr &frame,
                              int regnum, int print_all)
 {
   int i;
@@ -2165,25 +2269,24 @@ default_print_registers_info (struct gdbarch *gdbarch,
 
       /* If the register name is empty, it is undefined for this
         processor, so don't display anything.  */
-      if (gdbarch_register_name (gdbarch, i) == NULL
-         || *(gdbarch_register_name (gdbarch, i)) == '\0')
+      if (*(gdbarch_register_name (gdbarch, i)) == '\0')
        continue;
 
-      default_print_one_register_info (file,
-                                      gdbarch_register_name (gdbarch, i),
-                                      value_of_register (i, frame));
+      default_print_one_register_info
+       (file, gdbarch_register_name (gdbarch, i),
+        value_of_register (i, get_next_frame_sentinel_okay (frame)));
     }
 }
 
 void
 registers_info (const char *addr_exp, int fpregs)
 {
-  struct frame_info *frame;
+  frame_info_ptr frame;
   struct gdbarch *gdbarch;
 
   if (!target_has_registers ())
     error (_("The program has no registers now."));
-  frame = get_selected_frame (NULL);
+  frame = get_selected_frame (nullptr);
   gdbarch = get_frame_arch (frame);
 
   if (!addr_exp)
@@ -2247,19 +2350,19 @@ registers_info (const char *addr_exp, int fpregs)
 
       /* A register group?  */
       {
-       struct reggroup *group;
-
-       for (group = reggroup_next (gdbarch, NULL);
-            group != NULL;
-            group = reggroup_next (gdbarch, group))
+       const struct reggroup *group = nullptr;
+       for (const struct reggroup *g : gdbarch_reggroups (gdbarch))
          {
            /* Don't bother with a length check.  Should the user
               enter a short register group name, go with the first
               group that matches.  */
-           if (strncmp (start, reggroup_name (group), end - start) == 0)
-             break;
+           if (strncmp (start, g->name (), end - start) == 0)
+             {
+               group = g;
+               break;
+             }
          }
-       if (group != NULL)
+       if (group != nullptr)
          {
            int regnum;
 
@@ -2295,7 +2398,7 @@ info_registers_command (const char *addr_exp, int from_tty)
 
 static void
 print_vector_info (struct ui_file *file,
-                  struct frame_info *frame, const char *args)
+                  const frame_info_ptr &frame, const char *args)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
 
@@ -2315,7 +2418,7 @@ print_vector_info (struct ui_file *file,
            }
        }
       if (!printed_something)
-       fprintf_filtered (file, "No vector information\n");
+       gdb_printf (file, "No vector information\n");
     }
 }
 
@@ -2325,7 +2428,7 @@ info_vector_command (const char *args, int from_tty)
   if (!target_has_registers ())
     error (_("The program has no registers now."));
 
-  print_vector_info (gdb_stdout, get_selected_frame (NULL), args);
+  print_vector_info (gdb_stdout, get_selected_frame (nullptr), args);
 }
 \f
 /* Kill the inferior process.  Make us have no inferior.  */
@@ -2349,11 +2452,12 @@ kill_command (const char *arg, int from_tty)
   int infnum = current_inferior ()->num;
 
   target_kill ();
-  bfd_cache_close_all ();
+
+  update_previous_thread ();
 
   if (print_inferior_events)
-    printf_filtered (_("[Inferior %d (%s) killed]\n"),
-                    infnum, pid_str.c_str ());
+    gdb_printf (_("[Inferior %d (%s) killed]\n"),
+               infnum, pid_str.c_str ());
 }
 
 /* Used in `attach&' command.  Proceed threads of inferior INF iff
@@ -2389,11 +2493,11 @@ setup_inferior (int from_tty)
   struct inferior *inferior;
 
   inferior = current_inferior ();
-  inferior->needs_setup = 0;
+  inferior->needs_setup = false;
 
   /* If no exec file is yet known, try to determine it from the
      process itself.  */
-  if (get_exec_file (0) == NULL)
+  if (get_exec_file (0) == nullptr)
     exec_file_locate_attach (inferior_ptid.pid (), 1, from_tty);
   else
     {
@@ -2473,7 +2577,7 @@ attach_post_wait (int from_tty, enum attach_post_wait_mode mode)
        {
          struct thread_info *lowest = inferior_thread ();
 
-         stop_all_threads ();
+         stop_all_threads ("attaching");
 
          /* It's not defined which thread will report the attach
             stop.  For consistency, always select the thread with
@@ -2510,7 +2614,7 @@ attach_command (const char *args, int from_tty)
 
   scoped_disable_commit_resumed disable_commit_resumed ("attaching");
 
-  if (gdbarch_has_global_solist (target_gdbarch ()))
+  if (gdbarch_has_global_solist (current_inferior ()->arch ()))
     /* Don't complain if all processes share the same symbol
        space.  */
     ;
@@ -2539,19 +2643,14 @@ attach_command (const char *args, int from_tty)
   attach_target->attach (args, from_tty);
   /* to_attach should push the target, so after this point we
      shouldn't refer to attach_target again.  */
-  attach_target = NULL;
+  attach_target = nullptr;
 
-  if (debug_infrun)
-    {
-      infrun_debug_printf ("immediately after attach:");
-      for (thread_info *thread : inferior->non_exited_threads ())
-       infrun_debug_printf ("  thread %s, executing = %d, resumed = %d, "
-                            "state = %s",
-                            thread->ptid.to_string ().c_str (),
-                            thread->executing (),
-                            thread->resumed (),
-                            thread_state_string (thread->state));
-    }
+  infrun_debug_show_threads ("immediately after attach",
+                            current_inferior ()->non_exited_threads ());
+
+  /* Enable async mode if it is supported by the target.  */
+  if (target_can_async_p ())
+    target_async (true);
 
   /* Set up the "saved terminal modes" of the inferior
      based on what modes we are starting it with.  */
@@ -2577,7 +2676,7 @@ attach_command (const char *args, int from_tty)
      wait_for_inferior as soon as the target reports a stop.  */
   init_wait_for_inferior ();
 
-  inferior->needs_setup = 1;
+  inferior->needs_setup = true;
 
   if (target_is_non_stop_p ())
     {
@@ -2644,7 +2743,7 @@ notice_new_inferior (thread_info *thr, bool leave_running, int from_tty)
   enum attach_post_wait_mode mode
     = leave_running ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING;
 
-  gdb::optional<scoped_restore_current_thread> restore_thread;
+  std::optional<scoped_restore_current_thread> restore_thread;
 
   if (inferior_ptid != null_ptid)
     restore_thread.emplace ();
@@ -2707,26 +2806,28 @@ detach_command (const char *args, int from_tty)
   /* Hold a strong reference to the target while (maybe)
      detaching the parent.  Otherwise detaching could close the
      target.  */
-  auto target_ref
-    = target_ops_ref::new_reference (current_inferior ()->process_target ());
+  inferior *inf = current_inferior ();
+  auto target_ref = target_ops_ref::new_reference (inf->process_target ());
 
   /* Save this before detaching, since detaching may unpush the
      process_stratum target.  */
   bool was_non_stop_p = target_is_non_stop_p ();
 
-  target_detach (current_inferior (), from_tty);
+  target_detach (inf, from_tty);
+
+  update_previous_thread ();
 
   /* The current inferior process was just detached successfully.  Get
      rid of breakpoints that no longer make sense.  Note we don't do
      this within target_detach because that is also used when
      following child forks, and in that case we will want to transfer
      breakpoints to the child, not delete them.  */
-  breakpoint_init_inferior (inf_exited);
+  breakpoint_init_inferior (inf, inf_exited);
 
   /* If the solist is global across inferiors, don't clear it when we
      detach from a single inferior.  */
-  if (!gdbarch_has_global_solist (target_gdbarch ()))
-    no_shared_libraries (NULL, from_tty);
+  if (!gdbarch_has_global_solist (inf->arch ()))
+    no_shared_libraries (nullptr, from_tty);
 
   if (deprecated_detach_hook)
     deprecated_detach_hook ();
@@ -2752,8 +2853,9 @@ disconnect_command (const char *args, int from_tty)
   query_if_trace_running (from_tty);
   disconnect_tracing ();
   target_disconnect (args, from_tty);
-  no_shared_libraries (NULL, from_tty);
+  no_shared_libraries (nullptr, from_tty);
   init_thread_list ();
+  update_previous_thread ();
   if (deprecated_detach_hook)
     deprecated_detach_hook ();
 }
@@ -2821,13 +2923,10 @@ interrupt_command (const char *args, int from_tty)
 
       dont_repeat ();          /* Not for the faint of heart.  */
 
-      if (args != NULL
+      if (args != nullptr
          && startswith (args, "-a"))
        all_threads = 1;
 
-      if (!non_stop && all_threads)
-       error (_("-a is meaningless in all-stop mode."));
-
       interrupt_target_1 (all_threads);
     }
 }
@@ -2836,7 +2935,7 @@ interrupt_command (const char *args, int from_tty)
 
 void
 default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
-                         struct frame_info *frame, const char *args)
+                         const frame_info_ptr &frame, const char *args)
 {
   int regnum;
   int printed_something = 0;
@@ -2850,19 +2949,19 @@ default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
        }
     }
   if (!printed_something)
-    fprintf_filtered (file, "No floating-point info "
-                     "available for this processor.\n");
+    gdb_printf (file, "No floating-point info "
+               "available for this processor.\n");
 }
 
 static void
 info_float_command (const char *args, int from_tty)
 {
-  struct frame_info *frame;
+  frame_info_ptr frame;
 
   if (!target_has_registers ())
     error (_("The program has no registers now."));
 
-  frame = get_selected_frame (NULL);
+  frame = get_selected_frame (nullptr);
   gdbarch_print_float_info (get_frame_arch (frame), gdb_stdout, frame, args);
 }
 \f
@@ -2961,9 +3060,9 @@ show_print_finish (struct ui_file *file, int from_tty,
                   struct cmd_list_element *c,
                   const char *value)
 {
-  fprintf_filtered (file, _("\
+  gdb_printf (file, _("\
 Printing of return value after `finish' is %s.\n"),
-                   value);
+             value);
 }
 
 
@@ -2977,7 +3076,7 @@ shell that will start the program (specified by the \"$SHELL\" environment\n\
 variable).  Input and output redirection with \">\", \"<\", or \">>\"\n\
 are also allowed.\n\
 \n\
-With no arguments, uses arguments last specified (with \"run\" or \n\
+With no arguments, uses arguments last specified (with \"run\" or\n\
 \"set args\").  To cancel previous arguments and run with no arguments,\n\
 use \"set args\" without arguments.\n\
 \n\
@@ -2988,56 +3087,48 @@ void
 _initialize_infcmd ()
 {
   static struct cmd_list_element *info_proc_cmdlist;
-  struct cmd_list_element *c = NULL;
-  const char *cmd_name;
+  struct cmd_list_element *c = nullptr;
 
   /* Add the filename of the terminal connected to inferior I/O.  */
-  add_setshow_optional_filename_cmd ("inferior-tty", class_run,
-                                    &inferior_io_terminal_scratch, _("\
+  auto tty_set_show
+    = add_setshow_optional_filename_cmd ("inferior-tty", class_run, _("\
 Set terminal for future runs of program being debugged."), _("\
 Show terminal for future runs of program being debugged."), _("\
 Usage: set inferior-tty [TTY]\n\n\
 If TTY is omitted, the default behavior of using the same terminal as GDB\n\
 is restored."),
-                                    set_inferior_tty_command,
-                                    show_inferior_tty_command,
-                                    &setlist, &showlist);
-  cmd_name = "inferior-tty";
-  c = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
-  gdb_assert (c != NULL);
-  add_alias_cmd ("tty", c, class_run, 0, &cmdlist);
-
-  cmd_name = "args";
-  add_setshow_string_noescape_cmd (cmd_name, class_run,
-                                  &inferior_args_scratch, _("\
+                                        set_tty_value,
+                                        get_tty_value,
+                                        show_inferior_tty_command,
+                                        &setlist, &showlist);
+  add_alias_cmd ("tty", tty_set_show.set, class_run, 0, &cmdlist);
+
+  auto args_set_show
+    = add_setshow_string_noescape_cmd ("args", class_run, _("\
 Set argument list to give program being debugged when it is started."), _("\
 Show argument list to give program being debugged when it is started."), _("\
 Follow this command with any number of args, to be passed to the program."),
-                                  set_args_command,
-                                  show_args_command,
-                                  &setlist, &showlist);
-  c = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
-  gdb_assert (c != NULL);
-  set_cmd_completer (c, filename_completer);
-
-  cmd_name = "cwd";
-  add_setshow_string_noescape_cmd (cmd_name, class_run,
-                                  &inferior_cwd_scratch, _("\
+                                      set_args_value,
+                                      get_args_value,
+                                      show_args_command,
+                                      &setlist, &showlist);
+  set_cmd_completer (args_set_show.set, filename_completer);
+
+  auto cwd_set_show
+    = add_setshow_string_noescape_cmd ("cwd", class_run, _("\
 Set the current working directory to be used when the inferior is started.\n\
 Changing this setting does not have any effect on inferiors that are\n\
 already running."),
-                                  _("\
+                                      _("\
 Show the current working directory that is used when the inferior is started."),
-                                  _("\
+                                      _("\
 Use this command to change the current working directory that will be used\n\
 when the inferior is started.  This setting does not affect GDB's current\n\
 working directory."),
-                                  set_cwd_command,
-                                  show_cwd_command,
-                                  &setlist, &showlist);
-  c = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
-  gdb_assert (c != NULL);
-  set_cmd_completer (c, filename_completer);
+                                      set_cwd_value, get_inferior_cwd,
+                                      show_cwd_command,
+                                      &setlist, &showlist);
+  set_cmd_completer (cwd_set_show.set, filename_completer);
 
   c = add_cmd ("environment", no_class, environment_info, _("\
 The environment to give the program, or one variable's value.\n\
@@ -3211,7 +3302,7 @@ which means to set the ignore count of that breakpoint to N - 1 (so that\n\
 the breakpoint won't break until the Nth time it is reached).\n\
 \n\
 If non-stop mode is enabled, continue only the current thread,\n\
-otherwise all the threads in the program are continued.  To \n\
+otherwise all the threads in the program are continued.  To\n\
 continue all stopped threads in non-stop mode, use the -a option.\n\
 Specifying -a and an ignore count simultaneously is an error."));
   add_com_alias ("c", continue_cmd, class_run, 1);
@@ -3237,7 +3328,7 @@ RUN_ARGS_HELP));
   add_com ("interrupt", class_run, interrupt_command,
           _("Interrupt the execution of the debugged program.\n\
 If non-stop mode is enabled, interrupt only the current thread,\n\
-otherwise all the threads in the program are stopped.  To \n\
+otherwise all the threads in the program are stopped.  To\n\
 interrupt all running threads in non-stop mode, use the -a option."));
 
   cmd_list_element *info_registers_cmd
@@ -3305,10 +3396,10 @@ List all available info about the specified process."),
           &info_proc_cmdlist);
 
   add_setshow_boolean_cmd ("finish", class_support,
-                          &user_print_options.finish_print, _("\
+                          &finish_print, _("\
 Set whether `finish' prints the return value."), _("\
-Show whether `finish' prints the return value."), NULL,
-                          NULL,
+Show whether `finish' prints the return value."), nullptr,
+                          nullptr,
                           show_print_finish,
                           &setprintlist, &showprintlist);
 }