gdb/
[deliverable/binutils-gdb.git] / gdb / infcall.c
index c065b59b42d2355e822f32dda4dabba39b2f96cd..51cd11829d9948d6a8e42dca50379cf47e620b76 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-2012 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -21,6 +19,7 @@
 
 #include "defs.h"
 #include "breakpoint.h"
+#include "tracepoint.h"
 #include "target.h"
 #include "regcache.h"
 #include "inferior.h"
 #include "infcall.h"
 #include "dummy-frame.h"
 #include "ada-lang.h"
+#include "gdbthread.h"
+#include "exceptions.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 +75,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 +86,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 +134,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 +159,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 +176,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:
@@ -191,6 +226,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 +248,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,61 +311,13 @@ 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);
-}
-
-/* Call breakpoint_auto_delete on the current contents of the bpstat
-   pointed to by arg (which is really a bpstat *).  */
-
-static void
-breakpoint_auto_delete_contents (void *arg)
-{
-  breakpoint_auto_delete (*(bpstat *) arg);
-}
-
-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)
-{
-  /* 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))
-    {
-      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?  */
-    }      
-  else
-    {
-      (*bp_addr) = sp;
-      gdbarch_breakpoint_from_pc (gdbarch, bp_addr, &bplen);
-      sp = gdbarch_frame_align (gdbarch, sp + bplen);
-    }
-  /* Inferior resumes at the function entry point.  */
-  (*real_pc) = funaddr;
-  return sp;
+  return funaddr + gdbarch_deprecated_function_start_offset (gdbarch);
 }
 
 /* For CALL_DUMMY_ON_STACK, push a breakpoint sequence that the called
@@ -319,14 +331,114 @@ push_dummy_code (struct gdbarch *gdbarch,
                 CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
                 struct regcache *regcache)
 {
-  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);
+  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);
+}
+
+/* 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)
+{
+  {
+    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);
+  }
+
+  {
+    char *tmp = xstrprintf (_(RAW_FUNCTION_ADDRESS_FORMAT),
+                            hex_string (funaddr));
+
+    gdb_assert (strlen (tmp) + 1 <= buf_size);
+    strcpy (buf, tmp);
+    xfree (tmp);
+    return buf;
+  }
+}
+
+/* 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 thread_info *call_thread, CORE_ADDR real_pc)
+{
+  volatile struct gdb_exception e;
+  int saved_in_infcall = call_thread->control.in_infcall;
+  ptid_t call_thread_ptid = call_thread->ptid;
+
+  call_thread->control.in_infcall = 1;
+
+  clear_proceed_status ();
+
+  disable_watchpoints_before_interactive_call_start ();
+
+  /* We want stop_registers, please...  */
+  call_thread->control.proceed_to_finish = 1;
+
+  TRY_CATCH (e, RETURN_MASK_ALL)
+    {
+      proceed (real_pc, GDB_SIGNAL_0, 0);
+
+      /* Inferior function calls are always synchronous, even if the
+        target supports asynchronous execution.  Do here what
+        `proceed' itself does in sync mode.  */
+      if (target_can_async_p () && is_running (inferior_ptid))
+       {
+         wait_for_inferior ();
+         normal_stop ();
+       }
+    }
+
+  /* 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);
+
+  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 (e.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 e;
+}
+
+/* A cleanup function that calls delete_std_terminate_breakpoint.  */
+static void
+cleanup_delete_std_terminate_breakpoint (void *ignore)
+{
+  delete_std_terminate_breakpoint ();
 }
 
 /* All this stuff with a dummy frame may seem unnecessarily complicated
@@ -345,30 +457,30 @@ 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)
 {
   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];
 
   if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
     ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
@@ -376,35 +488,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 +561,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,7 +573,7 @@ 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
@@ -470,6 +582,9 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
   }
 
   funaddr = find_function_addr (function, &values_type);
+  if (!values_type)
+    values_type = builtin_type (gdbarch)->builtin_int;
+
   CHECK_TYPEDEF (values_type);
 
   /* Are we returning a value using a structure return (passing a
@@ -483,17 +598,17 @@ 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;
     }
 
@@ -509,56 +624,18 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
   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,
+      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 ());
-       }
       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.  */
        bp_addr = dummy_addr;
        break;
       }
