Introduce procedure use_gdb_stub
[deliverable/binutils-gdb.git] / gdb / infcall.c
index 559b4a2e7b965cd0700b7eda4e0cbcf5ffb74983..77cd931d35f5e5b88c43be91b16ae96f7074aa5d 100644 (file)
@@ -1,8 +1,6 @@
 /* Perform an inferior function call, for GDB, the GNU debugger.
 
-   Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008 Free Software Foundation, Inc.
+   Copyright (C) 1986-2016 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "infcall.h"
 #include "breakpoint.h"
+#include "tracepoint.h"
 #include "target.h"
 #include "regcache.h"
 #include "inferior.h"
-#include "gdb_assert.h"
+#include "infrun.h"
 #include "block.h"
 #include "gdbcore.h"
 #include "language.h"
 #include "objfiles.h"
 #include "gdbcmd.h"
 #include "command.h"
-#include "gdb_string.h"
-#include "infcall.h"
 #include "dummy-frame.h"
 #include "ada-lang.h"
+#include "gdbthread.h"
+#include "event-top.h"
+#include "observer.h"
+#include "top.h"
+#include "interps.h"
+#include "thread-fsm.h"
+
+/* If we can't find a function's name from its address,
+   we print this instead.  */
+#define RAW_FUNCTION_ADDRESS_FORMAT "at 0x%s"
+#define RAW_FUNCTION_ADDRESS_SIZE (sizeof (RAW_FUNCTION_ADDRESS_FORMAT) \
+                                   + 2 * sizeof (CORE_ADDR))
 
 /* NOTE: cagney/2003-04-16: What's the future of this code?
 
@@ -68,8 +78,9 @@ static void
 show_coerce_float_to_double_p (struct ui_file *file, int from_tty,
                               struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("\
-Coercion of floats to doubles when calling functions is %s.\n"),
+  fprintf_filtered (file,
+                   _("Coercion of floats to doubles "
+                     "when calling functions is %s.\n"),
                    value);
 }
 
@@ -78,18 +89,44 @@ Coercion of floats to doubles when calling functions is %s.\n"),
    the stack and restore the context to what as it was before the
    call.
 
-   The default is to stop in the frame where the signal was received. */
+   The default is to stop in the frame where the signal was received.  */
 
-int unwind_on_signal_p = 0;
+static int unwind_on_signal_p = 0;
 static void
 show_unwind_on_signal_p (struct ui_file *file, int from_tty,
                         struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("\
-Unwinding of stack if a signal is received while in a call dummy is %s.\n"),
+  fprintf_filtered (file,
+                   _("Unwinding of stack if a signal is "
+                     "received while in a call dummy is %s.\n"),
                    value);
 }
 
+/* This boolean tells what gdb should do if a std::terminate call is
+   made while in a function called from gdb (call dummy).
+   As the confines of a single dummy stack prohibit out-of-frame
+   handlers from handling a raised exception, and as out-of-frame
+   handlers are common in C++, this can lead to no handler being found
+   by the unwinder, and a std::terminate call.  This is a false positive.
+   If set, gdb unwinds the stack and restores the context to what it
+   was before the call.
+
+   The default is to unwind the frame if a std::terminate call is
+   made.  */
+
+static int unwind_on_terminating_exception_p = 1;
+
+static void
+show_unwind_on_terminating_exception_p (struct ui_file *file, int from_tty,
+                                       struct cmd_list_element *c,
+                                       const char *value)
+
+{
+  fprintf_filtered (file,
+                   _("Unwind stack if a C++ exception is "
+                     "unhandled while in a call dummy is %s.\n"),
+                   value);
+}
 
 /* Perform the standard coercions that are specified
    for arguments to be passed to C or Ada functions.
@@ -100,16 +137,17 @@ Unwinding of stack if a signal is received while in a call dummy is %s.\n"),
    its value as needed).  */
 
 static struct value *
-value_arg_coerce (struct value *arg, struct type *param_type,
-                 int is_prototyped, CORE_ADDR *sp)
+value_arg_coerce (struct gdbarch *gdbarch, struct value *arg,
+                 struct type *param_type, int is_prototyped, CORE_ADDR *sp)
 {
+  const struct builtin_type *builtin = builtin_type (gdbarch);
   struct type *arg_type = check_typedef (value_type (arg));
   struct type *type
     = param_type ? check_typedef (param_type) : arg_type;
 
   /* Perform any Ada-specific coercion first.  */
   if (current_language->la_language == language_ada)
-    arg = ada_convert_actual (arg, type, sp);
+    arg = ada_convert_actual (arg, type);
 
   /* Force the value to the target if we will need its address.  At
      this point, we could allocate arguments on the stack instead of
@@ -124,7 +162,7 @@ value_arg_coerce (struct value *arg, struct type *param_type,
        struct value *new_value;
 
        if (TYPE_CODE (arg_type) == TYPE_CODE_REF)
-         return value_cast_pointers (type, arg);
+         return value_cast_pointers (type, arg, 0);
 
        /* Cast the value to the reference's target type, and then
           convert it back to a reference.  This will issue an error
@@ -141,22 +179,22 @@ value_arg_coerce (struct value *arg, struct type *param_type,
       /* If we don't have a prototype, coerce to integer type if necessary.  */
       if (!is_prototyped)
        {
-         if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
-           type = builtin_type_int;
+         if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin->builtin_int))
+           type = builtin->builtin_int;
        }
       /* Currently all target ABIs require at least the width of an integer
          type for an argument.  We may have to conditionalize the following
          type coercion for future targets.  */
-      if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
-       type = builtin_type_int;
+      if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin->builtin_int))
+       type = builtin->builtin_int;
       break;
     case TYPE_CODE_FLT:
       if (!is_prototyped && coerce_float_to_double_p)
        {
-         if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double))
-           type = builtin_type_double;
-         else if (TYPE_LENGTH (type) > TYPE_LENGTH (builtin_type_double))
-           type = builtin_type_long_double;
+         if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin->builtin_double))
+           type = builtin->builtin_double;
+         else if (TYPE_LENGTH (type) > TYPE_LENGTH (builtin->builtin_double))
+           type = builtin->builtin_long_double;
        }
       break;
     case TYPE_CODE_FUNC:
@@ -178,7 +216,6 @@ value_arg_coerce (struct value *arg, struct type *param_type,
     case TYPE_CODE_SET:
     case TYPE_CODE_RANGE:
     case TYPE_CODE_STRING:
-    case TYPE_CODE_BITSTRING:
     case TYPE_CODE_ERROR:
     case TYPE_CODE_MEMBERPTR:
     case TYPE_CODE_METHODPTR:
@@ -191,6 +228,21 @@ value_arg_coerce (struct value *arg, struct type *param_type,
   return value_cast (type, arg);
 }
 
+/* Return the return type of a function with its first instruction exactly at
+   the PC address.  Return NULL otherwise.  */
+
+static struct type *
+find_function_return_type (CORE_ADDR pc)
+{
+  struct symbol *sym = find_pc_function (pc);
+
+  if (sym != NULL && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) == pc
+      && SYMBOL_TYPE (sym) != NULL)
+    return TYPE_TARGET_TYPE (SYMBOL_TYPE (sym));
+
+  return NULL;
+}
+
 /* Determine a function's address and its return type from its value.
    Calls error() if the function is not valid for calling.  */
 
