summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/dcrt0.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/dcrt0.cc')
-rw-r--r--winsup/cygwin/dcrt0.cc84
1 files changed, 48 insertions, 36 deletions
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 26b7ec3b4..27450940c 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -782,11 +782,6 @@ dll_crt0_0 ()
description in wow64_test_for_64bit_parent. */
if (wincap.wow64_has_secondary_stack ())
wow64_needs_stack_adjustment = wow64_test_for_64bit_parent ();
-#else
- /* Windows 10 1511 has a stack move when a 64 bit process is started from
- a 32 bit process, just as it was vice versa in XP/2003. */
- if (wincap.has_3264_stack_broken ())
- wow64_needs_stack_adjustment = !wow64_test_for_64bit_parent ();
#endif /* !__x86_64__ */
}
else
@@ -1068,59 +1063,76 @@ extern "C" void __stdcall
_dll_crt0 ()
{
#ifdef __x86_64__
- /* Handle 64 bit process on Windows 10 rel 1511 which has been started from
- 32 bit WOW64 process. See comment in wow64_test_for_64bit_parent for a
- problem description. Unfortunately the areas the stacks would have to
- be moved to are both taken by "something else"(tm) in both, forker and
- forkee, so we can't use the wow64_revert_to_original_stack method as in
- the 32 bit case. Rather, we move the main thread stack to the stack area
- reserved for pthread stacks for this process. */
-#define CREATE_STACK(a) create_new_main_thread_stack(a)
-#define FIX_STACK(s) __asm__ ("\n" \
- "movq %[ADDR], %%rsp \n" \
- "movq %%rsp, %%rbp \n" \
- : : [ADDR] "r" (s))
+ /* 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 always 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 (!dynamically_loaded)
+ {
+ if (!in_forkee || fork_info->from_main)
+ {
+ /* Must be static since it's referenced after the stack and frame
+ pointer registers have been changed. */
+ static PVOID allocationbase;
+ SIZE_T commitsize = in_forkee ? (PBYTE) fork_info->stackbase
+ - (PBYTE) fork_info->stacklimit
+ : 0;
+ PVOID stackaddr = create_new_main_thread_stack (allocationbase,
+ commitsize);
+ if (stackaddr)
+ {
+ /* Set stack pointer to new address. Set frame pointer to
+ stack pointer and subtract 32 bytes for shadow space. */
+ __asm__ ("\n\
+ movq %[ADDR], %%rsp \n\
+ movq %%rsp, %%rbp \n\
+ subq $32,%%rsp \n"
+ : : [ADDR] "r" (stackaddr));
+ /* We're on the new stack now. Free up space taken by the former
+ main thread stack and set DeallocationStack correctly. */
+ VirtualFree (NtCurrentTeb ()->DeallocationStack, 0, MEM_RELEASE);
+ NtCurrentTeb ()->DeallocationStack = allocationbase;
+ }
+ }
+ else
+ fork_info->alloc_stack ();
+ }
#else
/* Handle WOW64 process on XP/2K3 which has been started from native 64 bit
process. See comment in wow64_test_for_64bit_parent for a full problem
description. */
-#define CREATE_STACK(a) wow64_revert_to_original_stack(a)
-#define FIX_STACK(s) __asm__ ("\n" \
- "movl %[ADDR], %%esp \n" \
- "xorl %%ebp, %%ebp \n" \
- : : [ADDR] "r" (s))
-#endif
if (wow64_needs_stack_adjustment && !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_STACK (allocationbase);
+ PVOID stackaddr = wow64_revert_to_original_stack (allocationbase);
if (stackaddr)
{
- /* 2nd half of the stack move. Set stack pointer to new address.
- Set frame pointer to 0. */
- FIX_STACK (stackaddr);
- /* Now we're back on the original stack. Free up space taken by the
+ /* Set stack pointer to new address. Set frame pointer to 0. */
+ __asm__ ("\n\
+ movl %[ADDR], %%esp \n\
+ xorl %%ebp, %%ebp \n"
+ : : [ADDR] "r" (stackaddr));
+ /* We're back on the original stack now. Free up space taken by the
former main thread stack and set DeallocationStack correctly. */
VirtualFree (NtCurrentTeb ()->DeallocationStack, 0, MEM_RELEASE);
NtCurrentTeb ()->DeallocationStack = allocationbase;
}
else
/* Fall back to respawning if creating a new stack fails. */
- wow64_respawn_process ();
+ wow64_respawn_process();
}
- _feinitialise ();
-#ifndef __x86_64__
main_environ = user_data->envptr;
-#endif
if (in_forkee)
- {
- fork_info->alloc_stack ();
- _main_tls = &_my_tls;
- }
+ fork_info->alloc_stack ();
+#endif
+ _feinitialise ();
+ _main_tls = &_my_tls;
_main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
}