Improve MSP430 section placement.
[deliverable/binutils-gdb.git] / gdb / infcall.c
index 8a7c86b1e53bcfb8ed5f8d01c8226625af8ce798..38335a799627c491826c41f3191cead06a223243 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, 2009 Free Software Foundation, Inc.
+   Copyright (C) 1986-2017 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 "exceptions.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.  */
 
    Unfortunately, on certain older platforms, the debug info doesn't
    indicate reliably how each function was defined.  A function type's
-   TYPE_FLAG_PROTOTYPED flag may be clear, even if the function was
-   defined in prototype style.  When calling a function whose
-   TYPE_FLAG_PROTOTYPED flag is clear, GDB consults this flag to
-   decide what to do.
+   TYPE_PROTOTYPED flag may be clear, even if the function was defined
+   in prototype style.  When calling a function whose TYPE_PROTOTYPED
+   flag is clear, GDB consults this flag to decide what to do.
 
    For modern targets, it is proper to assume that, if the prototype
    flag is clear, that can be trusted: `float' arguments should be
@@ -76,8 +77,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);
 }
 
@@ -86,15 +88,16 @@ 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);
 }
 
@@ -118,8 +121,9 @@ show_unwind_on_terminating_exception_p (struct ui_file *file, int from_tty,
                                        const char *value)
 
 {
-  fprintf_filtered (file, _("\
-Unwind stack if a C++ exception is unhandled while in a call dummy is %s.\n"),
+  fprintf_filtered (file,
+                   _("Unwind stack if a C++ exception is "
+                     "unhandled while in a call dummy is %s.\n"),
                    value);
 }
 
@@ -142,7 +146,7 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg,
 
   /* Perform any Ada-specific coercion first.  */
   if (current_language->la_language == language_ada)
-    arg = ada_convert_actual (arg, type, gdbarch, 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
@@ -153,18 +157,19 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg,
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_REF:
+    case TYPE_CODE_RVALUE_REF:
       {
        struct value *new_value;
 
-       if (TYPE_CODE (arg_type) == TYPE_CODE_REF)
-         return value_cast_pointers (type, arg);
+       if (TYPE_IS_REFERENCE (arg_type))
+         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
           if the value was not previously in memory - in some cases
           we should clearly be allowing this, but how?  */
        new_value = value_cast (TYPE_TARGET_TYPE (type), arg);
-       new_value = value_ref (new_value);
+       new_value = value_ref (new_value, TYPE_CODE (type));
        return new_value;
       }
     case TYPE_CODE_INT:
@@ -211,7 +216,6 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg,
     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:
@@ -224,6 +228,21 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg,
   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.  */
 
@@ -232,45 +251,57 @@ find_function_addr (struct value *function, struct type **retval_type)
 {
   struct type *ftype = check_typedef (value_type (function));
   struct gdbarch *gdbarch = get_type_arch (ftype);
-  enum type_code code = TYPE_CODE (ftype);
   struct type *value_type = NULL;
-  CORE_ADDR funaddr;
+  /* 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 (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 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 (gdbarch, funaddr,
@@ -320,20 +351,23 @@ get_function_name (CORE_ADDR funaddr, char *buf, int buf_size)
 {
   {
     struct symbol *symbol = find_pc_function (funaddr);
+
     if (symbol)
       return SYMBOL_PRINT_NAME (symbol);
   }
 
   {
     /* Try the minimal symbols.  */
-    struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (funaddr);
-    if (msymbol)
-      return SYMBOL_PRINT_NAME (msymbol);
+    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);
@@ -341,6 +375,185 @@ get_function_name (CORE_ADDR funaddr, char *buf, int buf_size)
   }
 }
 
+/* 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)
+    {
+      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
+    {
+      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);
+       }
+    }
+
+  gdb_assert (retval != NULL);
+  return retval;
+}
+
+/* Data for the FSM that manages an infcall.  It's main job is to
+   record the called function's return value.  */
+
+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;
+
+  /* The top level that started the infcall (and is synchronously
+     waiting for it to end).  */
+  struct ui *waiting_ui;
+};
+
+static int call_thread_fsm_should_stop (struct thread_fsm *self,
+                                       struct thread_info *thread);
+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 ui *waiting_ui, struct interp *cmd_interp,
+                    struct gdbarch *gdbarch, struct value *function,
+                    struct type *value_type,
+                    int struct_return_p, CORE_ADDR struct_addr)
+{
+  struct call_thread_fsm *sm;
+
+  sm = XCNEW (struct call_thread_fsm);
+  thread_fsm_ctor (&sm->thread_fsm, &call_thread_fsm_ops, cmd_interp);
+
+  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;
+
+  sm->waiting_ui = waiting_ui;
+
+  return sm;
+}
+
+/* Implementation of should_stop method for infcalls.  */
+
+static int
+call_thread_fsm_should_stop (struct thread_fsm *self,
+                            struct thread_info *thread)
+{
+  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.  */
+      scoped_restore save_ui = make_scoped_restore (&current_ui, f->waiting_ui);
+      target_terminal_ours ();
+      f->waiting_ui->prompt_state = PROMPT_NEEDED;
+    }
+
+  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
@@ -350,36 +563,86 @@ get_function_name (CORE_ADDR funaddr, char *buf, int buf_size)
    thrown errors.  The caller should rethrow if there's an error.  */
 
 static struct gdb_exception
-run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc)
+run_inferior_call (struct call_thread_fsm *sm,
+                  struct thread_info *call_thread, CORE_ADDR real_pc)
 {
-  volatile struct gdb_exception e;
-  int saved_async = 0;
-  int saved_in_infcall = call_thread->in_infcall;
+  struct gdb_exception caught_error = exception_none;
+  int saved_in_infcall = call_thread->control.in_infcall;
   ptid_t call_thread_ptid = call_thread->ptid;
-  char *saved_target_shortname = xstrdup (target_shortname);
+  enum prompt_state saved_prompt_state = current_ui->prompt_state;
+  int was_running = call_thread->state == THREAD_RUNNING;
+  int saved_ui_async = current_ui->async;
+
+  /* Infcalls run synchronously, in the foreground.  */
+  current_ui->prompt_state = PROMPT_BLOCKED;
+  /* So that we don't print the prompt prematurely in
+     fetch_inferior_event.  */
+  current_ui->async = 0;
+
+  delete_file_handler (current_ui->input_fd);
 
-  call_thread->in_infcall = 1;
+  call_thread->control.in_infcall = 1;
 
-  clear_proceed_status ();
+  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 ();
-  call_thread->proceed_to_finish = 1; /* We want stop_registers, please... */
 
-  if (target_can_async_p ())
-    saved_async = target_async_mask (0);
+  /* We want to print return value, please...  */
+  call_thread->control.proceed_to_finish = 1;
 
-  TRY_CATCH (e, RETURN_MASK_ALL)
-    proceed (real_pc, TARGET_SIGNAL_0, 0);
+  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 has the prompt blocked before, then ensure that it remains
+     so.  normal_stop calls async_enable_stdin, so reset the prompt
+     state again here.  In other cases, stdin will be re-enabled by
+     inferior_event_handler, when an exception is thrown.  */
+  current_ui->prompt_state = saved_prompt_state;
+  if (current_ui->prompt_state == PROMPT_BLOCKED)
+    delete_file_handler (current_ui->input_fd);
+  else
+    ui_register_input_event_handler (current_ui);
+  current_ui->async = saved_ui_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);
 
-  /* Don't restore the async mask if the target has changed,
-     saved_async is for the original target.  */
-  if (saved_async
-      && strcmp (saved_target_shortname, target_shortname) == 0)
-    target_async_mask (saved_async);
+  /* 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 ();
 
@@ -388,18 +651,31 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc)
      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 (e.reason < 0)
+  if (caught_error.reason < 0)
     {
       if (call_thread != NULL)
-       breakpoint_auto_delete (call_thread->stop_bpstat);
+       breakpoint_auto_delete (call_thread->control.stop_bpstat);
     }
 
   if (call_thread != NULL)
-    call_thread->in_infcall = saved_in_infcall;
+    call_thread->control.in_infcall = saved_in_infcall;
 
-  xfree (saved_target_shortname);
+  return caught_error;
+}
 
-  return e;
+/* 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
@@ -418,19 +694,21 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc)
    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;
   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 inferior_status *inf_status;
+  struct infcall_control_state *inf_status;
   struct cleanup *inf_status_cleanup;
-  struct inferior_thread_state *caller_state;
-  struct cleanup *caller_state_cleanup;
+  struct infcall_suspend_state *caller_state;
   CORE_ADDR funaddr;
   CORE_ADDR real_pc;
   struct type *ftype = check_typedef (value_type (function));
@@ -439,12 +717,11 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
   struct cleanup *args_cleanup;
   struct frame_info *frame;
   struct gdbarch *gdbarch;
-  struct breakpoint *terminate_bp = NULL;
-  struct minimal_symbol *tm;
+  struct cleanup *terminate_bp_cleanup;
   ptid_t call_thread_ptid;
   struct gdb_exception e;
-  const char *name;
   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));
@@ -452,6 +729,12 @@ 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);
 
@@ -460,20 +743,22 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 
   /* A cleanup for the inferior status.
      This is only needed while we're preparing the inferior function call.  */
-  inf_status = save_inferior_status ();
-  inf_status_cleanup = make_cleanup_restore_inferior_status (inf_status);
+  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_state = save_inferior_thread_state ();
-  caller_state_cleanup = make_cleanup_restore_inferior_thread_state (caller_state);
+  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);
@@ -517,10 +802,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!
@@ -530,19 +814,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);
   if (!values_type)
     values_type = builtin_type (gdbarch)->builtin_int;
 
-  CHECK_TYPEDEF (values_type);
+  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?
@@ -555,9 +866,9 @@ 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.  */
@@ -565,26 +876,50 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
     }
   else
     {
-      struct_return = using_struct_return (gdbarch,
-                                          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:
-      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:
       {
@@ -592,38 +927,12 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 
        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
-          its 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;
+          its address is the same as the address of the dummy.
 
-       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.  */
+          The actual breakpoint is inserted separatly so there is no need to
+          write that out.  */
        bp_addr = dummy_addr;
        break;
       }
@@ -636,6 +945,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 
   {
     int i;
+
     for (i = nargs - 1; i >= 0; i--)
       {
        int prototyped;
@@ -665,16 +975,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;
@@ -682,22 +1003,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);
@@ -730,16 +1051,33 @@ 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.
@@ -755,27 +1093,24 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
      call.  Place a momentary breakpoint in the std::terminate function
      and if triggered in the call, rewind.  */
   if (unwind_on_terminating_exception_p)
-     {
-       struct minimal_symbol *tm = lookup_minimal_symbol  ("std::terminate()",
-                                                          NULL, NULL);
-       if (tm != NULL)
-          terminate_bp = set_momentary_breakpoint_at_pc
-            (SYMBOL_VALUE_ADDRESS (tm),  bp_breakpoint);
-     }
-
-  /* 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_state, &dummy_id);
+    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_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.  */
-  if (terminate_bp)
-    make_cleanup_delete_breakpoint (terminate_bp);
+  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
@@ -785,6 +1120,12 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
      in a block so that it's only in scope during the time it's valid.  */
   {
     struct thread_info *tp = inferior_thread ();
+    struct thread_fsm *saved_sm;
+    struct call_thread_fsm *sm;
+
+    /* 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.  */
@@ -792,7 +1133,57 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 
     /* Run the inferior until it stops.  */
 
-    e = run_inferior_call (tp, real_pc);
+    /* 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 (current_ui, command_interp (),
+                             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)
+      {
+       /* The FSM should still be the same.  */
+       gdb_assert (tp->thread_fsm == &sm->thread_fsm);
+
+       if (thread_fsm_finished_p (tp->thread_fsm))
+         {
+           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, tp);
+           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.  */
@@ -802,7 +1193,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
       const char *name = get_function_name (funaddr,
                                             name_buf, sizeof (name_buf));
 
-      discard_inferior_status (inf_status);
+      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
@@ -811,8 +1202,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
       switch (e.reason)
        {
        case RETURN_ERROR:
-         throw_error (e.error, _("\
-%s\n\
+         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\
@@ -834,16 +1224,16 @@ When the function is done executing, GDB will silently stop."),
 
       /* If we try to restore the inferior status,
         we'll crash as the inferior is no longer running.  */
-      discard_inferior_status (inf_status);
+      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."),
+      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);
     }
 
@@ -856,7 +1246,7 @@ Evaluation of the expression containing the function\n\
         signal or breakpoint while our thread was running.
         There's no point in restoring the inferior status,
         we're in a different thread.  */
-      discard_inferior_status (inf_status);
+      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)
@@ -876,28 +1266,30 @@ When the function is done executing, GDB will silently stop."),
               name);
     }
 
-  if (stopped_by_random_signal || !stop_stack_dummy)
     {
-      const char *name = get_function_name (funaddr,
-                                           name_buf, sizeof (name_buf));
+      /* 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.  */
-             dummy_frame_pop (dummy_id);
+             dummy_frame_pop (dummy_id, call_thread_ptid);
 
              /* We also need to restore inferior status to that before the
                 dummy call.  */
-             restore_inferior_status (inf_status);
+             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.  */
@@ -915,7 +1307,7 @@ Evaluation of the expression containing the function\n\
                 (default).
                 Discard inferior status, we're not at the same point
                 we started at.  */
-             discard_inferior_status (inf_status);
+             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.  */
@@ -930,30 +1322,17 @@ When the function is done executing, GDB will silently stop."),
            }
        }
 
-      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);
 
-         /* Check if unwind on terminating exception behaviour is on.  */
-         if (unwind_on_terminating_exception_p)
-           {
-             /* Check that the breakpoint is our special std::terminate
-                breakpoint.  If it is, we do not want to kill the inferior
-                in an inferior function call. Rewind, and warn the
-                user.  */
-
-             if (terminate_bp != NULL
-                 && (inferior_thread()->stop_bpstat->breakpoint_at->address
-                     == terminate_bp->loc->address))
-               {
-                 /* We must get back to the frame we were before the
-                    dummy call.  */
-                 dummy_frame_pop (dummy_id);
-
-                 /* We also need to restore inferior status to that before the
-                    dummy call.  */
-                 restore_inferior_status (inf_status);
-
-                 error (_("\
+         /* 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\
@@ -961,14 +1340,16 @@ 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);
-               }
-           }
+                name);
+       }
+      else if (stop_stack_dummy == STOP_NONE)
+       {
+
          /* 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_inferior_status (inf_status);
+         discard_infcall_control_state (inf_status);
 
          /* The following error message used to say "The expression
             which contained the function call has been discarded."
@@ -986,57 +1367,10 @@ 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 ran to completion,
-     and the dummy frame has already been popped.  */
-
-  {
-    struct regcache *retbuf = regcache_xmalloc (gdbarch);
-    struct cleanup *retbuf_cleanup = make_cleanup_regcache_xfree (retbuf);
-    struct value *retval = NULL;
-
-    regcache_cpy_no_passthrough (retbuf, stop_registers);
-
-    /* Inferior call is successful.  Restore the inferior status.
-       At this stage, leave the RETBUF alone.  */
-    restore_inferior_status (inf_status);
-
-    /* Figure out the value returned by the function.  */
-
-    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
 
@@ -1076,7 +1410,8 @@ The default is to stop in the frame where the signal was received."),
   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."), _("\
+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\
This page took 0.041435 seconds and 4 git commands to generate.