From dfc361dad46347fea1089fff9ecd4dd3235703d3 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 6 Nov 2014 15:32:21 +0000 Subject: [PATCH] * dcrt0.cc (cygwin_atexit): Change preceeding comment to reflect API version numbers. * external.cc (cygwin_internal): disable setting cxx_malloc on 64 bit. Add CW_FIXED_ATEXIT case. * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump. * include/sys/cygwin.h (cygwin_getinfo_types): Add CW_FIXED_ATEXIT. * lib/atexit.c (atexit): Test running Cygwin version by checking return value of cygwin_internal (CW_FIXED_ATEXIT). --- winsup/cygwin/ChangeLog | 11 +++++++++++ winsup/cygwin/dcrt0.cc | 12 ++++++------ winsup/cygwin/external.cc | 6 ++++++ winsup/cygwin/include/cygwin/version.h | 3 ++- winsup/cygwin/include/sys/cygwin.h | 4 +++- winsup/cygwin/lib/atexit.c | 21 ++++++++++++++++++--- 6 files changed, 46 insertions(+), 11 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 8b1098e5c..7f001ced5 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2014-11-06 Corinna Vinschen + + * dcrt0.cc (cygwin_atexit): Change preceeding comment to reflect + API version numbers. + * external.cc (cygwin_internal): disable setting cxx_malloc on 64 bit. + Add CW_FIXED_ATEXIT case. + * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump. + * include/sys/cygwin.h (cygwin_getinfo_types): Add CW_FIXED_ATEXIT. + * lib/atexit.c (atexit): Test running Cygwin version by checking + return value of cygwin_internal (CW_FIXED_ATEXIT). + 2014-11-05 Corinna Vinschen * lib/atexit.c (atexit): Check for being linked into the executable. diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 673f87a15..19fb46d2c 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -1251,12 +1251,12 @@ cygwin__cxa_atexit (void (*fn)(void *), void *obj, void *dso_handle) } /* This function is only called for applications built with Cygwin versions - up to 1.7.32. Starting with 1.7.33, atexit is a statically linked function - inside of libcygwin.a. The reason is that the old method to fetch the - caller return address is unreliable given GCCs ability to perform tail call - elimination. For the details, see the below comment. - The atexit replacement is defined in libcygwin.a to allow reliable access - to the correct DSO handle. */ + up to API 0.279. Starting with API 0.280 (Cygwin 1.7.33/1.8.6-2), atexit + is a statically linked function inside of libcygwin.a. The reason is that + the old method to fetch the caller return address is unreliable given GCCs + ability to perform tail call elimination. For the details, see the below + comment. The atexit replacement is defined in libcygwin.a to allow reliable + access to the correct DSO handle. */ extern "C" int cygwin_atexit (void (*fn) (void)) { diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index edc9d5d29..fce161192 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -243,11 +243,13 @@ cygwin_internal (cygwin_getinfo_types t, ...) break; case CW_USER_DATA: +#ifndef __x86_64__ /* This is a kludge to work around a version of _cygwin_common_crt0 which overwrote the cxx_malloc field with the local DLL copy. Hilarity ensues if the DLL is not loaded like while the process is forking. */ __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc; +#endif res = (uintptr_t) &__cygwin_user_data; break; @@ -673,6 +675,10 @@ cygwin_internal (cygwin_getinfo_types t, ...) } break; + case CW_FIXED_ATEXIT: + res = 0; + break; + default: set_errno (ENOSYS); } diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 813220e61..e1ac2cee9 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -455,12 +455,13 @@ details. */ 277: Add setsockopt(SO_PEERCRED). 278: Add quotactl. 279: Export stime. + 280: Static atexit in libcygwin.a, CW_FIXED_ATEXIT. */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 279 +#define CYGWIN_VERSION_API_MINOR 280 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h index 39639b877..7f40475e8 100644 --- a/winsup/cygwin/include/sys/cygwin.h +++ b/winsup/cygwin/include/sys/cygwin.h @@ -150,7 +150,8 @@ typedef enum CW_GETNSSSEP, CW_GETPWSID, CW_GETGRSID, - CW_CYGNAME_FROM_WINNAME + CW_CYGNAME_FROM_WINNAME, + CW_FIXED_ATEXIT } cygwin_getinfo_types; #define CW_LOCK_PINFO CW_LOCK_PINFO @@ -208,6 +209,7 @@ typedef enum #define CW_GETPWSID CW_GETPWSID #define CW_GETGRSID CW_GETGRSID #define CW_CYGNAME_FROM_WINNAME CW_CYGNAME_FROM_WINNAME +#define CW_FIXED_ATEXIT CW_FIXED_ATEXIT /* Token type for CW_SET_EXTERNAL_TOKEN */ enum diff --git a/winsup/cygwin/lib/atexit.c b/winsup/cygwin/lib/atexit.c index af82d1de7..a2dec6267 100644 --- a/winsup/cygwin/lib/atexit.c +++ b/winsup/cygwin/lib/atexit.c @@ -9,11 +9,13 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ #include +#include #include /* Statically linked replacement for the former cygwin_atexit. We need the function here to be able to access the correct __dso_handle of the caller's DSO. */ + int atexit (void (*fn) (void)) { @@ -21,6 +23,7 @@ atexit (void (*fn) (void)) extern void *__dso_handle; extern void *__ImageBase; + void *fixed_dso_handle = &__dso_handle; /* Check for being called from inside the executable. If so, use NULL as __dso_handle. This allows to link executables with GCC versions not providing __dso_handle in crtbegin{S}.o. In this case our own @@ -28,7 +31,19 @@ atexit (void (*fn) (void)) __dso_handle always points to &__ImageBase, while the __dso_handle for executables provided by crtbegin.o usually points to NULL. That's what we remodel here. */ - return __cxa_atexit ((void (*)(void*))fn, NULL, - &__ImageBase == (void **) GetModuleHandleW (NULL) - ? NULL : &__dso_handle); + if (&__ImageBase == (void **) GetModuleHandleW (NULL)) + fixed_dso_handle = NULL; + /* With recent Cygwin versions starting with API version 0.280 we call + __cxa_atexit (which is actually the cygwin__cxa_atexit wrapper in + dcrt0.cc) with the address of __dso_handle since that's how g++ generates + calls to __cxa_atexit as well. However, when running an application + built with this atexit under an older Cygwin version, the __cxa_atexit + entry point is the one from newlib, which expects the *value* of + __dso_handle. So, check for the Cygwin version we're running under. + Older version prior to 0.280 don't know CW_FIXED_ATEXIT and return -1. + 0.280 and later return 0. */ + else if (cygwin_internal (CW_FIXED_ATEXIT) != 0) + fixed_dso_handle = __dso_handle; + + return __cxa_atexit ((void (*)(void*))fn, NULL, fixed_dso_handle); }