summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-11-01 20:44:15 +0000
committerRoland McGrath <roland@gnu.org>2002-11-01 20:44:15 +0000
commitc877418f2e806a5d2a07c036bb4ac192a53ccdbf (patch)
tree198ff8cab8ac7ddfa07b46091cbe4c4a1b50f876
parentaa9937f78c2a5c3b1496888e06b1925a4bd1aba8 (diff)
downloadglibc-c877418f2e806a5d2a07c036bb4ac192a53ccdbf.tar.gz
* 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 <jakub@redhat.com> * 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 <jakub@redhat.com> * malloc/obstack.c [_LIBC] (obstack_free): Change into strong_alias instead of duplicating the whole function in libc.
-rw-r--r--ChangeLog106
-rw-r--r--Makerules3
-rw-r--r--crypt/md5-crypt.c11
-rw-r--r--elf/dl-close.c45
-rw-r--r--elf/dl-libc.c4
-rw-r--r--grp/fgetgrent.c14
-rw-r--r--iconv/gconv_cache.c5
-rw-r--r--iconv/gconv_conf.c5
-rw-r--r--iconv/gconv_db.c5
-rw-r--r--iconv/gconv_dl.c4
-rw-r--r--include/libc-symbols.h27
-rw-r--r--inet/getnetgrent.c18
-rw-r--r--inet/rcmd.c20
-rw-r--r--inet/rexec.c14
-rw-r--r--intl/dcigettext.c5
-rw-r--r--intl/finddomain.c5
-rw-r--r--intl/localealias.c21
-rw-r--r--locale/loadarchive.c2
-rw-r--r--locale/setlocale.c4
-rw-r--r--login/getutent.c15
-rw-r--r--login/getutid.c15
-rw-r--r--login/getutline.c14
-rw-r--r--malloc/mtrace.c11
-rw-r--r--malloc/obstack.c5
-rw-r--r--malloc/set-freeres.c10
-rw-r--r--misc/efgcvt.c14
-rw-r--r--misc/fstab.c6
-rw-r--r--misc/mntent.c16
-rw-r--r--nss/getXXbyYY.c12
-rw-r--r--nss/getXXent.c12
-rw-r--r--nss/nsswitch.c5
-rw-r--r--posix/regcomp.c4
-rw-r--r--pwd/fgetpwent.c14
-rw-r--r--resolv/gai_misc.c5
-rw-r--r--resolv/ns_print.c4
-rw-r--r--resolv/nsap_addr.c2
-rw-r--r--resolv/res_hconf.c13
-rw-r--r--shadow/fgetspent.c14
-rw-r--r--stdio-common/printf-parse.h4
-rw-r--r--stdio-common/reg-printf.c19
-rw-r--r--stdlib/fmtmsg.c4
-rw-r--r--string/strerror.c20
-rw-r--r--sunrpc/clnt_perr.c5
-rw-r--r--sysdeps/generic/setenv.c5
-rw-r--r--sysdeps/posix/ttyname.c12
-rw-r--r--sysdeps/pthread/aio_misc.c7
-rw-r--r--sysdeps/unix/sysv/linux/getsysstats.c10
-rw-r--r--sysdeps/unix/sysv/linux/shm_open.c10
-rw-r--r--sysdeps/unix/sysv/linux/ttyname.c13
-rw-r--r--time/tzfile.c13
-rw-r--r--time/tzset.c4
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 <jakub@redhat.com>
+
+ * 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 <jakub@redhat.com>
+
+ * 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 <jakub@redhat.com>
+
+ * malloc/obstack.c [_LIBC] (obstack_free): Change into strong_alias
+ instead of duplicating the whole function in libc.
+
2002-10-31 Roland McGrath <roland@redhat.com>
* 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 <drepper@cygnus.com>, 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 <stdlib.h>
#include <bits/libc-lock.h>
-/* 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 <unistd.h>
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 <drepper@cygnus.com>, 1996.
@@ -17,12 +17,12 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-#include <stddef.h> /* For NULL. */
+#include <stdlib.h>
#include <utmp.h>
/* 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 <drepper@cygnus.com>, 1996.
@@ -17,20 +17,25 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-#include <stddef.h> /* For NULL. */
+#include <stdlib.h>
#include <utmp.h>
/* 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 <drepper@cygnus.com>, 1996.
@@ -17,12 +17,12 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-#include <stddef.h> /* For NULL. */
+#include <stdlib.h>
#include <utmp.h>
/* 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 <printf.h>
/* 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 <libintl.h>
#include <stdio.h>
#include <string.h>
+#include <errno.h>
/* 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);