"thread apply 1 -- -" vs "frame apply level 0 -- -"
[deliverable/binutils-gdb.git] / gdb / infcall.c
index 96d43704fa2368b22ad69e0cad4ed61c51cfab83..84092d37e6418d00d2255a52947c1ecf1c7b9bb4 100644 (file)
@@ -1,6 +1,6 @@
 /* Perform an inferior function call, for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2018 Free Software Foundation, Inc.
+   Copyright (C) 1986-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -33,6 +33,7 @@
 #include "command.h"
 #include "dummy-frame.h"
 #include "ada-lang.h"
+#include "f-lang.h"
 #include "gdbthread.h"
 #include "event-top.h"
 #include "observable.h"
@@ -40,6 +41,7 @@
 #include "interps.h"
 #include "thread-fsm.h"
 #include <algorithm>
+#include "common/scope-exit.h"
 
 /* If we can't find a function's name from its address,
    we print this instead.  */
    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 void
+show_may_call_functions_p (struct ui_file *file, int from_tty,
+                          struct cmd_list_element *c,
+                          const char *value)
+{
+  fprintf_filtered (file,
+                   _("Permission to call functions in the program is %s.\n"),
+                   value);
+}
+
 /* How you should pass arguments to a function depends on whether it
    was defined in K&R style or prototype style.  If you define a
    function using the K&R syntax that takes a `float' argument, then
@@ -129,7 +142,7 @@ show_unwind_on_terminating_exception_p (struct ui_file *file, int from_tty,
 }
 
 /* Perform the standard coercions that are specified
-   for arguments to be passed to C or Ada functions.
+   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.
@@ -145,9 +158,11 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg,
   struct type *type
     = param_type ? check_typedef (param_type) : arg_type;
 
-  /* Perform any Ada-specific coercion first.  */
+  /* Perform any Ada- and Fortran-specific coercion first.  */
   if (current_language->la_language == language_ada)
     arg = ada_convert_actual (arg, type);
+  else if (current_language->la_language == language_fortran)
+    type = fortran_preserve_arg_pointer (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
@@ -334,7 +349,7 @@ find_function_addr (struct value *function,
 static CORE_ADDR
 push_dummy_code (struct gdbarch *gdbarch,
                 CORE_ADDR sp, CORE_ADDR funaddr,
-                struct value **args, int nargs,
+                gdb::array_view<value *> args,
                 struct type *value_type,
                 CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
                 struct regcache *regcache)
@@ -342,7 +357,8 @@ push_dummy_code (struct gdbarch *gdbarch,
   gdb_assert (gdbarch_push_dummy_code_p (gdbarch));
 
   return gdbarch_push_dummy_code (gdbarch, sp, funaddr,
-                                 args, nargs, value_type, real_pc, bp_addr,
+                                 args.data (), args.size (),
+                                 value_type, real_pc, bp_addr,
                                  regcache);
 }
 
@@ -468,106 +484,87 @@ get_call_return_value (struct call_return_meta_info *ri)
 /* 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
+struct call_thread_fsm : public 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;
+  struct value *return_value = nullptr;
 
   /* 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 (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);
 
-/* call_thread_fsm's vtable.  */
+  bool should_stop (struct thread_info *thread) override;
 
-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,
+  bool should_notify_stop () override;
 };
 
 /* 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)
+call_thread_fsm::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)
+  : thread_fsm (cmd_interp),
+    waiting_ui (waiting_ui)
 {
-  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;
+  return_meta_info.gdbarch = gdbarch;
+  return_meta_info.function = function;
+  return_meta_info.value_type = value_type;
+  return_meta_info.struct_return_p = struct_return_p;
+  return_meta_info.struct_addr = struct_addr;
 }
 
 /* Implementation of should_stop method for infcalls.  */
 
-static int
-call_thread_fsm_should_stop (struct thread_fsm *self,
-                            struct thread_info *thread)
+bool
+call_thread_fsm::should_stop (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);
+      set_finished ();
 
       /* 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);
+      return_value = get_call_return_value (&return_meta_info);
 
       /* Break out of wait_sync_command_done.  */
-      scoped_restore save_ui = make_scoped_restore (&current_ui, f->waiting_ui);
+      scoped_restore save_ui = make_scoped_restore (&current_ui, waiting_ui);
       target_terminal::ours ();
-      f->waiting_ui->prompt_state = PROMPT_NEEDED;
+      waiting_ui->prompt_state = PROMPT_NEEDED;
     }
 
-  return 1;
+  return true;
 }
 
 /* Implementation of should_notify_stop method for infcalls.  */
 