@@ -198,51 +250,61 @@ CORE_ADDR
 find_function_addr (struct value *function, struct type **retval_type)
 {
   struct type *ftype = check_typedef (value_type (function));
-  enum type_code code = TYPE_CODE (ftype);
-  struct type *value_type;
-  CORE_ADDR funaddr;
+  struct gdbarch *gdbarch = get_type_arch (ftype);
+  struct type *value_type = NULL;
+  /* Initialize it just to avoid a GCC false warning.  */
+  CORE_ADDR funaddr = 0;
 
   /* If it's a member function, just look at the function
      part of it.  */
 
   /* Determine address to call.  */
-  if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
-    {
-      funaddr = VALUE_ADDRESS (function);
-      value_type = TYPE_TARGET_TYPE (ftype);
-    }
-  else if (code == TYPE_CODE_PTR)
+  if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
+      || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+    funaddr = value_address (function);
+  else if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
     {
       funaddr = value_as_address (function);
       ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
       if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
          || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+       funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
+                                                     &current_target);
+    }
+  if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
+      || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+    {
+      value_type = TYPE_TARGET_TYPE (ftype);
+
+      if (TYPE_GNU_IFUNC (ftype))
        {
-         funaddr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
-                                                       funaddr,
-                                                       &current_target);
-         value_type = TYPE_TARGET_TYPE (ftype);
+         funaddr = gnu_ifunc_resolve_addr (gdbarch, funaddr);
+
+         /* Skip querying the function symbol if no RETVAL_TYPE has been
+            asked for.  */
+         if (retval_type)
+           value_type = find_function_return_type (funaddr);
        }
-      else
-       value_type = builtin_type_int;
     }
-  else if (code == TYPE_CODE_INT)
+  else if (TYPE_CODE (ftype) == TYPE_CODE_INT)
     {
       /* Handle the case of functions lacking debugging info.
-         Their values are characters since their addresses are char */
+         Their values are characters since their addresses are char */
       if (TYPE_LENGTH (ftype) == 1)
        funaddr = value_as_address (value_addr (function));
       else
        {
          /* Handle function descriptors lacking debug info.  */
          int found_descriptor = 0;
+
+         funaddr = 0;  /* pacify "gcc -Werror" */
          if (VALUE_LVAL (function) == lval_memory)
            {
              CORE_ADDR nfunaddr;
+
              funaddr = value_as_address (value_addr (function));
              nfunaddr = funaddr;
-             funaddr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
-                                                           funaddr,
+             funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
                                                            &current_target);
              if (funaddr != nfunaddr)
                found_descriptor = 1;
@@ -251,82 +313,352 @@ find_function_addr (struct value *function, struct type **retval_type)
            /* Handle integer used as address of a function.  */
            funaddr = (CORE_ADDR) value_as_long (function);
        }
-
-      value_type = builtin_type_int;
     }
   else
     error (_("Invalid data type for function to be called."));
 
   if (retval_type != NULL)
     *retval_type = value_type;
-  return funaddr + gdbarch_deprecated_function_start_offset (current_gdbarch);
+  return funaddr + gdbarch_deprecated_function_start_offset (gdbarch);
 }
 
-/* Call breakpoint_auto_delete on the current contents of the bpstat
-   pointed to by arg (which is really a bpstat *).  */
+/* For CALL_DUMMY_ON_STACK, push a breakpoint sequence that the called
+   function returns to.  */
 
-static void
-breakpoint_auto_delete_contents (void *arg)
+static CORE_ADDR
+push_dummy_code (struct gdbarch *gdbarch,
+                CORE_ADDR sp, CORE_ADDR funaddr,
+                struct value **args, int nargs,
+                struct type *value_type,
+                CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
+                struct regcache *regcache)
 {
-  breakpoint_auto_delete (*(bpstat *) arg);
+  gdb_assert (gdbarch_push_dummy_code_p (gdbarch));
+
+  return gdbarch_push_dummy_code (gdbarch, sp, funaddr,
+                                 args, nargs, value_type, real_pc, bp_addr,
+                                 regcache);
 }
 
-static CORE_ADDR
-generic_push_dummy_code (struct gdbarch *gdbarch,
-                        CORE_ADDR sp, CORE_ADDR funaddr,
-                        struct value **args, int nargs,
-                        struct type *value_type,
-                        CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
-                        struct regcache *regcache)
+/* Fetch the name of the function at FUNADDR.
+   This is used in printing an error message for call_function_by_hand.
+   BUF is used to print FUNADDR in hex if the function name cannot be
+   determined.  It must be large enough to hold formatted result of
+   RAW_FUNCTION_ADDRESS_FORMAT.  */
+
+static const char *
+get_function_name (CORE_ADDR funaddr, char *buf, int buf_size)
 {
-  /* Something here to findout the size of a breakpoint and then
-     allocate space for it on the stack.  */
-  int bplen;
-  /* This code assumes frame align.  */
-  gdb_assert (gdbarch_frame_align_p (gdbarch));
-  /* Force the stack's alignment.  The intent is to ensure that the SP
-     is aligned to at least a breakpoint instruction's boundary.  */
-  sp = gdbarch_frame_align (gdbarch, sp);
-  /* Allocate space for, and then position the breakpoint on the
-     stack.  */
-  if (gdbarch_inner_than (gdbarch, 1, 2))
+  {
+    struct symbol *symbol = find_pc_function (funaddr);
+
+    if (symbol)
+      return SYMBOL_PRINT_NAME (symbol);
+  }
+
+  {
+    /* Try the minimal symbols.  */
+    struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (funaddr);
+
+    if (msymbol.minsym)
+      return MSYMBOL_PRINT_NAME (msymbol.minsym);
+  }
+
+  {
+    char *tmp = xstrprintf (_(RAW_FUNCTION_ADDRESS_FORMAT),
+                            hex_string (funaddr));
+
+    gdb_assert (strlen (tmp) + 1 <= buf_size);
+    strcpy (buf, tmp);
+    xfree (tmp);
+    return buf;
+  }
+}
+
+/* All the meta data necessary to extract the call's return value.  */
+
+struct call_return_meta_info
+{
+  /* The caller frame's architecture.  */
+  struct gdbarch *gdbarch;
+
+  /* The called function.  */
+  struct value *function;
+
+  /* The return value's type.  */
+  struct type *value_type;
+
+  /* Are we returning a value using a structure return or a normal
+     value return?  */
+  int struct_return_p;
+
+  /* If using a structure return, this is the structure's address.  */
+  CORE_ADDR struct_addr;
+
+  /* Whether stack temporaries are enabled.  */
+  int stack_temporaries_enabled;
+};
+
+/* Extract the called function's return value.  */
+
+static struct value *
+get_call_return_value (struct call_return_meta_info *ri)
+{
+  struct value *retval = NULL;
+  int stack_temporaries = thread_stack_temporaries_enabled_p (inferior_ptid);
+
+  if (TYPE_CODE (ri->value_type) == TYPE_CODE_VOID)
+    retval = allocate_value (ri->value_type);
+  else if (ri->struct_return_p)
     {
-      CORE_ADDR bppc = sp;
-      gdbarch_breakpoint_from_pc (gdbarch, &bppc, &bplen);
-      sp = gdbarch_frame_align (gdbarch, sp - bplen);
-      (*bp_addr) = sp;
-      /* Should the breakpoint size/location be re-computed here?  */
-    }      
+      if (stack_temporaries)
+       {
+         retval = value_from_contents_and_address (ri->value_type, NULL,
+                                                   ri->struct_addr);
+         push_thread_stack_temporary (inferior_ptid, retval);
+       }
+      else
+       {
+         retval = allocate_value (ri->value_type);
+         read_value_memory (retval, 0, 1, ri->struct_addr,
+                            value_contents_raw (retval),
+                            TYPE_LENGTH (ri->value_type));
+       }
+    }
   else
     {
-      (*bp_addr) = sp;
-      gdbarch_breakpoint_from_pc (gdbarch, bp_addr, &bplen);
-      sp = gdbarch_frame_align (gdbarch, sp + bplen);
+      retval = allocate_value (ri->value_type);
+      gdbarch_return_value (ri->gdbarch, ri->function, ri->value_type,
+                           get_current_regcache (),
+                           value_contents_raw (retval), NULL);
+      if (stack_temporaries && class_or_union_p (ri->value_type))
+       {
+         /* Values of class type returned in registers are copied onto
+            the stack and their lval_type set to lval_memory.  This is
+            required because further evaluation of the expression
+            could potentially invoke methods on the return value
+            requiring GDB to evaluate the "this" pointer.  To evaluate
+            the this pointer, GDB needs the memory address of the
+            value.  */
+         value_force_lval (retval, ri->struct_addr);
+         push_thread_stack_temporary (inferior_ptid, retval);
+       }
     }
