generic-morestack.c (__generic_morestack): Align the returned stack pointer to a 32 byte boundary.

* generic-morestack.c (__generic_morestack): Align the returned
	stack pointer to a 32 byte boundary.
	* config/i386/morestack.S (__morestack_non_split) [32-bit]: Don't
	increment the return address until we have decided that we don't
	have a varargs function.
	(__morestack) [32-bit]: Align stack correctly when calling C
	functions.
	(__morestack) [64-bit]: Likewise.

From-SVN: r193264
This commit is contained in:
Ian Lance Taylor 2012-11-06 23:04:28 +00:00 committed by Ian Lance Taylor
parent b142d8a2b5
commit e808687a8c
3 changed files with 46 additions and 13 deletions

View File

@ -1,3 +1,14 @@
2012-11-06 Ian Lance Taylor <iant@google.com>
* generic-morestack.c (__generic_morestack): Align the returned
stack pointer to a 32 byte boundary.
* config/i386/morestack.S (__morestack_non_split) [32-bit]: Don't
increment the return address until we have decided that we don't
have a varargs function.
(__morestack) [32-bit]: Align stack correctly when calling C
functions.
(__morestack) [64-bit]: Likewise.
2012-11-04 Thomas Schwinge <thomas@codesourcery.com>
* configure: Regenerate.

View File

@ -200,18 +200,19 @@ __morestack_non_split:
jb 2f # Get more space if we need it.
# This breaks call/return prediction, as described above.
incq 8(%rsp) # Increment the return address.
# If the instruction that we return to is
# leaq 24(%rbp), %r11n
# then we have been called by a varargs function that expects
# %ebp to hold a real value. That can only work if we do the
# full stack split routine. FIXME: This is fragile.
movq 8(%rsp),%rax
incq %rax # Skip ret instruction in caller.
cmpl $0x185d8d4c,(%rax)
je 2f
# This breaks call/return prediction, as described above.
incq 8(%rsp) # Increment the return address.
popq %rax # Restore register.
.cfi_adjust_cfa_offset -8 # Adjust for popped register.
@ -296,9 +297,13 @@ __morestack:
# argument size is pushed then the new stack frame size is
# pushed.
# Align stack to 16-byte boundary with enough space for saving
# registers and passing parameters to functions we call.
subl $40,%esp
# In the body of a non-leaf function, the stack pointer will
# be aligned to a 16-byte boundary. That is CFA + 12 in the
# stack picture above: (CFA + 12) % 16 == 0. At this point we
# have %esp == CFA - 8, so %esp % 16 == 12. We need some
# space for saving registers and passing parameters, and we
# need to wind up with %esp % 16 == 0.
subl $44,%esp
# Because our cleanup code may need to clobber %ebx, we need
# to save it here so the unwinder can restore the value used
@ -393,13 +398,15 @@ __morestack:
movl %ebp,%esp # Restore stack pointer.
# As before, we now have %esp % 16 == 12.
pushl %eax # Push return value on old stack.
pushl %edx
subl $8,%esp # Align stack to 16-byte boundary.
subl $4,%esp # Align stack to 16-byte boundary.
call __morestack_unblock_signals
addl $8,%esp
addl $4,%esp
popl %edx # Restore return value.
popl %eax
@ -485,15 +492,21 @@ __morestack:
pushq %r9
pushq %r11
pushq $0 # For alignment.
# We entered morestack with the stack pointer aligned to a
# 16-byte boundary (the call to morestack's caller used 8
# bytes, and the call to morestack used 8 bytes). We have now
# pushed 10 registers, so we are still aligned to a 16-byte
# boundary.
call __morestack_block_signals
leaq -8(%rbp),%rdi # Address of new frame size.
leaq 24(%rbp),%rsi # The caller's parameters.
addq $8,%rsp
popq %rdx # The size of the parameters.
subq $8,%rsp # Align stack.
call __generic_morestack
movq -8(%rbp),%r10 # Reload modified frame size
@ -564,6 +577,9 @@ __morestack:
movq %rbp,%rsp # Restore stack pointer.
# Now (%rsp & 16) == 8.
subq $8,%rsp # For alignment.
pushq %rax # Push return value on old stack.
pushq %rdx
@ -571,6 +587,7 @@ __morestack:
popq %rdx # Restore return value.
popq %rax
addq $8,%rsp
.cfi_remember_state
popq %rbp

View File

@ -549,6 +549,7 @@ __generic_morestack (size_t *pframe_size, void *old_stack, size_t param_size)
char *to;
void *ret;
size_t i;
size_t aligned;
current = __morestack_current_segment;
@ -580,15 +581,19 @@ __generic_morestack (size_t *pframe_size, void *old_stack, size_t param_size)
*pframe_size = current->size - param_size;
/* Align the returned stack to a 32-byte boundary. */
aligned = (param_size + 31) & ~ (size_t) 31;
#ifdef STACK_GROWS_DOWNWARD
{
char *bottom = (char *) (current + 1) + current->size;
to = bottom - param_size;
ret = bottom - param_size;
to = bottom - aligned;
ret = bottom - aligned;
}
#else
to = current + 1;
ret = (char *) (current + 1) + param_size;
to += aligned - param_size;
ret = (char *) (current + 1) + aligned;
#endif
/* We don't call memcpy to avoid worrying about the dynamic linker