-static int
-call_thread_fsm_should_notify_stop (struct thread_fsm *self)
+bool
+call_thread_fsm::should_notify_stop ()
 {
-  if (thread_fsm_finished_p (self))
+  if (finished_p ())
     {
       /* Infcall succeeded.  Be silent and proceed with evaluating the
         expression.  */
-      return 0;
+      return false;
     }
 
   /* Something wrong happened.  E.g., an unexpected breakpoint
      triggered, or a signal was intercepted.  Notify the stop.  */
-  return 1;
+  return true;
 }
 
 /* Subroutine of call_function_by_hand to simplify it.
@@ -582,7 +579,7 @@ static struct gdb_exception
 run_inferior_call (struct call_thread_fsm *sm,
                   struct thread_info *call_thread, CORE_ADDR real_pc)
 {
-  struct gdb_exception caught_error = exception_none;
+  struct gdb_exception caught_error;
   int saved_in_infcall = call_thread->control.in_infcall;
   ptid_t call_thread_ptid = call_thread->ptid;
   enum prompt_state saved_prompt_state = current_ui->prompt_state;
@@ -604,14 +601,14 @@ run_inferior_call (struct call_thread_fsm *sm,
   /* 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;
+  call_thread->thread_fsm = sm;
 
   disable_watchpoints_before_interactive_call_start ();
 
   /* We want to print return value, please...  */
   call_thread->control.proceed_to_finish = 1;
 
