*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / infcall.c
index 64772d7590fdcdf61d5600eab1dc2fd1d0ac32c9..3012d7f45d9e19c0903e35be1681f4b2934a1968 100644 (file)
@@ -1,14 +1,14 @@
 /* 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
+   Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +17,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "breakpoint.h"
@@ -222,8 +220,24 @@ find_function_addr (struct value *function, struct type **retval_type)
       if (TYPE_LENGTH (ftype) == 1)
        funaddr = value_as_address (value_addr (function));
       else
-       /* Handle integer used as address of a function.  */
-       funaddr = (CORE_ADDR) value_as_long (function);
+       {
+         /* Handle function descriptors lacking debug info.  */
+         int found_descriptor = 0;
+         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,
+                                                           &current_target);
+             if (funaddr != nfunaddr)
+               found_descriptor = 1;
+           }
+         if (!found_descriptor)
+           /* Handle integer used as address of a function.  */
+           funaddr = (CORE_ADDR) value_as_long (function);
+       }
 
       value_type = builtin_type_int;
     }
@@ -232,7 +246,7 @@ find_function_addr (struct value *function, struct type **retval_type)
 
   if (retval_type != NULL)
     *retval_type = value_type;
-  return funaddr + DEPRECATED_FUNCTION_START_OFFSET;
+  return funaddr + gdbarch_deprecated_function_start_offset (current_gdbarch);
 }
 
 /* Call breakpoint_auto_delete on the current contents of the bpstat
@@ -249,7 +263,8 @@ generic_push_dummy_code (struct gdbarch *gdbarch,
                         CORE_ADDR sp, CORE_ADDR funaddr, int using_gcc,
                         struct value **args, int nargs,
                         struct type *value_type,
-                        CORE_ADDR *real_pc, CORE_ADDR *bp_addr)
+                        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.  */
@@ -288,14 +303,17 @@ push_dummy_code (struct gdbarch *gdbarch,
                 CORE_ADDR sp, CORE_ADDR funaddr, int using_gcc,
                 struct value **args, int nargs,
                 struct type *value_type,
-                CORE_ADDR *real_pc, CORE_ADDR *bp_addr)
+                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, using_gcc,
-                                   args, nargs, value_type, real_pc, bp_addr);
+                                   args, nargs, value_type, real_pc, bp_addr,
+                                   regcache);
   else    
     return generic_push_dummy_code (gdbarch, sp, funaddr, using_gcc,
-                                   args, nargs, value_type, real_pc, bp_addr);
+                                   args, nargs, value_type, real_pc, bp_addr,
+                                   regcache);
 }
 
 /* All this stuff with a dummy frame may seem unnecessarily complicated
@@ -321,8 +339,8 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 {
   CORE_ADDR sp;
   CORE_ADDR dummy_addr;
-  struct type *values_type;
-  unsigned char struct_return;
+  struct type *values_type, *target_values_type;
+  unsigned char struct_return = 0, lang_struct_return = 0;
   CORE_ADDR struct_addr = 0;
   struct regcache *retbuf;
   struct cleanup *retbuf_cleanup;
@@ -336,6 +354,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
   struct regcache *caller_regcache;
   struct cleanup *caller_regcache_cleanup;
   struct frame_id dummy_id;
+  struct cleanup *args_cleanup;
 
   if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
     ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
@@ -368,7 +387,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 
   /* Ensure that the initial SP is correctly aligned.  */
   {
-    CORE_ADDR old_sp = read_sp ();
+    CORE_ADDR old_sp = get_frame_sp (get_current_frame ());
     if (gdbarch_frame_align_p (current_gdbarch))
       {
        sp = gdbarch_frame_align (current_gdbarch, old_sp);
@@ -377,7 +396,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
           address.  AMD64 called that region the "red zone".  Skip at
           least the "red zone" size before allocating any space on
           the stack.  */
-       if (INNER_THAN (1, 2))
+       if (gdbarch_inner_than (current_gdbarch, 1, 2))
          sp -= gdbarch_frame_red_zone_size (current_gdbarch);
        else
          sp += gdbarch_frame_red_zone_size (current_gdbarch);
@@ -405,15 +424,17 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
           to pay :-).  */
        if (sp == old_sp)
          {
-           if (INNER_THAN (1, 2))
+           if (gdbarch_inner_than (current_gdbarch, 1, 2))
              /* Stack grows down.  */
              sp = gdbarch_frame_align (current_gdbarch, old_sp - 1);
            else
              /* Stack grows up.  */
              sp = gdbarch_frame_align (current_gdbarch, old_sp + 1);
          }
-       gdb_assert ((INNER_THAN (1, 2) && sp <= old_sp)
-                   || (INNER_THAN (2, 1) && sp >= old_sp));
+       gdb_assert ((gdbarch_inner_than (current_gdbarch, 1, 2)
+                   && sp <= old_sp)
+                   || (gdbarch_inner_than (current_gdbarch, 2, 1)
+                      && sp >= old_sp));
       }
     else
       /* FIXME: cagney/2002-09-18: Hey, you loose!
@@ -440,10 +461,30 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
     using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
   }
 
-  /* Are we returning a value using a structure return or a normal
-     value return? */
+  /* Are we returning a value using a structure return (passing a
+     hidden argument pointing to storage) or a normal value return?
+     There are two cases: language-mandated structure return and
+     target ABI structure return.  The variable STRUCT_RETURN only
+     describes the latter.  The language version is handled by passing
+     the return location as the first parameter to the function,
+     even preceding "this".  This is different from the target
+     ABI version, which is target-specific; for instance, on ia64
+     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))
+    {
+      lang_struct_return = 1;
 
-  struct_return = using_struct_return (values_type, using_gcc);
+      /* Tell the target specific argument pushing routine not to
+        expect a value.  */
+      target_values_type = builtin_type_void;
+    }
+  else
+    {
+      struct_return = using_struct_return (values_type, using_gcc);
+      target_values_type = values_type;
+    }
 
   /* Determine the location of the breakpoint (and possibly other
      stuff) that the called function will return to.  The SPARC, for a
@@ -454,24 +495,24 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
   /* The actual breakpoint (at BP_ADDR) is inserted separatly so there
      is no need to write that out.  */
 
