]> 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 bf4a68e3557eb79029d242b7c284a6ba4eeed191..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
@@ -105,15 +87,24 @@ 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)
+{
+  current_inferior ()->set_tty (tty);
+}
+
+/* Get the current 'inferior-tty' value.  */
+
+static const std::string &
+get_tty_value ()
 {
-  /* 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);
+  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)
@@ -127,34 +118,33 @@ show_inferior_tty_command (struct ui_file *file, int from_tty,
                "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.  */
@@ -165,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.  */
@@ -207,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);
@@ -295,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);
        }
     }
 
@@ -424,11 +414,9 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
   if (run_how == RUN_STOP_AT_MAIN)
     {
       /* To avoid other inferiors hitting this breakpoint, make it
-        inferior-specific using a condition.  A better solution would be to
-        have proper inferior-specific breakpoint support, in the breakpoint
-        machinery.  We could then avoid inserting a breakpoint in the program
-        spaces unrelated to this inferior.  */
-      std::string arg = string_printf ("-qualified %s if $_inferior == %d", main_name (),
+        inferior-specific.  */
+      std::string arg = string_printf ("-qualified %s inferior %d",
+                                      main_name (),
                                       current_inferior ()->num);
       tbreak_command (arg.c_str (), 0);
     }
@@ -444,12 +432,12 @@ 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,
@@ -466,7 +454,7 @@ 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 ());
@@ -506,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.  */
@@ -624,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)
        {
@@ -669,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;
@@ -704,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)
@@ -729,7 +718,6 @@ continue_command (const char *args, int from_tty)
        }
     }
 
-  ERROR_NO_INFERIOR;
   ensure_not_tfind_mode ();
 
   if (!non_stop || !all_threads_p)
@@ -879,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 ();
+      bool proceeded = normal_stop ();
       if (!proceeded)
        inferior_event_handler (INF_EXEC_COMPLETE);
       all_uis_check_sync_execution_done ();
@@ -958,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;
 
@@ -972,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
@@ -988,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.  */
@@ -1074,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];
 
@@ -1087,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 ()))
@@ -1098,11 +1110,10 @@ 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 (sfn->objfile ());
       if (section_is_overlay (section)
          && !section_is_mapped (section))
@@ -1239,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,
@@ -1350,7 +1361,7 @@ 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 = msymbol.value_address ();
@@ -1364,45 +1375,6 @@ until_next_command (int from_tty)
 
       tp->control.step_range_start = func->value_block ()->entry_pc ();
       tp->control.step_range_end = sal.end;
-
-      /* By setting the step_range_end based on the current pc, we are
-        assuming that the last line table entry for any given source line
-        will have is_stmt set to true.  This is not necessarily the case,
-        there may be additional entries for the same source line with
-        is_stmt set false.  Consider the following code:
-
-        for (int i = 0; i < 10; i++)
-          loop_body ();
-
-        Clang-13, will generate multiple line table entries at the end of
-        the loop all associated with the 'for' line.  The first of these
-        entries is marked is_stmt true, but the other entries are is_stmt
-        false.
-
-        If we only use the values in SAL, then our stepping range may not
-        extend to the end of the loop. The until command will reach the
-        end of the range, find a non is_stmt instruction, and step to the
-        next is_stmt instruction. This stopping point, however, will be
-        inside the loop, which is not what we wanted.
-
-        Instead, we now check any subsequent line table entries to see if
-        they are for the same line.  If they are, and they are marked
-        is_stmt false, then we extend the end of our stepping range.
-
-        When we finish this process the end of the stepping range will
-        point either to a line with a different line number, or, will
-        point at an address for the same line number that is marked as a
-        statement.  */
-
-      struct symtab_and_line final_sal
-       = find_pc_line (tp->control.step_range_end, 0);
-
-      while (final_sal.line == sal.line && final_sal.symtab == sal.symtab
-            && !final_sal.is_stmt)
-       {
-         tp->control.step_range_end = final_sal.end;
-         final_sal = find_pc_line (final_sal.end, 0);
-       }
     }
   tp->control.may_range_step = 1;
 