-  TRY
+  try
     {
       proceed (real_pc, GDB_SIGNAL_0);
 
@@ -619,11 +616,10 @@ run_inferior_call (struct call_thread_fsm *sm,
         target supports asynchronous execution.  */
       wait_sync_command_done ();
     }
-  CATCH (e, RETURN_MASK_ALL)
+  catch (gdb_exception &e)
     {
-      caught_error = e;
+      caught_error = std::move (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
@@ -674,22 +670,15 @@ run_inferior_call (struct call_thread_fsm *sm,
   return caught_error;
 }
 
-/* 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,
                       type *default_return_type,
-                      int nargs, struct value **args)
+                      gdb::array_view<value *> args)
 {
   return call_function_by_hand_dummy (function, default_return_type,
-                                     nargs, args, NULL, NULL);
+                                     args, NULL, NULL);
 }
 
 /* All this stuff with a dummy frame may seem unnecessarily complicated
@@ -713,24 +702,27 @@ call_function_by_hand (struct value *function,
 struct value *
 call_function_by_hand_dummy (struct value *function,
                             type *default_return_type,
-                            int nargs, struct value **args,
+                            gdb::array_view<value *> args,
                             dummy_frame_dtor_ftype *dummy_dtor,
                             void *dummy_dtor_data)
 {
   CORE_ADDR sp;
   struct type *target_values_type;
-  unsigned char struct_return = 0, hidden_first_param_p = 0;
+  function_call_return_method return_method = return_method_normal;
   CORE_ADDR struct_addr = 0;
   CORE_ADDR real_pc;
   CORE_ADDR bp_addr;
   struct frame_id dummy_id;
   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 (!may_call_functions_p)
+    error (_("Cannot call functions in the program: "
+            "may-call-functions is off."));
+
   if (!target_has_execution)
     noprocess ();
 
@@ -876,20 +868,11 @@ call_function_by_hand_dummy (struct value *function,
 
   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?
-     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.  */
+  /* Are we returning a value using a structure return?  */
 
   if (gdbarch_return_in_first_hidden_param_p (gdbarch, values_type))
     {
-      hidden_first_param_p = 1;
+      return_method = return_method_hidden_param;
 
       /* Tell the target specific argument pushing routine not to
         expect a value.  */
@@ -897,7 +880,8 @@ call_function_by_hand_dummy (struct value *function,
     }
   else
     {
-      struct_return = using_struct_return (gdbarch, function, values_type);
+      if (using_struct_return (gdbarch, function, values_type))
+       return_method = return_method_struct;
       target_values_type = values_type;
     }
 
@@ -920,7 +904,7 @@ call_function_by_hand_dummy (struct value *function,
        /* 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,
+       sp = push_dummy_code (gdbarch, sp, funaddr, args,
                              target_values_type, &real_pc, &bp_addr,
                              get_current_regcache ());
 
@@ -961,14 +945,14 @@ call_function_by_hand_dummy (struct value *function,
       internal_error (__FILE__, __LINE__, _("bad switch"));
     }
 
-  if (nargs < TYPE_NFIELDS (ftype))
+  if (args.size () < TYPE_NFIELDS (ftype))
     error (_("Too few arguments in function call."));
 
-  for (int i = nargs - 1; i >= 0; i--)
+  for (int i = args.size () - 1; i >= 0; i--)
     {
       int prototyped;
       struct type *param_type;
-       
+
       /* FIXME drow/2002-05-31: Should just always mark methods as
         prototyped.  Can we respect TYPE_VARARGS?  Probably not.  */
       if (TYPE_CODE (ftype) == TYPE_CODE_METHOD)
@@ -1020,7 +1004,7 @@ call_function_by_hand_dummy (struct value *function,
      is being evaluated is OK because the thread is stopped until the
      expression is completely evaluated.  */
 
-  if (struct_return || hidden_first_param_p
+  if (return_method != return_method_normal
       || (stack_temporaries && class_or_union_p (values_type)))
     {
       if (gdbarch_inner_than (gdbarch, 1, 2))
@@ -1046,22 +1030,22 @@ call_function_by_hand_dummy (struct value *function,
     }
 
   std::vector<struct value *> new_args;
-  if (hidden_first_param_p)
+  if (return_method == return_method_hidden_param)
     {
       /* Add the new argument to the front of the argument list.  */
+      new_args.reserve (args.size ());
       new_args.push_back
        (value_from_pointer (lookup_pointer_type (values_type), struct_addr));
-      std::copy (&args[0], &args[nargs], std::back_inserter (new_args));
-      args = new_args.data ();
-      nargs++;
+      new_args.insert (new_args.end (), args.begin (), args.end ());
+      args = new_args;
     }
 
   /* 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 (gdbarch, function, get_current_regcache (),
-                               bp_addr, nargs, args,
-                               sp, struct_return, struct_addr);
+                               bp_addr, args.size (), args.data (),
+                               sp, return_method, struct_addr);
 
   /* 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
@@ -1129,8 +1113,7 @@ call_function_by_hand_dummy (struct value *function,
                               dummy_dtor, dummy_dtor_data);
 
   /* Register a clean-up for unwind_on_terminating_exception_breakpoint.  */
-  terminate_bp_cleanup = make_cleanup (cleanup_delete_std_terminate_breakpoint,
-                                      NULL);
+  SCOPE_EXIT { delete_std_terminate_breakpoint (); };
 
   /* - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP - SNIP -
      If you're looking to implement asynchronous dummy-frames, then
@@ -1154,10 +1137,10 @@ call_function_by_hand_dummy (struct value *function,
        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 (),
+    sm = new call_thread_fsm (current_ui, command_interp (),
                              gdbarch, function,
                              values_type,
-                             struct_return || hidden_first_param_p,
+                             return_method != return_method_normal,
                              struct_addr);
 
     e = run_inferior_call (sm, call_thread.get (), real_pc);
@@ -1167,9 +1150,9 @@ call_function_by_hand_dummy (struct value *function,
     if (call_thread->state != THREAD_EXITED)
       {
        /* The FSM should still be the same.  */
-       gdb_assert (call_thread->thread_fsm == &sm->thread_fsm);
+       gdb_assert (call_thread->thread_fsm == sm);
 
-       if (thread_fsm_finished_p (call_thread->thread_fsm))
+       if (call_thread->thread_fsm->finished_p ())
          {
            struct value *retval;
 
@@ -1185,19 +1168,20 @@ call_function_by_hand_dummy (struct value *function,
 
            /* Clean up / destroy the call FSM, and restore the
               original one.  */
-           thread_fsm_clean_up (call_thread->thread_fsm, call_thread.get ());
-           thread_fsm_delete (call_thread->thread_fsm);
+           call_thread->thread_fsm->clean_up (call_thread.get ());
+           delete call_thread->thread_fsm;
            call_thread->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.  */
+       /* Didn't complete.  Clean up / destroy the call FSM, and restore the
+          previous state machine, and handle the error.  */
+       call_thread->thread_fsm->clean_up (call_thread.get ());
+       delete call_thread->thread_fsm;
        call_thread->thread_fsm = saved_sm;
       }
   }
@@ -1223,10 +1207,10 @@ 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);
+                      e.what (), name);
        case RETURN_QUIT:
        default:
-         throw_exception (e);
+         throw_exception (std::move (e));
        }
     }
 
@@ -1390,6 +1374,17 @@ When the function is done executing, GDB will silently stop."),
 void
 _initialize_infcall (void)
 {
+  add_setshow_boolean_cmd ("may-call-functions", no_class,
+                          &may_call_functions_p, _("\
+Set permission to call functions in the program."), _("\
+Show permission to call functions in the program."), _("\
+When this permission is on, GDB may call functions in the program.\n\
+Otherwise, any sort of attempt to call a function in the program\n\
+will result in an error."),
+                          NULL,
+                          show_may_call_functions_p,
+                          &setlist, &showlist);
+
   add_setshow_boolean_cmd ("coerce-float-to-double", class_obscure,
                           &coerce_float_to_double_p, _("\
 Set coercion of floats to doubles when calling functions."), _("\
@@ -1400,7 +1395,7 @@ function.  However, some older debug info formats do not provide enough\n\
 information to determine that a function is prototyped.  If this flag is\n\
 set, GDB will perform the conversion for a function it considers\n\
 unprototyped.\n\
-The default is to perform the conversion.\n"),
+The default is to perform the conversion."),
                           NULL,
                           show_coerce_float_to_double_p,
                           &setlist, &showlist);
This page took 0.036409 seconds and 4 git commands to generate.