From bd4339e2a2905d6f62b9510067360badc27da591 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 15 Dec 2015 15:48:44 +0100 Subject: [PATCH] Drop wow64_has_secondary_stack flag --- winsup/cygwin/Makefile.in | 1 - winsup/cygwin/dcrt0.cc | 47 +-------- winsup/cygwin/init.cc | 11 +- winsup/cygwin/wincap.cc | 8 -- winsup/cygwin/wincap.h | 2 - winsup/cygwin/wow64.cc | 213 -------------------------------------- winsup/cygwin/wow64.h | 19 ---- 7 files changed, 4 insertions(+), 297 deletions(-) delete mode 100644 winsup/cygwin/wow64.cc delete mode 100644 winsup/cygwin/wow64.h diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 70da06fdf..7c01df7b8 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -395,7 +395,6 @@ DLL_OFILES:= \ wincap.o \ window.o \ winf.o \ - wow64.o \ xsique.o \ $(EXTRA_OFILES) \ $(MALLOC_OFILES) \ diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index fda4b58b8..822e36e62 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -35,7 +35,6 @@ details. */ #include "cygxdr.h" #include "fenv.h" #include "ntdll.h" -#include "wow64.h" #define MAX_AT_FILE_LEVEL 10 @@ -406,18 +405,8 @@ child_info NO_COPY *child_proc_info; void child_info_fork::alloc_stack () { - /* Make sure not to try a hard allocation if we have been forked off from - the main thread of a Cygwin process which has been started from a 64 bit - parent. In that case the StackBase of the forked child is not the same - as the StackBase of the parent (== this.stackbase), but only because the - stack of the parent has been slightly rearranged. See comment in - wow64_revert_to_original_stack for details. We check here if the - parent stack fits into the child stack. */ PTEB teb = NtCurrentTeb (); - if (teb->Tib.StackBase != stackbase - && (!wincap.is_wow64 () - || stacklimit < teb->DeallocationStack - || stackbase > teb->Tib.StackBase)) + if (teb->Tib.StackBase != stackbase) { void *stack_ptr; size_t stacksize; @@ -772,14 +761,6 @@ dll_crt0_0 () { setup_cygheap (); memory_init (); -#ifndef __x86_64__ - /* WOW64 process on XP/64 or Server 2003/64? Check if we have been - started from 64 bit process and if our stack is at an unusual - address. Set wow64_needs_stack_adjustment if so. Problem - description in wow64_test_for_64bit_parent. */ - if (wincap.wow64_has_secondary_stack ()) - wow64_needs_stack_adjustment = wow64_test_for_64bit_parent (); -#endif /* !__x86_64__ */ } else { @@ -1091,32 +1072,6 @@ _dll_crt0 () 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. */ - 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 = wow64_revert_to_original_stack (allocationbase); - if (stackaddr) - { - /* 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 (); - } main_environ = user_data->envptr; if (in_forkee) fork_info->alloc_stack (); diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc index d1b342886..7285e3db6 100644 --- a/winsup/cygwin/init.cc +++ b/winsup/cygwin/init.cc @@ -54,14 +54,9 @@ munge_threadfunc () { char *threadfunc = NULL; - /* This call to NtQueryInformationThread crashes under WOW64 on - 64 bit XP and Server 2003. */ - if (wincap.wow64_has_secondary_stack ()) - threadfunc = ebp[threadfunc_ix[0]]; - else - NtQueryInformationThread (NtCurrentThread (), - ThreadQuerySetWin32StartAddress, - &threadfunc, sizeof threadfunc, NULL); + NtQueryInformationThread (NtCurrentThread (), + ThreadQuerySetWin32StartAddress, + &threadfunc, sizeof threadfunc, NULL); if (!search_for || threadfunc == search_for) { search_for = NULL; diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index 0f38b6a47..5605af628 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -25,7 +25,6 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = { has_gaa_largeaddress_bug:false, has_broken_alloc_console:false, has_console_logon_sid:false, - wow64_has_secondary_stack:false, has_program_compatibility_assistant:false, has_pipe_reject_remote_clients:false, terminate_thread_frees_stack:false, @@ -47,7 +46,6 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = { has_gaa_largeaddress_bug:false, has_broken_alloc_console:false, has_console_logon_sid:false, - wow64_has_secondary_stack:true, has_program_compatibility_assistant:false, has_pipe_reject_remote_clients:false, terminate_thread_frees_stack:false, @@ -69,7 +67,6 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = { has_gaa_largeaddress_bug:true, has_broken_alloc_console:false, has_console_logon_sid:false, - wow64_has_secondary_stack:false, has_program_compatibility_assistant:true, has_pipe_reject_remote_clients:true, terminate_thread_frees_stack:true, @@ -91,7 +88,6 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = { has_gaa_largeaddress_bug:true, has_broken_alloc_console:true, has_console_logon_sid:true, - wow64_has_secondary_stack:false, has_program_compatibility_assistant:true, has_pipe_reject_remote_clients:true, terminate_thread_frees_stack:true, @@ -113,7 +109,6 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = { has_gaa_largeaddress_bug:false, has_broken_alloc_console:true, has_console_logon_sid:true, - wow64_has_secondary_stack:false, has_program_compatibility_assistant:true, has_pipe_reject_remote_clients:true, terminate_thread_frees_stack:true, @@ -135,7 +130,6 @@ wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = { has_gaa_largeaddress_bug:false, has_broken_alloc_console:true, has_console_logon_sid:true, - wow64_has_secondary_stack:false, has_program_compatibility_assistant:true, has_pipe_reject_remote_clients:true, terminate_thread_frees_stack:true, @@ -157,7 +151,6 @@ wincaps wincap_10_1511 __attribute__((section (".cygwin_dll_common"), shared)) = has_gaa_largeaddress_bug:false, has_broken_alloc_console:true, has_console_logon_sid:true, - wow64_has_secondary_stack:false, has_program_compatibility_assistant:true, has_pipe_reject_remote_clients:true, terminate_thread_frees_stack:true, @@ -248,7 +241,6 @@ wincapc::init () #endif { ((wincaps *)caps)->needs_count_in_si_lpres2 = false; - ((wincaps *)caps)->wow64_has_secondary_stack = false; ((wincaps *)caps)->has_gaa_largeaddress_bug = false; ((wincaps *)caps)->has_broken_prefetchvm = false; } diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index bdbb0f294..7d7dbc792 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -18,7 +18,6 @@ struct wincaps unsigned has_gaa_largeaddress_bug : 1; unsigned has_broken_alloc_console : 1; unsigned has_console_logon_sid : 1; - unsigned wow64_has_secondary_stack : 1; unsigned has_program_compatibility_assistant : 1; unsigned has_pipe_reject_remote_clients : 1; unsigned terminate_thread_frees_stack : 1; @@ -65,7 +64,6 @@ public: bool IMPLEMENT (has_gaa_largeaddress_bug) bool IMPLEMENT (has_broken_alloc_console) bool IMPLEMENT (has_console_logon_sid) - bool IMPLEMENT (wow64_has_secondary_stack) bool IMPLEMENT (has_program_compatibility_assistant) bool IMPLEMENT (has_pipe_reject_remote_clients) bool IMPLEMENT (terminate_thread_frees_stack) diff --git a/winsup/cygwin/wow64.cc b/winsup/cygwin/wow64.cc deleted file mode 100644 index 95651a8c0..000000000 --- a/winsup/cygwin/wow64.cc +++ /dev/null @@ -1,213 +0,0 @@ -/* wow64.cc - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#ifndef __x86_64__ -/* WOW64 only plays a role in the 32 bit version. Don't use any of this - in the 64 bit version. */ - -#include "winsup.h" -#include "cygtls.h" -#include "ntdll.h" -#include - -#define PTR_ADD(p,o) ((PVOID)((PBYTE)(p)+(o))) - -bool NO_COPY wow64_needs_stack_adjustment = false; - -static void -wow64_eval_expected_main_stack (PVOID &allocbase, PVOID &stackbase) -{ - PIMAGE_DOS_HEADER dosheader; - PIMAGE_NT_HEADERS ntheader; - SIZE_T size; - - dosheader = (PIMAGE_DOS_HEADER) GetModuleHandle (NULL); - ntheader = (PIMAGE_NT_HEADERS) ((PBYTE) dosheader + dosheader->e_lfanew); - /* The main thread stack is expected to be located at 0x30000, which is the - case for all observed NT systems up to Server 2003 R2, unless the - stacksize requested by the StackReserve field in the PE/COFF header is - so big that the stack doesn't fit in the area between 0x30000 and the - start of the image. In case of a conflict, the OS allocates the stack - right after the image. - Sidenote: While post-2K3 32 bit systems continue to have the default - main thread stack address located at 0x30000, the default main thread - stack address on Vista/2008 64 bit is 0x80000 and on W7/2K8R2 64 bit - it is 0x90000. However, this is no problem because the system sticks - to that address for all WOW64 processes, not only for the first one - started from a 64 bit parent. */ - allocbase = (PVOID) 0x30000; - /* Stack size. The OS always rounds the size up to allocation granularity - and it never allocates less than 256K. */ - size = roundup2 (ntheader->OptionalHeader.SizeOfStackReserve, - wincap.allocation_granularity ()); - if (size < 256 * 1024) - size = 256 * 1024; - /* If the stack doesn't fit in the area before the image, it's allocated - right after the image, rounded up to allocation granularity boundary. */ - if (PTR_ADD (allocbase, size) > (PVOID) ntheader->OptionalHeader.ImageBase) - allocbase = PTR_ADD (ntheader->OptionalHeader.ImageBase, - ntheader->OptionalHeader.SizeOfImage); - allocbase = (PVOID) roundup2 ((uintptr_t) allocbase, - wincap.allocation_granularity ()); - stackbase = PTR_ADD (allocbase, size); - debug_printf ("expected allocbase: %p, stackbase: %p", allocbase, stackbase); -} - -bool -wow64_test_for_64bit_parent () -{ - /* On Windows XP 64 and 2003 64 there's a problem with processes running - under WOW64. The first process started from a 64 bit process has its - main thread stack not where it should be. Rather, it uses another - stack while the original stack is used for other purposes. - The problem is, the child has its stack in the usual spot again, thus - we have to "alloc_stack_hard_way". However, this fails in almost all - cases because the stack slot of the parent process is taken by something - else in the child process. - What we do here is to check if the current stack is the expected main - thread stack and if not, if we really have been started from a 64 bit - process here. If so, we note this fact in wow64_needs_stack_adjustment - so we can workaround the stack problem in _dll_crt0. See there for how - we go along. */ - NTSTATUS ret; - PROCESS_BASIC_INFORMATION pbi; - HANDLE parent; - PVOID allocbase, stackbase; - - ULONG_PTR wow64 = TRUE; /* Opt on the safe side. */ - - /* First check if the current stack is where it belongs. If so, we don't - have to do anything special. This is the case on Vista and later. */ - wow64_eval_expected_main_stack (allocbase, stackbase); - if (&wow64 >= (PULONG_PTR) allocbase && &wow64 < (PULONG_PTR) stackbase) - return false; - - /* Check if the parent is a native 64 bit process. Unfortunately there's - no simpler way to retrieve the parent process in NT, as far as I know. - Hints welcome. */ - ret = NtQueryInformationProcess (NtCurrentProcess (), - ProcessBasicInformation, - &pbi, sizeof pbi, NULL); - if (NT_SUCCESS (ret) - && (parent = OpenProcess (PROCESS_QUERY_INFORMATION, - FALSE, - (DWORD) pbi.InheritedFromUniqueProcessId))) - { - NtQueryInformationProcess (parent, ProcessWow64Information, - &wow64, sizeof wow64, NULL); - CloseHandle (parent); - } - return !wow64; -} - -PVOID -wow64_revert_to_original_stack (PVOID &allocationbase) -{ - /* Test if the original stack exists and has been set up as usual. Even - though the stack of the WOW64 process is at an unusual address, it appears - that the "normal" stack has been created as usual. It's partially in use - by the 32->64 bit transition layer of the OS to help along the WOW64 - process, but it's otherwise mostly unused. */ - MEMORY_BASIC_INFORMATION mbi; - PVOID stackbase; - - wow64_eval_expected_main_stack (allocationbase, stackbase); - - /* The stack is allocated in a single call, so the entire stack has the - same AllocationBase. At the start we expect a reserved region big - enough still to host as the main stack. The OS apparently reserves - always at least 256K for the main thread stack. We err on the side - of caution so we test here for a reserved region of at least 256K. - That should be enough (knock on wood). */ - VirtualQuery (allocationbase, &mbi, sizeof mbi); - if (mbi.State != MEM_RESERVE || mbi.RegionSize < 256 * 1024) - return NULL; - - /* Next we expect a guard page. We fetch the size of the guard area to - see how big it is. Apparently the guard area on 64 bit systems spans - 2 pages, only for the main thread for some reason. We better keep it - that way. */ - PVOID addr = PTR_ADD (mbi.BaseAddress, mbi.RegionSize); - VirtualQuery (addr, &mbi, sizeof mbi); - if (mbi.AllocationBase != allocationbase - || mbi.State != MEM_COMMIT - || !(mbi.Protect & PAGE_GUARD)) - return NULL; - PVOID guardaddr = mbi.BaseAddress; - SIZE_T guardsize = mbi.RegionSize; - - /* Next we expect a committed R/W region, the in-use area of that stack. - This is just a sanity check. */ - addr = PTR_ADD (mbi.BaseAddress, mbi.RegionSize); - VirtualQuery (addr, &mbi, sizeof mbi); - if (mbi.AllocationBase != allocationbase - || PTR_ADD (mbi.BaseAddress, mbi.RegionSize) != stackbase - || mbi.State != MEM_COMMIT - || mbi.Protect != PAGE_READWRITE) - return NULL; - - /* The original stack is used by the OS. Leave enough space for the OS - to be happy (another 64K) and constitute a second stack within the so - far reserved stack area. */ - PVOID newbase = PTR_ADD (guardaddr, -wincap.allocation_granularity ()); - PVOID newtop = PTR_ADD (newbase, -wincap.allocation_granularity ()); - guardaddr = PTR_ADD (newtop, -guardsize); - if (!VirtualAlloc (newtop, wincap.allocation_granularity (), - MEM_COMMIT, PAGE_READWRITE)) - return NULL; - if (!VirtualAlloc (guardaddr, guardsize, MEM_COMMIT, - PAGE_READWRITE | PAGE_GUARD)) - return NULL; - - /* We're going to reuse the original stack. Yay, no more respawn! - Set the StackBase and StackLimit values in the TEB, set _main_tls - accordingly, and return the new, 16 byte aligned address for the - stack pointer. The second half of the stack move is done by the - caller _dll_crt0. */ - NtCurrentTeb ()->Tib.StackBase = (char *) newbase; - NtCurrentTeb ()->Tib.StackLimit = (char *) newtop; - _main_tls = &_my_tls; - return PTR_ADD (NtCurrentTeb ()->Tib.StackBase, -16); -} - -/* Respawn WOW64 process. This is only called if we can't reuse the original - stack. See comment in wow64_revert_to_original_stack for details. See - _dll_crt0 for the call of this function. - - Historical note: - - Originally we just always respawned, right from dll_entry. This stopped - working with Cygwin 1.7.10 on Windows 2003 R2 64. Starting with Cygwin - 1.7.10 we don't link against advapi32.dll anymore. However, any process - linked against advapi32, directly or indirectly, failed to respawn when - trying respawning during DLL_PROCESS_ATTACH initialization. In that - case CreateProcessW returns with ERROR_ACCESS_DENIED for some reason. */ -void -wow64_respawn_process () -{ - PROCESS_INFORMATION pi; - STARTUPINFOW si; - DWORD ret = 0; - - GetStartupInfoW (&si); - if (!CreateProcessW (global_progname, GetCommandLineW (), NULL, NULL, TRUE, - CREATE_DEFAULT_ERROR_MODE - | GetPriorityClass (GetCurrentProcess ()), - NULL, NULL, &si, &pi)) - api_fatal ("Failed to create process <%W> <%W>, %E", - global_progname, GetCommandLineW ()); - CloseHandle (pi.hThread); - if (WaitForSingleObject (pi.hProcess, INFINITE) == WAIT_FAILED) - api_fatal ("Waiting for process %u failed, %E", pi.dwProcessId); - GetExitCodeProcess (pi.hProcess, &ret); - CloseHandle (pi.hProcess); - TerminateProcess (GetCurrentProcess (), ret); - ExitProcess (ret); -} - -#endif /* !__x86_64__ */ diff --git a/winsup/cygwin/wow64.h b/winsup/cygwin/wow64.h deleted file mode 100644 index b1271bf28..000000000 --- a/winsup/cygwin/wow64.h +++ /dev/null @@ -1,19 +0,0 @@ -/* wow64.h - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#ifndef __x86_64__ -/* WOW64 only plays a role in the 32 bit version. Don't use any of this - in the 64 bit version. */ - -extern bool NO_COPY wow64_needs_stack_adjustment; - -extern bool wow64_test_for_64bit_parent (); -extern PVOID wow64_revert_to_original_stack (PVOID &allocationbase); -extern void wow64_respawn_process () __attribute__ ((noreturn)); - -#endif /* !__x86_64__ */ -- 2.43.5