* 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.
This commit is contained in:
parent
a2ba36a67d
commit
4d67bb4936
|
@ -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
|
||||
|
|
|
@ -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= \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue