This is the mail archive of the cygwin-cvs@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[newlib-cygwin] Always move 64 bit main thread stack to defined pthread stack area


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=8a14e51901a40c5bfaf09915f88249173d9b2b05

commit 8a14e51901a40c5bfaf09915f88249173d9b2b05
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Thu Dec 3 13:02:55 2015 +0100

    Always move 64 bit main thread stack to defined pthread stack area
    
             x86_64 only:
            * dcrt0.cc (_dll_crt0): Always move stack to pthread stack area.
            Explain why.
            * miscfuncs.cc (create_new_main_thread_stack): New function to create
            OS-like stack for main thread in pthread stack area.
            * miscfuncs.cc (create_new_main_thread_stack): Declare.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/ChangeLog    |  9 +++++++++
 winsup/cygwin/dcrt0.cc     | 29 +++++++++++++++++++++++++++++
 winsup/cygwin/miscfuncs.cc | 41 +++++++++++++++++++++++++++++++++++++++++
 winsup/cygwin/miscfuncs.h  |  4 ++++
 4 files changed, 83 insertions(+)

diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 149270a..803cb4f 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,14 @@
 2015-12-03  Corinna Vinschen  <corinna@vinschen.de>
 
+	x86_64 only:
+	* dcrt0.cc (_dll_crt0): Always move stack to pthread stack area.
+	Explain why.
+	* miscfuncs.cc (create_new_main_thread_stack): New function to create
+	OS-like stack for main thread in pthread stack area.
+	* miscfuncs.cc (create_new_main_thread_stack): Declare.
+
+2015-12-03  Corinna Vinschen  <corinna@vinschen.de>
+
 	* dcrt0.cc (child_info_fork::alloc_stack): Fix formatting.
 	* fork.cc (frok::parent): Fix formatting.
 	(child_copy): Change type of res to BOOL.
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index a34f643..5865426 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -1093,6 +1093,35 @@ _dll_crt0 ()
 	/* Fall back to respawn if wow64_revert_to_original_stack fails. */
 	wow64_respawn_process ();
     }
+#else
+  /* Starting with Windows 10 rel 1511, the main stack of an application is
+     not reproducible if a 64 bit process has been started from a 32 bit
+     process.  Given that we have enough virtual address space on 64 bit
+     anyway, we now move the main thread stack to the stack area reserved for
+     pthread stacks.  This allows a reproducible stack space under our own
+     control and avoids collision with the OS. */
+  if (!in_forkee && !dynamically_loaded)
+    {
+      /* Must be static since it's referenced after the stack and frame
+	 pointer registers have been changed. */
+      static PVOID allocationbase;
+
+      PVOID stackaddr = create_new_main_thread_stack (allocationbase);
+      if (stackaddr)
+	{
+	  /* 2nd half of the stack move.  Set stack pointer to new address.
+	     Don't set frame pointer to 0 since x86_64 uses the stack while
+	     evaluating NtCurrentTeb (). */
+	  __asm__ ("\n\
+		   movq %[ADDR], %%rsp \n\
+		   movq  %%rsp, %%rbp   \n"
+		   : : [ADDR] "r" (stackaddr));
+	  /* Now we're back on the new stack.  Free up space taken by the
+	     former main thread stack and set DeallocationStack correctly. */
+	  VirtualFree (NtCurrentTeb ()->DeallocationStack, 0, MEM_RELEASE);
+	  NtCurrentTeb ()->DeallocationStack = allocationbase;
+	}
+    }
 #endif /* !__x86_64__ */
   _feinitialise ();
 #ifndef __x86_64__
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index cb34596..320a3c2 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -760,6 +760,47 @@ public:
 };
 
 thread_allocator thr_alloc NO_COPY;
+
+/* Just set up a system-like main thread stack from the pthread stack area
+   maintained by the thr_alloc class.  See the description in the x86_64-only
+   code in _dll_crt0 to understand why we have to do this. */
+PVOID
+create_new_main_thread_stack (PVOID &allocationbase)
+{
+  PIMAGE_DOS_HEADER dosheader;
+  PIMAGE_NT_HEADERS ntheader;
+  SIZE_T stacksize;
+  ULONG guardsize;
+  ULONG commitsize;
+  PBYTE stacklimit;
+
+  dosheader = (PIMAGE_DOS_HEADER) GetModuleHandle (NULL);
+  ntheader = (PIMAGE_NT_HEADERS)
+	     ((PBYTE) dosheader + dosheader->e_lfanew);
+  stacksize = ntheader->OptionalHeader.SizeOfStackReserve;
+  stacksize = roundup2 (stacksize, wincap.allocation_granularity ());
+
+  allocationbase
+	= thr_alloc.alloc (ntheader->OptionalHeader.SizeOfStackReserve);
+  guardsize = wincap.def_guard_page_size ();
+  commitsize = ntheader->OptionalHeader.SizeOfStackCommit;
+  commitsize = roundup2 (commitsize, wincap.page_size ());
+  if (commitsize > stacksize - guardsize - wincap.page_size ())
+    commitsize = stacksize - guardsize - wincap.page_size ();
+  stacklimit = (PBYTE) allocationbase + stacksize - commitsize - guardsize;
+  /* Setup guardpage. */
+  if (!VirtualAlloc (stacklimit, guardsize,
+		     MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD))
+    return NULL;
+  /* Setup committed region. */
+  stacklimit += guardsize;
+  if (!VirtualAlloc (stacklimit, commitsize, MEM_COMMIT, PAGE_READWRITE))
+    return NULL;
+  NtCurrentTeb()->Tib.StackBase = ((PBYTE) allocationbase + stacksize);
+  NtCurrentTeb()->Tib.StackLimit = stacklimit;
+  _main_tls = &_my_tls;
+  return stacklimit - 64;
+}
 #endif
 
 HANDLE WINAPI
diff --git a/winsup/cygwin/miscfuncs.h b/winsup/cygwin/miscfuncs.h
index c9248f6..8ff85d9 100644
--- a/winsup/cygwin/miscfuncs.h
+++ b/winsup/cygwin/miscfuncs.h
@@ -70,6 +70,10 @@ ssize_t __reg3 check_iovec (const struct iovec *, int, bool);
 #define check_iovec_for_read(a, b) check_iovec ((a), (b), false)
 #define check_iovec_for_write(a, b) check_iovec ((a), (b), true)
 
+#ifdef __x86_64__
+extern PVOID create_new_main_thread_stack (PVOID &allocationbase);
+#endif
+
 extern "C" DWORD WINAPI pthread_wrapper (PVOID arg);
 extern "C" HANDLE WINAPI CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func,
 					     PVOID thread_arg, PVOID stackaddr,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]