+/* Fetch the name of the function at FUNADDR.
+ This is used in printing an error message for call_function_by_hand.
+ BUF is used to print FUNADDR in hex if the function name cannot be
+ determined. It must be large enough to hold formatted result of
+ RAW_FUNCTION_ADDRESS_FORMAT. */
+
+static const char *
+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);
+ }
+
+ {
+ /* Try the minimal symbols. */
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (funaddr);
+ if (msymbol)
+ return SYMBOL_PRINT_NAME (msymbol);
+ }
+
+ {
+ char *tmp = xstrprintf (_(RAW_FUNCTION_ADDRESS_FORMAT),
+ hex_string (funaddr));
+ gdb_assert (strlen (tmp) + 1 <= buf_size);
+ strcpy (buf, tmp);
+ xfree (tmp);
+ return buf;
+ }
+}
+
+/* Subroutine of call_function_by_hand to simplify it.
+ Start up the inferior and wait for it to stop.
+ Return the exception if there's an error, or an exception with
+ reason >= 0 if there's no error.
+
+ This is done inside a TRY_CATCH so the caller needn't worry about
+ thrown errors. The caller should rethrow if there's an error. */
+
+static struct gdb_exception
+run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc)
+{
+ volatile struct gdb_exception e;
+ int saved_async = 0;
+ int saved_in_infcall = call_thread->in_infcall;
+ ptid_t call_thread_ptid = call_thread->ptid;
+ char *saved_target_shortname = xstrdup (target_shortname);
+
+ call_thread->in_infcall = 1;
+
+ clear_proceed_status ();
+
+ disable_watchpoints_before_interactive_call_start ();
+ call_thread->proceed_to_finish = 1; /* We want stop_registers, please... */
+
+ if (target_can_async_p ())
+ saved_async = target_async_mask (0);
+
+ TRY_CATCH (e, RETURN_MASK_ALL)
+ proceed (real_pc, TARGET_SIGNAL_0, 0);
+
+ /* 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);
+
+ /* Don't restore the async mask if the target has changed,
+ saved_async is for the original target. */
+ if (saved_async
+ && strcmp (saved_target_shortname, target_shortname) == 0)
+ target_async_mask (saved_async);
+
+ enable_watchpoints_after_interactive_call_stop ();
+
+ /* Call breakpoint_auto_delete on the current contents of the bpstat
+ of inferior call 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. */
+ if (e.reason < 0)
+ {
+ if (call_thread != NULL)
+ breakpoint_auto_delete (call_thread->stop_bpstat);
+ }
+
+ if (call_thread != NULL)
+ call_thread->in_infcall = saved_in_infcall;
+
+ xfree (saved_target_shortname);
+
+ return e;
+}
+