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
path: root/winsup
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
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')
-rw-r--r--winsup/cygwin/ChangeLog9
-rw-r--r--winsup/cygwin/Makefile.in1
-rw-r--r--winsup/cygwin/dcrt0.cc35
-rw-r--r--winsup/cygwin/lib/atexit.c23
4 files changed, 51 insertions, 17 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index bba6ce4cf..69ad486e0 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,14 @@
2014-11-05 Corinna Vinschen <corinna@vinschen.de>
+ * 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.
+
+2014-11-05 Corinna Vinschen <corinna@vinschen.de>
+
* Makefile.in (NEW_FUNCTIONS): Define target-independent. Add target
dependent stuff afterwards. Globally define timezone and all xdr
symbols as non-exported from libcygwin.a.
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index 2d8c1d620..6f603d887 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -330,6 +330,7 @@ endif
GMON_OFILES:=gmon.o mcount.o profil.o mcountFunc.o
NEW_FUNCTIONS:=$(addprefix --replace=,\
+ atexit= \
timezone= \
__xdrrec_getrec= \
__xdrrec_setnonblock= \
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;
diff --git a/winsup/cygwin/lib/atexit.c b/winsup/cygwin/lib/atexit.c
new file mode 100644
index 000000000..0b724771a
--- /dev/null
+++ b/winsup/cygwin/lib/atexit.c
@@ -0,0 +1,23 @@
+/* atexit.c: atexit entry point
+
+ Copyright 2014 Red Hat, Inc.
+
+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. */
+
+#include <stddef.h>
+
+/* 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))
+{
+ extern int __cxa_atexit(void (*)(void*), void*, void*);
+ extern void *__dso_handle;
+
+ return __cxa_atexit ((void (*)(void*))fn, NULL, &__dso_handle);
+}