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>
This commit is contained in:
parent
81e6c7515d
commit
8a14e51901
|
@ -1,3 +1,12 @@
|
|||
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.
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue