/* Perform an inferior function call, for GDB, the GNU debugger.
Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
- Free Software Foundation, Inc.
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+ 2008 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdb_string.h"
#include "infcall.h"
#include "dummy-frame.h"
+#include "ada-lang.h"
/* NOTE: cagney/2003-04-16: What's the future of this code?
/* Perform the standard coercions that are specified
- for arguments to be passed to C functions.
+ for arguments to be passed to C or Ada functions.
If PARAM_TYPE is non-NULL, it is the expected parameter type.
- IS_PROTOTYPED is non-zero if the function declaration is prototyped. */
+ 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). */
static struct value *
value_arg_coerce (struct value *arg, struct type *param_type,
- int is_prototyped)
+ int is_prototyped, CORE_ADDR *sp)
{
struct type *arg_type = check_typedef (value_type (arg));
struct type *type
= param_type ? check_typedef (param_type) : arg_type;
+ /* Perform any Ada-specific coercion first. */
+ if (current_language->la_language == language_ada)
+ arg = ada_convert_actual (arg, type, sp);
+
+ /* Force the value to the target if we will need its address. At
+ this point, we could allocate arguments on the stack instead of
+ calling malloc if we knew that their addresses would not be
+ saved by the called function. */
+ arg = value_coerce_to_target (arg);
+
switch (TYPE_CODE (type))
{
case TYPE_CODE_REF:
struct cleanup *caller_regcache_cleanup;
struct frame_id dummy_id;
struct cleanup *args_cleanup;
+ struct frame_info *frame;
+ struct gdbarch *gdbarch;
if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
if (!target_has_execution)
noprocess ();
- if (!gdbarch_push_dummy_call_p (current_gdbarch))
+ frame = get_current_frame ();
+ gdbarch = get_frame_arch (frame);
+
+ if (!gdbarch_push_dummy_call_p (gdbarch))
error (_("This target does not support function calls"));
/* Create a cleanup chain that contains the retbuf (buffer
containing the register values). This chain is create BEFORE the
inf_status chain so that the inferior status can cleaned up
(restored or discarded) without having the retbuf freed. */
- retbuf = regcache_xmalloc (current_gdbarch);
+ retbuf = regcache_xmalloc (gdbarch);
retbuf_cleanup = make_cleanup_regcache_xfree (retbuf);
/* A cleanup for the inferior status. Create this AFTER the retbuf
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_regcache = frame_save_as_regcache (get_current_frame ());
+ caller_regcache = frame_save_as_regcache (frame);
caller_regcache_cleanup = make_cleanup_regcache_xfree (caller_regcache);
/* Ensure that the initial SP is correctly aligned. */
{
- CORE_ADDR old_sp = get_frame_sp (get_current_frame ());
- if (gdbarch_frame_align_p (current_gdbarch))
+ CORE_ADDR old_sp = get_frame_sp (frame);
+ if (gdbarch_frame_align_p (gdbarch))
{
- sp = gdbarch_frame_align (current_gdbarch, old_sp);
+ sp = gdbarch_frame_align (gdbarch, old_sp);
/* NOTE: cagney/2003-08-13: Skip the "red zone". For some
ABIs, a function can use memory beyond the inner most stack
address. AMD64 called that region the "red zone". Skip at
least the "red zone" size before allocating any space on
the stack. */
- if (gdbarch_inner_than (current_gdbarch, 1, 2))
- sp -= gdbarch_frame_red_zone_size (current_gdbarch);
+ if (gdbarch_inner_than (gdbarch, 1, 2))
+ sp -= gdbarch_frame_red_zone_size (gdbarch);
else
- sp += gdbarch_frame_red_zone_size (current_gdbarch);
+ sp += gdbarch_frame_red_zone_size (gdbarch);
/* Still aligned? */
- gdb_assert (sp == gdbarch_frame_align (current_gdbarch, sp));
+ gdb_assert (sp == gdbarch_frame_align (gdbarch, sp));
/* NOTE: cagney/2002-09-18:
On a RISC architecture, a void parameterless generic dummy
to pay :-). */
if (sp == old_sp)
{
- if (gdbarch_inner_than (current_gdbarch, 1, 2))
+ if (gdbarch_inner_than (gdbarch, 1, 2))
/* Stack grows down. */
- sp = gdbarch_frame_align (current_gdbarch, old_sp - 1);
+ sp = gdbarch_frame_align (gdbarch, old_sp - 1);
else
/* Stack grows up. */
- sp = gdbarch_frame_align (current_gdbarch, old_sp + 1);
+ sp = gdbarch_frame_align (gdbarch, old_sp + 1);
}
- gdb_assert ((gdbarch_inner_than (current_gdbarch, 1, 2)
+ gdb_assert ((gdbarch_inner_than (gdbarch, 1, 2)
&& sp <= old_sp)
- || (gdbarch_inner_than (current_gdbarch, 2, 1)
+ || (gdbarch_inner_than (gdbarch, 2, 1)
&& sp >= old_sp));
}
else
pushed) GDB won't be able to correctly perform back traces.
If a target is having trouble with backtraces, first thing to
do is add FRAME_ALIGN() to the architecture vector. If that
- fails, try unwind_dummy_id().
+ fails, try dummy_id().
If the ABI specifies a "Red Zone" (see the doco) the code
below will quietly trash it. */
}
else
{
- struct_return = using_struct_return (values_type);
+ struct_return = using_struct_return (value_type (function), values_type);
target_values_type = values_type;
}
/* The actual breakpoint (at BP_ADDR) is inserted separatly so there
is no need to write that out. */
- switch (gdbarch_call_dummy_location (current_gdbarch))
+ switch (gdbarch_call_dummy_location (gdbarch))
{
case ON_STACK:
/* "dummy_addr" is here just to keep old targets happy. New
targets return that same information via "sp" and "bp_addr". */
- if (gdbarch_inner_than (current_gdbarch, 1, 2))
+ if (gdbarch_inner_than (gdbarch, 1, 2))
{
- sp = push_dummy_code (current_gdbarch, sp, funaddr,
+ sp = push_dummy_code (gdbarch, sp, funaddr,
args, nargs, target_values_type,
&real_pc, &bp_addr, get_current_regcache ());
dummy_addr = sp;
else
{
dummy_addr = sp;
- sp = push_dummy_code (current_gdbarch, sp, funaddr,
+ sp = push_dummy_code (gdbarch, sp, funaddr,
args, nargs, target_values_type,
&real_pc, &bp_addr, get_current_regcache ());
}
dummy_addr = entry_point_address ();
/* Make certain that the address points at real code, and not a
function descriptor. */
- dummy_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
+ dummy_addr = gdbarch_convert_from_func_ptr_addr (gdbarch,
dummy_addr,
¤t_target);
/* A call dummy always consists of just a single breakpoint, so
dummy_addr = entry_point_address ();
/* Make certain that the address points at real code, and not
a function descriptor. */
- dummy_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
+ dummy_addr = gdbarch_convert_from_func_ptr_addr (gdbarch,
dummy_addr,
¤t_target);
/* A call dummy always consists of just a single breakpoint,
else
param_type = NULL;
- args[i] = value_arg_coerce (args[i], param_type, prototyped);
+ args[i] = value_arg_coerce (args[i], param_type, prototyped, &sp);
if (param_type != NULL && language_pass_by_reference (param_type))
args[i] = value_addr (args[i]);
if (struct_return || lang_struct_return)
{
int len = TYPE_LENGTH (values_type);
- if (gdbarch_inner_than (current_gdbarch, 1, 2))
+ if (gdbarch_inner_than (gdbarch, 1, 2))
{
/* Stack grows downward. Align STRUCT_ADDR and SP after
making space for the return value. */
sp -= len;
- if (gdbarch_frame_align_p (current_gdbarch))
- sp = gdbarch_frame_align (current_gdbarch, sp);
+ 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 (current_gdbarch))
- sp = gdbarch_frame_align (current_gdbarch, sp);
+ if (gdbarch_frame_align_p (gdbarch))
+ sp = gdbarch_frame_align (gdbarch, sp);
struct_addr = sp;
sp += len;
- if (gdbarch_frame_align_p (current_gdbarch))
- sp = gdbarch_frame_align (current_gdbarch, sp);
+ if (gdbarch_frame_align_p (gdbarch))
+ sp = gdbarch_frame_align (gdbarch, sp);
}
}
/* 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 (current_gdbarch, function,
- get_current_regcache (), bp_addr, nargs, args,
+ sp = gdbarch_push_dummy_call (gdbarch, function, get_current_regcache (),
+ bp_addr, nargs, args,
sp, struct_return, struct_addr);
do_cleanups (args_cleanup);
ID so that the breakpoint code can correctly re-identify the
dummy breakpoint. */
/* Sanity. The exact same SP value is returned by PUSH_DUMMY_CALL,
- saved as the dummy-frame TOS, and used by unwind_dummy_id to form
+ saved as the dummy-frame TOS, and used by dummy_id to form
the frame ID's stack address. */
dummy_id = frame_id_build (sp, bp_addr);
sal.section = find_pc_overlay (sal.pc);
/* Sanity. The exact same SP value is returned by
PUSH_DUMMY_CALL, saved as the dummy-frame TOS, and used by
- unwind_dummy_id to form the frame ID's stack address. */
+ dummy_id to form the frame ID's stack address. */
bpt = set_momentary_breakpoint (sal, dummy_id, bp_call_dummy);
bpt->disposition = disp_del;
}
{
struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
+ struct cleanup *old_cleanups2;
int saved_async = 0;
/* If all error()s out of proceed ended up calling normal_stop
if (target_can_async_p ())
saved_async = target_async_mask (0);
-
+
+ old_cleanups2 = make_cleanup_restore_integer (&suppress_resume_observer);
+ suppress_resume_observer = 1;
+ make_cleanup_restore_integer (&suppress_stop_observer);
+ suppress_stop_observer = 1;
proceed (real_pc, TARGET_SIGNAL_0, 0);
+ do_cleanups (old_cleanups2);
if (saved_async)
target_async_mask (saved_async);
}
else
{
- struct gdbarch *arch = current_gdbarch;
-
- switch (gdbarch_return_value (arch, target_values_type, NULL, NULL, NULL))
+ switch (gdbarch_return_value (gdbarch, value_type (function),
+ target_values_type, NULL, NULL, NULL))
{
case RETURN_VALUE_REGISTER_CONVENTION:
case RETURN_VALUE_ABI_RETURNS_ADDRESS:
case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
retval = allocate_value (values_type);
- gdbarch_return_value (current_gdbarch, values_type, retbuf,
- value_contents_raw (retval), NULL);
+ gdbarch_return_value (gdbarch, value_type (function), values_type,
+ retbuf, value_contents_raw (retval), NULL);
break;
case RETURN_VALUE_STRUCT_CONVENTION:
retval = value_at (values_type, struct_addr);