@@ -567,10 +644,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 +668,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,11 +678,12 @@ 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)
+  if (struct_return || hidden_first_param_p)
     {
       int len = TYPE_LENGTH (values_type);
+
       if (gdbarch_inner_than (gdbarch, 1, 2))
        {
          /* Stack grows downward.  Align STRUCT_ADDR and SP after
@@ -616,7 +696,7 @@ 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;
@@ -626,7 +706,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
        }
     }
 
-  if (lang_struct_return)
+  if (hidden_first_param_p)
     {
       struct value **new_args;
 
@@ -664,152 +744,245 @@ 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 ();
+
   /* 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);
+
+  /* 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);
+
+  /* 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);
-    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);
-    
-    proceed (real_pc, TARGET_SIGNAL_0, 0);
-    
-    if (saved_async)
-      target_async_mask (saved_async);
-    
-    enable_watchpoints_after_interactive_call_stop ();
-      
-    discard_cleanups (old_cleanups);
+    struct thread_info *tp = inferior_thread ();
+
+    /* 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.  */
+
+    e = run_inferior_call (tp, real_pc);
   }
 
-  if (stopped_by_random_signal || !stop_stack_dummy)
+  /* Rethrow an error if we got one trying to run the inferior.  */
+
+  if (e.reason < 0)
     {
-      /* Find the name of the function we're about to complain about.  */
-      const char *name = 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)
-         {
-           /* 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;
-         }
-      }
+      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);
+    }
+
+  if (stopped_by_random_signal || stop_stack_dummy != STOP_STACK_DUMMY)
+    {
+      const char *name = get_function_name (funaddr,
+                                           name_buf, sizeof (name_buf));
+
       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);
+
+             /* 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);
+
+         /* 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,
@@ -820,57 +993,64 @@ 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);
+  do_cleanups (terminate_bp_cleanup);
 
-  /* Restore the inferior status, via its cleanup.  At this stage,
-     leave the RETBUF alone.  */
-  do_cleanups (inf_status_cleanup);
+  /* If we get here the called FUNCTION ran to completion,
+     and the dummy frame has already been popped.  */
 
-  /* Figure out the value returned by the function.  */
   {
+    struct address_space *aspace = get_regcache_aspace (stop_registers);
+    struct regcache *retbuf = regcache_xmalloc (gdbarch, aspace);
+    struct cleanup *retbuf_cleanup = make_cleanup_regcache_xfree (retbuf);
     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)
+    regcache_cpy_no_passthrough (retbuf, stop_registers);
+
+    /* Inferior call is successful.  Restore the inferior status.
+       At this stage, leave the RETBUF alone.  */
+    restore_infcall_control_state (inf_status);
+
+    /* Figure out the value returned by the function.  */
+    retval = allocate_value (values_type);
+
+    if (hidden_first_param_p)
+      read_value_memory (retval, 0, 1, struct_addr,
+                        value_contents_raw (retval),
+                        TYPE_LENGTH (values_type));
+    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))
+       switch (gdbarch_return_value (gdbarch, 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,
+           gdbarch_return_value (gdbarch, function, values_type,
                                  retbuf, value_contents_raw (retval), NULL);
            break;
          case RETURN_VALUE_STRUCT_CONVENTION:
-           retval = value_at (values_type, struct_addr);
+           read_value_memory (retval, 0, 1, struct_addr,
+                              value_contents_raw (retval),
+                              TYPE_LENGTH (values_type));
            break;
          }
       }
 
     do_cleanups (retbuf_cleanup);
 
-    gdb_assert(retval);
+    gdb_assert (retval);
     return retval;
   }
 }
@@ -908,4 +1088,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.035989 seconds and 4 git commands to generate.