arm-pikeos: software single step
[deliverable/binutils-gdb.git] / gdb / infcall.c
index c20ab6f877124c534f90b9a2cbe72f848f23ba10..96d43704fa2368b22ad69e0cad4ed61c51cfab83 100644 (file)
@@ -385,13 +385,11 @@ get_function_name (CORE_ADDR funaddr, char *buf, int buf_size)
   }
 
   {
-    char *tmp = xstrprintf (_(RAW_FUNCTION_ADDRESS_FORMAT),
-                            hex_string (funaddr));
+    std::string tmp = string_printf (_(RAW_FUNCTION_ADDRESS_FORMAT),
+                                    hex_string (funaddr));
 
-    gdb_assert (strlen (tmp) + 1 <= buf_size);
-    strcpy (buf, tmp);
-    xfree (tmp);
-    return buf;
+    gdb_assert (tmp.length () + 1 <= buf_size);
+    return strcpy (buf, tmp.c_str ());
   }
 }
 
@@ -422,7 +420,8 @@ static struct value *
 get_call_return_value (struct call_return_meta_info *ri)
 {
   struct value *retval = NULL;
-  bool stack_temporaries = thread_stack_temporaries_enabled_p (inferior_ptid);
+  thread_info *thr = inferior_thread ();
+  bool stack_temporaries = thread_stack_temporaries_enabled_p (thr);
 
   if (TYPE_CODE (ri->value_type) == TYPE_CODE_VOID)
     retval = allocate_value (ri->value_type);
@@ -432,7 +431,7 @@ get_call_return_value (struct call_return_meta_info *ri)
        {
          retval = value_from_contents_and_address (ri->value_type, NULL,
                                                    ri->struct_addr);
-         push_thread_stack_temporary (inferior_ptid, retval);
+         push_thread_stack_temporary (thr, retval);
        }
       else
        {
@@ -458,7 +457,7 @@ get_call_return_value (struct call_return_meta_info *ri)
             the this pointer, GDB needs the memory address of the
             value.  */
          value_force_lval (retval, ri->struct_addr);
-         push_thread_stack_temporary (inferior_ptid, retval);
+         push_thread_stack_temporary (thr, retval);
        }
     }
 
@@ -637,10 +636,6 @@ run_inferior_call (struct call_thread_fsm *sm,
     ui_register_input_event_handler (current_ui);
   current_ui->async = saved_ui_async;
 
-  /* 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);
-
   /* If the infcall does NOT succeed, normal_stop will have already
      finished the thread states.  However, on success, normal_stop
      defers here, so that we can set back the thread states to what
@@ -657,7 +652,7 @@ run_inferior_call (struct call_thread_fsm *sm,
      evaluates true and thus we'll present a user-visible stop is
      decided elsewhere.  */
   if (!was_running
-      && ptid_equal (call_thread_ptid, inferior_ptid)
+      && call_thread_ptid == inferior_ptid
       && stop_stack_dummy == STOP_STACK_DUMMY)
     finish_thread_state (user_visible_resume_ptid (0));
 
@@ -670,12 +665,11 @@ run_inferior_call (struct call_thread_fsm *sm,
      of error out of resume()), then we wouldn't need this.  */
   if (caught_error.reason < 0)
     {
-      if (call_thread != NULL)
+      if (call_thread->state != THREAD_EXITED)
        breakpoint_auto_delete (call_thread->control.stop_bpstat);
     }
 
-  if (call_thread != NULL)
-    call_thread->control.in_infcall = saved_in_infcall;
+  call_thread->control.in_infcall = saved_in_infcall;
 
   return caught_error;
 }
