diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 30140b532..00d0bc86e 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,13 @@ +2010-06-04 Mark Mitchell + + * 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 * libc/stdlib/mallocr.c (malloc_extend_top): Backport the diff --git a/newlib/libc/misc/Makefile.am b/newlib/libc/misc/Makefile.am index 56eeeee0e..8ac62a25e 100644 --- a/newlib/libc/misc/Makefile.am +++ b/newlib/libc/misc/Makefile.am @@ -4,7 +4,7 @@ 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 diff --git a/newlib/libc/misc/Makefile.in b/newlib/libc/misc/Makefile.in index 50aaae6d5..8f183bd18 100644 --- a/newlib/libc/misc/Makefile.in +++ b/newlib/libc/misc/Makefile.in @@ -56,12 +56,12 @@ ARFLAGS = cru 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) \ @@ -228,7 +228,7 @@ top_builddir = @top_builddir@ 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) @@ -334,6 +334,12 @@ lib_a-init.o: init.c 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 diff --git a/newlib/libc/misc/fini.c b/newlib/libc/misc/fini.c new file mode 100644 index 000000000..ab4203bf8 --- /dev/null +++ b/newlib/libc/misc/fini.c @@ -0,0 +1,35 @@ +/* + * 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 + +#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 diff --git a/newlib/libc/misc/init.c b/newlib/libc/misc/init.c index 50bac50c7..c85d6020f 100644 --- a/newlib/libc/misc/init.c +++ b/newlib/libc/misc/init.c @@ -20,11 +20,8 @@ extern void (*__preinit_array_start []) (void) __attribute__((weak)); 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 @@ -43,18 +40,4 @@ __libc_init_array (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 diff --git a/newlib/libc/stdlib/__call_atexit.c b/newlib/libc/stdlib/__call_atexit.c index 6dd2ec63a..c99b2744e 100644 --- a/newlib/libc/stdlib/__call_atexit.c +++ b/newlib/libc/stdlib/__call_atexit.c @@ -15,6 +15,42 @@ void free(void *) _ATTRIBUTE((__weak__)); 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.