-  switch (CALL_DUMMY_LOCATION)
+  switch (gdbarch_call_dummy_location (current_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 (INNER_THAN (1, 2))
+      if (gdbarch_inner_than (current_gdbarch, 1, 2))
        {
          sp = push_dummy_code (current_gdbarch, sp, funaddr,
-                               using_gcc, args, nargs, values_type,
-                               &real_pc, &bp_addr);
+                               using_gcc, args, nargs, target_values_type,
+                               &real_pc, &bp_addr, get_current_regcache ());
          dummy_addr = sp;
        }
       else
        {
          dummy_addr = sp;
          sp = push_dummy_code (current_gdbarch, sp, funaddr,
-                               using_gcc, args, nargs, values_type,
-                               &real_pc, &bp_addr);
+                               using_gcc, args, nargs, target_values_type,
+                               &real_pc, &bp_addr, get_current_regcache ());
        }
       break;
     case AT_ENTRY_POINT:
@@ -537,9 +578,12 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
          param_type = TYPE_FIELD_TYPE (ftype, i);
        else
          param_type = NULL;
-       
+
        args[i] = value_arg_coerce (args[i], param_type, prototyped);
 
+       if (param_type != NULL && language_pass_by_reference (param_type))
+         args[i] = value_addr (args[i]);
+
        /* elz: this code is to handle the case in which the function
           to be called has a pointer to function as parameter and the
           corresponding actual argument is the address of a function
@@ -580,7 +624,7 @@ You must use a pointer to function type variable. Command ignored."), arg_name);
       }
   }
 
-  if (DEPRECATED_REG_STRUCT_HAS_ADDR_P ())
+  if (gdbarch_deprecated_reg_struct_has_addr_p (current_gdbarch))
     {
       int i;
       /* This is a machine like the sparc, where we may need to pass a
@@ -597,7 +641,8 @@ You must use a pointer to function type variable. Command ignored."), arg_name);
               || (TYPE_CODE (arg_type) == TYPE_CODE_FLT
                   && TYPE_LENGTH (arg_type) > 8)
               )
-             && DEPRECATED_REG_STRUCT_HAS_ADDR (using_gcc, arg_type))
+             && gdbarch_deprecated_reg_struct_has_addr
+                  (current_gdbarch, using_gcc, arg_type))
            {
              CORE_ADDR addr;
              int len;          /*  = TYPE_LENGTH (arg_type); */
@@ -606,7 +651,7 @@ You must use a pointer to function type variable. Command ignored."), arg_name);
              len = TYPE_LENGTH (arg_type);
 
              aligned_len = len;
-             if (INNER_THAN (1, 2))
+             if (gdbarch_inner_than (current_gdbarch, 1, 2))
                {
                  /* stack grows downward */
                  sp -= aligned_len;
@@ -638,10 +683,10 @@ You must use a pointer to function type variable. Command ignored."), arg_name);
      stack, if necessary.  Make certain that the value is correctly
      aligned. */
 
-  if (struct_return)
+  if (struct_return || lang_struct_return)
     {
       int len = TYPE_LENGTH (values_type);
-      if (INNER_THAN (1, 2))
+      if (gdbarch_inner_than (current_gdbarch, 1, 2))
        {
          /* Stack grows downward.  Align STRUCT_ADDR and SP after
              making space for the return value.  */
@@ -663,12 +708,30 @@ You must use a pointer to function type variable. Command ignored."), arg_name);
        }
     }
 
+  if (lang_struct_return)
+    {
+      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[0] = value_from_pointer (lookup_pointer_type (values_type),
+                                       struct_addr);
+      memcpy (&new_args[1], &args[0], sizeof (struct value *) * nargs);
+      args = new_args;
+      nargs++;
+      args_cleanup = make_cleanup (xfree, args);
+    }
+  else
+    args_cleanup = make_cleanup (null_cleanup, NULL);
+
   /* Create the dummy stack frame.  Pass in the call dummy address as,
      presumably, the ABI code knows where, in the call dummy, the
      return address should be pointed.  */
-  sp = gdbarch_push_dummy_call (current_gdbarch, function, current_regcache,
-                               bp_addr, nargs, args, sp, struct_return,
-                               struct_addr);
+  sp = gdbarch_push_dummy_call (current_gdbarch, function,
+                               get_current_regcache (), bp_addr, nargs, args,
+                               sp, struct_return, struct_addr);
+
+  do_cleanups (args_cleanup);
 
   /* Set up a frame ID for the dummy frame so we can pass it to
      set_momentary_breakpoint.  We need to give the breakpoint a frame
@@ -861,7 +924,9 @@ the function call)."), name);
   {
     struct value *retval = NULL;
 
-    if (TYPE_CODE (values_type) == TYPE_CODE_VOID)
+    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.  */
@@ -871,7 +936,7 @@ the function call)."), name);
       {
        struct gdbarch *arch = current_gdbarch;
 
-       switch (gdbarch_return_value (arch, values_type, NULL, NULL, NULL))
+       switch (gdbarch_return_value (arch, target_values_type, NULL, NULL, NULL))
          {
          case RETURN_VALUE_REGISTER_CONVENTION:
          case RETURN_VALUE_ABI_RETURNS_ADDRESS:
This page took 0.027486 seconds and 4 git commands to generate.