This was already used in the FAST_CWD check, and could be used in a couple other places.
I found the "emulated"/process value returned from the function largely useless, so I did not cache it. It is useless because, as the docs say, it is set to IMAGE_FILE_MACHINE_UNKNOWN (0) if the process is not running under WOW64, but Microsoft also doesn't consider x64-on-ARM64 to be WOW64, so it is set to 0 regardless if the process is ARM64 or x64. You can tell the difference via GetProcessInformation(ProcessMachineTypeInfo), but for the current process even that's overkill: what we really want to know is the IMAGE_FILE_MACHINE_* constant for the Cygwin dll itself, which is conveniently located in memory already, so make an accessor function to access that. (It could also be cached in a member variable for a simpler accessor, and looked up in init). --- Note the elif defined (__i386__) case won't compile because it references the no-longer-present `wow64` value. This was written and tested against 3.3.6, and the __i386__ case could just go away here... winsup/cygwin/local_includes/wincap.h | 3 +++ winsup/cygwin/path.cc | 6 ++---- winsup/cygwin/wincap.cc | 28 +++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/winsup/cygwin/local_includes/wincap.h b/winsup/cygwin/local_includes/wincap.h index c14872787c..41d0e2c041 100644 --- a/winsup/cygwin/local_includes/wincap.h +++ b/winsup/cygwin/local_includes/wincap.h @@ -42,6 +42,7 @@ class wincapc RTL_OSVERSIONINFOEXW version; char osnam[40]; const void *caps; + USHORT host_mach; bool _is_server; public: @@ -61,6 +62,8 @@ public: { return (size_t) system_info.dwAllocationGranularity; } const char *osname () const { return osnam; } const DWORD build_number () const { return version.dwBuildNumber; } + const USHORT host_machine () const { return host_mach; } + const USHORT current_module_machine () const; #define IMPLEMENT(cap) cap() const { return ((wincaps *) this->caps)->cap; } diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 5cfcbc0f2f..869383c836 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -4617,14 +4617,12 @@ find_fast_cwd_pointer () static fcwd_access_t ** find_fast_cwd () { - USHORT emulated, hosted; fcwd_access_t **f_cwd_ptr; - /* First check if we're running in WOW64 on ARM64 emulating AMD64. Skip + /* First check if we're running on an ARM64 system. Skip fetching FAST_CWD pointer as long as there's no solution for finding it on that system. */ - if (IsWow64Process2 (GetCurrentProcess (), &emulated, &hosted) - && hosted == IMAGE_FILE_MACHINE_ARM64) + if (wincap.host_machine () == IMAGE_FILE_MACHINE_ARM64) return NULL; /* Fetch the pointer but don't set the global fast_cwd_ptr yet. First diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index 30d9c14e8d..76c10168d6 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -238,6 +238,8 @@ wincapc wincap __attribute__((section (".cygwin_dll_common"), shared)); void wincapc::init () { + USHORT emul_mach; + if (caps) return; // already initialized @@ -282,4 +284,30 @@ wincapc::init () __small_sprintf (osnam, "NT-%d.%d", version.dwMajorVersion, version.dwMinorVersion); + + if (!IsWow64Process2 (GetCurrentProcess (), &emul_mach, &host_mach)) + { + /* assume the only way IsWow64Process2 fails for the current process is + that we're running on an OS version where it's not implemented yet. + As such, the only two realistic options are AMD64 or I386 */ +#if defined (__x86_64__) + host_mach = IMAGE_FILE_MACHINE_AMD64; +#elif defined (__i386__) + host_mach = wow64 ? IMAGE_FILE_MACHINE_AMD64 : IMAGE_FILE_MACHINE_I386; +#else + /* this should not happen */ + host_mach = IMAGE_FILE_MACHINE_UNKNOWN; +#endif + } +} + +extern const IMAGE_DOS_HEADER +dosheader __asm__ ("__image_base__"); + +const USHORT +wincapc::current_module_machine () const +{ + PIMAGE_NT_HEADERS ntheader = (PIMAGE_NT_HEADERS)((LPBYTE) &dosheader + + dosheader.e_lfanew); + return ntheader->FileHeader.Machine; } -- 2.47.0.windows.2