@@ -1450,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.  */
@@ -1467,7 +1439,7 @@ advance_command (const char *arg, int from_tty)
 struct value *
 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;
 
@@ -1475,7 +1447,7 @@ get_return_value (struct symbol *func_symbol, struct value *function)
     = check_typedef (func_symbol->type ()->target_type ());
   gdb_assert (value_type->code () != TYPE_CODE_VOID);
 
-  if (is_nocall_function (check_typedef (::value_type (function))))
+  if (is_nocall_function (check_typedef (function->type ())))
     {
       warning (_("Function '%s' does not follow the target calling "
                 "convention, cannot determine its returned value."),
@@ -1491,18 +1463,17 @@ get_return_value (struct symbol *func_symbol, struct value *function)
      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 (_("bad switch"));
@@ -1511,29 +1482,12 @@ get_return_value (struct symbol *func_symbol, struct value *function)
   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)
     {
       /* Print it.  */
       uiout->text ("Value returned is ");
@@ -1572,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;
 
@@ -1583,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);
     }
@@ -1604,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)
   {
@@ -1625,25 +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 = function->type ()->target_type ();
-      if (rv->type == NULL)
+      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 (function, func);
-         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)
@@ -1696,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,
@@ -1714,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))
     {
-      frame_info_ptr 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);
@@ -1731,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);
     }
@@ -1742,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, frame_info_ptr 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);
@@ -1756,9 +1738,6 @@ finish_forward (struct finish_command_fsm *sm, frame_info_ptr 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...  */
@@ -1770,20 +1749,21 @@ finish_forward (struct finish_command_fsm *sm, frame_info_ptr frame)
 /* Skip frames for "finish".  */
 
 static frame_info_ptr
-skip_finish_frames (frame_info_ptr frame)
+skip_finish_frames (const frame_info_ptr &initial_frame)
 {
   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);
@@ -1819,7 +1799,6 @@ finish_command (const char *arg, int from_tty)
   frame = get_prev_frame (get_selected_frame (_("No selected frame.")));
   if (frame == 0)
     error (_("\"finish\" not meaningful in the outermost frame."));
-  frame.prepare_reinflate ();
 
   clear_proceed_status (0);
 
@@ -1849,7 +1828,7 @@ finish_command (const char *arg, int from_tty)
       if (from_tty)
        {
          gdb_printf (_("Run till exit from "));
-         print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
+         print_stack_frame (get_selected_frame (nullptr), 1, LOCATION, 0);
        }
 
       proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
@@ -1857,8 +1836,31 @@ 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.  */
+
+  /* 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 ());
 
-  sm->function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
+      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.  */
@@ -1868,7 +1870,7 @@ finish_command (const char *arg, int from_tty)
        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 ()))
@@ -1876,9 +1878,8 @@ finish_command (const char *arg, int from_tty)
          gdb_printf (_("Run till exit from "));
        }
 
-      print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
+      print_stack_frame (callee_frame, 1, LOCATION, 0);
     }
-  frame.reinflate ();
 
   if (execution_direction == EXEC_REVERSE)
     finish_backward (sm);