-  /* Inferior resumes at the function entry point.  */
-  (*real_pc) = funaddr;
-  return sp;
+
+  gdb_assert (retval != NULL);
+  return retval;
 }
 
-/* For CALL_DUMMY_ON_STACK, push a breakpoint sequence that the called
-   function returns to.  */
+/* Data for the FSM that manages an infcall.  It's main job is to
+   record the called function's return value.  */
 
-static CORE_ADDR
-push_dummy_code (struct gdbarch *gdbarch,
-                CORE_ADDR sp, CORE_ADDR funaddr,
-                struct value **args, int nargs,
-                struct type *value_type,
-                CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
-                struct regcache *regcache)
+struct call_thread_fsm
+{
+  /* The base class.  */
+  struct thread_fsm thread_fsm;
+
+  /* All the info necessary to be able to extract the return
+     value.  */
+  struct call_return_meta_info return_meta_info;
+
+  /* The called function's return value.  This is extracted from the
+     target before the dummy frame is popped.  */
+  struct value *return_value;
+};
+
+static int call_thread_fsm_should_stop (struct thread_fsm *self);
+static int call_thread_fsm_should_notify_stop (struct thread_fsm *self);
+
+/* call_thread_fsm's vtable.  */
+
+static struct thread_fsm_ops call_thread_fsm_ops =
+{
+  NULL, /*dtor */
+  NULL, /* clean_up */
+  call_thread_fsm_should_stop,
+  NULL, /* return_value */
+  NULL, /* async_reply_reason*/
+  call_thread_fsm_should_notify_stop,
+};
+
+/* Allocate a new call_thread_fsm object.  */
+
+static struct call_thread_fsm *
+new_call_thread_fsm (struct gdbarch *gdbarch, struct value *function,
+                    struct type *value_type,
+                    int struct_return_p, CORE_ADDR struct_addr)
 {
-  if (gdbarch_push_dummy_code_p (gdbarch))
-    return gdbarch_push_dummy_code (gdbarch, sp, funaddr,
-                                   args, nargs, value_type, real_pc, bp_addr,
-                                   regcache);
-  else    
-    return generic_push_dummy_code (gdbarch, sp, funaddr,
-                                   args, nargs, value_type, real_pc, bp_addr,
-                                   regcache);
+  struct call_thread_fsm *sm;
+
+  sm = XCNEW (struct call_thread_fsm);
+  thread_fsm_ctor (&sm->thread_fsm, &call_thread_fsm_ops);
+
+  sm->return_meta_info.gdbarch = gdbarch;
+  sm->return_meta_info.function = function;
+  sm->return_meta_info.value_type = value_type;
+  sm->return_meta_info.struct_return_p = struct_return_p;
+  sm->return_meta_info.struct_addr = struct_addr;
+
+  return sm;
+}
+
+/* Implementation of should_stop method for infcalls.  */
+
+static int
+call_thread_fsm_should_stop (struct thread_fsm *self)
+{
+  struct call_thread_fsm *f = (struct call_thread_fsm *) self;
+
+  if (stop_stack_dummy == STOP_STACK_DUMMY)
+    {
+      /* Done.  */
+      thread_fsm_set_finished (self);
+
+      /* Stash the return value before the dummy frame is popped and
+        registers are restored to what they were before the
+        call..  */
+      f->return_value = get_call_return_value (&f->return_meta_info);
+
+      /* Break out of wait_sync_command_done.  */
+      async_enable_stdin ();
+    }
+
+  return 1;
+}
+
+/* Implementation of should_notify_stop method for infcalls.  */
+
+static int
+call_thread_fsm_should_notify_stop (struct thread_fsm *self)
+{
+  if (thread_fsm_finished_p (self))
+    {
+      /* Infcall succeeded.  Be silent and proceed with evaluating the
+        expression.  */
+      return 0;
+    }
+
+  /* Something wrong happened.  E.g., an unexpected breakpoint
+     triggered, or a signal was intercepted.  Notify the stop.  */
+  return 1;
+}
+
+/* Subroutine of call_function_by_hand to simplify it.
+   Start up the inferior and wait for it to stop.
+   Return the exception if there's an error, or an exception with
+   reason >= 0 if there's no error.
+
+   This is done inside a TRY_CATCH so the caller needn't worry about
+   thrown errors.  The caller should rethrow if there's an error.  */
+
+static struct gdb_exception
+run_inferior_call (struct call_thread_fsm *sm,
+                  struct thread_info *call_thread, CORE_ADDR real_pc)
+{
+  struct gdb_exception caught_error = exception_none;
+  int saved_in_infcall = call_thread->control.in_infcall;
+  ptid_t call_thread_ptid = call_thread->ptid;
+  int saved_sync_execution = sync_execution;
+  int was_running = call_thread->state == THREAD_RUNNING;
+  int saved_interpreter_async = interpreter_async;
+
+  /* Infcalls run synchronously, in the foreground.  */
+  sync_execution = 1;
+  /* So that we don't print the prompt prematurely in
+     fetch_inferior_event.  */
+  interpreter_async = 0;
+
+  call_thread->control.in_infcall = 1;
+
+  clear_proceed_status (0);
+
+  /* Associate the FSM with the thread after clear_proceed_status
+     (otherwise it'd clear this FSM), and before anything throws, so
+     we don't leak it (and any resources it manages).  */
+  call_thread->thread_fsm = &sm->thread_fsm;
+
+  disable_watchpoints_before_interactive_call_start ();
+
+  /* We want to print return value, please...  */
+  call_thread->control.proceed_to_finish = 1;
+
+  TRY
+    {
+      proceed (real_pc, GDB_SIGNAL_0);
+
+      /* Inferior function calls are always synchronous, even if the
+        target supports asynchronous execution.  */
+      wait_sync_command_done ();
+    }
+  CATCH (e, RETURN_MASK_ALL)
+    {
+      caught_error = e;
+    }
+  END_CATCH
+
+  /* If GDB was previously in sync execution mode, then ensure that it
+     remains so.  normal_stop calls async_enable_stdin, so reset it
+     again here.  In other cases, stdin will be re-enabled by
+     inferior_event_handler, when an exception is thrown.  */
+  sync_execution = saved_sync_execution;
+  interpreter_async = saved_interpreter_async;
+
+  /* At this point the current thread may have changed.  Refresh
+     CALL_THREAD as it could be invalid if its thread has exited.  */
+  call_thread = find_thread_ptid (call_thread_ptid);
+
+  /* If the infcall does NOT succeed, normal_stop will have already
+     finished the thread states.  However, on success, normal_stop
+     defers here, so that we can set back the thread states to what
+     they were before the call.  Note that we must also finish the
+     state of new threads that might have spawned while the call was
+     running.  The main cases to handle are:
+
+     - "(gdb) print foo ()", or any other command that evaluates an
+     expression at the prompt.  (The thread was marked stopped before.)
+
+     - "(gdb) break foo if return_false()" or similar cases where we
+     do an infcall while handling an event (while the thread is still
+     marked running).  In this example, whether the condition
+     evaluates true and thus we'll present a user-visible stop is
+     decided elsewhere.  */
+  if (!was_running
+      && ptid_equal (call_thread_ptid, inferior_ptid)
+      && stop_stack_dummy == STOP_STACK_DUMMY)
+    finish_thread_state (user_visible_resume_ptid (0));
+
+  enable_watchpoints_after_interactive_call_stop ();
+
+  /* Call breakpoint_auto_delete on the current contents of the bpstat
+     of inferior call thread.
+     If all error()s out of proceed ended up calling normal_stop
+     (and perhaps they should; it already does in the special case
+     of error out of resume()), then we wouldn't need this.  */
+  if (caught_error.reason < 0)
+    {
+      if (call_thread != NULL)
+       breakpoint_auto_delete (call_thread->control.stop_bpstat);
+    }
+
+  if (call_thread != NULL)
+    call_thread->control.in_infcall = saved_in_infcall;
+
+  return caught_error;
+}
+
+/* A cleanup function that calls delete_std_terminate_breakpoint.  */
+static void
+cleanup_delete_std_terminate_breakpoint (void *ignore)
+{
+  delete_std_terminate_breakpoint ();
+}
+
+/* See infcall.h.  */
+
+struct value *
+call_function_by_hand (struct value *function, int nargs, struct value **args)
+{
+  return call_function_by_hand_dummy (function, nargs, args, NULL, NULL);
 }
 
 /* All this stuff with a dummy frame may seem unnecessarily complicated
@@ -345,30 +677,34 @@ push_dummy_code (struct gdbarch *gdbarch,
    May fail to return, if a breakpoint or signal is hit
    during the execution of the function.
 
-   ARGS is modified to contain coerced values. */
+   ARGS is modified to contain coerced values.  */
 
 struct value *
