]> sourceware.org Git - newlib-cygwin.git/commitdiff
* Makefile.in (NEW_FUNCTIONS): Add atexit to be not exported.
authorCorinna Vinschen <corinna@vinschen.de>
Wed, 5 Nov 2014 09:48:00 +0000 (09:48 +0000)
committerCorinna Vinschen <corinna@vinschen.de>
Wed, 5 Nov 2014 09:48:00 +0000 (09:48 +0000)
* 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.

winsup/cygwin/ChangeLog
winsup/cygwin/Makefile.in
winsup/cygwin/dcrt0.cc
winsup/cygwin/lib/atexit.c [new file with mode: 0644]

index bba6ce4cfab2db9ceb0d4194aae31c3d16f03168..69ad486e0681ecf4479ff825f9f41a8f535567cb 100644 (file)
@@ -1,3 +1,12 @@
+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
index 2d8c1d620bda9b865ad7cb247ee284146688f52a..6f603d887887fdfee67d618d7ee2b40ed3a580d3 100644 (file)
@@ -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= \
index f021f0281f14f4a81448e3b2daf64146fb7b454a..673f87a156c9b7df8fc50a0bfbf87cf1f2c469cf 100644 (file)
@@ -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 (file)
index 0000000..0b72477
--- /dev/null
@@ -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);
+}
This page took 0.039021 seconds and 5 git commands to generate.