@@ -1886,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);
@@ -1897,41 +1898,78 @@ 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 ())
-    {
-      gdb_printf (_("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 (ptid == null_ptid || ptid == minus_one_ptid)
-    error (_("No selected thread."));
+      if (tp == nullptr)
+       {
+         gdb_printf (_("The program being debugged is not being run.\n"));
+         return;
+       }
 
-  thread_info *tp = find_thread_ptid (proc_target, ptid);
+      switch_to_thread (tp);
 
-  if (tp->state == THREAD_EXITED)
-    error (_("Invalid selected thread."));
-  else if (tp->state == THREAD_RUNNING)
-    error (_("Selected thread is running."));
+      gdb_printf (_("Last stopped for thread %s (%s).\n"),
+                 print_thread_id (tp),
+                 target_pid_to_str (tp->ptid).c_str ());
 
-  bs = tp->control.stop_bpstat;
-  stat = bpstat_num (&bs, &num);
+      if (tp->state == THREAD_EXITED)
+       {
+         gdb_printf (_("Thread has since exited.\n"));
+         return;
+       }
+
+      if (tp->state == THREAD_RUNNING)
+       {
+         gdb_printf (_("Thread is now running.\n"));
+         return;
+       }
+    }
+
+  int num;
+  bpstat *bs = tp->control.stop_bpstat;
+  int stat = bpstat_num (&bs, &num);
 
   target_files_info ();
   gdb_printf (_("Program stopped at %s.\n"),
-             paddress (target_gdbarch (), tp->stop_pc ()));
+             paddress (current_inferior ()->arch (), tp->stop_pc ()));
   if (tp->control.stop_step)
     gdb_printf (_("It stopped after being stepped.\n"));
   else if (stat != 0)
@@ -1989,7 +2027,7 @@ environment_info (const char *var, int from_tty)
     {
       char **envp = current_inferior ()->environment.envp ();
 
-      for (int idx = 0; envp[idx] != NULL; ++idx)
+      for (int idx = 0; envp[idx] != nullptr; ++idx)
        {
          gdb_puts (envp[idx]);
          gdb_puts ("\n");
@@ -2101,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
 
@@ -2123,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
@@ -2137,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.  */
@@ -2146,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);
 
@@ -2169,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.  */
@@ -2177,7 +2215,7 @@ 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);
        }
     }
@@ -2200,7 +2238,7 @@ default_print_one_register_info (struct ui_file *file,
 void
 default_print_registers_info (struct gdbarch *gdbarch,
                              struct ui_file *file,
-                             frame_info_ptr frame,
+                             const frame_info_ptr &frame,
                              int regnum, int print_all)
 {
   int i;
@@ -2234,9 +2272,9 @@ default_print_registers_info (struct gdbarch *gdbarch,
       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)));
     }
 }
 
@@ -2248,7 +2286,7 @@ registers_info (const char *addr_exp, int fpregs)
 
   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)
@@ -2324,7 +2362,7 @@ registers_info (const char *addr_exp, int fpregs)
                break;
              }
          }
-       if (group != NULL)
+       if (group != nullptr)
          {
            int regnum;
 
@@ -2360,7 +2398,7 @@ info_registers_command (const char *addr_exp, int from_tty)
 
 static void
 print_vector_info (struct ui_file *file,
-                  frame_info_ptr frame, const char *args)
+                  const frame_info_ptr &frame, const char *args)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
 
@@ -2390,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.  */
@@ -2414,7 +2452,8 @@ 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)
     gdb_printf (_("[Inferior %d (%s) killed]\n"),
@@ -2454,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
     {
@@ -2575,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.  */
     ;
@@ -2604,7 +2643,7 @@ 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;
 
   infrun_debug_show_threads ("immediately after attach",
                             current_inferior ()->non_exited_threads ());
@@ -2637,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 ())
     {
@@ -2704,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 ();
@@ -2767,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 ();
@@ -2812,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 ();
 }
@@ -2881,7 +2923,7 @@ 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;
 
@@ -2893,7 +2935,7 @@ interrupt_command (const char *args, int from_tty)
 
 void
 default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
-                         frame_info_ptr frame, const char *args)
+                         const frame_info_ptr &frame, const char *args)
 {
   int regnum;
   int printed_something = 0;
@@ -2919,7 +2961,7 @@ info_float_command (const char *args, int from_tty)
   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
@@ -3034,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\
@@ -3045,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\
@@ -3268,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);
@@ -3294,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
@@ -3364,8 +3398,8 @@ List all available info about the specified process."),
   add_setshow_boolean_cmd ("finish", class_support,
                           &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);
 }