-call_function_by_hand (struct value *function, int nargs, struct value **args)
+call_function_by_hand_dummy (struct value *function,
+                            int nargs, struct value **args,
+                            dummy_frame_dtor_ftype *dummy_dtor,
+                            void *dummy_dtor_data)
 {
   CORE_ADDR sp;
-  CORE_ADDR dummy_addr;
   struct type *values_type, *target_values_type;
-  unsigned char struct_return = 0, lang_struct_return = 0;
+  unsigned char struct_return = 0, hidden_first_param_p = 0;
   CORE_ADDR struct_addr = 0;
-  struct regcache *retbuf;
-  struct cleanup *retbuf_cleanup;
-  struct inferior_status *inf_status;
+  struct infcall_control_state *inf_status;
   struct cleanup *inf_status_cleanup;
+  struct infcall_suspend_state *caller_state;
   CORE_ADDR funaddr;
   CORE_ADDR real_pc;
   struct type *ftype = check_typedef (value_type (function));
   CORE_ADDR bp_addr;
-  struct regcache *caller_regcache;
-  struct cleanup *caller_regcache_cleanup;
   struct frame_id dummy_id;
   struct cleanup *args_cleanup;
   struct frame_info *frame;
   struct gdbarch *gdbarch;
+  struct cleanup *terminate_bp_cleanup;
+  ptid_t call_thread_ptid;
+  struct gdb_exception e;
+  char name_buf[RAW_FUNCTION_ADDRESS_SIZE];
+  int stack_temporaries = thread_stack_temporaries_enabled_p (inferior_ptid);
 
   if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
     ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
@@ -376,35 +712,36 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
   if (!target_has_execution)
     noprocess ();
 
+  if (get_traceframe_number () >= 0)
+    error (_("May not call functions while looking at trace frames."));
+
+  if (execution_direction == EXEC_REVERSE)
+    error (_("Cannot call functions in reverse mode."));
+
   frame = get_current_frame ();
   gdbarch = get_frame_arch (frame);
 
   if (!gdbarch_push_dummy_call_p (gdbarch))
-    error (_("This target does not support function calls"));
-
-  /* Create a cleanup chain that contains the retbuf (buffer
-     containing the register values).  This chain is create BEFORE the
-     inf_status chain so that the inferior status can cleaned up
-     (restored or discarded) without having the retbuf freed.  */
-  retbuf = regcache_xmalloc (gdbarch);
-  retbuf_cleanup = make_cleanup_regcache_xfree (retbuf);
-
-  /* A cleanup for the inferior status.  Create this AFTER the retbuf
-     so that this can be discarded or applied without interfering with
-     the regbuf.  */
-  inf_status = save_inferior_status (1);
-  inf_status_cleanup = make_cleanup_restore_inferior_status (inf_status);
-
-  /* Save the caller's registers so that they can be restored once the
+    error (_("This target does not support function calls."));
+
+  /* A cleanup for the inferior status.
+     This is only needed while we're preparing the inferior function call.  */
+  inf_status = save_infcall_control_state ();
+  inf_status_cleanup
+    = make_cleanup_restore_infcall_control_state (inf_status);
+
+  /* Save the caller's registers and other state associated with the
+     inferior itself so that they can be restored once the
      callee returns.  To allow nested calls the registers are (further
      down) pushed onto a dummy frame stack.  Include a cleanup (which
      is tossed once the regcache has been pushed).  */
-  caller_regcache = frame_save_as_regcache (frame);
-  caller_regcache_cleanup = make_cleanup_regcache_xfree (caller_regcache);
+  caller_state = save_infcall_suspend_state ();
+  make_cleanup_restore_infcall_suspend_state (caller_state);
 
   /* Ensure that the initial SP is correctly aligned.  */
   {
     CORE_ADDR old_sp = get_frame_sp (frame);
+
     if (gdbarch_frame_align_p (gdbarch))
       {
        sp = gdbarch_frame_align (gdbarch, old_sp);
@@ -448,10 +785,9 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
              /* Stack grows up.  */
              sp = gdbarch_frame_align (gdbarch, old_sp + 1);
          }
-       gdb_assert ((gdbarch_inner_than (gdbarch, 1, 2)
-                   && sp <= old_sp)
-                   || (gdbarch_inner_than (gdbarch, 2, 1)
-                      && sp >= old_sp));
+       /* SP may have underflown address zero here from OLD_SP.  Memory access
+          functions will probably fail in such case but that is a target's
+          problem.  */
       }
     else
       /* FIXME: cagney/2002-09-18: Hey, you loose!
@@ -461,16 +797,46 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
         If the generic dummy frame ends up empty (because nothing is
         pushed) GDB won't be able to correctly perform back traces.
         If a target is having trouble with backtraces, first thing to
-        do is add FRAME_ALIGN() to the architecture vector. If that
+        do is add FRAME_ALIGN() to the architecture vector.  If that
         fails, try dummy_id().
 
          If the ABI specifies a "Red Zone" (see the doco) the code
          below will quietly trash it.  */
       sp = old_sp;
+
+    /* Skip over the stack temporaries that might have been generated during
+       the evaluation of an expression.  */
+    if (stack_temporaries)
+      {
+       struct value *lastval;
+
+       lastval = get_last_thread_stack_temporary (inferior_ptid);
+        if (lastval != NULL)
+         {
+           CORE_ADDR lastval_addr = value_address (lastval);
+
+           if (gdbarch_inner_than (gdbarch, 1, 2))
+             {
+               gdb_assert (sp >= lastval_addr);
+               sp = lastval_addr;
+             }
+           else
+             {
+               gdb_assert (sp <= lastval_addr);
+               sp = lastval_addr + TYPE_LENGTH (value_type (lastval));
+             }
+
+           if (gdbarch_frame_align_p (gdbarch))
+             sp = gdbarch_frame_align (gdbarch, sp);
+         }
+      }
   }
 
   funaddr = find_function_addr (function, &values_type);
