/* Perform an inferior function call, for GDB, the GNU debugger.
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
+ Copyright (C) 1986-2015 Free Software Foundation, Inc.
This file is part of GDB.
#include "ada-lang.h"
#include "gdbthread.h"
#include "event-top.h"
+#include "observer.h"
/* If we can't find a function's name from its address,
we print this instead. */
static struct gdb_exception
run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc)
{
- volatile struct gdb_exception e;
+ struct gdb_exception caught_error = exception_none;
int saved_in_infcall = call_thread->control.in_infcall;
ptid_t call_thread_ptid = call_thread->ptid;
int saved_sync_execution = sync_execution;
/* We want stop_registers, please... */
call_thread->control.proceed_to_finish = 1;
- TRY_CATCH (e, RETURN_MASK_ALL)
+ TRY
{
int was_sync = sync_execution;
- proceed (real_pc, GDB_SIGNAL_0, 0);
+ proceed (real_pc, GDB_SIGNAL_0);
/* Inferior function calls are always synchronous, even if the
target supports asynchronous execution. Do here what
async_disable_stdin ();
}
}
+ CATCH (e, RETURN_MASK_ALL)
+ {
+ caught_error = e;
+ }
+ END_CATCH
/* At this point the current thread may have changed. Refresh
CALL_THREAD as it could be invalid if its thread has exited. */
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 (caught_error.reason < 0)
{
if (call_thread != NULL)
breakpoint_auto_delete (call_thread->control.stop_bpstat);
sync_execution = saved_sync_execution;
- return e;
+ return caught_error;
}
/* A cleanup function that calls delete_std_terminate_breakpoint. */
delete_std_terminate_breakpoint ();
}
+/* See infcall.h. */
+
+struct value *
+call_function_by_hand (struct value *function, int nargs, struct value **args)
+{
+ return call_function_by_hand_dummy (function, nargs, args, NULL, NULL);
+}
+
/* All this stuff with a dummy frame may seem unnecessarily complicated
(why not just save registers in GDB?). The purpose of pushing a dummy
frame which looks just like a real frame is so that if you call a
ARGS is modified to contain coerced values. */
struct value *
-call_function_by_hand (struct value *function, int nargs, struct value **args)
+call_function_by_hand_dummy (struct value *function,
+ int nargs, struct value **args,
+ call_function_by_hand_dummy_dtor_ftype *dummy_dtor,
+ void *dummy_dtor_data)
{
CORE_ADDR sp;
struct type *values_type, *target_values_type;
target_values_type = values_type;
}
+ observer_notify_inferior_call_pre (inferior_ptid, funaddr);
+
/* Determine the location of the breakpoint (and possibly other
stuff) that the called function will return to. The SPARC, for a
function returning a structure or union, needs to make space for
caller (and identify the dummy-frame) onto the dummy-frame
stack. */
dummy_frame_push (caller_state, &dummy_id, inferior_ptid);
+ if (dummy_dtor != NULL)
+ register_dummy_frame_dtor (dummy_id, inferior_ptid,
+ dummy_dtor, dummy_dtor_data);
/* Discard both inf_status and caller_state cleanups.
From this point on we explicitly restore the associated state
e = run_inferior_call (tp, real_pc);
}
+ observer_notify_inferior_call_post (call_thread_ptid, funaddr);
+
/* Rethrow an error if we got one trying to run the inferior. */
if (e.reason < 0)