summaryrefslogtreecommitdiffstats
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2015-12-03 13:02:55 +0100
committerCorinna Vinschen <corinna@vinschen.de>2015-12-03 13:31:18 +0100
commit8a14e51901a40c5bfaf09915f88249173d9b2b05 (patch)
tree6a78c053897a90d8e477cf7bed032c335f9b9fb9 /winsup
parent81e6c7515da61c8dc8426804f1eeb25981b13d55 (diff)
downloadcygnal-8a14e51901a40c5bfaf09915f88249173d9b2b05.tar.gz
cygnal-8a14e51901a40c5bfaf09915f88249173d9b2b05.tar.bz2
cygnal-8a14e51901a40c5bfaf09915f88249173d9b2b05.zip
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>
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog9
-rw-r--r--winsup/cygwin/dcrt0.cc29
-rw-r--r--winsup/cygwin/miscfuncs.cc41
-rw-r--r--winsup/cygwin/miscfuncs.h4
4 files changed, 83 insertions, 0 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 149270a9c..803cb4f5c 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 a34f64365..5865426e1 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 cb3459630..320a3c2f3 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 c9248f6f7..8ff85d970 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,