2008-11-12 Tristan Gingold <gingold@adacore.com>
[binutils-gdb.git] / gdb / infcall.c
index 82130c69bbefcff7c07363913470b16e1d5ecf16..aa3bee0999ad3e22f8d5ef841a07d8901341b8db 100644 (file)
@@ -34,6 +34,8 @@
 #include "gdb_string.h"
 #include "infcall.h"
 #include "dummy-frame.h"
+#include "ada-lang.h"
+#include "gdbthread.h"
 
 /* NOTE: cagney/2003-04-16: What's the future of this code?
 
@@ -91,19 +93,32 @@ Unwinding of stack if a signal is received while in a call dummy is %s.\n"),
 
 
 /* Perform the standard coercions that are specified
-   for arguments to be passed to C functions.
+   for arguments to be passed to C or Ada functions.
 
    If PARAM_TYPE is non-NULL, it is the expected parameter type.
-   IS_PROTOTYPED is non-zero if the function declaration is prototyped.  */
+   IS_PROTOTYPED is non-zero if the function declaration is prototyped.
+   SP is the stack pointer were additional data can be pushed (updating
+   its value as needed).  */
 
 static struct value *
-value_arg_coerce (struct value *arg, struct type *param_type,
-                 int is_prototyped)
+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);
+
+  /* Force the value to the target if we will need its address.  At
+     this point, we could allocate arguments on the stack instead of
+     calling malloc if we knew that their addresses would not be
+     saved by the called function.  */
+  arg = value_coerce_to_target (arg);
+
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_REF:
@@ -128,22 +143,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:
@@ -186,7 +201,7 @@ 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;
+  struct type *value_type = NULL;
   CORE_ADDR funaddr;
 
   /* If it's a member function, just look at the function
@@ -210,8 +225,6 @@ find_function_addr (struct value *function, struct type **retval_type)
                                                        &current_target);
          value_type = TYPE_TARGET_TYPE (ftype);
        }
-      else
-       value_type = builtin_type_int;
     }
   else if (code == TYPE_CODE_INT)
     {
@@ -238,8 +251,6 @@ 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."));
@@ -250,49 +261,13 @@ find_function_addr (struct value *function, struct type **retval_type)
 }
 
 /* Call breakpoint_auto_delete on the current contents of the bpstat
-   pointed to by arg (which is really a bpstat *).  */
+   of the current thread.  */
 
 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;
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    breakpoint_auto_delete (inferior_thread ()->stop_bpstat);
 }
 
 /* For CALL_DUMMY_ON_STACK, push a breakpoint sequence that the called
@@ -306,14 +281,11 @@ 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);
 }
 
 /* All this stuff with a dummy frame may seem unnecessarily complicated
@@ -449,7 +421,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
         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
-        fails, try unwind_dummy_id().
+        fails, try dummy_id().
 
          If the ABI specifies a "Red Zone" (see the doco) the code
          below will quietly trash it.  */
@@ -457,6 +429,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
@@ -480,7 +455,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
     }
   else
     {
-      struct_return = using_struct_return (values_type);
+      struct_return = using_struct_return (value_type (function), values_type);
       target_values_type = values_type;
     }
 
@@ -577,7 +552,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);
+       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]);
@@ -643,7 +619,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
      ID so that the breakpoint code can correctly re-identify the
      dummy breakpoint.  */
   /* Sanity.  The exact same SP value is returned by PUSH_DUMMY_CALL,
-     saved as the dummy-frame TOS, and used by unwind_dummy_id to form
+     saved as the dummy-frame TOS, and used by dummy_id to form
      the frame ID's stack address.  */
   dummy_id = frame_id_build (sp, bp_addr);
 
@@ -658,7 +634,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
     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
-       unwind_dummy_id to form the frame ID's stack address.  */
+       dummy_id to form the frame ID's stack address.  */
     bpt = set_momentary_breakpoint (sal, dummy_id, bp_call_dummy);
     bpt->disposition = disp_del;
   }
@@ -693,20 +669,27 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 
   {
     struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
+    struct cleanup *old_cleanups2;
     int saved_async = 0;
+    struct thread_info *tp = inferior_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.  */
-    make_cleanup (breakpoint_auto_delete_contents, &stop_bpstat);
+    make_cleanup (breakpoint_auto_delete_contents, NULL);
 
     disable_watchpoints_before_interactive_call_start ();
-    proceed_to_finish = 1;     /* We want stop_registers, please... */
+    tp->proceed_to_finish = 1; /* We want stop_registers, please... */
 
     if (target_can_async_p ())
       saved_async = target_async_mask (0);
-    
+
+    old_cleanups2 = make_cleanup_restore_integer (&suppress_resume_observer);
+    suppress_resume_observer = 1;
+    make_cleanup_restore_integer (&suppress_stop_observer);
+    suppress_stop_observer = 1;
     proceed (real_pc, TARGET_SIGNAL_0, 0);
+    do_cleanups (old_cleanups2);
     
     if (saved_async)
       target_async_mask (saved_async);
@@ -716,6 +699,16 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
     discard_cleanups (old_cleanups);
   }
 
+  if (! target_has_execution)
+    {
+      /* If we try to restore the inferior status (via the cleanup),
+        we'll crash as the inferior is no longer running.  */
+      discard_cleanups (inf_status_cleanup);
+      discard_inferior_status (inf_status);
+      error (_("\
+The program being debugged exited while in a function called from GDB."));
+    }
+
   if (stopped_by_random_signal || !stop_stack_dummy)
     {
       /* Find the name of the function we're about to complain about.  */
@@ -839,15 +832,15 @@ the function call)."), name);
       }
     else
       {
-       switch (gdbarch_return_value (gdbarch, target_values_type,
-                                     NULL, NULL, NULL))
+       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, values_type, retbuf,
-                                 value_contents_raw (retval), NULL);
+           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);