-  CHECK_TYPEDEF (values_type);
+  if (!values_type)
+    values_type = builtin_type (gdbarch)->builtin_int;
+
+  values_type = check_typedef (values_type);
 
   /* Are we returning a value using a structure return (passing a
      hidden argument pointing to storage) or a normal value return?
@@ -483,82 +849,73 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
      the first argument is passed in out0 but the hidden structure
      return pointer would normally be passed in r8.  */
 
-  if (language_pass_by_reference (values_type))
+  if (gdbarch_return_in_first_hidden_param_p (gdbarch, values_type))
     {
-      lang_struct_return = 1;
+      hidden_first_param_p = 1;
 
       /* Tell the target specific argument pushing routine not to
         expect a value.  */
-      target_values_type = builtin_type_void;
+      target_values_type = builtin_type (gdbarch)->builtin_void;
     }
   else
     {
-      struct_return = using_struct_return (value_type (function), values_type);
+      struct_return = using_struct_return (gdbarch, function, values_type);
       target_values_type = values_type;
     }
 
+  observer_notify_inferior_call_pre (inferior_ptid, funaddr);
+
   /* Determine the location of the breakpoint (and possibly other
      stuff) that the called function will return to.  The SPARC, for a
      function returning a structure or union, needs to make space for
      not just the breakpoint but also an extra word containing the
      size (?) of the structure being passed.  */
 
-  /* The actual breakpoint (at BP_ADDR) is inserted separatly so there
-     is no need to write that out.  */
-
   switch (gdbarch_call_dummy_location (gdbarch))
     {
     case ON_STACK:
-      /* "dummy_addr" is here just to keep old targets happy.  New
-        targets return that same information via "sp" and "bp_addr".  */
-      if (gdbarch_inner_than (gdbarch, 1, 2))
-       {
-         sp = push_dummy_code (gdbarch, sp, funaddr,
-                               args, nargs, target_values_type,
-                               &real_pc, &bp_addr, get_current_regcache ());
-         dummy_addr = sp;
-       }
-      else
-       {
-         dummy_addr = sp;
-         sp = push_dummy_code (gdbarch, sp, funaddr,
-                               args, nargs, target_values_type,
-                               &real_pc, &bp_addr, get_current_regcache ());
-       }
+      {
+       const gdb_byte *bp_bytes;
+       CORE_ADDR bp_addr_as_address;
+       int bp_size;
+
+       /* Be careful BP_ADDR is in inferior PC encoding while
+          BP_ADDR_AS_ADDRESS is a plain memory address.  */
+
+       sp = push_dummy_code (gdbarch, sp, funaddr, args, nargs,
+                             target_values_type, &real_pc, &bp_addr,
+                             get_current_regcache ());
+
+       /* Write a legitimate instruction at the point where the infcall
+          breakpoint is going to be inserted.  While this instruction
+          is never going to be executed, a user investigating the
+          memory from GDB would see this instruction instead of random
+          uninitialized bytes.  We chose the breakpoint instruction
+          as it may look as the most logical one to the user and also
+          valgrind 3.7.0 needs it for proper vgdb inferior calls.
+
+          If software breakpoints are unsupported for this target we
+          leave the user visible memory content uninitialized.  */
+
+       bp_addr_as_address = bp_addr;
+       bp_bytes = gdbarch_breakpoint_from_pc (gdbarch, &bp_addr_as_address,
+                                              &bp_size);
+       if (bp_bytes != NULL)
+         write_memory (bp_addr_as_address, bp_bytes, bp_size);
+      }
       break;
     case AT_ENTRY_POINT:
-      real_pc = funaddr;
-      dummy_addr = entry_point_address ();
-      /* Make certain that the address points at real code, and not a
-         function descriptor.  */
-      dummy_addr = gdbarch_convert_from_func_ptr_addr (gdbarch,
-                                                      dummy_addr,
-                                                      &current_target);
-      /* A call dummy always consists of just a single breakpoint, so
-         it's address is the same as the address of the dummy.  */
-      bp_addr = dummy_addr;
-      break;
-    case AT_SYMBOL:
-      /* Some executables define a symbol __CALL_DUMMY_ADDRESS whose
-        address is the location where the breakpoint should be
-        placed.  Once all targets are using the overhauled frame code
-        this can be deleted - ON_STACK is a better option.  */
       {
-       struct minimal_symbol *sym;
+       CORE_ADDR dummy_addr;
 
-       sym = lookup_minimal_symbol ("__CALL_DUMMY_ADDRESS", NULL, NULL);
        real_pc = funaddr;
-       if (sym)
-         dummy_addr = SYMBOL_VALUE_ADDRESS (sym);
-       else
-         dummy_addr = entry_point_address ();
-       /* Make certain that the address points at real code, and not
-          a function descriptor.  */
-       dummy_addr = gdbarch_convert_from_func_ptr_addr (gdbarch,
-                                                        dummy_addr,
-                                                        &current_target);
-       /* A call dummy always consists of just a single breakpoint,
-          so it's address is the same as the address of the dummy.  */
+       dummy_addr = entry_point_address ();
+
+       /* A call dummy always consists of just a single breakpoint, so
+          its address is the same as the address of the dummy.
+
+          The actual breakpoint is inserted separatly so there is no need to
+          write that out.  */
        bp_addr = dummy_addr;
        break;
       }
@@ -567,10 +924,11 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
     }
 
   if (nargs < TYPE_NFIELDS (ftype))
