diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S index 92e7648..f7ed5c5 100644 --- a/libgloss/arm/crt0.S +++ b/libgloss/arm/crt0.S @@ -390,12 +390,21 @@ __change_mode: for _fini to be called at program exit. */ movs r4, r0 movs r5, r1 +#ifdef _LITE_EXIT + /* Make reference to atexit weak to avoid unconditionally pulling in + support code. Refer to comments in __atexit.c for more details. */ + .weak FUNCTION(atexit) + ldr r0, .Latexit + cmp r0, #0 + beq .Lweak_atexit +#endif ldr r0, .Lfini bl FUNCTION (atexit) +.Lweak_atexit: bl FUNCTION (_init) movs r0, r4 movs r1, r5 -#endif +#endif bl FUNCTION (main) bl FUNCTION (exit) /* Should not return. */ @@ -465,6 +474,13 @@ change_back: .LC2: .word __bss_end__ #ifdef __USES_INITFINI__ +#ifdef _LITE_EXIT +.Latexit: + .word FUNCTION(atexit) + + /* Weak reference _fini in case of lite exit. */ + .weak FUNCTION(_fini) +#endif .Lfini: .word FUNCTION(_fini) #endif diff --git a/newlib/README b/newlib/README index d1753fc..a8aba99 100644 --- a/newlib/README +++ b/newlib/README @@ -361,6 +361,11 @@ One feature can be enabled by specifying `--enable-FEATURE=yes' or Disable newlib from supplying syscalls. Enabled by default. +`--enable-lite-exit' + Enable lite exit, a size-reduced implementation of exit that doesn't + invoke clean-up functions such as _fini or global destructors. + Disabled by default. + Running the Testsuite ===================== diff --git a/newlib/acconfig.h b/newlib/acconfig.h index e51eba3..b14a3d3 100644 --- a/newlib/acconfig.h +++ b/newlib/acconfig.h @@ -67,6 +67,9 @@ /* Define if unbuffered stream file optimization is supported. */ #undef _UNBUF_STREAM_OPT +/* Define if enable lite version of exit. */ +#undef _LITE_EXIT + @BOTTOM@ /* * Iconv encodings enabled ("to" direction) diff --git a/newlib/configure b/newlib/configure index 7f6155d..e05a2d3 100755 --- a/newlib/configure +++ b/newlib/configure @@ -794,6 +794,7 @@ enable_newlib_fseek_optimization enable_newlib_wide_orient enable_newlib_nano_malloc enable_newlib_unbuf_stream_opt +enable_lite_exit enable_multilib enable_target_optspace enable_malloc_debugging @@ -1462,6 +1463,7 @@ Optional Features: --disable-newlib-wide-orient Turn off wide orientation in streamio --enable-newlib-nano-malloc use small-footprint nano-malloc implementation --disable-newlib-unbuf-stream-opt disable unbuffered stream optimization in streamio + --enable-lite-exit enable light weight exit --enable-multilib build many library versions (default) --enable-target-optspace optimize for space --enable-malloc-debugging indicate malloc debugging requested @@ -2425,6 +2427,19 @@ else newlib_unbuf_stream_opt=yes fi +# Check whether --enable-lite-exit was given. +if test "${enable_lite_exit+set}" = set; then : + enableval=$enable_lite_exit; if test "${lite_exit+set}" != set; then + case "${enableval}" in + yes) lite_exit=yes ;; + no) lite_exit=no ;; + *) as_fn_error $? "bad value ${enableval} for lite-exit option" "$LINENO" 5 ;; + esac + fi +else + lite_exit=no +fi + # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || @@ -11725,7 +11740,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11698 "configure" +#line 11743 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11831,7 +11846,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11804 "configure" +#line 11849 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12341,6 +12356,13 @@ _ACEOF fi +if test "${lite_exit}" = "yes"; then +cat >>confdefs.h <<_ACEOF +#define _LITE_EXIT 1 +_ACEOF + +fi + if test "x${iconv_encodings}" != "x" \ || test "x${iconv_to_encodings}" != "x" \ diff --git a/newlib/configure.in b/newlib/configure.in index db1c6b1..8e742f7 100644 --- a/newlib/configure.in +++ b/newlib/configure.in @@ -181,6 +181,19 @@ AC_ARG_ENABLE(newlib-unbuf-stream-opt, esac fi], [newlib_unbuf_stream_opt=yes])dnl +dnl Support --enable-lite-exit +dnl Lite exit is a size-reduced implementation of exit that doesn't invoke +dnl clean-up functions such as _fini or global destructors. +AC_ARG_ENABLE(lite-exit, +[ --enable-lite-exit enable light weight exit], +[if test "${lite_exit+set}" != set; then + case "${enableval}" in + yes) lite_exit=yes ;; + no) lite_exit=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for lite-exit option) ;; + esac + fi], [lite_exit=no])dnl + NEWLIB_CONFIGURE(.) dnl We have to enable libtool after NEWLIB_CONFIGURE because if we try and @@ -390,6 +403,10 @@ if test "${newlib_unbuf_stream_opt}" = "yes"; then AC_DEFINE_UNQUOTED(_UNBUF_STREAM_OPT) fi +if test "${lite_exit}" = "yes"; then +AC_DEFINE_UNQUOTED(_LITE_EXIT) +fi + dnl dnl Parse --enable-newlib-iconv-encodings option argument dnl diff --git a/newlib/libc/stdlib/__atexit.c b/newlib/libc/stdlib/__atexit.c index f04f00d..d36a1a4 100644 --- a/newlib/libc/stdlib/__atexit.c +++ b/newlib/libc/stdlib/__atexit.c @@ -1,5 +1,35 @@ /* * Common routine to implement atexit-like functionality. + * + * This is also the key function to be configured as lite exit, a size-reduced + * implementation of exit that doesn't invoke clean-up functions such as _fini + * or global destructors. + * + * Default (without lite exit) call graph is like: + * _start -> atexit -> __register_exitproc + * _start -> __libc_init_array -> __cxa_atexit -> __register_exitproc + * on_exit -> __register_exitproc + * _start -> exit -> __call_exitprocs + * + * Here an -> means arrow tail invokes arrow head. All invocations here + * are non-weak reference in current newlib/libgloss. + * + * Lite exit makes some of above calls as weak reference, so that size expansive + * functions __register_exitproc and __call_exitprocs may not be linked. These + * calls are: + * _start w-> atexit + * __cxa_atexit w-> __register_exitproc + * exit w-> __call_exitprocs + * + * Lite exit also makes sure that __call_exitprocs will be referenced as non-weak + * whenever __register_exitproc is referenced as non-weak. + * + * Thus with lite exit libs, a program not explicitly calling atexit or on_exit + * will escape from the burden of cleaning up code. A program with atexit or on_exit + * will work consistently to normal libs. + * + * Lite exit is enabled with --enable-lite-exit, and is controlled with macro + * _LITE_EXIT. */ #include @@ -11,6 +41,12 @@ /* Make this a weak reference to avoid pulling in malloc. */ void * malloc(size_t) _ATTRIBUTE((__weak__)); +#ifdef _LITE_EXIT +/* As __call_exitprocs is weak reference in lite exit, make a + non-weak reference to it here. */ +const void * __atexit_dummy = &__call_exitprocs; +#endif + #ifndef __SINGLE_THREAD__ extern _LOCK_RECURSIVE_T __atexit_lock; #endif diff --git a/newlib/libc/stdlib/cxa_atexit.c b/newlib/libc/stdlib/cxa_atexit.c index 8c39236..c3c0d2a 100644 --- a/newlib/libc/stdlib/cxa_atexit.c +++ b/newlib/libc/stdlib/cxa_atexit.c @@ -19,5 +19,14 @@ _DEFUN (__cxa_atexit, void *arg _AND void *d) { - return __register_exitproc (__et_cxa, (void (*)(void)) fn, arg, d); +#ifdef _LITE_EXIT + /* Refer to comments in __atexit.c for more details of lite exit. */ + int __register_exitproc _PARAMS ((int, void (*fn) (void), _PTR, _PTR)) + __attribute__ ((weak)); + + if (!__register_exitproc) + return 0; + else +#endif + return __register_exitproc (__et_cxa, (void (*)(void)) fn, arg, d); } diff --git a/newlib/libc/stdlib/exit.c b/newlib/libc/stdlib/exit.c index 195b724..1dc5694 100644 --- a/newlib/libc/stdlib/exit.c +++ b/newlib/libc/stdlib/exit.c @@ -54,11 +54,16 @@ Supporting OS subroutines required: <<_exit>>. * Exit, flushing stdio buffers if necessary. */ -void +void _DEFUN (exit, (code), int code) { - __call_exitprocs (code, NULL); +#ifdef _LITE_EXIT + /* Refer to comments in __atexit.c for more details of lite exit. */ + void __call_exitprocs _PARAMS ((int, _PTR)) __attribute__((weak)); + if (__call_exitprocs) +#endif + __call_exitprocs (code, NULL); if (_GLOBAL_REENT->__cleanup) (*_GLOBAL_REENT->__cleanup) (_GLOBAL_REENT); diff --git a/newlib/newlib.hin b/newlib/newlib.hin index c6637cb..e4f6230 100644 --- a/newlib/newlib.hin +++ b/newlib/newlib.hin @@ -70,6 +70,9 @@ /* Define if unbuffered stream file optimization is supported. */ #undef _UNBUF_STREAM_OPT +/* Define if lite version of exit supported. */ +#undef _LITE_EXIT + /* * Iconv encodings enabled ("to" direction) */