* libc/stdlib/__call_atexit.c (__libc_fini): Declare.
(register_fini): New function.
* libc/misc/init.c (_fini): Remove.
(__libc_fini_array): Likewise.
* libc/misc/fini.c: New file.
* libc/misc/Makefile.am (LIB_SOURCES): Add fini.c.
* libc/misc/Makefile.in: Regenerate.
+2010-06-04 Mark Mitchell <mark@codesourcery.com>
+
+ * libc/stdlib/__call_atexit.c (__libc_fini): Declare.
+ (register_fini): New function.
+ * libc/misc/init.c (_fini): Remove.
+ (__libc_fini_array): Likewise.
+ * libc/misc/fini.c: New file.
+ * libc/misc/Makefile.am (LIB_SOURCES): Add fini.c.
+ * libc/misc/Makefile.in: Regenerate.
+
2010-05-31 Kazu Hirata <kazu@codesourcery.com>
* libc/stdlib/mallocr.c (malloc_extend_top): Backport the
INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
-LIB_SOURCES = __dprintf.c unctrl.c ffs.c init.c
+LIB_SOURCES = __dprintf.c unctrl.c ffs.c init.c fini.c
libmisc_la_LDFLAGS = -Xcompiler -nostdlib
lib_a_AR = $(AR) $(ARFLAGS)
lib_a_LIBADD =
am__objects_1 = lib_a-__dprintf.$(OBJEXT) lib_a-unctrl.$(OBJEXT) \
- lib_a-ffs.$(OBJEXT) lib_a-init.$(OBJEXT)
+ lib_a-ffs.$(OBJEXT) lib_a-init.$(OBJEXT) lib_a-fini.$(OBJEXT)
@USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_1)
lib_a_OBJECTS = $(am_lib_a_OBJECTS)
LTLIBRARIES = $(noinst_LTLIBRARIES)
libmisc_la_LIBADD =
-am__objects_2 = __dprintf.lo unctrl.lo ffs.lo init.lo
+am__objects_2 = __dprintf.lo unctrl.lo ffs.lo init.lo fini.lo
@USE_LIBTOOL_TRUE@am_libmisc_la_OBJECTS = $(am__objects_2)
libmisc_la_OBJECTS = $(am_libmisc_la_OBJECTS)
libmisc_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = cygnus
INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
-LIB_SOURCES = __dprintf.c unctrl.c ffs.c init.c
+LIB_SOURCES = __dprintf.c unctrl.c ffs.c init.c fini.c
libmisc_la_LDFLAGS = -Xcompiler -nostdlib
@USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = libmisc.la
@USE_LIBTOOL_TRUE@libmisc_la_SOURCES = $(LIB_SOURCES)
lib_a-init.obj: init.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-init.obj `if test -f 'init.c'; then $(CYGPATH_W) 'init.c'; else $(CYGPATH_W) '$(srcdir)/init.c'; fi`
+lib_a-fini.o: fini.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fini.o `test -f 'fini.c' || echo '$(srcdir)/'`fini.c
+
+lib_a-fini.obj: fini.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fini.obj `if test -f 'fini.c'; then $(CYGPATH_W) 'fini.c'; else $(CYGPATH_W) '$(srcdir)/fini.c'; fi`
+
mostlyclean-libtool:
-rm -f *.lo
--- /dev/null
+/*
+ * Copyright (C) 2010 CodeSourcery, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies.
+ *
+ * This file is distributed WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Handle ELF .{pre_init,init,fini}_array sections. */
+#include <sys/types.h>
+
+#ifdef HAVE_INITFINI_ARRAY
+extern void (*__fini_array_start []) (void) __attribute__((weak));
+extern void (*__fini_array_end []) (void) __attribute__((weak));
+
+extern void _fini (void);
+
+/* Run all the cleanup routines. */
+void
+__libc_fini_array (void)
+{
+ size_t count;
+ size_t i;
+
+ count = __fini_array_end - __fini_array_start;
+ for (i = count; i > 0; i--)
+ __fini_array_start[i-1] ();
+
+ _fini ();
+}
+#endif
extern void (*__preinit_array_end []) (void) __attribute__((weak));
extern void (*__init_array_start []) (void) __attribute__((weak));
extern void (*__init_array_end []) (void) __attribute__((weak));
-extern void (*__fini_array_start []) (void) __attribute__((weak));
-extern void (*__fini_array_end []) (void) __attribute__((weak));
extern void _init (void);
-extern void _fini (void);
/* Iterate over all the init routines. */
void
for (i = 0; i < count; i++)
__init_array_start[i] ();
}
-
-/* Run all the cleanup routines. */
-void
-__libc_fini_array (void)
-{
- size_t count;
- size_t i;
-
- count = __fini_array_end - __fini_array_start;
- for (i = count; i > 0; i--)
- __fini_array_start[i-1] ();
-
- _fini ();
-}
#endif
extern _LOCK_RECURSIVE_T __atexit_lock;
#endif
+/* If "__libc_fini" is defined, finalizers (either
+ "__libc_fini_array", or "_fini", as appropriate) will be run after
+ all user-specified atexit handlers. For example, you can define
+ "__libc_fini" to "_fini" in your linker script if you want the C
+ library, rather than startup code, to register finalizers. If you
+ do that, then your startup code need not contain references to
+ "atexit" or "exit". As a result, only applications that reference
+ "exit" explicitly will pull in finalization code.
+
+ The choice of whether to register finalizers from libc or from
+ startup code is deferred to link-time, rather than being a
+ configure-time option, so that the same C library binary can be
+ used with multiple BSPs, some of which register finalizers from
+ startup code, while others defer to the C library. */
+extern char __libc_fini __attribute__((weak));
+
+/* Register the application finalization function with atexit. These
+ finalizers should run last. Therefore, we want to call atexit as
+ soon as possible. */
+static void
+register_fini(void) __attribute__((constructor (0)));
+
+static void
+register_fini(void)
+{
+ if (&__libc_fini) {
+#ifdef HAVE_INITFINI_ARRAY
+ extern void __libc_fini_array (void);
+ atexit (__libc_fini_array);
+#else
+ extern void _fini (void);
+ atexit (_fini);
+#endif
+ }
+}
+
/*
* Call registered exit handlers. If D is null then all handlers are called,
* otherwise only the handlers from that DSO are called.