Patchwork [gccgo] Split stack fixups

login
register
mail settings
Submitter Ian Taylor
Date July 1, 2010, 8:56 p.m.
Message ID <mcr7hleq5uk.fsf@google.com>
Download mbox | patch
Permalink /patch/57598/
State New
Headers show

Comments

Ian Taylor - July 1, 2010, 8:56 p.m.
This patch has a couple more split stack fixups.  On x86_64 we ensure
that more stack space is available, since 64-bit addresses use up the
stack faster.  We ensure that the dynamic linker resolves getpagesize
early.  We avoid calling __builtin_memcpy, because in some cases it is
compiled into a call to memcpy which could require the dynamic linker to
resolve it when stack space is low.  It's hard to absolutely ensure that
memcpy is resolved because the compiler will some times compile it into
a loop.  Since the size argument to memcpy is just the size of the
parameters, and is thus sure to be relatively small, I think using a
simple loop is OK.

Committed to gccgo branch.

Ian

Patch

Index: generic-morestack.c
===================================================================
--- generic-morestack.c	(revision 161452)
+++ generic-morestack.c	(working copy)
@@ -298,6 +298,10 @@  __generic_morestack (size_t *pframe_size
   size_t frame_size = *pframe_size;
   struct stack_segment *current;
   struct stack_segment **pp;
+  char *from;
+  char *to;
+  void *ret;
+  size_t i;
 
   current = __morestack_current_segment;
 
@@ -318,13 +322,21 @@  __generic_morestack (size_t *pframe_size
 #ifdef STACK_GROWS_DOWNWARD
   {
     char *bottom = (char *) (current + 1) + current->size;
-    __builtin_memcpy (bottom - param_size, old_stack, param_size);
-    return bottom - param_size;
+    to = bottom - param_size;
+    ret = bottom - param_size;
   }
 #else
-  __builtin_memcpy (current + 1, old_stack, param_size);
-  return (char *) (current + 1) + param_size;
+  to = current + 1;
+  ret = (char *) (current + 1) + param_size;
 #endif
+
+  /* We don't call memcpy to avoid worrying about the dynamic linker
+     trying to resolve it.  */
+  from = (char *) old_stack;
+  for (i = 0; i < param_size; i++)
+    *to++ = *from++;
+
+  return ret;
 }
 
 /* This function is called by a processor specific function when it is
@@ -394,9 +406,9 @@  __generic_findstack (void *stack)
 }
 
 /* This function is called at program startup time to make sure that
-   mmap and munmap are resolved if linking dynamically.  We want to
-   resolve them while we have enough stack for them, rather than
-   calling into the dynamic linker while low on stack space.  */
+   mmap, munmap, and getpagesize are resolved if linking dynamically.
+   We want to resolve them while we have enough stack for them, rather
+   than calling into the dynamic linker while low on stack space.  */
 
 void
 __morestack_load_mmap (void)
@@ -405,7 +417,7 @@  __morestack_load_mmap (void)
      fails.  Pass __MORESTACK_CURRENT_SEGMENT to make sure that any
      TLS accessor function is resolved.  */
   mmap (__morestack_current_segment, 0, PROT_READ, MAP_ANONYMOUS, -1, 0);
-  munmap (0, 0);
+  munmap (0, getpagesize ());
 }
 
 #endif /* !defined (inhibit_libc) */
Index: config/i386/morestack.S
===================================================================
--- config/i386/morestack.S	(revision 161452)
+++ config/i386/morestack.S	(working copy)
@@ -76,6 +76,15 @@ 
 # __morestack to call __morestack_non_split instead.  We just bump the
 # requested stack space by 16K.
 
+# The amount of extra space we ask for.  In general this has to be
+# enough for the dynamic loader to find a symbol.
+	
+#ifndef __x86_64__
+#define BACKOFF (512)
+#else
+#define BACKOFF (1024)
+#endif
+
 	.global __morestack_non_split
 
 #ifdef __ELF__
@@ -147,7 +156,7 @@  __morestack:
 	pushl	12(%ebp)		# The size of the parameters.
 	leal	20(%ebp),%eax		# Address of caller's parameters.
 	pushl	%eax
-	addl	$512,8(%ebp)		# Ask for backoff bytes.
+	addl	$BACKOFF,8(%ebp)	# Ask for backoff bytes.
 	leal	8(%ebp),%eax		# The address of the new frame size.
 	pushl	%eax
 
@@ -158,7 +167,7 @@  __morestack:
 
 	movl	%eax,%esp		# Switch to the new stack.
 	subl	8(%ebp),%eax		# The end of the stack space.
-	addl	$512,%eax		# Back off 512 bytes.
+	addl	$BACKOFF,%eax		# Back off 512 bytes.
 
 	# FIXME: The offset must match
 	# TARGET_THREAD_SPLIT_STACK_OFFSET in
@@ -197,7 +206,7 @@  __morestack:
 	call	__generic_releasestack
 
 	subl	4(%esp),%eax		# Subtract available space.
-	addl	$512,%eax		# Back off 512 bytes.
+	addl	$BACKOFF,%eax		# Back off 512 bytes.
 .LEHE0:
 	movl	%eax,%gs:0x30		# Save the new stack boundary.
 
@@ -226,7 +235,7 @@  __morestack:
 	call	__generic_findstack
 	movl	%ebp,%ecx		# Get the stack pointer.
 	subl	%eax,%ecx		# Subtract available space.
-	addl	$512,%ecx		# Back off 512 bytes.
+	addl	$BACKOFF,%ecx		# Back off 512 bytes.
 	movl	%ecx,%gs:0x30		# Save new stack boundary.
 	movl	4(%esp),%eax		# Function argument.
 	movl	%eax,(%esp)
@@ -258,7 +267,7 @@  __morestack:
 	# In 64-bit mode the new stack frame size is passed in r10
         # and the argument size is passed in r11.
 
-	addq	$512,%r10		# Ask for backoff bytes.
+	addq	$BACKOFF,%r10		# Ask for backoff bytes.
 	pushq	%r10			# Save new frame size.
 
 	# In 64-bit mode the registers %rdi, %rsi, %rdx, %rcx, %r8,
@@ -291,7 +300,7 @@  __morestack:
 	popq	%r10			# Reload modified frame size
 	movq	%rax,%rsp		# Switch to the new stack.
 	subq	%r10,%rax		# The end of the stack space.
-	addq	$512,%rax		# Back off 512 bytes.
+	addq	$BACKOFF,%rax		# Back off 1024 bytes.
 
 	# FIXME: The offset must match
 	# TARGET_THREAD_SPLIT_STACK_OFFSET in
@@ -321,7 +330,7 @@  __morestack:
 	call	__generic_releasestack
 
 	subq	0(%rsp),%rax		# Subtract available space.
-	addq	$512,%rax		# Back off 512 bytes.
+	addq	$BACKOFF,%rax		# Back off 1024 bytes.
 .LEHE0:
 	movq	%rax,%fs:0x70		# Save the new stack boundary.
 
@@ -349,7 +358,7 @@  __morestack:
 	call	__generic_findstack
 	movq	%rbp,%rcx		# Get the stack pointer.
 	subq	%rax,%rcx		# Subtract available space.
-	addq	$512,%rcx		# Back off 512 bytes.
+	addq	$BACKOFF,%rcx		# Back off 1024 bytes.
 	movq	%rcx,%fs:0x70		# Save new stack boundary.
 	movq	(%rsp),%rdi		# Restore exception data for call.
 #ifdef __PIC__