summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny Smith <dannysmith@users.sourceforge.net>2002-04-25 22:06:14 +0000
committerDanny Smith <dannysmith@users.sourceforge.net>2002-04-25 22:06:14 +0000
commit13ce6427583eace9b739472d37e6296c30788b04 (patch)
tree383fa9b2e66e1a28a8bbe96f6ee8c5674de54f91
parent635f90951fd0ba96b3f57bd44ae0b4a79ee63a74 (diff)
downloadgdb-13ce6427583eace9b739472d37e6296c30788b04.tar.gz
Add atexit support for dlls.
* crt1.c (atexit): Force thunk to _imp__atexit. (_onexit): Force thunk to _imp___onexit. * dllcrt1.c (DllMainCRTStartup): Initialise private atexit table on DLL_PROCESS_ATTACH, clean it up on DLL_PROCESS_DETACH. (__dll_exit): New function to run atexit-registered functions and flush output buffers on DLL_PROCESS_DETACH or failed DLL_PROCESS_ATTACH. (atexit): Force use of private atexit table via _dllonexit, (_onexit): New function. Force use of private atexit table via _dllonexit, * mscvrt.def (atexit, _onexit): Add DATA keyword so that only _imp_<_symbol> is visible in import lib. * mscvrt20.def: Likewise. * mscvrt40.def: Likewise. * crtdll.def: Likewise.
-rw-r--r--winsup/mingw/ChangeLog19
-rw-r--r--winsup/mingw/crt1.c17
-rw-r--r--winsup/mingw/crtdll.def4
-rw-r--r--winsup/mingw/dllcrt1.c196
-rw-r--r--winsup/mingw/msvcrt.def4
-rw-r--r--winsup/mingw/msvcrt20.def4
-rw-r--r--winsup/mingw/msvcrt40.def4
7 files changed, 240 insertions, 8 deletions
diff --git a/winsup/mingw/ChangeLog b/winsup/mingw/ChangeLog
index 19768b45b8b..f82b2b01526 100644
--- a/winsup/mingw/ChangeLog
+++ b/winsup/mingw/ChangeLog
@@ -1,5 +1,24 @@
2002-04-26 Danny Smith <dannysmith@users.sourceforge.net>
+ Add atexit support for dlls.
+ * crt1.c (atexit): Force thunk to _imp__atexit.
+ (_onexit): Force thunk to _imp___onexit.
+ * dllcrt1.c (DllMainCRTStartup): Initialise private atexit
+ table on DLL_PROCESS_ATTACH, clean it up on DLL_PROCESS_DETACH.
+ (__dll_exit): New function to run atexit-registered functions
+ and flush output buffers on DLL_PROCESS_DETACH or failed
+ DLL_PROCESS_ATTACH.
+ (atexit): Force use of private atexit table via _dllonexit,
+ (_onexit): New function. Force use of private atexit table via
+ _dllonexit,
+ * mscvrt.def (atexit, _onexit): Add DATA keyword so that only
+ _imp_<_symbol> is visible in import lib.
+ * mscvrt20.def: Likewise.
+ * mscvrt40.def: Likewise.
+ * crtdll.def: Likewise.
+
+2002-04-26 Danny Smith <dannysmith@users.sourceforge.net>
+
* include/fenv.h: Change header guard macro to _FENV_H_.
(fenv_t, fexcept_t): Move into block protected by
#ifndef RC_INVOKED.
diff --git a/winsup/mingw/crt1.c b/winsup/mingw/crt1.c
index f91f1da28f1..a11c2fb039f 100644
--- a/winsup/mingw/crt1.c
+++ b/winsup/mingw/crt1.c
@@ -232,3 +232,20 @@ WinMainCRTStartup ()
__mingw_CRTStartup ();
}
+/*
+ * We force use of library version of atexit, which is only
+ * visible in import lib as _imp__atexit
+ */
+extern int (*_imp__atexit)(void (*)(void));
+int atexit (void (* pfn )(void) )
+{
+ return ( (*_imp__atexit)(pfn));
+}
+
+/* Likewise for non-ANSI _onexit */
+extern _onexit_t (*_imp___onexit)(_onexit_t);
+_onexit_t
+_onexit (_onexit_t pfn )
+{
+ return (*_imp___onexit)(pfn);
+}
diff --git a/winsup/mingw/crtdll.def b/winsup/mingw/crtdll.def
index 694547471e6..6f924fb7b34 100644
--- a/winsup/mingw/crtdll.def
+++ b/winsup/mingw/crtdll.def
@@ -414,7 +414,7 @@ _mkdir
_mktemp
_msize
_nextafter
-_onexit
+_onexit DATA
_open
_open_osfhandle
_osmajor_dll DATA
@@ -520,7 +520,7 @@ asctime
asin
atan
atan2
-atexit
+atexit DATA
atof
atoi
atol
diff --git a/winsup/mingw/dllcrt1.c b/winsup/mingw/dllcrt1.c
new file mode 100644
index 00000000000..fe351eb1090
--- /dev/null
+++ b/winsup/mingw/dllcrt1.c
@@ -0,0 +1,196 @@
+/*
+ * dllcrt1.c
+ *
+ * Initialization code for DLLs.
+ *
+ * This file is part of the Mingw32 package.
+ *
+ * Contributors:
+ * Created by Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
+ * DLL support adapted from Gunther Ebert <gunther.ebert@ixos-leipzig.de>
+ * Maintained by Mumit Khan <khan@xraylith.wisc.EDU>
+ *
+ * THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ * This source code is offered for use in the public domain. You may
+ * use, modify or distribute it freely.
+ *
+ * This code is distributed in the hope that it will be useful but
+ * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
+ * DISCLAMED. This includes but is not limited to warrenties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Revision$
+ * $Author$
+ * $Date$
+ *
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <io.h>
+#include <process.h>
+#include <errno.h>
+#include <windows.h>
+
+/* Unlike normal crt1, I don't initialize the FPU, because the process
+ * should have done that already. I also don't set the file handle modes,
+ * because that would be rude. */
+
+#ifdef __GNUC__
+extern void __main ();
+extern void __do_global_dtors ();
+#endif
+
+typedef void (* p_atexit_fn )(void);
+static p_atexit_fn* first_atexit;
+static p_atexit_fn* next_atexit;
+
+static void
+__dll_exit (void);
+
+/* This is based on the function in the Wine project's exit.c */
+p_atexit_fn __dllonexit (p_atexit_fn, p_atexit_fn**, p_atexit_fn**);
+
+
+extern BOOL WINAPI DllMain (HANDLE, DWORD, LPVOID);
+
+
+BOOL WINAPI
+DllMainCRTStartup (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
+{
+ BOOL bRet;
+
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ /* Initialize private atexit table for this dll.
+ 32 is min size required by ANSI */
+
+ first_atexit = (p_atexit_fn*) malloc (32 * sizeof (p_atexit_fn));
+ if (first_atexit == NULL ) /* can't allocate memory */
+ {
+ errno=ENOMEM;
+ return FALSE;
+ }
+ *first_atexit = NULL;
+ next_atexit = first_atexit;
+
+#ifdef DEBUG
+ printf ("%s: DLL_PROCESS_ATTACH (%d)\n", __FUNCTION__);
+#endif
+
+
+#ifdef __GNUC__
+ /* From libgcc.a, __main calls global class constructors,
+ __do_global_ctors, which registers __do_global_dtors
+ as the first entry of the private atexit table we
+ have just initialised */
+ __main ();
+
+#endif
+ }
+
+ /*
+ * Call the user-supplied DllMain subroutine.
+ * This has to come after initialization of atexit table and
+ * registration of global constructors.
+ * NOTE: DllMain is optional, so libmingw32.a includes a stub
+ * which will be used if the user does not supply one.
+ */
+
+ bRet = DllMain (hDll, dwReason, lpReserved);
+ /* Handle case where DllMain returns FALSE on attachment attempt. */
+
+ if ( (dwReason == DLL_PROCESS_ATTACH) && !bRet)
+ {
+#ifdef DEBUG
+ printf ("%s: DLL_PROCESS_ATTACH failed, cleaning up\n", __FUNCTION__);
+#endif
+
+ __dll_exit (); /* Cleanup now. This will set first_atexit to NULL so we
+ know we've cleaned up */
+ }
+
+ if (dwReason == DLL_PROCESS_DETACH)
+ {
+#ifdef DEBUG
+ printf ("%s: DLL_PROCESS_DETACH (%d)\n", __FUNCTION__);
+#endif
+ /* If not attached, return FALSE. Cleanup already done above
+ if failed attachment attempt. */
+ if (! first_atexit )
+ bRet = FALSE;
+ else
+ /*
+ * We used to call __do_global_dtors () here. This is
+ * no longer necessary since __do_global_dtors is now
+ * registered at start (last out) of private atexit table.
+ */
+ __dll_exit ();
+ }
+ return bRet;
+}
+
+static
+void
+__dll_exit(void)
+/* Run LIFO terminators registered in private atexit table */
+{
+ if ( first_atexit )
+ {
+ p_atexit_fn* __last = next_atexit - 1;
+ while ( __last >= first_atexit )
+ {
+ if ( *__last != NULL )
+ {
+#ifdef DEBUG
+ printf ("%s: Calling exit function 0x%x from 0x%x\n",
+ __FUNCTION__, (unsigned)(*__last),(unsigned)__last);
+#endif
+ (**__last) ();
+ }
+ __last--;
+ }
+ free ( first_atexit ) ;
+ first_atexit = NULL ;
+ }
+ /*
+ Make sure output buffers opened by DllMain or
+ atexit-registered functions are flushed before detaching,
+ otherwise we can have problems with redirected output.
+ */
+ fflush (NULL);
+}
+
+/*
+ * The atexit exported from msvcrt.dll causes problems in DLLs.
+ * Here, we override the exported version of atexit with one that passes the
+ * private table initialised in DllMainCRTStartup to __dllonexit.
+ * That means we have to hide the mscvrt.dll atexit because the
+ * atexit defined here gets __dllonexit from the same lib.
+ */
+
+int
+atexit (p_atexit_fn pfn )
+{
+#ifdef DEBUG
+ printf ("%s: registering exit function 0x%x at 0x%x\n",
+ __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit);
+#endif
+ return (__dllonexit (pfn, &first_atexit, &next_atexit)
+ == NULL ? -1 : 0 );
+}
+
+/*
+ * Likewise for non-ANSI function _onexit that may be called by
+ * code in the dll.
+ */
+
+_onexit_t
+_onexit (_onexit_t pfn )
+{
+#ifdef DEBUG
+ printf ("%s: registering exit function 0x%x at 0x%x\n",
+ __FUNCTION__, (unsigned)pfn, (unsigned)next_atexit);
+#endif
+ return ((_onexit_t) __dllonexit ((p_atexit_fn)pfn, &first_atexit, &next_atexit));
+}
diff --git a/winsup/mingw/msvcrt.def b/winsup/mingw/msvcrt.def
index 8d3e1a8cc21..0b85e9e1cb1 100644
--- a/winsup/mingw/msvcrt.def
+++ b/winsup/mingw/msvcrt.def
@@ -365,7 +365,7 @@ _mkdir
_mktemp
_msize
_nextafter
-_onexit
+_onexit DATA
_open
_open_osfhandle
_osver DATA
@@ -546,7 +546,7 @@ asctime
asin
atan
atan2
-atexit
+atexit DATA
atof
atoi
atol
diff --git a/winsup/mingw/msvcrt20.def b/winsup/mingw/msvcrt20.def
index 77ff49510cc..9ceb0750e7b 100644
--- a/winsup/mingw/msvcrt20.def
+++ b/winsup/mingw/msvcrt20.def
@@ -329,7 +329,7 @@ _msize
_mtlock
_mtunlock
_nextafter
-_onexit
+_onexit DATA
_open
_open_osfhandle
_osver
@@ -528,7 +528,7 @@ asctime
asin
atan
atan2
-atexit
+atexit DATA
atof
atoi
atol
diff --git a/winsup/mingw/msvcrt40.def b/winsup/mingw/msvcrt40.def
index 936aff962ee..e4b09f999eb 100644
--- a/winsup/mingw/msvcrt40.def
+++ b/winsup/mingw/msvcrt40.def
@@ -312,7 +312,7 @@ _msize
_mtlock
_mtunlock
_nextafter
-_onexit
+_onexit DATA
_open
_open_osfhandle
_osver
@@ -485,7 +485,7 @@ asctime
asin
atan
atan2
-atexit
+atexit DATA
atof
atoi
atol