Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2014-11-05 12:48:00 +0300
committerCorinna Vinschen <corinna@vinschen.de>2014-11-05 12:48:00 +0300
commit4d67bb4936135c7089f1f6e7a1208c30af2c5ee9 (patch)
treee3af795a62d33ab67227b9b64abf5cba6543c96b /winsup/cygwin/dcrt0.cc
parenta2ba36a67d4d6caa4da75bbd18a467651caf1497 (diff)
* Makefile.in (NEW_FUNCTIONS): Add atexit to be not exported.
* lib/atexit.c (atexit): New, statically linkable version of atexit. * dcrt0.cc (cygwin_atexit): Add comment to mark this function as old entry point. Indiscriminately check for DSO of function pointer for all functions, if checking for DSO of return address fails on x86_64. Change comment accordingly.
Diffstat (limited to 'winsup/cygwin/dcrt0.cc')
-rw-r--r--winsup/cygwin/dcrt0.cc35
1 files changed, 18 insertions, 17 deletions
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index f021f0281..673f87a15 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -1250,6 +1250,13 @@ cygwin__cxa_atexit (void (*fn)(void *), void *obj, void *dso_handle)
return __cxa_atexit (fn, obj, 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. */
extern "C" int
cygwin_atexit (void (*fn) (void))
{
@@ -1259,7 +1266,7 @@ cygwin_atexit (void (*fn) (void))
#ifdef __x86_64__
/* x86_64 DLLs created with GCC 4.8.3-3 register __gcc_deregister_frame
as atexit function using a call to atexit, rather than __cxa_atexit.
- Due to GCC's aggressive optimizing, cygwin_atexit doesn't get the correct
+ Due to GCC's tail call optimizing, cygwin_atexit doesn't get the correct
return address on the stack. As a result it fails to get the HMODULE of
the caller and thus calls atexit rather than __cxa_atexit. Then, if the
module gets dlclosed, __cxa_finalize (called from dll_list::detach) can't
@@ -1268,22 +1275,16 @@ cygwin_atexit (void (*fn) (void))
module is already unloaded and the __gcc_deregister_frame function not
available ==> SEGV.
- Workaround: If dlls.find fails, and _my_tls.retaddr is a Cygwin function
- address, and fn is a function address in another DLL, try to find the
- dll entry of the DLL containing fn. Then check if fn is the address of
- the DLLs __gcc_deregister_frame function. If so, proceed by calling
- __cxa_atexit, otherwise call atexit. */
- extern void *__image_base__;
- if (!d
- && (uintptr_t) _my_tls.retaddr () >= (uintptr_t) &__image_base__
- && (uintptr_t) _my_tls.retaddr () <= (uintptr_t) &_cygheap_start
- && (uintptr_t) fn > (uintptr_t) &_cygheap_start)
- {
- d = dlls.find ((void *) fn);
- if (d && (void *) GetProcAddress (d->handle, "__gcc_deregister_frame")
- != fn)
- d = NULL;
- }
+ This also occurs for other functions.
+
+ Workaround: If dlls.find fails, try to find the dll entry of the DLL
+ containing fn. If that works, proceed by calling __cxa_atexit, otherwise
+ call atexit.
+
+ This *should* be sufficiently safe. Ultimately, new applications will
+ use the statically linked atexit function though, as outlined above. */
+ if (!d)
+ d = dlls.find ((void *) fn);
#endif
res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d->handle) : atexit (fn);
return res;