2002-09-18 Andrew Cagney <ac131313@redhat.com>

* valops.c (hand_function_call): Align the initial stack pointer
	and STRUCT_ADDR using frame_align.  When STRUCT_RETURN and
	FRAME_ALIGN_P, use STRUCT_ADDR to obtain the called function's
	return value.
	* mips-tdep.c (mips_frame_align): New function.
	(mips_gdbarch_init): Set frame_align.
	* gdbarch.sh (FRAME_ALIGN): New method.
	* gdbarch.h, gdbarch.c: Re-generate.
This commit is contained in:
Andrew Cagney
2002-09-18 15:37:18 +00:00
parent 11350d2a6f
commit dc60453953
6 changed files with 153 additions and 18 deletions

View File

@ -1351,7 +1351,55 @@ hand_function_call (struct value *function, int nargs, struct value **args)
they are saved on the stack in the inferior. */
PUSH_DUMMY_FRAME;
old_sp = sp = read_sp ();
old_sp = read_sp ();
/* Ensure that the initial SP is correctly aligned. */
if (gdbarch_frame_align_p (current_gdbarch))
{
/* NOTE: cagney/2002-09-18:
On a RISC architecture, a void parameterless generic dummy
frame (i.e., no parameters, no result) typically does not
need to push anything the stack and hence can leave SP and
FP. Similarly, a framelss (possibly leaf) function does not
push anything on the stack and, hence, that too can leave FP
and SP unchanged. As a consequence, a sequence of void
parameterless generic dummy frame calls to frameless
functions will create a sequence of effectively identical
frames (SP, FP and TOS and PC the same). This, not
suprisingly, results in what appears to be a stack in an
infinite loop --- when GDB tries to find a generic dummy
frame on the internal dummy frame stack, it will always find
the first one.
To avoid this problem, the code below always grows the stack.
That way, two dummy frames can never be identical. It does
burn a few bytes of stack but that is a small price to pay
:-). */
sp = gdbarch_frame_align (current_gdbarch, old_sp);
if (sp == old_sp)
{
if (INNER_THAN (1, 2))
/* Stack grows down. */
sp = gdbarch_frame_align (current_gdbarch, old_sp - 1);
else
/* Stack grows up. */
sp = gdbarch_frame_align (current_gdbarch, old_sp + 1);
}
gdb_assert ((INNER_THAN (1, 2) && sp <= old_sp)
|| (INNER_THAN (2, 1) && sp >= old_sp));
}
else
/* FIXME: cagney/2002-09-18: Hey, you loose! Who knows how badly
aligned the SP is! Further, per comment above, if the generic
dummy frame ends up empty (because nothing is 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 its architecture vector. After that, try
adding SAVE_DUMMY_FRAME_TOS() and modifying FRAME_CHAIN so that
when the next outer frame is a generic dummy, it returns the
current frame's base. */
sp = old_sp;
if (INNER_THAN (1, 2))
{
@ -1366,6 +1414,11 @@ hand_function_call (struct value *function, int nargs, struct value **args)
sp += sizeof_dummy1;
}
/* NOTE: cagney/2002-09-10: Don't bother re-adjusting the stack
after allocating space for the call dummy. A target can specify
a SIZEOF_DUMMY1 (via SIZEOF_CALL_DUMMY_WORDS) such that all local
alignment requirements are met. */
funaddr = find_function_addr (function, &value_type);
CHECK_TYPEDEF (value_type);
@ -1562,7 +1615,8 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
/* Reserve space for the return structure to be written on the
stack, if necessary */
stack, if necessary. Make certain that the value is correctly
aligned. */
if (struct_return)
{
@ -1574,15 +1628,23 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
len = STACK_ALIGN (len);
if (INNER_THAN (1, 2))
{
/* stack grows downward */
/* 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);
struct_addr = sp;
}
else
{
/* stack grows upward */
/* 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);
struct_addr = sp;
sp += len;
if (gdbarch_frame_align_p (current_gdbarch))
sp = gdbarch_frame_align (current_gdbarch, sp);
}
}
@ -1778,14 +1840,13 @@ the function call).", name);
do_cleanups (inf_status_cleanup);
/* Figure out the value returned by the function. */
/* elz: I defined this new macro for the hppa architecture only.
this gives us a way to get the value returned by the function from the stack,
at the same address we told the function to put it.
We cannot assume on the pa that r28 still contains the address of the returned
structure. Usually this will be overwritten by the callee.
I don't know about other architectures, so I defined this macro
*/
/* elz: I defined this new macro for the hppa architecture only.
this gives us a way to get the value returned by the function
from the stack, at the same address we told the function to put
it. We cannot assume on the pa that r28 still contains the
address of the returned structure. Usually this will be
overwritten by the callee. I don't know about other
architectures, so I defined this macro */
#ifdef VALUE_RETURNED_FROM_STACK
if (struct_return)
{
@ -1793,12 +1854,26 @@ the function call).", name);
return VALUE_RETURNED_FROM_STACK (value_type, struct_addr);
}
#endif
{
struct value *retval = value_being_returned (value_type, retbuf, struct_return);
do_cleanups (retbuf_cleanup);
return retval;
}
/* NOTE: cagney/2002-09-10: Only when the stack has been correctly
aligned (using frame_align()) do we can trust STRUCT_ADDR and
fetch the return value direct from the stack. This lack of
trust comes about because legacy targets have a nasty habit of
silently, and local to PUSH_ARGUMENTS(), moving STRUCT_ADDR.
For such targets, just hope that value_being_returned() can
find the adjusted value. */
if (struct_return && gdbarch_frame_align_p (current_gdbarch))
{
struct value *retval = value_at (value_type, struct_addr, NULL);
do_cleanups (retbuf_cleanup);
return retval;
}
else
{
struct value *retval = value_being_returned (value_type, retbuf,
struct_return);
do_cleanups (retbuf_cleanup);
return retval;
}
}
}