]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/infcall.c
gdb: add back declarations for _initialize functions
[thirdparty/binutils-gdb.git] / gdb / infcall.c
index b2f8ed21dc92d10830f283c499887ec51ecc207f..b13c781c9d46b7d4615d2b7cc20b934d1c65f9be 100644 (file)
@@ -1,6 +1,6 @@
 /* Perform an inferior function call, for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2019 Free Software Foundation, Inc.
+   Copyright (C) 1986-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -42,6 +42,7 @@
 #include "thread-fsm.h"
 #include <algorithm>
 #include "gdbsupport/scope-exit.h"
+#include <list>
 
 /* If we can't find a function's name from its address,
    we print this instead.  */
@@ -55,7 +56,7 @@
    asynchronous inferior function call implementation, and that in
    turn means restructuring the code so that it is event driven.  */
 
-static int may_call_functions_p = 1;
+static bool may_call_functions_p = true;
 static void
 show_may_call_functions_p (struct ui_file *file, int from_tty,
                           struct cmd_list_element *c,
@@ -86,7 +87,7 @@ show_may_call_functions_p (struct ui_file *file, int from_tty,
    trust the debug information; the user can override this behavior
    with "set coerce-float-to-double 0".  */
 
-static int coerce_float_to_double_p = 1;
+static bool coerce_float_to_double_p = true;
 static void
 show_coerce_float_to_double_p (struct ui_file *file, int from_tty,
                               struct cmd_list_element *c, const char *value)
@@ -104,7 +105,7 @@ show_coerce_float_to_double_p (struct ui_file *file, int from_tty,
 
    The default is to stop in the frame where the signal was received.  */
 
-static int unwind_on_signal_p = 0;
+static bool unwind_on_signal_p = false;
 static void
 show_unwind_on_signal_p (struct ui_file *file, int from_tty,
                         struct cmd_list_element *c, const char *value)
@@ -127,7 +128,7 @@ show_unwind_on_signal_p (struct ui_file *file, int from_tty,
    The default is to unwind the frame if a std::terminate call is
    made.  */
 
-static int unwind_on_terminating_exception_p = 1;
+static bool unwind_on_terminating_exception_p = true;
 
 static void
 show_unwind_on_terminating_exception_p (struct ui_file *file, int from_tty,
@@ -145,13 +146,11 @@ show_unwind_on_terminating_exception_p (struct ui_file *file, int from_tty,
    for arguments to be passed to C, Ada or Fortran functions.
 
    If PARAM_TYPE is non-NULL, it is the expected parameter type.
-   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).  */
+   IS_PROTOTYPED is non-zero if the function declaration is prototyped.  */
 
 static struct value *
 value_arg_coerce (struct gdbarch *gdbarch, struct value *arg,
-                 struct type *param_type, int is_prototyped, CORE_ADDR *sp)
+                 struct type *param_type, int is_prototyped)
 {
   const struct builtin_type *builtin = builtin_type (gdbarch);
   struct type *arg_type = check_typedef (value_type (arg));
@@ -389,7 +388,7 @@ 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);
+      return symbol->print_name ();
   }
 
   {
@@ -397,7 +396,7 @@ get_function_name (CORE_ADDR funaddr, char *buf, int buf_size)
     struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (funaddr);
 
     if (msymbol.minsym)
-      return MSYMBOL_PRINT_NAME (msymbol.minsym);
+      return msymbol.minsym->print_name ();
   }
 
   {
@@ -650,7 +649,8 @@ run_inferior_call (struct call_thread_fsm *sm,
   if (!was_running
       && call_thread_ptid == inferior_ptid
       && stop_stack_dummy == STOP_STACK_DUMMY)
-    finish_thread_state (user_visible_resume_ptid (0));
+    finish_thread_state (call_thread->inf->process_target (),
+                        user_visible_resume_ptid (0));
 
   enable_watchpoints_after_interactive_call_stop ();
 
@@ -670,6 +670,69 @@ run_inferior_call (struct call_thread_fsm *sm,
   return caught_error;
 }
 
+/* Reserve space on the stack for a value of the given type.
+   Return the address of the allocated space.
+   Make certain that the value is correctly aligned.
+   The SP argument is modified.  */
+
+static CORE_ADDR
+reserve_stack_space (const type *values_type, CORE_ADDR &sp)
+{
+  struct frame_info *frame = get_current_frame ();
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  CORE_ADDR addr = 0;
+
+  if (gdbarch_inner_than (gdbarch, 1, 2))
+    {
+      /* Stack grows downward.  Align STRUCT_ADDR and SP after
+        making space.  */
+      sp -= TYPE_LENGTH (values_type);
+      if (gdbarch_frame_align_p (gdbarch))
+       sp = gdbarch_frame_align (gdbarch, sp);
+      addr = sp;
+    }
+  else
+    {
+      /* Stack grows upward.  Align the frame, allocate space, and
+        then again, re-align the frame???  */
+      if (gdbarch_frame_align_p (gdbarch))
+       sp = gdbarch_frame_align (gdbarch, sp);
+      addr = sp;
+      sp += TYPE_LENGTH (values_type);
+      if (gdbarch_frame_align_p (gdbarch))
+       sp = gdbarch_frame_align (gdbarch, sp);
+    }
+
+  return addr;
+}
+
+/* The data structure which keeps a destructor function and
+   its implicit 'this' parameter.  */
+
+struct destructor_info
+{
+  destructor_info (struct value *function, struct value *self)
+    : function (function), self (self) { }
+
+  struct value *function;
+  struct value *self;
+};
+
+
+/* Auxiliary function that takes a list of destructor functions
+   with their 'this' parameters, and invokes the functions.  */
+
+static void
+call_destructors (const std::list<destructor_info> &dtors_to_invoke,
+                 struct type *default_return_type)
+{
+  for (auto vals : dtors_to_invoke)
+    {
+      call_function_by_hand (vals.function, default_return_type,
+                            gdb::make_array_view (&(vals.self), 1));
+    }
+}
+
 /* See infcall.h.  */
 
 struct value *
@@ -691,7 +754,7 @@ call_function_by_hand (struct value *function,
    making dummy frames be different from normal frames, consider that.  */
 
 /* Perform a function call in the inferior.
-   ARGS is a vector of values of arguments (NARGS of them).
+   ARGS is a vector of values of arguments.
    FUNCTION is a value, the function to be called.
    Returns a value representing what the function returned.
    May fail to return, if a breakpoint or signal is hit
@@ -746,6 +809,27 @@ call_function_by_hand_dummy (struct value *function,
   if (!gdbarch_push_dummy_call_p (gdbarch))
     error (_("This target does not support function calls."));
 
+  /* Find the function type and do a sanity check.  */
+  type *ftype;
+  type *values_type;
+  CORE_ADDR funaddr = find_function_addr (function, &values_type, &ftype);
+
+  if (values_type == NULL)
+    values_type = default_return_type;
+  if (values_type == NULL)
+    {
+      const char *name = get_function_name (funaddr,
+                                           name_buf, sizeof (name_buf));
+      error (_("'%s' has unknown return type; "
+              "cast the call to its declared return type"),
+            name);
+    }
+
+  values_type = check_typedef (values_type);
+
+  if (args.size () < TYPE_NFIELDS (ftype))
+    error (_("Too few arguments in function call."));
+
   /* A holder for the inferior status.
      This is only needed while we're preparing the inferior function call.  */
   infcall_control_state_up inf_status (save_infcall_control_state ());
@@ -786,7 +870,7 @@ call_function_by_hand_dummy (struct value *function,
           void parameterless generic dummy frame calls to frameless
           functions will create a sequence of effectively identical
           frames (SP, FP and TOS and PC the same).  This, not
-          suprisingly, results in what appears to be a stack in an
+          surprisingly, results in what appears to be a stack in an
           infinite loop --- when GDB tries to find a generic dummy
           frame on the internal dummy frame stack, it will always
           find the first one.
@@ -851,23 +935,6 @@ call_function_by_hand_dummy (struct value *function,
       }
   }
 
-  type *ftype;
-  type *values_type;
-  CORE_ADDR funaddr = find_function_addr (function, &values_type, &ftype);
-
-  if (values_type == NULL)
-    values_type = default_return_type;
-  if (values_type == NULL)
-    {
-      const char *name = get_function_name (funaddr,
-                                           name_buf, sizeof (name_buf));
-      error (_("'%s' has unknown return type; "
-              "cast the call to its declared return type"),
-            name);
-    }
-
-  values_type = check_typedef (values_type);
-
   /* Are we returning a value using a structure return?  */
 
   if (gdbarch_return_in_first_hidden_param_p (gdbarch, values_type))
@@ -945,8 +1012,11 @@ call_function_by_hand_dummy (struct value *function,
       internal_error (__FILE__, __LINE__, _("bad switch"));
     }
 
-  if (args.size () < TYPE_NFIELDS (ftype))
-    error (_("Too few arguments in function call."));
+  /* Coerce the arguments and handle pass-by-reference.
+     We want to remember the destruction required for pass-by-ref values.
+     For these, store the dtor function and the 'this' argument
+     in DTORS_TO_INVOKE.  */
+  std::list<destructor_info> dtors_to_invoke;
 
   for (int i = args.size () - 1; i >= 0; i--)
     {
@@ -982,16 +1052,99 @@ call_function_by_hand_dummy (struct value *function,
       else
        param_type = NULL;
 
+      value *original_arg = args[i];
       args[i] = value_arg_coerce (gdbarch, args[i],
-                                 param_type, prototyped, &sp);
+                                 param_type, prototyped);
+
+      if (param_type == NULL)
+       continue;
+
+      auto info = language_pass_by_reference (param_type);
+      if (!info.copy_constructible)
+       error (_("expression cannot be evaluated because the type '%s' "
+                "is not copy constructible"), TYPE_NAME (param_type));
+
+      if (!info.destructible)
+       error (_("expression cannot be evaluated because the type '%s' "
+                "is not destructible"), TYPE_NAME (param_type));
+
+      if (info.trivially_copyable)
+       continue;
+
+      /* Make a copy of the argument on the stack.  If the argument is
+        trivially copy ctor'able, copy bit by bit.  Otherwise, call
+        the copy ctor to initialize the clone.  */
+      CORE_ADDR addr = reserve_stack_space (param_type, sp);
+      value *clone
+       = value_from_contents_and_address (param_type, nullptr, addr);
+      push_thread_stack_temporary (call_thread.get (), clone);
+      value *clone_ptr
+       = value_from_pointer (lookup_pointer_type (param_type), addr);
+
+      if (info.trivially_copy_constructible)
+       {
+         int length = TYPE_LENGTH (param_type);
+         write_memory (addr, value_contents (args[i]), length);
+       }
+      else
+       {
+         value *copy_ctor;
+         value *cctor_args[2] = { clone_ptr, original_arg };
+         find_overload_match (gdb::make_array_view (cctor_args, 2),
+                              TYPE_NAME (param_type), METHOD,
+                              &clone_ptr, nullptr, &copy_ctor, nullptr,
+                              nullptr, 0, EVAL_NORMAL);
+
+         if (copy_ctor == nullptr)
+           error (_("expression cannot be evaluated because a copy "
+                    "constructor for the type '%s' could not be found "
+                    "(maybe inlined?)"), TYPE_NAME (param_type));
+
+         call_function_by_hand (copy_ctor, default_return_type,
+                                gdb::make_array_view (cctor_args, 2));
+       }
+
+      /* If the argument has a destructor, remember it so that we
+        invoke it after the infcall is complete.  */
+      if (!info.trivially_destructible)
+       {
+         /* Looking up the function via overload resolution does not
+            work because the compiler (in particular, gcc) adds an
+            artificial int parameter in some cases.  So we look up
+            the function by using the "~" name.  This should be OK
+            because there can be only one dtor definition.  */
+         const char *dtor_name = nullptr;
+         for (int fieldnum = 0;
+              fieldnum < TYPE_NFN_FIELDS (param_type);
+              fieldnum++)
+           {
+             fn_field *fn
+               = TYPE_FN_FIELDLIST1 (param_type, fieldnum);
+             const char *field_name
+               = TYPE_FN_FIELDLIST_NAME (param_type, fieldnum);
+
+             if (field_name[0] == '~')
+               dtor_name = TYPE_FN_FIELD_PHYSNAME (fn, 0);
+           }
+
+         if (dtor_name == nullptr)
+           error (_("expression cannot be evaluated because a destructor "
+                    "for the type '%s' could not be found "
+                    "(maybe inlined?)"), TYPE_NAME (param_type));
+
+         value *dtor
+           = find_function_in_inferior (dtor_name, 0);
 
-      if (param_type != NULL && language_pass_by_reference (param_type))
-       args[i] = value_addr (args[i]);
+         /* Insert the dtor to the front of the list to call them
+            in reverse order later.  */
+         dtors_to_invoke.emplace_front (dtor, clone_ptr);
+       }
+
+      args[i] = clone_ptr;
     }
 
   /* Reserve space for the return structure to be written on the
-     stack, if necessary.  Make certain that the value is correctly
-     aligned.
+     stack, if necessary.
 
      While evaluating expressions, we reserve space on the stack for
      return values of class type even if the language ABI and the target
@@ -1006,28 +1159,7 @@ call_function_by_hand_dummy (struct value *function,
 
   if (return_method != return_method_normal
       || (stack_temporaries && class_or_union_p (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 -= TYPE_LENGTH (values_type);
-         if (gdbarch_frame_align_p (gdbarch))
-           sp = gdbarch_frame_align (gdbarch, sp);
-         struct_addr = sp;
-       }
-      else
-       {
-         /* Stack grows upward.  Align the frame, allocate space, and
-             then again, re-align the frame???  */
-         if (gdbarch_frame_align_p (gdbarch))
-           sp = gdbarch_frame_align (gdbarch, sp);
-         struct_addr = sp;
-         sp += TYPE_LENGTH (values_type);
-         if (gdbarch_frame_align_p (gdbarch))
-           sp = gdbarch_frame_align (gdbarch, sp);
-       }
-    }
+    struct_addr = reserve_stack_space (values_type, sp);
 
   std::vector<struct value *> new_args;
   if (return_method == return_method_hidden_param)
@@ -1175,6 +1307,10 @@ call_function_by_hand_dummy (struct value *function,
            maybe_remove_breakpoints ();
 
            gdb_assert (retval != NULL);
+
+           /* Destruct the pass-by-ref argument clones.  */
+           call_destructors (dtors_to_invoke, default_return_type);
+
            return retval;
          }
 
@@ -1371,8 +1507,9 @@ When the function is done executing, GDB will silently stop."),
   gdb_assert_not_reached ("... should not be here");
 }
 
+void _initialize_infcall ();
 void
-_initialize_infcall (void)
+_initialize_infcall ()
 {
   add_setshow_boolean_cmd ("may-call-functions", no_class,
                           &may_call_functions_p, _("\
@@ -1388,7 +1525,7 @@ will result in an error."),
   add_setshow_boolean_cmd ("coerce-float-to-double", class_obscure,
                           &coerce_float_to_double_p, _("\
 Set coercion of floats to doubles when calling functions."), _("\
-Show coercion of floats to doubles when calling functions"), _("\
+Show coercion of floats to doubles when calling functions."), _("\
 Variables of type float should generally be converted to doubles before\n\
 calling an unprototyped function, and left alone when calling a prototyped\n\
 function.  However, some older debug info formats do not provide enough\n\