diff options
Diffstat (limited to 'stdlib')
-rw-r--r-- | stdlib/Makefile | 13 | ||||
-rw-r--r-- | stdlib/Versions | 4 | ||||
-rw-r--r-- | stdlib/atexit.c | 75 | ||||
-rw-r--r-- | stdlib/cxa_atexit.c | 55 | ||||
-rw-r--r-- | stdlib/old_atexit.c | 8 |
5 files changed, 90 insertions, 65 deletions
diff --git a/stdlib/Makefile b/stdlib/Makefile index 6faa1c54f7..193c42b284 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -29,7 +29,7 @@ routines := \ abort \ bsearch qsort msort \ getenv putenv setenv secure-getenv \ - exit on_exit atexit cxa_atexit cxa_finalize \ + exit on_exit atexit cxa_atexit cxa_finalize old_atexit \ abs labs llabs \ div ldiv lldiv \ mblen mbstowcs mbtowc wcstombs wctomb \ @@ -49,6 +49,11 @@ routines := \ strtoimax strtoumax wcstoimax wcstoumax \ getcontext setcontext makecontext swapcontext +# These routines will be omitted from the libc shared object. +# Instead the static object files will be included in a special archive +# linked against when the shared library will be used. +static-only-routines = atexit + distribute := exit.h grouping.h abort-instr.h isomac.c tst-fmtmsg.sh test-srcs := tst-fmtmsg tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ @@ -81,6 +86,10 @@ CFLAGS-strfmon.c = -D_IO_MTSAFE_IO CFLAGS-strfmon_l.c = -D_IO_MTSAFE_IO endif +ifeq (yes,$(have-protected)) +CFLAGS-atexit.c = -DHAVE_DOT_HIDDEN +endif + include ../Rules @@ -141,7 +150,7 @@ test-canon-ARGS = --test-dir=${common-objpfx}stdlib tst-strtod-ENV = LOCPATH=$(common-objpfx)localedata # Run a test on the header files we use. -tests: $(objpfx)isomac.out +tests: $(objpfx)isomac.out ifeq (no,$(cross-compiling)) tests: $(objpfx)tst-fmtmsg.out diff --git a/stdlib/Versions b/stdlib/Versions index 034125a200..c13ef2761a 100644 --- a/stdlib/Versions +++ b/stdlib/Versions @@ -94,4 +94,8 @@ libc { # used by new G++ ABI __cxa_atexit; __cxa_finalize; } + GLIBC_2.2.3 { + # Used by atexit in libc_nonshared. + __new_exitfn; + } } diff --git a/stdlib/atexit.c b/stdlib/atexit.c index e9648d60e1..19a1575d2c 100644 --- a/stdlib/atexit.c +++ b/stdlib/atexit.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1996, 1999 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1996, 1999, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,75 +16,24 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <bits/libc-lock.h> #include <stdlib.h> #include "exit.h" +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + + /* Register FUNC to be executed by `exit'. */ int atexit (void (*func) (void)) { - struct exit_function *new = __new_exitfn (); - - if (new == NULL) - return -1; - - new->flavor = ef_at; - new->func.at = func; - return 0; + return __cxa_atexit ((void (*) (void *)) func, NULL, + &__dso_handle == NULL ? NULL : __dso_handle); } - -/* We change global data, so we need locking. */ -__libc_lock_define_initialized (static, lock) - - -static struct exit_function_list initial; -struct exit_function_list *__exit_funcs = &initial; - -struct exit_function * -__new_exitfn (void) -{ - struct exit_function_list *l; - size_t i = 0; - - __libc_lock_lock (lock); - - for (l = __exit_funcs; l != NULL; l = l->next) - { - for (i = 0; i < l->idx; ++i) - if (l->fns[i].flavor == ef_free) - break; - if (i < l->idx) - break; - - if (l->idx < sizeof (l->fns) / sizeof (l->fns[0])) - { - i = l->idx++; - break; - } - } - - if (l == NULL) - { - l = (struct exit_function_list *) - malloc (sizeof (struct exit_function_list)); - if (l != NULL) - { - l->next = __exit_funcs; - __exit_funcs = l; - - l->idx = 1; - i = 0; - } - } - - /* Mark entry as used, but we don't know the flavor now. */ - if (l != NULL) - l->fns[i].flavor = ef_us; - - __libc_lock_unlock (lock); - - return l == NULL ? NULL : &l->fns[i]; -} +/* Hide the symbol so that no definition but the one locally in the + executable or DSO is used. */ +#ifdef HAVE_DOT_HIDDEN +asm (".hidden\tatexit"); +#endif diff --git a/stdlib/cxa_atexit.c b/stdlib/cxa_atexit.c index e07d0eda35..f602b7a1af 100644 --- a/stdlib/cxa_atexit.c +++ b/stdlib/cxa_atexit.c @@ -16,6 +16,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <bits/libc-lock.h> #include <stdlib.h> #include "exit.h" @@ -36,3 +37,57 @@ __cxa_atexit (void (*func) (void *), void *arg, void *d) new->func.cxa.dso_handle = d; return 0; } + + +/* We change global data, so we need locking. */ +__libc_lock_define_initialized (static, lock) + + +static struct exit_function_list initial; +struct exit_function_list *__exit_funcs = &initial; + +struct exit_function * +__new_exitfn (void) +{ + struct exit_function_list *l; + size_t i = 0; + + __libc_lock_lock (lock); + + for (l = __exit_funcs; l != NULL; l = l->next) + { + for (i = 0; i < l->idx; ++i) + if (l->fns[i].flavor == ef_free) + break; + if (i < l->idx) + break; + + if (l->idx < sizeof (l->fns) / sizeof (l->fns[0])) + { + i = l->idx++; + break; + } + } + + if (l == NULL) + { + l = (struct exit_function_list *) + malloc (sizeof (struct exit_function_list)); + if (l != NULL) + { + l->next = __exit_funcs; + __exit_funcs = l; + + l->idx = 1; + i = 0; + } + } + + /* Mark entry as used, but we don't know the flavor now. */ + if (l != NULL) + l->fns[i].flavor = ef_us; + + __libc_lock_unlock (lock); + + return l == NULL ? NULL : &l->fns[i]; +} diff --git a/stdlib/old_atexit.c b/stdlib/old_atexit.c new file mode 100644 index 0000000000..45f330bec8 --- /dev/null +++ b/stdlib/old_atexit.c @@ -0,0 +1,8 @@ +#include <shlib-compat.h> + +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2_2) +# define atexit __dyn_atexit +# include "atexit.c" +# undef atexit +compat_symbol (libc, __dyn_atexit, atexit, GLIBC_2_0); +#endif |