diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2015-12-03 13:02:55 +0100 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2015-12-03 13:31:18 +0100 |
commit | 8a14e51901a40c5bfaf09915f88249173d9b2b05 (patch) | |
tree | 6a78c053897a90d8e477cf7bed032c335f9b9fb9 | |
parent | 81e6c7515da61c8dc8426804f1eeb25981b13d55 (diff) | |
download | newlib-8a14e51901a40c5bfaf09915f88249173d9b2b05.zip newlib-8a14e51901a40c5bfaf09915f88249173d9b2b05.tar.gz newlib-8a14e51901a40c5bfaf09915f88249173d9b2b05.tar.bz2 |
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>
-rw-r--r-- | winsup/cygwin/ChangeLog | 9 | ||||
-rw-r--r-- | winsup/cygwin/dcrt0.cc | 29 | ||||
-rw-r--r-- | winsup/cygwin/miscfuncs.cc | 41 | ||||
-rw-r--r-- | winsup/cygwin/miscfuncs.h | 4 |
4 files changed, 83 insertions, 0 deletions
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, |