aboutsummaryrefslogtreecommitdiff
path: root/gdb/valops.c
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2002-09-18 15:37:18 +0000
committerAndrew Cagney <cagney@redhat.com>2002-09-18 15:37:18 +0000
commitdc60453953d816e84c32b10bcc187100ec090206 (patch)
tree4ebb3131ab59d027361b42aa01174a3911a506a0 /gdb/valops.c
parent11350d2a6f73a4a510fa335553e1363857f8b84f (diff)
downloadfsf-binutils-gdb-dc60453953d816e84c32b10bcc187100ec090206.zip
fsf-binutils-gdb-dc60453953d816e84c32b10bcc187100ec090206.tar.gz
fsf-binutils-gdb-dc60453953d816e84c32b10bcc187100ec090206.tar.bz2
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.
Diffstat (limited to 'gdb/valops.c')
-rw-r--r--gdb/valops.c111
1 files changed, 93 insertions, 18 deletions
diff --git a/gdb/valops.c b/gdb/valops.c
index 2e61e88..eaf4295 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -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;
+ }
}
}