@@ -727,9 +721,6 @@ call_function_by_hand_dummy (struct value *function,
   struct type *target_values_type;
   unsigned char struct_return = 0, hidden_first_param_p = 0;
   CORE_ADDR struct_addr = 0;
-  struct infcall_control_state *inf_status;
-  struct cleanup *inf_status_cleanup;
-  struct infcall_suspend_state *caller_state;
   CORE_ADDR real_pc;
   CORE_ADDR bp_addr;
   struct frame_id dummy_id;
@@ -739,7 +730,6 @@ call_function_by_hand_dummy (struct value *function,
   ptid_t call_thread_ptid;
   struct gdb_exception e;
   char name_buf[RAW_FUNCTION_ADDRESS_SIZE];
-  bool stack_temporaries = thread_stack_temporaries_enabled_p (inferior_ptid);
 
   if (!target_has_execution)
     noprocess ();
@@ -750,25 +740,30 @@ call_function_by_hand_dummy (struct value *function,
   if (execution_direction == EXEC_REVERSE)
     error (_("Cannot call functions in reverse mode."));
 
+  /* We're going to run the target, and inspect the thread's state
+     afterwards.  Hold a strong reference so that the pointer remains
+     valid even if the thread exits.  */
+  thread_info_ref call_thread
+    = thread_info_ref::new_reference (inferior_thread ());
+
+  bool stack_temporaries = thread_stack_temporaries_enabled_p (call_thread.get ());
+
   frame = get_current_frame ();
   gdbarch = get_frame_arch (frame);
 
   if (!gdbarch_push_dummy_call_p (gdbarch))
     error (_("This target does not support function calls."));
 
-  /* A cleanup for the inferior status.
+  /* A holder 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);
+  infcall_control_state_up inf_status (save_infcall_control_state ());
 
   /* 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_state = save_infcall_suspend_state ();
-  make_cleanup_restore_infcall_suspend_state (caller_state);
+     down) pushed onto a dummy frame stack.  This unique pointer
+     is released once the regcache has been pushed).  */
+  infcall_suspend_state_up caller_state (save_infcall_suspend_state ());
 
   /* Ensure that the initial SP is correctly aligned.  */
   {
@@ -842,7 +837,7 @@ call_function_by_hand_dummy (struct value *function,
       {
        struct value *lastval;
 
-       lastval = get_last_thread_stack_temporary (inferior_ptid);
+       lastval = get_last_thread_stack_temporary (call_thread.get ());
         if (lastval != NULL)
          {
            CORE_ADDR lastval_addr = value_address (lastval);
@@ -969,50 +964,46 @@ call_function_by_hand_dummy (struct value *function,
   if (nargs < TYPE_NFIELDS (ftype))
     error (_("Too few arguments in function call."));
 
-  {
-    int i;
-
-    for (i = nargs - 1; i >= 0; i--)
-      {
-       int prototyped;
-       struct type *param_type;
+  for (int i = nargs - 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)
+      /* 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)
+       prototyped = 1;
+      if (TYPE_TARGET_TYPE (ftype) == NULL && TYPE_NFIELDS (ftype) == 0
+         && default_return_type != NULL)
+       {
+         /* Calling a no-debug function with the return type
+            explicitly cast.  Assume the function is prototyped,
+            with a prototype matching the types of the arguments.
+            E.g., with:
+            float mult (float v1, float v2) { return v1 * v2; }
+            This:
+            (gdb) p (float) mult (2.0f, 3.0f)
+            Is a simpler alternative to:
+            (gdb) p ((float (*) (float, float)) mult) (2.0f, 3.0f)
+         */
          prototyped = 1;
-       if (TYPE_TARGET_TYPE (ftype) == NULL && TYPE_NFIELDS (ftype) == 0
-           && default_return_type != NULL)
-         {
-           /* Calling a no-debug function with the return type
-              explicitly cast.  Assume the function is prototyped,
-              with a prototype matching the types of the arguments.
-              E.g., with:
-                float mult (float v1, float v2) { return v1 * v2; }
-              This:
-                (gdb) p (float) mult (2.0f, 3.0f)
-              Is a simpler alternative to:
-                (gdb) p ((float (*) (float, float)) mult) (2.0f, 3.0f)
-            */
-           prototyped = 1;
-         }
-       else if (i < TYPE_NFIELDS (ftype))
-         prototyped = TYPE_PROTOTYPED (ftype);
-       else
-         prototyped = 0;
+       }
+      else if (i < TYPE_NFIELDS (ftype))
+       prototyped = TYPE_PROTOTYPED (ftype);
+      else
+       prototyped = 0;
 
-       if (i < TYPE_NFIELDS (ftype))
-         param_type = TYPE_FIELD_TYPE (ftype, i);
-       else
-         param_type = NULL;
+      if (i < TYPE_NFIELDS (ftype))
+       param_type = TYPE_FIELD_TYPE (ftype, i);
+      else
+       param_type = NULL;
 
-       args[i] = value_arg_coerce (gdbarch, 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]);
-      }
-  }
+      if (param_type != NULL && language_pass_by_reference (param_type))
+       args[i] = value_addr (args[i]);
+    }
 
   /* Reserve space for the return structure to be written on the
      stack, if necessary.  Make certain that the value is correctly
@@ -1129,17 +1120,12 @@ call_function_by_hand_dummy (struct value *function,
   if (unwind_on_terminating_exception_p)
     set_std_terminate_breakpoint ();
 
-  /* 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);
-
   /* 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_state, &dummy_id, inferior_ptid);
+  dummy_frame_push (caller_state.release (), &dummy_id, call_thread.get ());
   if (dummy_dtor != NULL)
-    register_dummy_frame_dtor (dummy_id, inferior_ptid,
+    register_dummy_frame_dtor (dummy_id, call_thread.get (),
                               dummy_dtor, dummy_dtor_data);
 
   /* Register a clean-up for unwind_on_terminating_exception_breakpoint.  */
@@ -1150,20 +1136,17 @@ call_function_by_hand_dummy (struct value *function,
      If you're looking to implement asynchronous dummy-frames, then
      just below is the place to chop this function in two..  */
 
-  /* 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 thread_info *tp = inferior_thread ();
     struct thread_fsm *saved_sm;
     struct call_thread_fsm *sm;
 
     /* Save the current FSM.  We'll override it.  */
-    saved_sm = tp->thread_fsm;
-    tp->thread_fsm = NULL;
+    saved_sm = call_thread->thread_fsm;
+    call_thread->thread_fsm = NULL;
 
     /* Save this thread's ptid, we need it later but the thread
        may have exited.  */
-    call_thread_ptid = tp->ptid;
+    call_thread_ptid = call_thread->ptid;
 
     /* Run the inferior until it stops.  */
 
@@ -1177,17 +1160,16 @@ call_function_by_hand_dummy (struct value *function,
                              struct_return || hidden_first_param_p,
                              struct_addr);
 
-    e = run_inferior_call (sm, tp, real_pc);
+    e = run_inferior_call (sm, call_thread.get (), real_pc);
 
     gdb::observers::inferior_call_post.notify (call_thread_ptid, funaddr);
 
-    tp = find_thread_ptid (call_thread_ptid);
-    if (tp != NULL)
+    if (call_thread->state != THREAD_EXITED)
       {
        /* The FSM should still be the same.  */
-       gdb_assert (tp->thread_fsm == &sm->thread_fsm);
+       gdb_assert (call_thread->thread_fsm == &sm->thread_fsm);
 
-       if (thread_fsm_finished_p (tp->thread_fsm))
+       if (thread_fsm_finished_p (call_thread->thread_fsm))
          {
            struct value *retval;
 
@@ -1195,17 +1177,17 @@ call_function_by_hand_dummy (struct value *function,
               which runs its destructors and restores the inferior's
               suspend state, and restore the inferior control
               state.  */
-           dummy_frame_pop (dummy_id, call_thread_ptid);
-           restore_infcall_control_state (inf_status);
+           dummy_frame_pop (dummy_id, call_thread.get ());
+           restore_infcall_control_state (inf_status.release ());
 
            /* Get the return value.  */
            retval = sm->return_value;
 
            /* Clean up / destroy the call FSM, and restore the
               original one.  */
-           thread_fsm_clean_up (tp->thread_fsm, tp);
-           thread_fsm_delete (tp->thread_fsm);
-           tp->thread_fsm = saved_sm;
+           thread_fsm_clean_up (call_thread->thread_fsm, call_thread.get ());
+           thread_fsm_delete (call_thread->thread_fsm);
+           call_thread->thread_fsm = saved_sm;
 
            maybe_remove_breakpoints ();
 
@@ -1216,7 +1198,7 @@ call_function_by_hand_dummy (struct value *function,
 
        /* Didn't complete.  Restore previous state machine, and
           handle the error.  */
-       tp->thread_fsm = saved_sm;
+       call_thread->thread_fsm = saved_sm;
       }
   }
 
@@ -1227,7 +1209,7 @@ call_function_by_hand_dummy (struct value *function,
       const char *name = get_function_name (funaddr,
                                             name_buf, sizeof (name_buf));
 
-      discard_infcall_control_state (inf_status);
+      discard_infcall_control_state (inf_status.release ());
 
       /* We could discard the dummy frame here if the program exited,
          but it will get garbage collected the next time the program is
@@ -1258,7 +1240,7 @@ When the function is done executing, GDB will silently stop."),
 
       /* If we try to restore the inferior status,
         we'll crash as the inferior is no longer running.  */
-      discard_infcall_control_state (inf_status);
+      discard_infcall_control_state (inf_status.release ());
 
       /* We could discard the dummy frame here given that the program exited,
          but it will get garbage collected the next time the program is
@@ -1271,7 +1253,7 @@ When the function is done executing, GDB will silently stop."),
             name);
     }
 
-  if (! ptid_equal (call_thread_ptid, inferior_ptid))
+  if (call_thread_ptid != inferior_ptid)
     {
       const char *name = get_function_name (funaddr,
                                            name_buf, sizeof (name_buf));
@@ -1280,7 +1262,7 @@ When the function is done executing, GDB will silently stop."),
         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);
+      discard_infcall_control_state (inf_status.release ());
       /* 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)
@@ -1317,11 +1299,11 @@ When the function is done executing, GDB will silently stop."),
 
              /* We must get back to the frame we were before the
                 dummy call.  */
-             dummy_frame_pop (dummy_id, call_thread_ptid);
+             dummy_frame_pop (dummy_id, call_thread.get ());
 
              /* We also need to restore inferior status to that before the
                 dummy call.  */
-             restore_infcall_control_state (inf_status);
+             restore_infcall_control_state (inf_status.release ());
 
              /* FIXME: Insert a bunch of wrap_here; name can be very
                 long if it's a C++ name with arguments and stuff.  */
@@ -1339,7 +1321,7 @@ Evaluation of the expression containing the function\n\
                 (default).
                 Discard inferior status, we're not at the same point
                 we started at.  */
-             discard_infcall_control_state (inf_status);
+             discard_infcall_control_state (inf_status.release ());
 
              /* FIXME: Insert a bunch of wrap_here; name can be very
                 long if it's a C++ name with arguments and stuff.  */
@@ -1358,11 +1340,11 @@ When the function is done executing, GDB will silently stop."),
        {
          /* We must get back to the frame we were before the dummy
             call.  */
-         dummy_frame_pop (dummy_id, call_thread_ptid);
+         dummy_frame_pop (dummy_id, call_thread.get ());
 
          /* We also need to restore inferior status to that before
             the dummy call.  */
-         restore_infcall_control_state (inf_status);
+         restore_infcall_control_state (inf_status.release ());
 
          error (_("\
 The program being debugged entered a std::terminate call, most likely\n\
@@ -1381,7 +1363,7 @@ will be abandoned."),
             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);
+         discard_infcall_control_state (inf_status.release ());
 
          /* The following error message used to say "The expression
             which contained the function call has been discarded."
This page took 0.045128 seconds and 4 git commands to generate.