From c877418f2e806a5d2a07c036bb4ac192a53ccdbf Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 1 Nov 2002 20:44:15 +0000 Subject: [PATCH] * include/libc-symbols.h (__libc_freeres_fn_section, libc_freeres_fn): New macros. * elf/dl-close.c (free_mem): Use libc_freeres_fn macro, remove text_set_element. * elf/dl-libc.c (free_mem): Likewise. * iconv/gconv_conf.c (free_mem): Likewise. * iconv/gconv_db.c (free_mem): Likewise. * iconv/gconv_dl.c (free_mem): Likewise. * iconv/gconv_cache.c (free_mem): Likewise. * intl/finddomain.c (free_mem): Likewise. * intl/dcigettext.c (free_mem): Likewise. * locale/setlocale.c (free_mem): Likewise. * misc/fstab.c (fstab_free): Likewise. * nss/nsswitch.c (free_mem): Likewise. * posix/regcomp.c (free_mem): Likewise. * resolv/gai_misc.c (free_res): Likewise. * stdlib/fmtmsg.c (free_mem): Likewise. * sunrpc/clnt_perr.c (free_mem): Likewise. * sysdeps/generic/setenv.c (free_mem): Likewise. * sysdeps/unix/sysv/linux/shm_open.c (freeit): Likewise. * sysdeps/pthread/aio_misc.c (free_res): Likewise. * time/tzset.c (free_mem): Likewise. * malloc/mtrace.c (release_libc_mem): Add __libc_freeres_fn_section. * locale/loadarchive.c (_nl_archive_subfreeres): Likewise. * malloc/set-freeres.c (__libc_freeres): Likewise. * login/getutent.c: Include stdlib.h instead of stddef.h. (buffer): Change into pointer to utmp, add libc_freeres_ptr. (__getutent): Allocate buffer the first time it is run. * login/getutid.c: Include stdlib.h instead of stddef.h. (buffer): Change into pointer to utmp, add libc_freeres_ptr. (__getutid): Allocate buffer the first time it is run. * login/getutline.c: Include stdlib.h instead of stddef.h. (buffer): Change into pointer to utmp, add libc_freeres_ptr. (__getutline): Allocate buffer the first time it is run. * malloc/mtrace.c (malloc_trace_buffer): Change into char *. (mtrace): Allocate malloc_trace_buffer. * resolv/nsap_addr.c (inet_nsap_ntoa): Decrease size of tmpbuf. * resolv/ns_print.c (ns_sprintrrf): Decrease size of t. * string/strerror.c: Include libintl.h and errno.h. (buf): New variable. (strerror): Only allocate buffer if actually needed (unknown error). * time/tzfile.c (transitions): Add libc_freeres_ptr. (freeres): Remove. 2002-10-25 Jakub Jelinek * include/libc-symbols.h (libc_freeres_ptr): New macro. * malloc/set-freeres.c (__libc_freeres_ptrs): Define using symbol_set_define. (__libc_freeres): Free all pointers in that section. * Makerules (build-shlib): Add $(LDSEDCMD-$(@F:lib%.so=%).so) to sed commands when creating .lds script. (LDSEDCMD-c.so): New variable. * inet/rcmd.c (ahostbuf): Change into char *. Add libc_freeres_ptr. (rcmd_af): Use strdup to allocate ahostbuf. * inet/rexec.c (ahostbuf): Change into char *. Add libc_freeres_ptr. (rexec_af): Use strdup to allocate ahostbuf. * stdio-common/reg-printf.c (printf_funcs): Remove. (__printf_arginfo_table): Change into printf_arginfo_function **. Add libc_freeres_ptr. (__register_printf_function): Allocate __printf_arginfo_table and __printf_function_table the first time it is called. * stdio-common/printf-parse.h (__printf_arginfo_table): Change into printf_arginfo_function **. (parse_one_spec): Add __builtin_expect. * grp/fgetgrent.c (buffer): Add libc_freeres_ptr. (free_mem): Remove. * inet/getnetgrent.c (buffer): Add libc_freeres_ptr. (free_mem): Remove. * intl/localealias.c (libc_freeres_ptr): Define if !_LIBC. (string_space, map): Add libc_freeres_ptr. (free_mem): Remove. * misc/efgcvt.c (FCVT_BUFPTR): Add libc_freeres_ptr. (free_mem): Remove. * misc/mntent.c (getmntent_buffer): Add libc_freeres_ptr. (free_mem): Remove. * crypt/md5-crypt.c (libc_freeres_ptr): Define if !_LIBC. (buffer): Add libc_freeres_ptr. (free_mem): Remove for _LIBC. * nss/getXXbyYY.c (buffer): Add libc_freeres_ptr. (free_mem): Remove. * nss/getXXent.c (buffer): Add libc_freeres_ptr. (free_mem): Remove. * pwd/fgetpwent.c (buffer): Add libc_freeres_ptr. (free_mem): Remove. * resolv/res_hconf.c (ifaddrs): Add libc_freeres_ptr. (free_mem): Remove. * shadow/fgetspent.c (buffer): Add libc_freeres_ptr. (free_mem): Remove. * sysdeps/posix/ttyname.c (getttyname_name): Add libc_freeres_ptr. (free_mem): Remove. * sysdeps/unix/sysv/linux/getsysstats.c (mount_proc): Add libc_freeres_ptr. (free_mem): Remove. * sysdeps/unix/sysv/linux/ttyname.c (getttyname_name, ttyname_buf): Add libc_freeres_ptr. (free_mem): Remove. 2002-10-30 Jakub Jelinek * malloc/obstack.c [_LIBC] (obstack_free): Change into strong_alias instead of duplicating the whole function in libc. --- ChangeLog | 106 ++++++++++++++++++++++++++ Makerules | 3 +- crypt/md5-crypt.c | 11 ++- elf/dl-close.c | 45 +++++++++-- elf/dl-libc.c | 4 +- grp/fgetgrent.c | 14 +--- iconv/gconv_cache.c | 5 +- iconv/gconv_conf.c | 5 +- iconv/gconv_db.c | 5 +- iconv/gconv_dl.c | 4 +- include/libc-symbols.h | 27 +++++-- inet/getnetgrent.c | 18 +---- inet/rcmd.c | 20 +++-- inet/rexec.c | 14 ++-- intl/dcigettext.c | 5 +- intl/finddomain.c | 5 +- intl/localealias.c | 21 ++--- locale/loadarchive.c | 2 +- locale/setlocale.c | 4 +- login/getutent.c | 15 +++- login/getutid.c | 15 ++-- login/getutline.c | 14 +++- malloc/mtrace.c | 11 ++- malloc/obstack.c | 5 ++ malloc/set-freeres.c | 10 ++- misc/efgcvt.c | 14 +--- misc/fstab.c | 6 +- misc/mntent.c | 16 +--- nss/getXXbyYY.c | 12 +-- nss/getXXent.c | 12 +-- nss/nsswitch.c | 5 +- posix/regcomp.c | 4 +- pwd/fgetpwent.c | 14 +--- resolv/gai_misc.c | 5 +- resolv/ns_print.c | 4 +- resolv/nsap_addr.c | 2 +- resolv/res_hconf.c | 13 +--- shadow/fgetspent.c | 14 +--- stdio-common/printf-parse.h | 4 +- stdio-common/reg-printf.c | 19 +++-- stdlib/fmtmsg.c | 4 +- string/strerror.c | 20 ++++- sunrpc/clnt_perr.c | 5 +- sysdeps/generic/setenv.c | 5 +- sysdeps/posix/ttyname.c | 12 +-- sysdeps/pthread/aio_misc.c | 7 +- sysdeps/unix/sysv/linux/getsysstats.c | 10 +-- sysdeps/unix/sysv/linux/shm_open.c | 10 +-- sysdeps/unix/sysv/linux/ttyname.c | 13 +--- time/tzfile.c | 13 +--- time/tzset.c | 4 +- 51 files changed, 337 insertions(+), 298 deletions(-) diff --git a/ChangeLog b/ChangeLog index 271e451301..8226c644e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,109 @@ +2002-10-30 Jakub Jelinek + + * include/libc-symbols.h (__libc_freeres_fn_section, libc_freeres_fn): + New macros. + * elf/dl-close.c (free_mem): Use libc_freeres_fn macro, remove + text_set_element. + * elf/dl-libc.c (free_mem): Likewise. + * iconv/gconv_conf.c (free_mem): Likewise. + * iconv/gconv_db.c (free_mem): Likewise. + * iconv/gconv_dl.c (free_mem): Likewise. + * iconv/gconv_cache.c (free_mem): Likewise. + * intl/finddomain.c (free_mem): Likewise. + * intl/dcigettext.c (free_mem): Likewise. + * locale/setlocale.c (free_mem): Likewise. + * misc/fstab.c (fstab_free): Likewise. + * nss/nsswitch.c (free_mem): Likewise. + * posix/regcomp.c (free_mem): Likewise. + * resolv/gai_misc.c (free_res): Likewise. + * stdlib/fmtmsg.c (free_mem): Likewise. + * sunrpc/clnt_perr.c (free_mem): Likewise. + * sysdeps/generic/setenv.c (free_mem): Likewise. + * sysdeps/unix/sysv/linux/shm_open.c (freeit): Likewise. + * sysdeps/pthread/aio_misc.c (free_res): Likewise. + * time/tzset.c (free_mem): Likewise. + * malloc/mtrace.c (release_libc_mem): Add __libc_freeres_fn_section. + * locale/loadarchive.c (_nl_archive_subfreeres): Likewise. + * malloc/set-freeres.c (__libc_freeres): Likewise. + + * login/getutent.c: Include stdlib.h instead of stddef.h. + (buffer): Change into pointer to utmp, add libc_freeres_ptr. + (__getutent): Allocate buffer the first time it is run. + * login/getutid.c: Include stdlib.h instead of stddef.h. + (buffer): Change into pointer to utmp, add libc_freeres_ptr. + (__getutid): Allocate buffer the first time it is run. + * login/getutline.c: Include stdlib.h instead of stddef.h. + (buffer): Change into pointer to utmp, add libc_freeres_ptr. + (__getutline): Allocate buffer the first time it is run. + * malloc/mtrace.c (malloc_trace_buffer): Change into char *. + (mtrace): Allocate malloc_trace_buffer. + * resolv/nsap_addr.c (inet_nsap_ntoa): Decrease size of tmpbuf. + * resolv/ns_print.c (ns_sprintrrf): Decrease size of t. + * string/strerror.c: Include libintl.h and errno.h. + (buf): New variable. + (strerror): Only allocate buffer if actually needed (unknown error). + * time/tzfile.c (transitions): Add libc_freeres_ptr. + (freeres): Remove. + +2002-10-25 Jakub Jelinek + + * include/libc-symbols.h (libc_freeres_ptr): New macro. + * malloc/set-freeres.c (__libc_freeres_ptrs): Define using + symbol_set_define. + (__libc_freeres): Free all pointers in that section. + * Makerules (build-shlib): Add $(LDSEDCMD-$(@F:lib%.so=%).so) to sed + commands when creating .lds script. + (LDSEDCMD-c.so): New variable. + * inet/rcmd.c (ahostbuf): Change into char *. Add libc_freeres_ptr. + (rcmd_af): Use strdup to allocate ahostbuf. + * inet/rexec.c (ahostbuf): Change into char *. Add libc_freeres_ptr. + (rexec_af): Use strdup to allocate ahostbuf. + * stdio-common/reg-printf.c (printf_funcs): Remove. + (__printf_arginfo_table): Change into printf_arginfo_function **. + Add libc_freeres_ptr. + (__register_printf_function): Allocate __printf_arginfo_table + and __printf_function_table the first time it is called. + * stdio-common/printf-parse.h (__printf_arginfo_table): Change into + printf_arginfo_function **. + (parse_one_spec): Add __builtin_expect. + * grp/fgetgrent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * inet/getnetgrent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * intl/localealias.c (libc_freeres_ptr): Define if !_LIBC. + (string_space, map): Add libc_freeres_ptr. + (free_mem): Remove. + * misc/efgcvt.c (FCVT_BUFPTR): Add libc_freeres_ptr. + (free_mem): Remove. + * misc/mntent.c (getmntent_buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * crypt/md5-crypt.c (libc_freeres_ptr): Define if !_LIBC. + (buffer): Add libc_freeres_ptr. + (free_mem): Remove for _LIBC. + * nss/getXXbyYY.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * nss/getXXent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * pwd/fgetpwent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * resolv/res_hconf.c (ifaddrs): Add libc_freeres_ptr. + (free_mem): Remove. + * shadow/fgetspent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * sysdeps/posix/ttyname.c (getttyname_name): Add libc_freeres_ptr. + (free_mem): Remove. + * sysdeps/unix/sysv/linux/getsysstats.c (mount_proc): Add + libc_freeres_ptr. + (free_mem): Remove. + * sysdeps/unix/sysv/linux/ttyname.c (getttyname_name, ttyname_buf): Add + libc_freeres_ptr. + (free_mem): Remove. + +2002-10-30 Jakub Jelinek + + * malloc/obstack.c [_LIBC] (obstack_free): Change into strong_alias + instead of duplicating the whole function in libc. + 2002-10-31 Roland McGrath * sysdeps/i386/bits/byteswap.h [__GNUC__ < 2] (__bswap_32): diff --git a/Makerules b/Makerules index d66feb5b75..071352db51 100644 --- a/Makerules +++ b/Makerules @@ -447,7 +447,7 @@ $(build-shlib-helper) \ $(LDLIBS-$(@F:lib%.so=%).so) 2>&1 | \ sed -e '/^=========/,/^=========/!d;/^=========/d' \ -e 's/^.*\.hash[ ]*:.*$$/ .note.ABI-tag : { *(.note.ABI-tag) } &/' \ - > $@.lds + $(LDSEDCMD-$(@F:lib%.so=%).so) > $@.lds rm -f $@.new $(build-shlib-helper) -o $@ -T $@.lds \ $(csu-objpfx)abi-note.o $(build-shlib-objlist) @@ -548,6 +548,7 @@ ifeq ($(elf),yes) $(common-objpfx)libc_pic.os: $(common-objpfx)libc_pic.a $(LINK.o) -nostdlib -nostartfiles -r -o $@ \ $(LDFLAGS-c_pic.os) -Wl,-d -Wl,--whole-archive $^ +LDSEDCMD-c.so = -e 's/^.*\*(\.dynbss).*$$/& __start___libc_freeres_ptrs = .; *(__libc_freeres_ptrs) __stop___libc_freeres_ptrs = .;/' # Use our own special initializer and finalizer files for libc.so. $(common-objpfx)libc.so: $(elfobjdir)/soinit.os \ $(common-objpfx)libc_pic.os \ diff --git a/crypt/md5-crypt.c b/crypt/md5-crypt.c index 0f7f3ecce3..8cd23e3fa6 100644 --- a/crypt/md5-crypt.c +++ b/crypt/md5-crypt.c @@ -1,5 +1,5 @@ /* One way encryption based on MD5 sum. - Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1996,1997,1999,2000,2001,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1996. @@ -233,8 +233,10 @@ __md5_crypt_r (key, salt, buffer, buflen) return buffer; } - -static char *buffer; +#ifndef _LIBC +# define libc_freeres_ptr(decl) decl +#endif +libc_freeres_ptr (static char *buffer); char * __md5_crypt (const char *key, const char *salt) @@ -261,10 +263,11 @@ __md5_crypt (const char *key, const char *salt) return __md5_crypt_r (key, salt, buffer, buflen); } - +#ifndef _LIBC static void __attribute__ ((__destructor__)) free_mem (void) { free (buffer); } +#endif diff --git a/elf/dl-close.c b/elf/dl-close.c index 094db533dd..632f8ba9fc 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -247,6 +247,11 @@ _dl_close (void *_map) _r_debug.r_state = RT_DELETE; _dl_debug_state (); +#ifdef USE_TLS + size_t tls_free_start, tls_free_end; + tls_free_start = tls_free_end = GL(dl_tls_static_used); +#endif + /* Check each element of the search list to see if all references to it are gone. */ for (i = 0; list[i] != NULL; ++i) @@ -286,6 +291,30 @@ _dl_close (void *_map) imap->l_init_called)) /* All dynamically loaded modules with TLS are unloaded. */ GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem); + + if (imap->l_tls_offset != 0) + { + /* Collect a contiguous chunk built from the objects in + this search list, going in either direction. When the + whole chunk is at the end of the used area then we can + reclaim it. */ + if (imap->l_tls_offset == tls_free_end) + /* Extend the contiguous chunk being reclaimed. */ + tls_free_end += imap->l_tls_blocksize; + else if (imap->l_tls_offset + imap->l_tls_blocksize + == tls_free_start) + /* Extend the chunk backwards. */ + tls_free_start = imap->l_tls_offset; + else + { + /* This isn't contiguous with the last chunk freed. + One of them will be leaked. */ + if (tls_free_end == GL(dl_tls_static_used)) + GL(dl_tls_static_used) = tls_free_start; + tls_free_start = imap->l_tls_offset; + tls_free_end = tls_free_start + imap->l_tls_blocksize; + } + } } #endif @@ -363,11 +392,15 @@ _dl_close (void *_map) } #ifdef USE_TLS - /* If we removed any object which uses TLS bumnp the generation - counter. */ + /* If we removed any object which uses TLS bump the generation counter. */ if (any_tls) - if (__builtin_expect (++GL(dl_tls_generation) == 0, 0)) - __libc_fatal (_("TLS generation counter wrapped! Please send report with the 'glibcbug' script.")); + { + if (__builtin_expect (++GL(dl_tls_generation) == 0, 0)) + __libc_fatal (_("TLS generation counter wrapped! Please send report with the 'glibcbug' script.")); + + if (tls_free_end == GL(dl_tls_static_used)) + GL(dl_tls_static_used) = tls_free_start; + } #endif /* Notify the debugger those objects are finalized and gone. */ @@ -424,8 +457,7 @@ free_slotinfo (struct dtv_slotinfo_list *elemp) #endif -static void -free_mem (void) +libc_freeres_fn (free_mem) { if (__builtin_expect (GL(dl_global_scope_alloc), 0) != 0 && GL(dl_main_searchlist)->r_nlist == GL(dl_initial_searchlist).r_nlist) @@ -453,4 +485,3 @@ free_mem (void) GL(dl_tls_dtv_slotinfo_list)->next = NULL; #endif } -text_set_element (__libc_subfreeres, free_mem); diff --git a/elf/dl-libc.c b/elf/dl-libc.c index 938b5d707d..d69e49f359 100644 --- a/elf/dl-libc.c +++ b/elf/dl-libc.c @@ -123,8 +123,7 @@ __libc_dlclose (void *__map) } -static void -free_mem (void) +libc_freeres_fn (free_mem) { struct link_map *l; struct r_search_path_elem *d; @@ -154,4 +153,3 @@ free_mem (void) } } } -text_set_element (__libc_subfreeres, free_mem); diff --git a/grp/fgetgrent.c b/grp/fgetgrent.c index a004aabdf1..684018c429 100644 --- a/grp/fgetgrent.c +++ b/grp/fgetgrent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1996, 1997, 1999, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1991,1996,1997,1999,2000,2002 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 @@ -26,7 +26,7 @@ /* We need to protect the dynamic buffer handling. */ __libc_lock_define_initialized (static, lock); -static char *buffer; +libc_freeres_ptr (static char *buffer); /* Read one entry from the given stream. */ struct group * @@ -83,13 +83,3 @@ fgetgrent (FILE *stream) return result; } - - -/* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) -{ - free (buffer); -} - -text_set_element (__libc_subfreeres, free_mem); diff --git a/iconv/gconv_cache.c b/iconv/gconv_cache.c index f7dca0285a..8f92cbaf67 100644 --- a/iconv/gconv_cache.c +++ b/iconv/gconv_cache.c @@ -445,8 +445,7 @@ __gconv_release_cache (struct __gconv_step *steps, size_t nsteps) /* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) +libc_freeres_fn (free_mem) { if (cache_malloced) free (gconv_cache); @@ -455,5 +454,3 @@ free_mem (void) __munmap (gconv_cache, cache_size); #endif } - -text_set_element (__libc_subfreeres, free_mem); diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c index 8c2f4b014e..cd5055c303 100644 --- a/iconv/gconv_conf.c +++ b/iconv/gconv_conf.c @@ -597,11 +597,8 @@ __gconv_read_conf (void) /* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) +libc_freeres_fn (free_mem) { if (__gconv_path_elem != NULL && __gconv_path_elem != &empty_path_elem) free ((void *) __gconv_path_elem); } - -text_set_element (__libc_subfreeres, free_mem); diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c index 25b06d07e4..70c33df16d 100644 --- a/iconv/gconv_db.c +++ b/iconv/gconv_db.c @@ -778,8 +778,7 @@ free_modules_db (struct gconv_module *node) /* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) +libc_freeres_fn (free_mem) { if (__gconv_alias_db != NULL) __tdestroy (__gconv_alias_db, free); @@ -790,5 +789,3 @@ free_mem (void) if (known_derivations != NULL) __tdestroy (known_derivations, free_derivation); } - -text_set_element (__libc_subfreeres, free_mem); diff --git a/iconv/gconv_dl.c b/iconv/gconv_dl.c index 990338f070..ff90a54b41 100644 --- a/iconv/gconv_dl.c +++ b/iconv/gconv_dl.c @@ -203,12 +203,10 @@ do_release_all (void *nodep) free (obj); } -static void __attribute__ ((unused)) -free_mem (void) +libc_freeres_fn (free_mem) { __tdestroy (loaded, do_release_all); } -text_set_element (__libc_subfreeres, free_mem); #ifdef DEBUG diff --git a/include/libc-symbols.h b/include/libc-symbols.h index 69fe729d73..f47a849a75 100644 --- a/include/libc-symbols.h +++ b/include/libc-symbols.h @@ -253,17 +253,20 @@ /* Tacking on "\n\t#" to the section name makes gcc put it's bogus section attributes on what looks like a comment to the assembler. */ # ifdef HAVE_SECTION_QUOTES -# define link_warning(symbol, msg) \ - __make_section_unallocated (".gnu.warning." #symbol) \ - static const char __evoke_link_warning_##symbol[] \ - __attribute__ ((unused, section (".gnu.warning." #symbol "\"\n\t#\""))) \ - = msg; +# define __sec_comment "\"\n\t#\"" # else -# define link_warning(symbol, msg) \ +# define __sec_comment "\n\t#" +# endif +# define link_warning(symbol, msg) \ __make_section_unallocated (".gnu.warning." #symbol) \ static const char __evoke_link_warning_##symbol[] \ - __attribute__ ((unused, section (".gnu.warning." #symbol "\n\t#"))) = msg; -# endif + __attribute__ ((unused, section (".gnu.warning." #symbol __sec_comment))) \ + = msg; +# define libc_freeres_ptr(decl) \ + __make_section_unallocated ("__libc_freeres_ptrs, \"aw\", @nobits") \ + decl __attribute__ ((section ("__libc_freeres_ptrs" __sec_comment))) +# define __libc_freeres_fn_section \ + __attribute__ ((section ("__libc_freeres_fn"))) # else /* Not ELF: a.out */ # ifdef HAVE_XCOFF /* XCOFF does not support .stabs. @@ -276,11 +279,19 @@ asm (".stabs \"" msg "\",30,0,0,0\n\t" \ ".stabs \"" __SYMBOL_PREFIX #symbol "\",1,0,0,0\n"); # endif /* XCOFF */ +# define libc_freeres_ptr(decl) decl +# define __libc_freeres_fn_section # endif #else /* We will never be heard; they will all die horribly. */ # define link_warning(symbol, msg) +# define libc_freeres_ptr(decl) decl +# define __libc_freeres_fn_section #endif +#define libc_freeres_fn(name) \ + static void name (void) __attribute_used__ __libc_freeres_fn_section; \ + text_set_element (__libc_subfreeres, name); \ + static void name (void) /* A canned warning for sysdeps/stub functions. */ #define stub_warning(name) \ diff --git a/inet/getnetgrent.c b/inet/getnetgrent.c index d464c10cde..07634daef2 100644 --- a/inet/getnetgrent.c +++ b/inet/getnetgrent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 2000, 2002 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 @@ -21,8 +21,8 @@ #include #include -/* Statis buffer for return value. We allocate it when needed. */ -static char *buffer; +/* Static buffer for return value. We allocate it when needed. */ +libc_freeres_ptr (static char *buffer); /* All three strings should fit in a block of 1kB size. */ #define BUFSIZE 1024 @@ -48,15 +48,3 @@ getnetgrent (char **hostp, char **userp, char **domainp) return __getnetgrent_r (hostp, userp, domainp, buffer, BUFSIZE); } - - -/* Make sure the memory is freed if the programs ends while in - memory-debugging mode and something actually was allocated. */ -static void -__attribute__ ((unused)) -free_mem (void) -{ - free (buffer); -} - -text_set_element (__libc_subfreeres, free_mem); diff --git a/inet/rcmd.c b/inet/rcmd.c index 08d9337431..eed5ed389e 100644 --- a/inet/rcmd.c +++ b/inet/rcmd.c @@ -101,7 +101,7 @@ int iruserok (u_int32_t raddr, int superuser, const char *ruser, libc_hidden_proto (iruserok_af) -static char ahostbuf[NI_MAXHOST]; +libc_freeres_ptr(static char *ahostbuf); int rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af) @@ -153,11 +153,21 @@ rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af) pfd[1].events = POLLIN; if (res->ai_canonname){ - strncpy(ahostbuf, res->ai_canonname, sizeof(ahostbuf)); - ahostbuf[sizeof(ahostbuf)-1] = '\0'; + free (ahostbuf); + ahostbuf = strdup (res->ai_canonname); + if (ahostbuf == NULL) { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf(stderr, L"%s", + _("rcmd: Cannot allocate memory\n")); + else +#endif + fputs(_("rcmd: Cannot allocate memory\n"), + stderr); + return (-1); + } *ahost = ahostbuf; - } - else + } else *ahost = NULL; ai = res; refused = 0; diff --git a/inet/rexec.c b/inet/rexec.c index 8f6190a834..c6b432a6f8 100644 --- a/inet/rexec.c +++ b/inet/rexec.c @@ -45,7 +45,7 @@ static char sccsid[] = "@(#)rexec.c 8.1 (Berkeley) 6/4/93"; #include int rexecoptions; -static char ahostbuf[NI_MAXHOST]; +libc_freeres_ptr (static char *ahostbuf); int rexec_af(ahost, rport, name, pass, cmd, fd2p, af) @@ -79,13 +79,15 @@ rexec_af(ahost, rport, name, pass, cmd, fd2p, af) } if (res0->ai_canonname){ - strncpy(ahostbuf, res0->ai_canonname, sizeof(ahostbuf)); - ahostbuf[sizeof(ahostbuf)-1] = '\0'; + free (ahostbuf); + ahostbuf = strdup (res0->ai_canonname); + if (ahostbuf == NULL) { + perror ("rexec: strdup"); + return (-1); + } *ahost = ahostbuf; - } - else{ + } else *ahost = NULL; - } ruserpass(res0->ai_canonname, &name, &pass); retry: s = __socket(res0->ai_family, res0->ai_socktype, 0); diff --git a/intl/dcigettext.c b/intl/dcigettext.c index 42d39a1771..80c71efbc4 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -1124,8 +1124,7 @@ mempcpy (dest, src, n) #ifdef _LIBC /* If we want to free all resources we have to do some work at program's end. */ -static void __attribute__ ((unused)) -free_mem (void) +libc_freeres_fn (free_mem) { void *old; @@ -1155,6 +1154,4 @@ free_mem (void) free (old); } } - -text_set_element (__libc_subfreeres, free_mem); #endif diff --git a/intl/finddomain.c b/intl/finddomain.c index e0e11f0b7e..1031e4d5b1 100644 --- a/intl/finddomain.c +++ b/intl/finddomain.c @@ -168,8 +168,7 @@ _nl_find_domain (dirname, locale, domainname, domainbinding) #ifdef _LIBC -static void __attribute__ ((unused)) -free_mem (void) +libc_freeres_fn (free_mem) { struct loaded_l10nfile *runp = _nl_loaded_domains; @@ -183,6 +182,4 @@ free_mem (void) free (here); } } - -text_set_element (__libc_subfreeres, free_mem); #endif diff --git a/intl/localealias.c b/intl/localealias.c index 0afe98134b..f5d4e57dc3 100644 --- a/intl/localealias.c +++ b/intl/localealias.c @@ -117,10 +117,14 @@ struct alias_map }; -static char *string_space; +#ifndef _LIBC +# define libc_freeres_ptr(decl) decl +#endif + +libc_freeres_ptr (static char *string_space); static size_t string_space_act; static size_t string_space_max; -static struct alias_map *map; +libc_freeres_ptr (static struct alias_map *map); static size_t nmap; static size_t maxmap; @@ -371,19 +375,6 @@ extend_alias_table () } -#ifdef _LIBC -static void __attribute__ ((unused)) -free_mem (void) -{ - if (string_space != NULL) - free (string_space); - if (map != NULL) - free (map); -} -text_set_element (__libc_subfreeres, free_mem); -#endif - - static int alias_compare (map1, map2) const struct alias_map *map1; diff --git a/locale/loadarchive.c b/locale/loadarchive.c index aa19dbd5f8..dbb4d7afd5 100644 --- a/locale/loadarchive.c +++ b/locale/loadarchive.c @@ -493,7 +493,7 @@ _nl_load_locale_from_archive (int category, const char **namep) return lia->data[category]; } -void +void __libc_freeres_fn_section _nl_archive_subfreeres (void) { struct locale_in_archive *lia; diff --git a/locale/setlocale.c b/locale/setlocale.c index 56a875e378..50c752826c 100644 --- a/locale/setlocale.c +++ b/locale/setlocale.c @@ -463,8 +463,7 @@ free_category (int category, } } -static void __attribute__ ((unused)) -free_mem (void) +libc_freeres_fn (free_mem) { #ifdef NL_CURRENT_INDIRECT /* We don't use the loop because we want to have individual weak @@ -494,4 +493,3 @@ free_mem (void) not called _nl_unload_locale on them above. */ _nl_archive_subfreeres (); } -text_set_element (__libc_subfreeres, free_mem); diff --git a/login/getutent.c b/login/getutent.c index 735cd9334a..561f17f4d9 100644 --- a/login/getutent.c +++ b/login/getutent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1996. @@ -17,12 +17,12 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include /* For NULL. */ +#include #include /* Local buffer to store the result. */ -static struct utmp buffer; +libc_freeres_ptr (static struct utmp *buffer); struct utmp * @@ -30,7 +30,14 @@ __getutent (void) { struct utmp *result; - if (__getutent_r (&buffer, &result) < 0) + if (buffer == NULL) + { + buffer = (struct utmp *) malloc (sizeof (struct utmp)); + if (buffer == NULL) + return NULL; + } + + if (__getutent_r (buffer, &result) < 0) return NULL; return result; diff --git a/login/getutid.c b/login/getutid.c index beeedb3749..3d022e405d 100644 --- a/login/getutid.c +++ b/login/getutid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1996. @@ -17,20 +17,25 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include /* For NULL. */ +#include #include /* Local buffer to store the result. */ -static struct utmp buffer; - +libc_freeres_ptr (static struct utmp *buffer); struct utmp * __getutid (const struct utmp *id) { struct utmp *result; - if (__getutid_r (id, &buffer, &result) < 0) + if (buffer == NULL) + { + buffer = (struct utmp *) malloc (sizeof (struct utmp)); + if (buffer == NULL) + return NULL; + } + if (__getutid_r (id, buffer, &result) < 0) return NULL; return result; diff --git a/login/getutline.c b/login/getutline.c index d1704ec31c..7618064d00 100644 --- a/login/getutline.c +++ b/login/getutline.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1996. @@ -17,12 +17,12 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include /* For NULL. */ +#include #include /* Local buffer to store the result. */ -static struct utmp buffer; +libc_freeres_ptr (static struct utmp *buffer); struct utmp * @@ -30,7 +30,13 @@ __getutline (const struct utmp *line) { struct utmp *result; - if (__getutline_r (line, &buffer, &result) < 0) + if (buffer == NULL) + { + buffer = (struct utmp *) malloc (sizeof (struct utmp)); + if (buffer == NULL) + return NULL; + } + if (__getutline_r (line, buffer, &result) < 0) return NULL; return result; diff --git a/malloc/mtrace.c b/malloc/mtrace.c index d9960bdaf3..c369ab577c 100644 --- a/malloc/mtrace.c +++ b/malloc/mtrace.c @@ -50,7 +50,7 @@ static FILE *mallstream; static const char mallenv[]= "MALLOC_TRACE"; -static char malloc_trace_buffer[TRACE_BUFFER_SIZE]; +static char *malloc_trace_buffer; __libc_lock_define_initialized (static, lock); @@ -237,7 +237,7 @@ tr_reallochook (ptr, size, caller) /* This function gets called to make sure all memory the library allocates get freed and so does not irritate the user when studying the mtrace output. */ -static void +static void __libc_freeres_fn_section release_libc_mem (void) { /* Only call the free function if we still are running in mtrace mode. */ @@ -274,6 +274,10 @@ mtrace () #endif if (mallfile != NULL || mallwatch != NULL) { + char *mtb = malloc (TRACE_BUFFER_SIZE); + if (mtb == NULL) + return; + mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w"); if (mallstream != NULL) { @@ -285,6 +289,7 @@ mtrace () __fcntl (fileno (mallstream), F_SETFD, flags); } /* Be sure it doesn't malloc its buffer! */ + malloc_trace_buffer = mtb; setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE); fprintf (mallstream, "= Start\n"); tr_old_free_hook = __free_hook; @@ -303,6 +308,8 @@ mtrace () } #endif } + else + free (mtb); } } diff --git a/malloc/obstack.c b/malloc/obstack.c index 5c5e8b09d8..2f5ff628f7 100644 --- a/malloc/obstack.c +++ b/malloc/obstack.c @@ -418,6 +418,10 @@ _obstack_free (h, obj) /* This function is used from ANSI code. */ +#ifdef _LIBC +strong_alias (_obstack_free, obstack_free) +#else + void obstack_free (h, obj) struct obstack *h; @@ -449,6 +453,7 @@ obstack_free (h, obj) /* obj is not in any of the chunks! */ abort (); } +#endif int _obstack_memory_used (h) diff --git a/malloc/set-freeres.c b/malloc/set-freeres.c index dfbd7b5908..67488a8214 100644 --- a/malloc/set-freeres.c +++ b/malloc/set-freeres.c @@ -27,7 +27,9 @@ DEFINE_HOOK (__libc_subfreeres, (void)); -void +symbol_set_define (__libc_freeres_ptrs); + +void __libc_freeres_fn_section __libc_freeres (void) { /* This function might be called from different places. So better @@ -36,11 +38,17 @@ __libc_freeres (void) if (compare_and_swap (&already_called, 0, 1)) { + void * const *p; + #ifdef USE_IN_LIBIO _IO_cleanup (); #endif RUN_HOOK (__libc_subfreeres, ()); + + for (p = symbol_set_first_element (__libc_freeres_ptrs); + ! symbol_set_end_p (__libc_freeres_ptrs, p); ++p) + free (*p); } } libc_hidden_def (__libc_freeres) diff --git a/misc/efgcvt.c b/misc/efgcvt.c index bc4bf91d02..915d00dfd5 100644 --- a/misc/efgcvt.c +++ b/misc/efgcvt.c @@ -1,5 +1,5 @@ /* Compatibility functions for floating point formatting. - Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1999, 2002 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 @@ -57,7 +57,7 @@ static char FCVT_BUFFER[MAXDIG]; static char ECVT_BUFFER[MAXDIG]; -static char *FCVT_BUFPTR; +libc_freeres_ptr (static char *FCVT_BUFPTR); char * APPEND (FUNC_PREFIX, fcvt) (value, ndigit, decpt, sign) @@ -102,13 +102,3 @@ APPEND (FUNC_PREFIX, gcvt) (value, ndigit, buf) sprintf (buf, "%.*" FLOAT_FMT_FLAG "g", MIN (ndigit, NDIGIT_MAX), value); return buf; } - -/* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) -{ - if (FCVT_BUFPTR != NULL) - free (FCVT_BUFPTR); -} - -text_set_element (__libc_subfreeres, free_mem); diff --git a/misc/fstab.c b/misc/fstab.c index 754ea1343a..b434203a86 100644 --- a/misc/fstab.c +++ b/misc/fstab.c @@ -180,9 +180,7 @@ fstab_convert (struct fstab_state *state) /* Make sure the memory is freed if the programs ends while in memory-debugging mode and something actually was allocated. */ -static void -__attribute__ ((unused)) -fstab_free (void) +libc_freeres_fn (fstab_free) { char *buffer; @@ -190,5 +188,3 @@ fstab_free (void) if (buffer != NULL) free ((void *) buffer); } - -text_set_element (__libc_subfreeres, fstab_free); diff --git a/misc/mntent.c b/misc/mntent.c index d7cff3c302..6e9795a1ea 100644 --- a/misc/mntent.c +++ b/misc/mntent.c @@ -1,5 +1,5 @@ /* Utilities for reading/writing fstab, mtab, etc. - Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 2000, 2002 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 @@ -24,7 +24,7 @@ /* We don't want to allocate the static buffer all the time since it is not always used (in fact, rather infrequently). Accept the extra cost of a `malloc'. */ -static char *getmntent_buffer; +libc_freeres_ptr (static char *getmntent_buffer); /* This is the size of the buffer. This is really big. */ #define BUFFER_SIZE 4096 @@ -52,15 +52,3 @@ getmntent (FILE *stream) return __getmntent_r (stream, &m, getmntent_buffer, BUFFER_SIZE); } - - -/* Make sure the memory is freed if the programs ends while in - memory-debugging mode and something actually was allocated. */ -static void -__attribute__ ((unused)) -free_mem (void) -{ - free (getmntent_buffer); -} - -text_set_element (__libc_subfreeres, free_mem); diff --git a/nss/getXXbyYY.c b/nss/getXXbyYY.c index ee6f640002..a9f1cfd5c8 100644 --- a/nss/getXXbyYY.c +++ b/nss/getXXbyYY.c @@ -86,7 +86,7 @@ extern int INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, __libc_lock_define_initialized (static, lock); /* This points to the static buffer used. */ -static char *buffer; +libc_freeres_ptr (static char *buffer); LOOKUP_TYPE * @@ -162,13 +162,3 @@ done: return result; } - - -/* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) -{ - free (buffer); -} - -text_set_element (__libc_subfreeres, free_mem); diff --git a/nss/getXXent.c b/nss/getXXent.c index d4a29ce46a..ebe6fff5f0 100644 --- a/nss/getXXent.c +++ b/nss/getXXent.c @@ -63,7 +63,7 @@ extern int INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *resbuf, char *buffer, __libc_lock_define_initialized (static, lock); /* This points to the static buffer used. */ -static char *buffer; +libc_freeres_ptr (static char *buffer); LOOKUP_TYPE * @@ -87,13 +87,3 @@ GETFUNC_NAME (void) __set_errno (save); return result; } - - -/* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) -{ - free (buffer); -} - -text_set_element (__libc_subfreeres, free_mem); diff --git a/nss/nsswitch.c b/nss/nsswitch.c index ca411b2cdc..1b3bb23e0b 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -697,8 +697,7 @@ nss_new_service (name_database *database, const char *name) /* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) +libc_freeres_fn (free_mem) { name_database *top = service_table; name_database_entry *entry; @@ -745,5 +744,3 @@ free_mem (void) free (top); } - -text_set_element (__libc_subfreeres, free_mem); diff --git a/posix/regcomp.c b/posix/regcomp.c index 9bb06aa7bf..14147804f4 100644 --- a/posix/regcomp.c +++ b/posix/regcomp.c @@ -696,12 +696,10 @@ re_comp (s) } #ifdef _LIBC -static void __attribute__ ((unused)) -free_mem (void) +libc_freeres_fn (free_mem) { __regfree (&re_comp_buf); } -text_set_element (__libc_subfreeres, free_mem); #endif #endif /* _REGEX_RE_COMP */ diff --git a/pwd/fgetpwent.c b/pwd/fgetpwent.c index 89f7996e3c..ad9ce63117 100644 --- a/pwd/fgetpwent.c +++ b/pwd/fgetpwent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1996, 1997, 1999, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1991,1996,1997,1999,2000,2002 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 @@ -26,7 +26,7 @@ /* We need to protect the dynamic buffer handling. */ __libc_lock_define_initialized (static, lock); -static char *buffer; +libc_freeres_ptr (static char *buffer); /* Read one entry from the given stream. */ struct passwd * @@ -83,13 +83,3 @@ fgetpwent (FILE *stream) return result; } - - -/* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) -{ - free (buffer); -} - -text_set_element (__libc_subfreeres, free_mem); diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c index b89abf984a..b3334f38ef 100644 --- a/resolv/gai_misc.c +++ b/resolv/gai_misc.c @@ -410,9 +410,7 @@ handle_requests (void *arg) /* Free allocated resources. */ -static void -__attribute__ ((unused)) -free_res (void) +libc_freeres_fn (free_res) { size_t row; @@ -421,4 +419,3 @@ free_res (void) free (pool); } -text_set_element (__libc_subfreeres, free_res); diff --git a/resolv/ns_print.c b/resolv/ns_print.c index 7a2ef70efc..12b2e67ea6 100644 --- a/resolv/ns_print.c +++ b/resolv/ns_print.c @@ -309,7 +309,9 @@ ns_sprintrrf(const u_char *msg, size_t msglen, break; case ns_t_nsap: { - char t[255*3]; + /* 2*255 for hex digits, 128 for '.' and '\0', 2 for + 0x if inet_nsap_ntoa starts using it. */ + char t[255*2 + 128 + 2]; (void) inet_nsap_ntoa(rdlen, rdata, t); T(addstr(t, strlen(t), &buf, &buflen)); diff --git a/resolv/nsap_addr.c b/resolv/nsap_addr.c index b3f2f77caf..7041e5282e 100644 --- a/resolv/nsap_addr.c +++ b/resolv/nsap_addr.c @@ -70,7 +70,7 @@ char * inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) { int nib; int i; - static char tmpbuf[255*3]; + static char tmpbuf[255*2 + 128]; char *start; if (ascii) diff --git a/resolv/res_hconf.c b/resolv/res_hconf.c index 132dda7599..40afeb0b94 100644 --- a/resolv/res_hconf.c +++ b/resolv/res_hconf.c @@ -489,6 +489,7 @@ _res_hconf_init (void) /* List of known interfaces. */ +libc_freeres_ptr ( static struct netaddr { int addrtype; @@ -500,7 +501,7 @@ static struct netaddr u_int32_t mask; } ipv4; } u; -} *ifaddrs; +} *ifaddrs); /* We need to protect the dynamic buffer handling. */ __libc_lock_define_initialized (static, lock); @@ -657,13 +658,3 @@ _res_hconf_trim_domains (struct hostent *hp) for (i = 0; hp->h_aliases[i]; ++i) _res_hconf_trim_domain (hp->h_aliases[i]); } - - -/* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) -{ - free (ifaddrs); -} - -text_set_element (__libc_subfreeres, free_mem); diff --git a/shadow/fgetspent.c b/shadow/fgetspent.c index 2b24bd8534..63f16a10db 100644 --- a/shadow/fgetspent.c +++ b/shadow/fgetspent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1999, 2000, 2002 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 @@ -29,7 +29,7 @@ /* We need to protect the dynamic buffer handling. */ __libc_lock_define_initialized (static, lock); -static char *buffer; +libc_freeres_ptr (static char *buffer); /* Read one shadow entry from the given stream. */ struct spwd * @@ -86,13 +86,3 @@ fgetspent (FILE *stream) return result; } - - -/* Free all resources if necessary. */ -static void __attribute__ ((unused)) -free_mem (void) -{ - free (buffer); -} - -text_set_element (__libc_subfreeres, free_mem); diff --git a/stdio-common/printf-parse.h b/stdio-common/printf-parse.h index 78811701bb..eff2816607 100644 --- a/stdio-common/printf-parse.h +++ b/stdio-common/printf-parse.h @@ -117,7 +117,7 @@ find_spec (const UCHAR_T *format, mbstate_t *ps) /* These are defined in reg-printf.c. */ -extern printf_arginfo_function *__printf_arginfo_table[] attribute_hidden; +extern printf_arginfo_function **__printf_arginfo_table attribute_hidden; extern printf_function **__printf_function_table attribute_hidden; @@ -354,7 +354,7 @@ parse_one_spec (const UCHAR_T *format, size_t posn, struct printf_spec *spec, /* Get the format specification. */ spec->info.spec = (wchar_t) *format++; - if (__printf_function_table != NULL + if (__builtin_expect (__printf_function_table != NULL, 0) && spec->info.spec <= UCHAR_MAX && __printf_arginfo_table[spec->info.spec] != NULL) /* We don't try to get the types for all arguments if the format diff --git a/stdio-common/reg-printf.c b/stdio-common/reg-printf.c index fe49633932..c42040ec3a 100644 --- a/stdio-common/reg-printf.c +++ b/stdio-common/reg-printf.c @@ -21,10 +21,8 @@ #include /* Array of functions indexed by format character. */ -static printf_function *printf_funcs[UCHAR_MAX + 1]; -printf_arginfo_function *__printf_arginfo_table[UCHAR_MAX + 1] - attribute_hidden; - +libc_freeres_ptr (printf_arginfo_function **__printf_arginfo_table) + attribute_hidden; printf_function **__printf_function_table attribute_hidden; int __register_printf_function __P ((int, printf_function, @@ -43,9 +41,18 @@ __register_printf_function (spec, converter, arginfo) return -1; } - __printf_function_table = printf_funcs; + if (__printf_function_table == NULL) + { + __printf_arginfo_table = (printf_arginfo_function **) + malloc ((UCHAR_MAX + 1) * sizeof (void *) * 2); + if (__printf_arginfo_table == NULL) + return -1; + __printf_function_table = (printf_function **) + (__printf_arginfo_table + UCHAR_MAX + 1); + } + + __printf_function_table[spec] = converter; __printf_arginfo_table[spec] = arginfo; - printf_funcs[spec] = converter; return 0; } diff --git a/stdlib/fmtmsg.c b/stdlib/fmtmsg.c index 660df1fdcb..37c641c7ef 100644 --- a/stdlib/fmtmsg.c +++ b/stdlib/fmtmsg.c @@ -390,8 +390,7 @@ addseverity (int severity, const char *string) } -static void __attribute__ ((unused)) -free_mem (void) +libc_freeres_fn (free_mem) { struct severity_info *runp = severity_list; @@ -407,4 +406,3 @@ free_mem (void) else runp = runp->next; } -text_set_element (__libc_subfreeres, free_mem); diff --git a/string/strerror.c b/string/strerror.c index 8a54a38ee0..5d829d0bf0 100644 --- a/string/strerror.c +++ b/string/strerror.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 93, 94, 95, 96, 98 Free Software Foundation, Inc. +/* Copyright (C) 1991, 93, 94, 95, 96, 98, 2002 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,16 +16,30 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include #include #include +#include /* Return a string describing the errno code in ERRNUM. The storage is good only until the next call to strerror. Writing to the storage causes undefined behavior. */ +libc_freeres_ptr (static char *buf); + char * strerror (errnum) int errnum; { - static char buf[1024]; - return __strerror_r (errnum, buf, sizeof buf); + char *ret = __strerror_r (errnum, NULL, 0); + int saved_errno; + + if (__builtin_expect (ret != NULL, 1)) + return ret; + saved_errno = errno; + if (buf == NULL) + buf = malloc (1024); + __set_errno (saved_errno); + if (buf == NULL) + return _("Unknown error"); + return __strerror_r (errnum, buf, 1024); } diff --git a/sunrpc/clnt_perr.c b/sunrpc/clnt_perr.c index ad96e4a0fe..4b34289a88 100644 --- a/sunrpc/clnt_perr.c +++ b/sunrpc/clnt_perr.c @@ -413,9 +413,8 @@ auth_errmsg (enum auth_stat stat) } -static void __attribute__ ((unused)) -free_mem (void) +libc_freeres_fn (free_mem) { + /* Not libc_freeres_ptr, since buf is a macro. */ free (buf); } -text_set_element (__libc_subfreeres, free_mem); diff --git a/sysdeps/generic/setenv.c b/sysdeps/generic/setenv.c index e5799e529d..e7fd49228c 100644 --- a/sysdeps/generic/setenv.c +++ b/sysdeps/generic/setenv.c @@ -323,8 +323,7 @@ clearenv () return 0; } #ifdef _LIBC -static void -free_mem (void) +libc_freeres_fn (free_mem) { /* Remove all traces. */ clearenv (); @@ -333,8 +332,6 @@ free_mem (void) __tdestroy (known_values, free); known_values = NULL; } -text_set_element (__libc_subfreeres, free_mem); - # undef setenv # undef unsetenv diff --git a/sysdeps/posix/ttyname.c b/sysdeps/posix/ttyname.c index e5c3b3fbe0..b7a5d85661 100644 --- a/sysdeps/posix/ttyname.c +++ b/sysdeps/posix/ttyname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 92, 93, 96, 97, 98, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,93,96,97,98,2000,2002 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 @@ -32,7 +32,7 @@ static char *getttyname (int fd, dev_t mydev, ino_t myino, int save, int *dostat) internal_function; -static char *getttyname_name; +libc_freeres_ptr (static char *getttyname_name); static char * internal_function @@ -134,11 +134,3 @@ ttyname (fd) return name; } - - -static void -free_mem (void) -{ - free (getttyname_name); -} -text_set_element (__libc_subfreeres, free_mem); diff --git a/sysdeps/pthread/aio_misc.c b/sysdeps/pthread/aio_misc.c index b0432e6e0e..78cf764837 100644 --- a/sysdeps/pthread/aio_misc.c +++ b/sysdeps/pthread/aio_misc.c @@ -530,7 +530,7 @@ handle_fildes_io (void *arg) aiocbp->aiocb64.aio_offset)); else aiocbp->aiocb.__return_value = - TEMP_FAILURE_RETRY (pwrite (fildes, (const void *) + TEMP_FAILURE_RETRY (__libc_pwrite (fildes, (const void *) aiocbp->aiocb.aio_buf, aiocbp->aiocb.aio_nbytes, aiocbp->aiocb.aio_offset)); @@ -665,9 +665,7 @@ handle_fildes_io (void *arg) /* Free allocated resources. */ -static void -__attribute__ ((unused)) -free_res (void) +libc_freeres_fn (free_res) { size_t row; @@ -676,7 +674,6 @@ free_res (void) free (pool); } -text_set_element (__libc_subfreeres, free_res); /* Add newrequest to the runlist. The __abs_prio flag of newrequest must diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c index eaacf3727c..55ef5b661a 100644 --- a/sysdeps/unix/sysv/linux/getsysstats.c +++ b/sysdeps/unix/sysv/linux/getsysstats.c @@ -38,7 +38,7 @@ static const char path_proc[] = "/proc"; /* Actual mount point of /proc filesystem. */ -static char *mount_proc; +libc_freeres_ptr (static char *mount_proc); /* Determine the path to the /proc filesystem if available. */ static const char * @@ -319,11 +319,3 @@ __get_avphys_pages () return phys_pages_info ("MemFree: %ld kB"); } weak_alias (__get_avphys_pages, get_avphys_pages) - - -static void -free_mem (void) -{ - free (mount_proc); -} -text_set_element (__libc_subfreeres, free_mem); diff --git a/sysdeps/unix/sysv/linux/shm_open.c b/sysdeps/unix/sysv/linux/shm_open.c index a96df2427c..b118533dca 100644 --- a/sysdeps/unix/sysv/linux/shm_open.c +++ b/sysdeps/unix/sysv/linux/shm_open.c @@ -226,14 +226,10 @@ shm_unlink (const char *name) } -static void __attribute__ ((unused)) -freeit (void) +/* Make sure the table is freed if we want to free everything before + exiting. */ +libc_freeres_fn (freeit) { if (mountpoint.dir != defaultdir) free (mountpoint.dir); } - - -/* Make sure the table is freed if we want to free everything before - exiting. */ -text_set_element (__libc_subfreeres, freeit); diff --git a/sysdeps/unix/sysv/linux/ttyname.c b/sysdeps/unix/sysv/linux/ttyname.c index f8e6e925a4..68d24f195e 100644 --- a/sysdeps/unix/sysv/linux/ttyname.c +++ b/sysdeps/unix/sysv/linux/ttyname.c @@ -38,7 +38,7 @@ static char *getttyname (const char *dev, dev_t mydev, internal_function; -static char *getttyname_name; +libc_freeres_ptr (static char *getttyname_name); static char * internal_function @@ -103,7 +103,7 @@ getttyname (const char *dev, dev_t mydev, ino64_t myino, int save, int *dostat) /* Static buffer in `ttyname'. */ -static char *ttyname_buf; +libc_freeres_ptr (static char *ttyname_buf); /* Return the pathname of the terminal FD is open on, or NULL on errors. @@ -186,12 +186,3 @@ ttyname (int fd) return name; } - - -static void -free_mem (void) -{ - free (ttyname_buf); - free (getttyname_name); -} -text_set_element (__libc_subfreeres, free_mem); diff --git a/time/tzfile.c b/time/tzfile.c index 5c2b28d582..24ef18f941 100644 --- a/time/tzfile.c +++ b/time/tzfile.c @@ -49,7 +49,7 @@ static struct ttinfo *find_transition (time_t timer) internal_function; static void compute_tzname_max (size_t) internal_function; static size_t num_transitions; -static time_t *transitions; +libc_freeres_ptr (static time_t *transitions); static unsigned char *type_idxs; static size_t num_types; static struct ttinfo *types; @@ -553,14 +553,3 @@ compute_tzname_max (size_t chars) } while (++p < &zone_names[chars]); } - -/* This function is only called when we are checking for memory leaks. */ -static void -freeres (void) -{ - if (transitions != NULL) - free ((void *) transitions); -} - -/* Make sure all allocated data is freed before exiting. */ -text_set_element (__libc_subfreeres, freeres); diff --git a/time/tzset.c b/time/tzset.c index c9a9783b2d..02940589f7 100644 --- a/time/tzset.c +++ b/time/tzset.c @@ -624,8 +624,7 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp) } -static void -free_mem (void) +libc_freeres_fn (free_mem) { while (tzstring_list != NULL) { @@ -637,4 +636,3 @@ free_mem (void) free (old_tz); old_tz = NULL; } -text_set_element (__libc_subfreeres, free_mem);