-    error (_("too few arguments in function call"));
+    error (_("Too few arguments in function call."));
 
   {
     int i;
+
     for (i = nargs - 1; i >= 0; i--)
       {
        int prototyped;
@@ -590,7 +948,8 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
        else
          param_type = NULL;
 
-       args[i] = value_arg_coerce (args[i], param_type, prototyped, &sp);
+       args[i] = value_arg_coerce (gdbarch, args[i],
+                                   param_type, prototyped, &sp);
 
        if (param_type != NULL && language_pass_by_reference (param_type))
          args[i] = value_addr (args[i]);
@@ -599,16 +958,27 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 
   /* Reserve space for the return structure to be written on the
      stack, if necessary.  Make certain that the value is correctly
-     aligned. */
+     aligned.
 
-  if (struct_return || lang_struct_return)
+     While evaluating expressions, we reserve space on the stack for
+     return values of class type even if the language ABI and the target
+     ABI do not require that the return value be passed as a hidden first
+     argument.  This is because we want to store the return value as an
+     on-stack temporary while the expression is being evaluated.  This
+     enables us to have chained function calls in expressions.
+
+     Keeping the return values as on-stack temporaries while the expression
+     is being evaluated is OK because the thread is stopped until the
+     expression is completely evaluated.  */
+
+  if (struct_return || hidden_first_param_p
+      || (stack_temporaries && class_or_union_p (values_type)))
     {
-      int len = TYPE_LENGTH (values_type);
       if (gdbarch_inner_than (gdbarch, 1, 2))
        {
          /* Stack grows downward.  Align STRUCT_ADDR and SP after
              making space for the return value.  */
-         sp -= len;
+         sp -= TYPE_LENGTH (values_type);
          if (gdbarch_frame_align_p (gdbarch))
            sp = gdbarch_frame_align (gdbarch, sp);
          struct_addr = sp;
@@ -616,22 +986,22 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
       else
        {
          /* Stack grows upward.  Align the frame, allocate space, and
-             then again, re-align the frame??? */
+             then again, re-align the frame???  */
          if (gdbarch_frame_align_p (gdbarch))
            sp = gdbarch_frame_align (gdbarch, sp);
          struct_addr = sp;
-         sp += len;
+         sp += TYPE_LENGTH (values_type);
          if (gdbarch_frame_align_p (gdbarch))
            sp = gdbarch_frame_align (gdbarch, sp);
        }
     }
 
-  if (lang_struct_return)
+  if (hidden_first_param_p)
     {
       struct value **new_args;
 
       /* Add the new argument to the front of the argument list.  */
-      new_args = xmalloc (sizeof (struct value *) * (nargs + 1));
+      new_args = XNEWVEC (struct value *, nargs + 1);
       new_args[0] = value_from_pointer (lookup_pointer_type (values_type),
                                        struct_addr);
       memcpy (&new_args[1], &args[0], sizeof (struct value *) * nargs);
@@ -664,158 +1034,305 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
      inferior.  That way it breaks when it returns.  */
 
   {
-    struct breakpoint *bpt;
+    struct breakpoint *bpt, *longjmp_b;
     struct symtab_and_line sal;
+
     init_sal (&sal);           /* initialize to zeroes */
+    sal.pspace = current_program_space;
     sal.pc = bp_addr;
     sal.section = find_pc_overlay (sal.pc);
     /* Sanity.  The exact same SP value is returned by
        PUSH_DUMMY_CALL, saved as the dummy-frame TOS, and used by
        dummy_id to form the frame ID's stack address.  */
-    bpt = set_momentary_breakpoint (sal, dummy_id, bp_call_dummy);
+    bpt = set_momentary_breakpoint (gdbarch, sal, dummy_id, bp_call_dummy);
+
+    /* set_momentary_breakpoint invalidates FRAME.  */
+    frame = NULL;
+
     bpt->disposition = disp_del;
+    gdb_assert (bpt->related_breakpoint == bpt);
+
+    longjmp_b = set_longjmp_breakpoint_for_call_dummy ();
+    if (longjmp_b)
+      {
+       /* Link BPT into the chain of LONGJMP_B.  */
+       bpt->related_breakpoint = longjmp_b;
+       while (longjmp_b->related_breakpoint != bpt->related_breakpoint)
+         longjmp_b = longjmp_b->related_breakpoint;
+       longjmp_b->related_breakpoint = bpt;
+      }
   }
 
+  /* Create a breakpoint in std::terminate.
+     If a C++ exception is raised in the dummy-frame, and the
+     exception handler is (normally, and expected to be) out-of-frame,
+     the default C++ handler will (wrongly) be called in an inferior
+     function call.  This is wrong, as an exception can be  normally
+     and legally handled out-of-frame.  The confines of the dummy frame
+     prevent the unwinder from finding the correct handler (or any
+     handler, unless it is in-frame).  The default handler calls
+     std::terminate.  This will kill the inferior.  Assert that
+     terminate should never be called in an inferior function
+     call.  Place a momentary breakpoint in the std::terminate function
+     and if triggered in the call, rewind.  */
+  if (unwind_on_terminating_exception_p)
+    set_std_terminate_breakpoint ();
+
+  /* Discard both inf_status and caller_state cleanups.
+     From this point on we explicitly restore the associated state
+     or discard it.  */
+  discard_cleanups (inf_status_cleanup);
+
   /* Everything's ready, push all the info needed to restore the
      caller (and identify the dummy-frame) onto the dummy-frame
      stack.  */
-  dummy_frame_push (caller_regcache, &dummy_id);
-  discard_cleanups (caller_regcache_cleanup);
+  dummy_frame_push (caller_state, &dummy_id, inferior_ptid);
+  if (dummy_dtor != NULL)
+    register_dummy_frame_dtor (dummy_id, inferior_ptid,
+                              dummy_dtor, dummy_dtor_data);
+
+  /* Register a clean-up for unwind_on_terminating_exception_breakpoint.  */
+  terminate_bp_cleanup = make_cleanup (cleanup_delete_std_terminate_breakpoint,
+                                      NULL);
 
   /* - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP -
      If you're looking to implement asynchronous dummy-frames, then
      just below is the place to chop this function in two..  */
 
-  /* Now proceed, having reached the desired place.  */
-  clear_proceed_status ();
-    
-  /* Execute a "stack dummy", a piece of code stored in the stack by
-     the debugger to be executed in the inferior.
-
-     The dummy's frame is automatically popped whenever that break is
-     hit.  If that is the first time the program stops,
-     call_function_by_hand returns to its caller with that frame
-     already gone and sets RC to 0.
-   
-     Otherwise, set RC to a non-zero value.  If the called function
-     receives a random signal, we do not allow the user to continue
-     executing it as this may not work.  The dummy frame is poped and
-     we return 1.  If we hit a breakpoint, we leave the frame in place
-     and return 2 (the frame will eventually be popped when we do hit
-     the dummy end breakpoint).  */
-
+  /* TP is invalid after run_inferior_call returns, so enclose this
+     in a block so that it's only in scope during the time it's valid.  */
   {
-    struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
-    struct cleanup *old_cleanups2;
-    int saved_async = 0;
-
-    /* If all error()s out of proceed ended up calling normal_stop
-       (and perhaps they should; it already does in the special case
-       of error out of resume()), then we wouldn't need this.  */
-    make_cleanup (breakpoint_auto_delete_contents, &stop_bpstat);
-
-    disable_watchpoints_before_interactive_call_start ();
-    proceed_to_finish = 1;     /* We want stop_registers, please... */
-
-    if (target_can_async_p ())
-      saved_async = target_async_mask (0);
-
-    old_cleanups2 = make_cleanup_restore_integer (&suppress_resume_observer);
-    suppress_resume_observer = 1;
-    make_cleanup_restore_integer (&suppress_stop_observer);
-    suppress_stop_observer = 1;
-    proceed (real_pc, TARGET_SIGNAL_0, 0);
-    do_cleanups (old_cleanups2);
-    
-    if (saved_async)
-      target_async_mask (saved_async);
-    
-    enable_watchpoints_after_interactive_call_stop ();
-      
-    discard_cleanups (old_cleanups);
-  }
+    struct thread_info *tp = inferior_thread ();
+    struct thread_fsm *saved_sm;
+    struct call_thread_fsm *sm;
 
-  if (stopped_by_random_signal || !stop_stack_dummy)
-    {
-      /* Find the name of the function we're about to complain about.  */
-      const char *name = NULL;
+    /* Save the current FSM.  We'll override it.  */
+    saved_sm = tp->thread_fsm;
+    tp->thread_fsm = NULL;
+
+    /* Save this thread's ptid, we need it later but the thread
+       may have exited.  */
+    call_thread_ptid = tp->ptid;
+
+    /* Run the inferior until it stops.  */
+
+    /* Create the FSM used to manage the infcall.  It tells infrun to
+       not report the stop to the user, and captures the return value
+       before the dummy frame is popped.  run_inferior_call registers
+       it with the thread ASAP.  */
+    sm = new_call_thread_fsm (gdbarch, function,
+                             values_type,
+                             struct_return || hidden_first_param_p,
+                             struct_addr);
+
+    e = run_inferior_call (sm, tp, real_pc);
+
+    observer_notify_inferior_call_post (call_thread_ptid, funaddr);
+
+    tp = find_thread_ptid (call_thread_ptid);
+    if (tp != NULL)
       {
-       struct symbol *symbol = find_pc_function (funaddr);
-       if (symbol)
-         name = SYMBOL_PRINT_NAME (symbol);
-       else
-         {
-           /* Try the minimal symbols.  */
-           struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (funaddr);
-           if (msymbol)
-             name = SYMBOL_PRINT_NAME (msymbol);
-         }
-       if (name == NULL)
+       /* The FSM should still be the same.  */
+       gdb_assert (tp->thread_fsm == &sm->thread_fsm);
+
+       if (thread_fsm_finished_p (tp->thread_fsm))
          {
-           /* Can't use a cleanup here.  It is discarded, instead use
-               an alloca.  */
-           char *tmp = xstrprintf ("at %s", hex_string (funaddr));
-           char *a = alloca (strlen (tmp) + 1);
-           strcpy (a, tmp);
-           xfree (tmp);
-           name = a;
+           struct value *retval;
+
+           /* The inferior call is successful.  Pop the dummy frame,
+              which runs its destructors and restores the inferior's
+              suspend state, and restore the inferior control
+              state.  */
+           dummy_frame_pop (dummy_id, call_thread_ptid);
+           restore_infcall_control_state (inf_status);
+
+           /* Get the return value.  */
+           retval = sm->return_value;
+
+           /* Clean up / destroy the call FSM, and restore the
+              original one.  */
+           thread_fsm_clean_up (tp->thread_fsm);
+           thread_fsm_delete (tp->thread_fsm);
+           tp->thread_fsm = saved_sm;
+
+           maybe_remove_breakpoints ();
+
+           do_cleanups (terminate_bp_cleanup);
+           gdb_assert (retval != NULL);
+           return retval;
          }
+
+       /* Didn't complete.  Restore previous state machine, and
+          handle the error.  */
+       tp->thread_fsm = saved_sm;
       }
+  }
+
+  /* Rethrow an error if we got one trying to run the inferior.  */
+
+  if (e.reason < 0)
+    {
+      const char *name = get_function_name (funaddr,
+                                            name_buf, sizeof (name_buf));
+
+      discard_infcall_control_state (inf_status);
+
+      /* We could discard the dummy frame here if the program exited,
+         but it will get garbage collected the next time the program is
+         run anyway.  */
+
+      switch (e.reason)
+       {
+       case RETURN_ERROR:
+         throw_error (e.error, _("%s\n\
+An error occurred while in a function called from GDB.\n\
+Evaluation of the expression containing the function\n\
+(%s) will be abandoned.\n\
+When the function is done executing, GDB will silently stop."),
+                      e.message, name);
+       case RETURN_QUIT:
+       default:
+         throw_exception (e);
+       }
+    }
+
+  /* If the program has exited, or we stopped at a different thread,
+     exit and inform the user.  */
+
+  if (! target_has_execution)
+    {
+      const char *name = get_function_name (funaddr,
+                                           name_buf, sizeof (name_buf));
+
+      /* If we try to restore the inferior status,
+        we'll crash as the inferior is no longer running.  */
+      discard_infcall_control_state (inf_status);
+
+      /* We could discard the dummy frame here given that the program exited,
+         but it will get garbage collected the next time the program is
+         run anyway.  */
+
+      error (_("The program being debugged exited while in a function "
+              "called from GDB.\n"
+              "Evaluation of the expression containing the function\n"
+              "(%s) will be abandoned."),
+            name);
+    }
+
+  if (! ptid_equal (call_thread_ptid, inferior_ptid))
+    {
+      const char *name = get_function_name (funaddr,
+                                           name_buf, sizeof (name_buf));
+
+      /* We've switched threads.  This can happen if another thread gets a
+        signal or breakpoint while our thread was running.
+        There's no point in restoring the inferior status,
+        we're in a different thread.  */
+      discard_infcall_control_state (inf_status);
+      /* Keep the dummy frame record, if the user switches back to the
+        thread with the hand-call, we'll need it.  */
+      if (stopped_by_random_signal)
+       error (_("\
+The program received a signal in another thread while\n\
+making a function call from GDB.\n\
+Evaluation of the expression containing the function\n\
+(%s) will be abandoned.\n\
+When the function is done executing, GDB will silently stop."),
+              name);
+      else
+       error (_("\
+The program stopped in another thread while making a function call from GDB.\n\
+Evaluation of the expression containing the function\n\
+(%s) will be abandoned.\n\
+When the function is done executing, GDB will silently stop."),
+              name);
+    }
+
+    {
+      /* Make a copy as NAME may be in an objfile freed by dummy_frame_pop.  */
+      char *name = xstrdup (get_function_name (funaddr,
+                                              name_buf, sizeof (name_buf)));
+      make_cleanup (xfree, name);
+
+
       if (stopped_by_random_signal)
        {
          /* We stopped inside the FUNCTION because of a random
             signal.  Further execution of the FUNCTION is not
-            allowed. */
+            allowed.  */
 
          if (unwind_on_signal_p)
            {
-             /* The user wants the context restored. */
+             /* The user wants the context restored.  */
 
              /* We must get back to the frame we were before the
-                dummy call. */
-             frame_pop (get_current_frame ());
+                dummy call.  */
+             dummy_frame_pop (dummy_id, call_thread_ptid);
+
+             /* We also need to restore inferior status to that before the
+                dummy call.  */
+             restore_infcall_control_state (inf_status);
 
              /* FIXME: Insert a bunch of wrap_here; name can be very
                 long if it's a C++ name with arguments and stuff.  */
              error (_("\
 The program being debugged was signaled while in a function called from GDB.\n\
 GDB has restored the context to what it was before the call.\n\
-To change this behavior use \"set unwindonsignal off\"\n\
-Evaluation of the expression containing the function (%s) will be abandoned."),
+To change this behavior use \"set unwindonsignal off\".\n\
+Evaluation of the expression containing the function\n\
+(%s) will be abandoned."),
                     name);
            }
          else
            {
              /* The user wants to stay in the frame where we stopped
-                 (default).*/
-             /* If we restored the inferior status (via the cleanup),
-                we would print a spurious error message (Unable to
-                restore previously selected frame), would write the
-                registers from the inf_status (which is wrong), and
-                would do other wrong things.  */
-             discard_cleanups (inf_status_cleanup);
-             discard_inferior_status (inf_status);
+                (default).
+                Discard inferior status, we're not at the same point
+                we started at.  */
+             discard_infcall_control_state (inf_status);
+
              /* FIXME: Insert a bunch of wrap_here; name can be very
                 long if it's a C++ name with arguments and stuff.  */
              error (_("\
 The program being debugged was signaled while in a function called from GDB.\n\
 GDB remains in the frame where the signal was received.\n\
-To change this behavior use \"set unwindonsignal on\"\n\
-Evaluation of the expression containing the function (%s) will be abandoned."),
+To change this behavior use \"set unwindonsignal on\".\n\
+Evaluation of the expression containing the function\n\
+(%s) will be abandoned.\n\
+When the function is done executing, GDB will silently stop."),
                     name);
            }
        }
 
-      if (!stop_stack_dummy)
+      if (stop_stack_dummy == STOP_STD_TERMINATE)
+       {
+         /* We must get back to the frame we were before the dummy
+            call.  */
+         dummy_frame_pop (dummy_id, call_thread_ptid);
+
+         /* We also need to restore inferior status to that before
+            the dummy call.  */
+         restore_infcall_control_state (inf_status);
+
+         error (_("\
+The program being debugged entered a std::terminate call, most likely\n\
+caused by an unhandled C++ exception.  GDB blocked this call in order\n\
+to prevent the program from being terminated, and has restored the\n\
+context to its original state before the call.\n\
+To change this behaviour use \"set unwind-on-terminating-exception off\".\n\
+Evaluation of the expression containing the function (%s)\n\
+will be abandoned."),
+                name);
+       }
+      else if (stop_stack_dummy == STOP_NONE)
        {
-         /* We hit a breakpoint inside the FUNCTION. */
-         /* If we restored the inferior status (via the cleanup), we
-            would print a spurious error message (Unable to restore
-            previously selected frame), would write the registers
-            from the inf_status (which is wrong), and would do other
-            wrong things.  */
-         discard_cleanups (inf_status_cleanup);
-         discard_inferior_status (inf_status);
+
+         /* We hit a breakpoint inside the FUNCTION.
+            Keep the dummy frame, the user may want to examine its state.
+            Discard inferior status, we're not at the same point
+            we started at.  */
+         discard_infcall_control_state (inf_status);
+
          /* The following error message used to say "The expression
             which contained the function call has been discarded."
             It is a hard concept to explain in a few words.  Ideally,
@@ -826,59 +1343,16 @@ Evaluation of the expression containing the function (%s) will be abandoned."),
             a C++ name with arguments and stuff.  */
          error (_("\
 The program being debugged stopped while in a function called from GDB.\n\
-When the function (%s) is done executing, GDB will silently\n\
-stop (instead of continuing to evaluate the expression containing\n\
-the function call)."), name);
+Evaluation of the expression containing the function\n\
+(%s) will be abandoned.\n\
+When the function is done executing, GDB will silently stop."),
+                name);
        }
 
-      /* The above code errors out, so ...  */
-      internal_error (__FILE__, __LINE__, _("... should not be here"));
     }
 
-  /* If we get here the called FUNCTION run to completion. */
-
-  /* On normal return, the stack dummy has been popped already.  */
-  regcache_cpy_no_passthrough (retbuf, stop_registers);
-
-  /* Restore the inferior status, via its cleanup.  At this stage,
-     leave the RETBUF alone.  */
-  do_cleanups (inf_status_cleanup);
-
-  /* Figure out the value returned by the function.  */
-  {
-    struct value *retval = NULL;
-
-    if (lang_struct_return)
-      retval = value_at (values_type, struct_addr);
-    else if (TYPE_CODE (target_values_type) == TYPE_CODE_VOID)
-      {
-       /* If the function returns void, don't bother fetching the
-          return value.  */
-       retval = allocate_value (values_type);
-      }
-    else
-      {
-       switch (gdbarch_return_value (gdbarch, value_type (function),
-                                     target_values_type, NULL, NULL, NULL))
-         {
-         case RETURN_VALUE_REGISTER_CONVENTION:
-         case RETURN_VALUE_ABI_RETURNS_ADDRESS:
-         case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
-           retval = allocate_value (values_type);
-           gdbarch_return_value (gdbarch, value_type (function), values_type,
-                                 retbuf, value_contents_raw (retval), NULL);
-           break;
-         case RETURN_VALUE_STRUCT_CONVENTION:
-           retval = value_at (values_type, struct_addr);
-           break;
-         }
-      }
-
-    do_cleanups (retbuf_cleanup);
-
-    gdb_assert(retval);
-    return retval;
-  }
+  /* The above code errors out, so ...  */
+  gdb_assert_not_reached ("... should not be here");
 }
 \f
 
@@ -914,4 +1388,20 @@ The default is to stop in the frame where the signal was received."),
                           NULL,
                           show_unwind_on_signal_p,
                           &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("unwind-on-terminating-exception", no_class,
+                          &unwind_on_terminating_exception_p, _("\
+Set unwinding of stack if std::terminate is called while in call dummy."), _("\
+Show unwinding of stack if std::terminate() is called while in a call dummy."),
+                          _("\
+The unwind on terminating exception flag lets the user determine\n\
+what gdb should do if a std::terminate() call is made from the\n\
+default exception handler.  If set, gdb unwinds the stack and restores\n\
+the context to what it was before the call.  If unset, gdb allows the\n\
+std::terminate call to proceed.\n\
+The default is to unwind the frame."),
+                          NULL,
+                          show_unwind_on_terminating_exception_p,
+                          &setlist, &showlist);
+
 }
This page took 0.039898 seconds and 4 git commands to generate.