# x86/x86_64 support for -fsplit-stack.
-# Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+# Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
# Contributed by Ian Lance Taylor <iant@google.com>.
# This file is part of GCC.
#endif
+# The amount of space we ask for when calling non-split-stack code.
+#define NON_SPLIT_STACK 0x100000
+
# This entry point is for split-stack code which calls non-split-stack
# code. When the linker sees this case, it converts the call to
# __morestack to call __morestack_non_split instead. We just bump the
movl %esp,%eax # Current stack,
subl 8(%esp),%eax # less required stack frame size,
- subl $0x4000,%eax # less space for non-split code.
+ subl $NON_SPLIT_STACK,%eax # less space for non-split code.
cmpl %gs:0x30,%eax # See if we have enough space.
jb 2f # Get more space if we need it.
je 1f # see above.
addl $2,%eax
1: inc %eax
+
+ # If the instruction that we return to is
+ # leal 20(%ebp),{%eax,%ecx,%edx}
+ # 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.
+ cmpb $0x8d,(%eax)
+ jne 3f
+ cmpb $0x14,2(%eax)
+ jne 3f
+ cmpb $0x45,1(%eax)
+ je 2f
+ cmpb $0x4d,1(%eax)
+ je 2f
+ cmpb $0x55,1(%eax)
+ je 2f
+
+3:
movl %eax,4(%esp) # Update return address.
popl %eax # Restore %eax and stack.
.cfi_adjust_cfa_offset -4 # Account for popped register.
- addl $0x5000+BACKOFF,4(%esp) # Increment space we request.
+ # Increment space we request.
+ addl $NON_SPLIT_STACK+0x1000+BACKOFF,4(%esp)
# Fall through into morestack.
movq %rsp,%rax # Current stack,
subq %r10,%rax # less required stack frame size,
- subq $0x4000,%rax # less space for non-split code.
+ subq $NON_SPLIT_STACK,%rax # less space for non-split code.
#ifdef __LP64__
cmpq %fs:0x70,%rax # See if we have enough space.
#else
cmpl %fs:0x40,%eax
#endif
- popq %rax # Restore register.
-
- .cfi_adjust_cfa_offset -8 # Adjust for popped register.
jb 2f # Get more space if we need it.
# This breaks call/return prediction, as described above.
- incq (%rsp) # Increment the return address.
+ 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
+ cmpl $0x185d8d4c,(%rax)
+ je 2f
+
+ popq %rax # Restore register.
+
+ .cfi_adjust_cfa_offset -8 # Adjust for popped register.
ret # Return to caller.
2:
- addq $0x5000+BACKOFF,%r10 # Increment space we request.
+ popq %rax # Restore register.
+
+ .cfi_adjust_cfa_offset -8 # Adjust for popped register.
+
+ # Increment space we request.
+ addq $NON_SPLIT_STACK+0x1000+BACKOFF,%r10
# Fall through into morestack.