From: Carlos O'Donell <carlos@redhat.com>
To: Adhemerval Zanella <adhemerval.zanella@linaro.org>,
libc-alpha@sourceware.org, Florian Weimer <fweimer@redhat.com>
Subject: Re: [PATCH v3 1/4] Move libc_freeres_ptrs and libc_subfreeres to hidden/weak functions
Date: Sat, 4 Mar 2023 12:37:07 -0500 [thread overview]
Message-ID: <35cd3223-8766-3b6f-2126-ea99d90ec1cb@redhat.com> (raw)
In-Reply-To: <20221227211145.3765256-2-adhemerval.zanella@linaro.org>
On 12/27/22 16:11, Adhemerval Zanella via Libc-alpha wrote:
> They are both used by __libc_freeres to free all library malloc
> allocated resources to help tooling like mtrace or valgrind on
s/on/with/g
> memory leak tracking.
>
> The current scheme uses assembly markers and linker script entries
> to consolidate the free routines function pointers on RELRO segment
s/routines/routine/g
s/on/in the/g
> and to be freed buffers on BSS.
s/on/in/g
>
> This patch changes it to use specific free functions for
> libc_freeres_ptrs buffers and call the function pointer array directly
> with call_function_static_weak.
Excellent work here. This completes a long-standing transition from magic sections to
explicit calls. I really like the direction you go with this.
>
> It allows to remove both the internal macros and the linker
s/to remove/the removal of/g
> script sections.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
>
> Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
> ---
> Makerules | 7 -
> crypt/md5-crypt.c | 7 +-
> crypt/sha256-crypt.c | 7 +-
> crypt/sha512-crypt.c | 7 +-
> dlfcn/dlerror.h | 1 -
> elf/dl-libc.c | 5 +-
> grp/fgetgrent.c | 5 +-
> gshadow/fgetsgent.c | 5 +-
> iconv/gconv_cache.c | 3 +-
> iconv/gconv_conf.c | 3 +-
> iconv/gconv_db.c | 6 +-
> iconv/gconv_dl.c | 5 +-
> include/libc-symbols.h | 73 --------
> include/set-freeres.h | 142 ++++++++++++++++
> inet/getnameinfo.c | 5 +-
> inet/getnetgrent.c | 5 +-
> inet/rcmd.c | 5 +-
> inet/rexec.c | 5 +-
> intl/dcigettext.c | 3 +-
> intl/finddomain.c | 2 +-
> intl/loadmsgcat.c | 1 -
> intl/localealias.c | 15 +-
> libio/fcloseall.c | 1 +
> libio/genops.c | 8 +-
> libio/libioP.h | 1 -
> locale/loadarchive.c | 2 +-
> locale/localeinfo.h | 4 +-
> locale/setlocale.c | 4 +-
> login/getutent.c | 5 +-
> login/getutid.c | 6 +-
> login/getutline.c | 5 +-
> malloc/set-freeres.c | 156 +++++++++++++++---
> malloc/thread-freeres.c | 9 +-
> misc/efgcvt-template.c | 5 +-
> misc/efgcvt.c | 1 +
> misc/fstab.c | 3 +-
> misc/hsearch.c | 4 -
> misc/mntent.c | 5 +-
> misc/qefgcvt.c | 1 +
> misc/unwind-link.c | 2 +-
> nptl/nptlfreeres.c | 1 -
> nscd/nscd_getgr_r.c | 3 +-
> nscd/nscd_gethst_r.c | 3 +-
> nscd/nscd_getpw_r.c | 3 +-
> nscd/nscd_getserv_r.c | 3 +-
> nscd/nscd_netgroup.c | 3 +-
> nss/getXXbyYY.c | 7 +-
> nss/getXXent.c | 7 +-
> nss/nss_action.c | 2 +-
> nss/nss_action.h | 3 -
> nss/nss_database.c | 2 +-
> nss/nss_database.h | 3 -
> nss/nss_module.c | 2 +-
> nss/nss_module.h | 3 -
> posix/regcomp.c | 3 +-
> posix/register-atfork.c | 3 +-
> pwd/fgetpwent.c | 5 +-
> resolv/gai_misc.c | 6 +-
> resolv/res-close.c | 2 -
> resolv/res_hconf.c | 16 +-
> resolv/resolv-internal.h | 14 ++
> resolv/resolv_conf.c | 3 +-
> resolv/tst-leaks2.c | 2 +
> rt/aio_misc.c | 6 +-
> shadow/fgetspent.c | 5 +-
> stdio-common/reg-modifier.c | 3 +-
> stdio-common/reg-printf.c | 6 +-
> stdio-common/reg-type.c | 6 +-
> stdlib/exit.c | 2 +-
> stdlib/fmtmsg.c | 3 +-
> stdlib/setenv.c | 3 +-
> sunrpc/clnt_perr.c | 4 +-
> sunrpc/rpc_thread.c | 1 -
> sunrpc/tst-svc_register.c | 6 +-
> sysdeps/generic/set-freeres-fp.h | 19 +++
> sysdeps/generic/set-freeres-os.h | 19 +++
> sysdeps/generic/set-freeres-system.h | 27 +++
> .../ldbl-128ibm-compat/ieee128-qefgcvt.c | 1 +
> .../ldbl-128ibm-compat/set-freeres-fp.h | 22 +++
> sysdeps/mach/hurd/bits/errno.h | 1 -
> sysdeps/posix/getaddrinfo.c | 5 +-
> sysdeps/posix/ttyname.c | 4 +-
> sysdeps/unix/sysv/linux/check_pf.c | 3 +-
> .../unix/sysv/linux/s390/s390-32/getutent.c | 1 +
> .../unix/sysv/linux/s390/s390-32/getutid.c | 1 +
> .../unix/sysv/linux/s390/s390-32/getutline.c | 1 +
> sysdeps/unix/sysv/linux/set-freeres-os.h | 24 +++
> sysdeps/unix/sysv/linux/ttyname.c | 8 +-
> time/tzfile.c | 5 +-
> time/tzset.c | 3 +-
> 90 files changed, 584 insertions(+), 243 deletions(-)
> create mode 100644 include/set-freeres.h
> create mode 100644 sysdeps/generic/set-freeres-fp.h
> create mode 100644 sysdeps/generic/set-freeres-os.h
> create mode 100644 sysdeps/generic/set-freeres-system.h
> create mode 100644 sysdeps/ieee754/ldbl-128ibm-compat/set-freeres-fp.h
> create mode 100644 sysdeps/unix/sysv/linux/set-freeres-os.h
>
> diff --git a/Makerules b/Makerules
> index 3226b7a12b..962b2cd90c 100644
> --- a/Makerules
> +++ b/Makerules
> @@ -560,14 +560,7 @@ $(common-objpfx)shlib.lds: $(common-objpfx)config.make $(..)Makerules
> -Wl,--verbose 2>/dev/null | \
> sed > $@T \
> -e '/^=========/,/^=========/!d;/^=========/d' \
> - -e 's/^.*\*(\.dynbss).*$$/& \
> - PROVIDE(__start___libc_freeres_ptrs = .); \
> - *(__libc_freeres_ptrs) \
> - PROVIDE(__stop___libc_freeres_ptrs = .);/'\
OK. Glad to see these go.
> -e 's@^.*\*(\.jcr).*$$@& \
> - PROVIDE(__start___libc_subfreeres = .);\
> - __libc_subfreeres : { *(__libc_subfreeres) }\
> - PROVIDE(__stop___libc_subfreeres = .);\
OK. Likewise. Neither of these sections should be ABI.
> PROVIDE(__start___libc_IO_vtables = .);\
> __libc_IO_vtables : { *(__libc_IO_vtables) }\
> PROVIDE(__stop___libc_IO_vtables = .);\
> diff --git a/crypt/md5-crypt.c b/crypt/md5-crypt.c
> index 7c4fb9fb97..b902abb77e 100644
> --- a/crypt/md5-crypt.c
> +++ b/crypt/md5-crypt.c
> @@ -299,10 +299,7 @@ __md5_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
> return buffer;
> }
>
> -#ifndef _LIBC
> -# define libc_freeres_ptr(decl) decl
> -#endif
> -libc_freeres_ptr (static char *buffer);
> +static char *buffer;
>
> char *
> __md5_crypt (const char *key, const char *salt)
> @@ -326,11 +323,9 @@ __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/crypt/sha256-crypt.c b/crypt/sha256-crypt.c
> index a98a968a8b..ce3b2fba79 100644
> --- a/crypt/sha256-crypt.c
> +++ b/crypt/sha256-crypt.c
> @@ -386,10 +386,7 @@ __sha256_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
> return buffer;
> }
>
> -#ifndef _LIBC
> -# define libc_freeres_ptr(decl) decl
> -#endif
> -libc_freeres_ptr (static char *buffer);
> +static char *buffer;
>
> /* This entry point is equivalent to the `crypt' function in Unix
> libcs. */
> @@ -418,11 +415,9 @@ __sha256_crypt (const char *key, const char *salt)
> return __sha256_crypt_r (key, salt, buffer, buflen);
> }
>
> -#ifndef _LIBC
> static void
> __attribute__ ((__destructor__))
> free_mem (void)
> {
> free (buffer);
> }
> -#endif
> diff --git a/crypt/sha512-crypt.c b/crypt/sha512-crypt.c
> index ea13527c09..c0469c363e 100644
> --- a/crypt/sha512-crypt.c
> +++ b/crypt/sha512-crypt.c
> @@ -408,10 +408,7 @@ __sha512_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
> return buffer;
> }
>
> -#ifndef _LIBC
> -# define libc_freeres_ptr(decl) decl
> -#endif
> -libc_freeres_ptr (static char *buffer);
> +static char *buffer;
>
> /* This entry point is equivalent to the `crypt' function in Unix
> libcs. */
> @@ -440,11 +437,9 @@ __sha512_crypt (const char *key, const char *salt)
> return __sha512_crypt_r (key, salt, buffer, buflen);
> }
>
> -#ifndef _LIBC
> static void
> __attribute__ ((__destructor__))
> free_mem (void)
> {
> free (buffer);
> }
> -#endif
> diff --git a/dlfcn/dlerror.h b/dlfcn/dlerror.h
> index d088cf40d9..e555ed7835 100644
> --- a/dlfcn/dlerror.h
> +++ b/dlfcn/dlerror.h
> @@ -87,6 +87,5 @@ static struct dl_action_result *const dl_action_result_malloc_failed
> reporting via dlerror. */
> extern __thread struct dl_action_result *__libc_dlerror_result
> attribute_tls_model_ie;
> -void __libc_dlerror_result_free (void) attribute_hidden;
>
> #endif /* _DLERROR_H */
> diff --git a/elf/dl-libc.c b/elf/dl-libc.c
> index 266e068da6..3299febe52 100644
> --- a/elf/dl-libc.c
> +++ b/elf/dl-libc.c
> @@ -228,7 +228,7 @@ __libc_dlclose (void *map)
> }
>
>
> -static bool __libc_freeres_fn_section
> +static bool
> free_slotinfo (struct dtv_slotinfo_list **elemp)
> {
> size_t cnt;
> @@ -256,7 +256,8 @@ free_slotinfo (struct dtv_slotinfo_list **elemp)
> }
>
>
> -libc_freeres_fn (free_mem)
> +void
> +__dl_libc_freemem (void)
> {
> struct link_map *l;
> struct r_search_path_elem *d;
> diff --git a/grp/fgetgrent.c b/grp/fgetgrent.c
> index fd2b4d32d6..cbbd9e2489 100644
> --- a/grp/fgetgrent.c
> +++ b/grp/fgetgrent.c
> @@ -20,12 +20,13 @@
> #include <libc-lock.h>
> #include <stdio.h>
> #include <stdlib.h>
> +#include <set-freeres.h>
>
>
> /* We need to protect the dynamic buffer handling. */
> __libc_lock_define_initialized (static, lock);
>
> -libc_freeres_ptr (static char *buffer);
> +static char *buffer;
>
> /* Read one entry from the given stream. */
> struct group *
> @@ -82,3 +83,5 @@ fgetgrent (FILE *stream)
>
> return result;
> }
> +
> +weak_alias (buffer, __libc_fgetgrent_freemem_ptr)
> diff --git a/gshadow/fgetsgent.c b/gshadow/fgetsgent.c
> index 02f9c7d643..1b1ac6cd97 100644
> --- a/gshadow/fgetsgent.c
> +++ b/gshadow/fgetsgent.c
> @@ -20,6 +20,7 @@
> #include <gshadow.h>
> #include <stdio.h>
> #include <stdlib.h>
> +#include <set-freeres.h>
>
>
> /* A reasonable size for a buffer to start with. */
> @@ -28,7 +29,7 @@
> /* We need to protect the dynamic buffer handling. */
> __libc_lock_define_initialized (static, lock);
>
> -libc_freeres_ptr (static char *buffer);
> +static char *buffer;
>
> /* Read one shadow entry from the given stream. */
> struct sgrp *
> @@ -85,3 +86,5 @@ fgetsgent (FILE *stream)
>
> return result;
> }
> +
> +weak_alias (buffer, __libc_fgetsgent_freeres_ptr);
> diff --git a/iconv/gconv_cache.c b/iconv/gconv_cache.c
> index 8d47545c41..e250228561 100644
> --- a/iconv/gconv_cache.c
> +++ b/iconv/gconv_cache.c
> @@ -449,7 +449,8 @@ __gconv_release_cache (struct __gconv_step *steps, size_t nsteps)
>
>
> /* Free all resources if necessary. */
> -libc_freeres_fn (free_mem)
> +void
> +__gconv_cache_freemem (void)
> {
> if (cache_malloced)
> free (gconv_cache);
> diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
> index f069e28323..608109c040 100644
> --- a/iconv/gconv_conf.c
> +++ b/iconv/gconv_conf.c
> @@ -530,7 +530,8 @@ __gconv_load_conf (void)
>
>
> /* Free all resources if necessary. */
> -libc_freeres_fn (free_mem)
> +void
> +__gconv_conf_freemem (void)
> {
> if (__gconv_path_elem != NULL && __gconv_path_elem != &empty_path_elem)
> free ((void *) __gconv_path_elem);
> diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c
> index 4943c954a3..7aeae5993c 100644
> --- a/iconv/gconv_db.c
> +++ b/iconv/gconv_db.c
> @@ -169,7 +169,7 @@ add_derivation (const char *fromset, const char *toset,
> not all memory will be freed. */
> }
>
> -static void __libc_freeres_fn_section
> +static void
> free_derivation (void *p)
> {
> struct known_derivation *deriv = (struct known_derivation *) p;
> @@ -793,7 +793,6 @@ __gconv_close_transform (struct __gconv_step *steps, size_t nsteps)
>
> /* Free the modules mentioned. */
> static void
> -__libc_freeres_fn_section
> free_modules_db (struct gconv_module *node)
> {
> if (node->left != NULL)
> @@ -812,7 +811,8 @@ free_modules_db (struct gconv_module *node)
>
>
> /* Free all resources if necessary. */
> -libc_freeres_fn (free_mem)
> +void
> +__gconv_db_freemem (void)
> {
> /* First free locale memory. This needs to be done before freeing
> derivations, as ctype cleanup functions dereference steps arrays which we
> diff --git a/iconv/gconv_dl.c b/iconv/gconv_dl.c
> index 5ed982636a..6cc05e42fc 100644
> --- a/iconv/gconv_dl.c
> +++ b/iconv/gconv_dl.c
> @@ -184,7 +184,7 @@ __gconv_release_shlib (struct __gconv_loaded_object *handle)
>
>
> /* We run this if we debug the memory allocation. */
> -static void __libc_freeres_fn_section
> +static void
> do_release_all (void *nodep)
> {
> struct __gconv_loaded_object *obj = (struct __gconv_loaded_object *) nodep;
> @@ -196,7 +196,8 @@ do_release_all (void *nodep)
> free (obj);
> }
>
> -libc_freeres_fn (free_mem)
> +void
> +__gconv_dl_freemem (void)
> {
> __tdestroy (loaded, do_release_all);
> loaded = NULL;
> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> index f4437ff6ad..a1d422131f 100644
> --- a/include/libc-symbols.h
> +++ b/include/libc-symbols.h
> @@ -237,79 +237,6 @@ requires at runtime the shared libraries from the glibc version used \
> for linking")
> #endif
>
> -/* Resource Freeing Hooks:
> -
> - Normally a process exits and the OS cleans up any allocated
> - memory. However, when tooling like mtrace or valgrind is monitoring
> - the process we need to free all resources that are part of the
> - process in order to provide the consistency required to track
> - memory leaks.
> -
> - A single public API exists and is __libc_freeres(), and this is used
> - by applications like valgrind to freee resouces.
> -
> - There are 3 cases:
> -
> - (a) __libc_freeres
> -
> - In this case all you need to do is define the freeing routine:
> -
> - foo.c:
> - libfoo_freeres_fn (foo_freeres)
> - {
> - complex_free (mem);
> - }
> -
> - This ensures the function is called at the right point to free
> - resources.
> -
> - (b) __libc_freeres_ptr
> -
> - The framework for (a) iterates over the list of pointers-to-free
> - in (b) and frees them.
> -
> - foo.c:
> - libc_freeres_ptr (static char *foo_buffer);
> -
> - Freeing these resources alaways happens last and is equivalent
> - to registering a function that does 'free (foo_buffer)'.
> -
> - (c) Explicit lists of free routines to call or objects to free.
> -
> - It is the intended goal to remove (a) and (b) which have some
> - non-determinism based on link order, and instead use explicit
> - lists of functions and frees to resolve cleanup ordering issues
> - and make it easy to debug and maintain.
> -
> - As of today the following subsystems use (c):
> -
> - Per-thread cleanup:
> - * malloc/thread-freeres.c
> -
> - libdl cleanup:
> - * dlfcn/dlfreeres.c
> -
> - libpthread cleanup:
> - * nptl/nptlfreeres.c
> -
> - So if you need any shutdown routines to run you should add them
> - directly to the appropriate subsystem's shutdown list. */
> -
> -/* Resource pointers to free in libc.so. */
> -#define libc_freeres_ptr(decl) \
> - __make_section_unallocated ("__libc_freeres_ptrs, \"aw\", %nobits") \
> - decl __attribute__ ((section ("__libc_freeres_ptrs" __sec_comment)))
> -
> -/* Resource freeing functions from libc.so go in this section. */
> -#define __libc_freeres_fn_section \
> - __attribute__ ((__used__, section ("__libc_freeres_fn")))
> -
> -/* Resource freeing functions for libc.so. */
> -#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)
> -
OK. Perfect, with the macros missing any uses backported immediately fail.
> /* Declare SYMBOL to be TYPE (`function' or `object') of SIZE bytes
> alias to ORIGINAL, when the assembler supports such declarations
> (such as in ELF).
> diff --git a/include/set-freeres.h b/include/set-freeres.h
> new file mode 100644
> index 0000000000..b7f66519a3
> --- /dev/null
> +++ b/include/set-freeres.h
> @@ -0,0 +1,142 @@
> +/* Macros for internal resource Freeing Hooks.
> + Copyright (C) 2022 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
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _SET_FREERES_H
> +#define _SET_FREERES_H 1
> +
> +#include <shlib-compat.h>
> +#include <printf.h>
> +#include <time.h>
> +#include <resolv/resolv-internal.h>
> +
> +/* Resource Freeing Hooks:
> +
> + Normally a process exits and the OS cleans up any allocated
> + memory. However, when tooling like mtrace or valgrind is monitoring
> + the process we need to free all resources that are part of the
> + process in order to provide the consistency required to track
> + memory leaks.
> +
> + A single public API exists and is __libc_freeres, and this is used
> + by applications like valgrind to freee resouces.
> +
> + Each free routines must be explicit listed below. */
> +
> +/* From libc.so. */
> +extern void __dl_libc_freemem (void) attribute_hidden;
> +extern void __hdestroy (void) attribute_hidden;
> +extern void __gconv_cache_freemem (void) attribute_hidden;
> +extern void __gconv_conf_freemem (void) attribute_hidden;
> +extern void __gconv_db_freemem (void) attribute_hidden;
> +extern void __gconv_dl_freemem (void) attribute_hidden;
> +extern void __intl_freemem (void) attribute_hidden;
> +extern void __libio_freemem (void) attribute_hidden;
> +extern void __libc_fstab_freemem (void) attribute_hidden;
> +extern void __nscd_gr_map_freemem (void) attribute_hidden;
> +extern void __nscd_hst_map_freemem (void) attribute_hidden;
> +extern void __nscd_pw_map_freemem (void) attribute_hidden;
> +extern void __nscd_serv_map_freemem (void) attribute_hidden;
> +extern void __nscd_group_map_freemem (void) attribute_hidden;
> +extern void __libc_regcomp_freemem (void) attribute_hidden;
> +extern void __libc_atfork_freemem (void) attribute_hidden;
> +extern void __libc_resolv_conf_freemem (void) attribute_hidden;
> +extern void __res_thread_freeres (void) attribute_hidden;
> +extern void __libc_printf_freemem (void) attribute_hidden;
> +extern void __libc_fmtmsg_freemem (void) attribute_hidden;
> +extern void __libc_setenv_freemem (void) attribute_hidden;
> +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_31)
> +extern void __rpc_freemem (void) attribute_hidden;
> +extern void __rpc_thread_destroy (void) attribute_hidden;
> +#endif
> +extern void __libc_getaddrinfo_freemem (void) attribute_hidden;
> +extern void __libc_tzset_freemem (void) attribute_hidden;
> +extern void __libc_localealias_freemem (void) attribute_hidden;
> +extern void __libc_getutent_freemem (void) attribute_hidden;
> +extern void __libc_getutline_freemem (void) attribute_hidden;
> +/* From nss/nss_module.c */
> +extern void __nss_module_freeres (void) attribute_hidden;
> +/* From nss/nss_action.c */
> +extern void __nss_action_freeres (void) attribute_hidden;
> +/* From nss/nss_database.c */
> +extern void __nss_database_freeres (void) attribute_hidden;
> +/* From libio/genops.c */
> +extern int _IO_cleanup (void) attribute_hidden;;
> +/* From dlfcn/dlerror.c */
> +extern void __libc_dlerror_result_free (void) attribute_hidden;
> +
> +/* From either libc.so or libpthread.so */
> +extern void __libpthread_freeres (void) attribute_hidden;
> +/* From either libc.so or libanl.so */
> +#if PTHREAD_IN_LIBC
> +extern void __gai_freemem (void) attribute_hidden;
> +/* From either libc.so or librt.so */
> +extern void __aio_freemem (void) attribute_hidden;
> +#endif
> +
> +/* From libc.so */
> +extern char * __libc_fgetgrent_freemem_ptr attribute_hidden;
> +extern char * __libc_fgetsgent_freeres_ptr attribute_hidden;
> +extern char * __libc_getnetgrent_freemem_ptr attribute_hidden;
> +extern char * __libc_rcmd_freemem_ptr attribute_hidden;
> +extern char * __libc_rexec_freemem_ptr attribute_hidden;
> +extern void * __libc_mntent_freemem_ptr attribute_hidden;
> +extern char * __libc_fgetpwent_freemem_ptr attribute_hidden;
> +extern struct netaddr * __libc_resolv_res_hconf_freemem_ptr attribute_hidden;
> +extern char * __libc_fgetspent_freemem_ptr attribute_hidden;
> +extern __time64_t * __libc_tzfile_freemem_ptr attribute_hidden;
> +extern char * __libc_getnameinfo_freemem_ptr attribute_hidden;
> +extern struct utmp * __libc_getutent_freemem_ptr attribute_hidden;
> +extern struct utmp * __libc_getutid_freemem_ptr attribute_hidden;
> +extern struct utmp * __libc_getutline_freemem_ptr attribute_hidden;
> +extern printf_arginfo_size_function ** __libc_reg_printf_freemem_ptr
> + attribute_hidden;
> +extern printf_va_arg_function ** __libc_reg_type_freemem_ptr
> + attribute_hidden;
> +/* From nss/getXXbyYY.c */
> +extern char * __libc_getgrgid_freemem_ptr attribute_hidden;
> +extern char * __libc_getgrnam_freemem_ptr attribute_hidden;
> +extern char * __libc_getpwnam_freemem_ptr attribute_hidden;
> +extern char * __libc_getpwuid_freemem_ptr attribute_hidden;
> +extern char * __libc_getspnam_freemem_ptr attribute_hidden;
> +extern char * __libc_getaliasbyname_freemem_ptr attribute_hidden;
> +extern char * __libc_gethostbyaddr_freemem_ptr attribute_hidden;
> +extern char * __libc_gethostbyname_freemem_ptr attribute_hidden;
> +extern char * __libc_gethostbyname2_freemem_ptr attribute_hidden;
> +extern char * __libc_getnetbyaddr_freemem_ptr attribute_hidden;
> +extern char * __libc_getnetbyname_freemem_ptr attribute_hidden;
> +extern char * __libc_getprotobynumber_freemem_ptr attribute_hidden;
> +extern char * __libc_getprotobyname_freemem_ptr attribute_hidden;
> +extern char * __libc_getrpcbyname_freemem_ptr attribute_hidden;
> +extern char * __libc_getrpcbynumber_freemem_ptr attribute_hidden;
> +extern char * __libc_getservbyname_freemem_ptr attribute_hidden;
> +extern char * __libc_getservbyport_freemem_ptr attribute_hidden;
> +/* From nss/getXXent.c */
> +extern char * __libc_getgrent_freemem_ptr attribute_hidden;
> +extern char * __libc_getpwent_freemem_ptr attribute_hidden;
> +extern char * __libc_getspent_freemem_ptr attribute_hidden;
> +extern char * __libc_getaliasent_freemem_ptr attribute_hidden;
> +extern char * __libc_gethostent_freemem_ptr attribute_hidden;
> +extern char * __libc_getnetent_freemem_ptr attribute_hidden;
> +extern char * __libc_getprotoent_freemem_ptr attribute_hidden;
> +extern char * __libc_getrpcent_freemem_ptr attribute_hidden;
> +extern char * __libc_getservent_freemem_ptr attribute_hidden;
> +/* From misc/efgcvt-template.c */
> +extern char * __libc_efgcvt_freemem_ptr attribute_hidden;
> +extern char * __libc_qefgcvt_freemem_ptr attribute_hidden;
> +
> +#endif
OK. List all the functions, and pointers.
> diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c
> index 4733be6f5b..4b1309979f 100644
> --- a/inet/getnameinfo.c
> +++ b/inet/getnameinfo.c
> @@ -72,12 +72,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> #include <libc-lock.h>
> #include <scratch_buffer.h>
> #include <net-internal.h>
> +#include <set-freeres.h>
>
> #ifndef min
> # define min(x,y) (((x) > (y)) ? (y) : (x))
> #endif /* min */
>
> -libc_freeres_ptr (static char *domain);
> +static char *domain;
>
> /* Former NI_IDN_ALLOW_UNASSIGNED, NI_IDN_USE_STD3_ASCII_RULES flags,
> now ignored. */
> @@ -556,3 +557,5 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
> return 0;
> }
> libc_hidden_def (getnameinfo)
> +
> +weak_alias (domain, __libc_getnameinfo_freemem_ptr)
> diff --git a/inet/getnetgrent.c b/inet/getnetgrent.c
> index e354194b72..53ddb2fd75 100644
> --- a/inet/getnetgrent.c
> +++ b/inet/getnetgrent.c
> @@ -19,9 +19,10 @@
> #include <netdb.h>
> #include <stdlib.h>
> #include <libc-lock.h>
> +#include <set-freeres.h>
>
> /* Static buffer for return value. We allocate it when needed. */
> -libc_freeres_ptr (static char *buffer);
> +static char *buffer;
> /* All three strings should fit in a block of 1kB size. */
> #define BUFSIZE 1024
>
> @@ -47,3 +48,5 @@ getnetgrent (char **hostp, char **userp, char **domainp)
>
> return __getnetgrent_r (hostp, userp, domainp, buffer, BUFSIZE);
> }
> +
> +weak_alias (buffer, __libc_getnetgrent_freemem_ptr)
> diff --git a/inet/rcmd.c b/inet/rcmd.c
> index 2b95fa11d8..ad8a894907 100644
> --- a/inet/rcmd.c
> +++ b/inet/rcmd.c
> @@ -80,6 +80,7 @@
> #include <sys/uio.h>
> #include <sigsetops.h>
> #include <shlib-compat.h>
> +#include <set-freeres.h>
>
>
> int __ivaliduser (FILE *, uint32_t, const char *, const char *);
> @@ -98,7 +99,7 @@ int iruserok (uint32_t raddr, int superuser, const char *ruser,
>
> libc_hidden_proto (iruserok_af)
>
> -libc_freeres_ptr(static char *ahostbuf);
> +static char *ahostbuf;
>
> int
> rcmd_af (char **ahost, u_short rport, const char *locuser, const char *remuser,
> @@ -817,3 +818,5 @@ __validuser2_sa (FILE *hostf, struct sockaddr *ra, size_t ralen,
>
> return retval;
> }
> +
> +weak_alias (ahostbuf, __libc_rcmd_freemem_ptr)
> diff --git a/inet/rexec.c b/inet/rexec.c
> index c647b7ac34..1985fa4418 100644
> --- a/inet/rexec.c
> +++ b/inet/rexec.c
> @@ -40,9 +40,10 @@
> #include <string.h>
> #include <unistd.h>
> #include <sys/uio.h>
> +#include <set-freeres.h>
>
> int rexecoptions;
> -libc_freeres_ptr (static char *ahostbuf);
> +static char *ahostbuf;
>
> int
> rexec_af (char **ahost, int rport, const char *name, const char *pass,
> @@ -196,3 +197,5 @@ rexec (char **ahost, int rport, const char *name, const char *pass,
> {
> return rexec_af(ahost, rport, name, pass, cmd, fd2p, AF_INET);
> }
> +
> +weak_alias (ahostbuf, __libc_rexec_freemem_ptr)
> diff --git a/intl/dcigettext.c b/intl/dcigettext.c
> index 1fc074a414..bfac152908 100644
> --- a/intl/dcigettext.c
> +++ b/intl/dcigettext.c
> @@ -1671,7 +1671,8 @@ mempcpy (void *dest, const void *src, size_t n)
> #ifdef _LIBC
> /* If we want to free all resources we have to do some work at
> program's end. */
> -libc_freeres_fn (free_mem)
> +void
> +__intl_freemem (void)
> {
> void *old;
>
> diff --git a/intl/finddomain.c b/intl/finddomain.c
> index 416e28ad76..58de876e28 100644
> --- a/intl/finddomain.c
> +++ b/intl/finddomain.c
> @@ -185,7 +185,7 @@ out:
> #ifdef _LIBC
> /* This is called from iconv/gconv_db.c's free_mem, as locales must
> be freed before freeing gconv steps arrays. */
> -void __libc_freeres_fn_section
> +void
> _nl_finddomain_subfreeres (void)
> {
> struct loaded_l10nfile *runp = _nl_loaded_domains;
> diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
> index 98d5f53232..0b98f233dd 100644
> --- a/intl/loadmsgcat.c
> +++ b/intl/loadmsgcat.c
> @@ -1284,7 +1284,6 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
>
> #ifdef _LIBC
> void
> -__libc_freeres_fn_section
> _nl_unload_domain (struct loaded_domain *domain)
> {
> size_t i;
> diff --git a/intl/localealias.c b/intl/localealias.c
> index b36092363a..4bf068d0ea 100644
> --- a/intl/localealias.c
> +++ b/intl/localealias.c
> @@ -126,14 +126,10 @@ struct alias_map
> };
>
>
> -#ifndef _LIBC
> -# define libc_freeres_ptr(decl) decl
> -#endif
> -
> -libc_freeres_ptr (static char *string_space);
> +static char *string_space;
> static size_t string_space_act;
> static size_t string_space_max;
> -libc_freeres_ptr (static struct alias_map *map);
> +static struct alias_map *map;
> static size_t nmap;
> static size_t maxmap;
>
> @@ -439,3 +435,10 @@ alias_compare (const struct alias_map *map1, const struct alias_map *map2)
> return c1 - c2;
> #endif
> }
> +
> +void
> +__libc_localealias_freemem (void)
> +{
> + free (string_space);
> + free (map);
> +}
> diff --git a/libio/fcloseall.c b/libio/fcloseall.c
> index 4e2a038d39..1ee8916078 100644
> --- a/libio/fcloseall.c
> +++ b/libio/fcloseall.c
> @@ -26,6 +26,7 @@
>
> #include "libioP.h"
> #include <stdio.h>
> +#include <set-freeres.h>
>
> int
> __fcloseall (void)
> diff --git a/libio/genops.c b/libio/genops.c
> index 8a7fc4f7c5..b3a0603a0a 100644
> --- a/libio/genops.c
> +++ b/libio/genops.c
> @@ -765,8 +765,8 @@ weak_alias (_IO_flush_all_linebuffered, _flushlbf)
> actual buffer because this will happen anyway once the program
> terminated. If we do want to look for memory leaks we have to free
> the buffers. Whether something is freed is determined by the
> - function sin the libc_freeres section. Those are called as part of
> - the atexit routine, just like _IO_cleanup. The problem is we do
> + function called by __libc_freeres (those are not called as part of
> + the atexit routine, different from _IO_cleanup). The problem is we do
> not know whether the freeres code is called first or _IO_cleanup.
> if the former is the case, we set the DEALLOC_BUFFER variable to
> true and _IO_unbuffer_all will take care of the rest. If
> @@ -844,8 +844,8 @@ _IO_unbuffer_all (void)
> #endif
> }
>
> -
> -libc_freeres_fn (buffer_free)
> +void
> +__libio_freemem (void)
> {
> dealloc_buffers = true;
>
> diff --git a/libio/libioP.h b/libio/libioP.h
> index 3a5498bd65..8500c75fa0 100644
> --- a/libio/libioP.h
> +++ b/libio/libioP.h
> @@ -491,7 +491,6 @@ libc_hidden_proto (_IO_wdo_write)
> extern int _IO_flush_all_lockp (int);
> extern int _IO_flush_all (void);
> libc_hidden_proto (_IO_flush_all)
> -extern int _IO_cleanup (void);
> extern void _IO_flush_all_linebuffered (void);
> libc_hidden_proto (_IO_flush_all_linebuffered)
> extern int _IO_new_fgetpos (FILE *, __fpos_t *);
> diff --git a/locale/loadarchive.c b/locale/loadarchive.c
> index fcc4913319..60ae1daa2c 100644
> --- a/locale/loadarchive.c
> +++ b/locale/loadarchive.c
> @@ -498,7 +498,7 @@ _nl_load_locale_from_archive (int category, const char **namep)
> return lia->data[category];
> }
>
> -void __libc_freeres_fn_section
> +void
> _nl_archive_subfreeres (void)
> {
> struct locale_in_archive *lia;
> diff --git a/locale/localeinfo.h b/locale/localeinfo.h
> index fd43033a19..1bf4215e71 100644
> --- a/locale/localeinfo.h
> +++ b/locale/localeinfo.h
> @@ -381,10 +381,10 @@ extern struct __locale_data *_nl_load_locale_from_archive (int category,
> const char **namep)
> attribute_hidden;
>
> -/* Subroutine of setlocale's __libc_subfreeres hook. */
> +/* Subroutine of setlocale's free resource. */
> extern void _nl_archive_subfreeres (void) attribute_hidden;
>
> -/* Subroutine of gconv-db's __libc_subfreeres hook. */
> +/* Subroutine of gconv-db's free resource. */
> extern void _nl_locale_subfreeres (void) attribute_hidden;
>
> /* Validate the contents of a locale file and set up the in-core
> diff --git a/locale/setlocale.c b/locale/setlocale.c
> index 56c14d8533..d1e773f46a 100644
> --- a/locale/setlocale.c
> +++ b/locale/setlocale.c
> @@ -468,7 +468,7 @@ setlocale (int category, const char *locale)
> }
> libc_hidden_def (setlocale)
>
> -static void __libc_freeres_fn_section
> +static void
> free_category (int category,
> struct __locale_data *here, struct __locale_data *c_data)
> {
> @@ -498,7 +498,7 @@ free_category (int category,
>
> /* This is called from iconv/gconv_db.c's free_mem, as locales must
> be freed before freeing gconv steps arrays. */
> -void __libc_freeres_fn_section
> +void
> _nl_locale_subfreeres (void)
> {
> #ifdef NL_CURRENT_INDIRECT
> diff --git a/login/getutent.c b/login/getutent.c
> index 8d2f1207f8..9627843def 100644
> --- a/login/getutent.c
> +++ b/login/getutent.c
> @@ -17,10 +17,11 @@
>
> #include <stdlib.h>
> #include <utmp.h>
> +#include <set-freeres.h>
>
>
> /* Local buffer to store the result. */
> -libc_freeres_ptr (static struct utmp *buffer);
> +static struct utmp *buffer;
>
>
> struct utmp *
> @@ -42,3 +43,5 @@ __getutent (void)
> }
> libc_hidden_def (__getutent)
> weak_alias (__getutent, getutent)
> +
> +weak_alias (buffer, __libc_getutent_freemem_ptr)
> diff --git a/login/getutid.c b/login/getutid.c
> index 303c178db1..87e662da63 100644
> --- a/login/getutid.c
> +++ b/login/getutid.c
> @@ -17,10 +17,10 @@
>
> #include <stdlib.h>
> #include <utmp.h>
> -
> +#include <set-freeres.h>
>
> /* Local buffer to store the result. */
> -libc_freeres_ptr (static struct utmp *buffer);
> +static struct utmp *buffer;
>
> struct utmp *
> __getutid (const struct utmp *id)
> @@ -40,3 +40,5 @@ __getutid (const struct utmp *id)
> }
> libc_hidden_def (__getutid)
> weak_alias (__getutid, getutid)
> +
> +weak_alias (buffer, __libc_getutid_freemem_ptr)
> diff --git a/login/getutline.c b/login/getutline.c
> index 661eff3a3c..837b70a151 100644
> --- a/login/getutline.c
> +++ b/login/getutline.c
> @@ -17,10 +17,11 @@
>
> #include <stdlib.h>
> #include <utmp.h>
> +#include <set-freeres.h>
>
>
> /* Local buffer to store the result. */
> -libc_freeres_ptr (static struct utmp *buffer);
> +static struct utmp *buffer;
>
>
> struct utmp *
> @@ -41,3 +42,5 @@ __getutline (const struct utmp *line)
> }
> libc_hidden_def (__getutline)
> weak_alias (__getutline, getutline)
> +
> +weak_alias (buffer, __libc_getutline_freemem_ptr)
> diff --git a/malloc/set-freeres.c b/malloc/set-freeres.c
> index be8c2a35fc..45642c3658 100644
> --- a/malloc/set-freeres.c
> +++ b/malloc/set-freeres.c
> @@ -15,32 +15,62 @@
> License along with the GNU C Library; if not, see
> <https://www.gnu.org/licenses/>. */
>
> +#include <array_length.h>
> #include <atomic.h>
> #include <stdlib.h>
> -#include <set-hooks.h>
> #include <libc-internal.h>
> #include <unwind-link.h>
> -#include <dlfcn/dlerror.h>
> #include <ldsodefs.h>
> +#include <set-freeres.h>
> +#include <set-freeres-system.h>
> +
> +#ifndef SHARED
> +# pragma weak __nss_module_freeres
> +# pragma weak __nss_action_freeres
> +# pragma weak __nss_database_freeres
> +# pragma weak __dl_libc_freemem
> +# pragma weak __hdestroy
> +# pragma weak __gconv_cache_freemem
> +# pragma weak __gconv_conf_freemem
> +# pragma weak __gconv_db_freemem
> +# pragma weak __gconv_dl_freemem
> +# pragma weak __intl_freemem
> +# pragma weak __libio_freemem
> +# pragma weak __libc_fstab_freemem
> +# pragma weak __nscd_gr_map_freemem
> +# pragma weak __nscd_hst_map_freemem
> +# pragma weak __nscd_pw_map_freemem
> +# pragma weak __nscd_serv_map_freemem
> +# pragma weak __nscd_group_map_freemem
> +# pragma weak __libc_regcomp_freemem
> +# pragma weak __libc_atfork_freemem
> +# pragma weak __res_thread_freeres
> +# pragma weak __libc_resolv_conf_freemem
> +# pragma weak __libc_printf_freemem
> +# pragma weak __libc_fmtmsg_freemem
> +# pragma weak __libc_setenv_freemem
> +# pragma weak __rpc_freemem
> +# pragma weak __rpc_thread_destroy
> +# pragma weak __libc_getaddrinfo_freemem
> +# pragma weak __libc_tzset_freemem
> +# pragma weak __libc_localealias_freemem
> +# pragma weak __gai_freemem
> +# pragma weak __aio_freemem
> +# pragma weak __libpthread_freeres
> +# pragma weak __libc_dlerror_result_free
> +# pragma weak __check_pf_freemem
> +#endif
>
> -#include "../nss/nsswitch.h"
> -#include "../libio/libioP.h"
> -
> -DEFINE_HOOK (__libc_subfreeres, (void));
> -
> -symbol_set_define (__libc_freeres_ptrs);
> -
> -extern void __libpthread_freeres (void)
> -#if PTHREAD_IN_LIBC && defined SHARED
> -/* It is possible to call __libpthread_freeres directly in shared
> - builds with an integrated libpthread. */
> - attribute_hidden
> +#ifdef SHARED
> +# define call_free_static_weak(__ptr) \
> + free (__ptr)
> #else
> - __attribute__ ((weak))
> +# define call_free_static_weak(__ptr) \
> + if (&__ptr != NULL) \
> + free (__ptr);
> #endif
> - ;
>
> -void __libc_freeres_fn_section
> +void
> __libc_freeres (void)
> {
> /* This function might be called from different places. So better
> @@ -49,8 +79,6 @@ __libc_freeres (void)
>
> if (!atomic_compare_and_exchange_bool_acq (&already_called, 1, 0))
> {
> - void *const *p;
> -
> call_function_static_weak (__nss_module_freeres);
> call_function_static_weak (__nss_action_freeres);
> call_function_static_weak (__nss_database_freeres);
> @@ -58,7 +86,43 @@ __libc_freeres (void)
> _IO_cleanup ();
>
> /* We run the resource freeing after IO cleanup. */
> - RUN_HOOK (__libc_subfreeres, ());
> + call_function_static_weak (__dl_libc_freemem);
> + call_function_static_weak (__hdestroy);
> + call_function_static_weak (__gconv_cache_freemem);
> + call_function_static_weak (__gconv_conf_freemem);
> + call_function_static_weak (__gconv_db_freemem);
> + call_function_static_weak (__gconv_dl_freemem);
> + call_function_static_weak (__intl_freemem);
> + call_function_static_weak (__libio_freemem);
> + call_function_static_weak (__libc_fstab_freemem);
> + call_function_static_weak (__nscd_gr_map_freemem);
> + call_function_static_weak (__nscd_hst_map_freemem);
> + call_function_static_weak (__nscd_pw_map_freemem);
> + call_function_static_weak (__nscd_serv_map_freemem);
> + call_function_static_weak (__nscd_group_map_freemem);
> + call_function_static_weak (__libc_regcomp_freemem);
> + call_function_static_weak (__libc_atfork_freemem);
> + /* __res_thread_freeres deallocates the per-thread resolv_context);
> + which in turn drop the reference count of the current global object.
> + So it need to be before __libc_resolv_conf_freemem. */
> + call_function_static_weak (__res_thread_freeres);
> + call_function_static_weak (__libc_resolv_conf_freemem);
> + call_function_static_weak (__libc_printf_freemem);
> + call_function_static_weak (__libc_fmtmsg_freemem);
> + call_function_static_weak (__libc_setenv_freemem);
> +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_31)
> + call_function_static_weak (__rpc_freemem);
> + call_function_static_weak (__rpc_thread_destroy);
> +#endif
> + call_function_static_weak (__libc_getaddrinfo_freemem);
> + call_function_static_weak (__libc_tzset_freemem);
> + call_function_static_weak (__libc_localealias_freemem);
> +
> +#if PTHREAD_IN_LIBC
> + call_function_static_weak (__gai_freemem);
> +
> + call_function_static_weak (__aio_freemem);
> +#endif
>
> call_function_static_weak (__libpthread_freeres);
>
> @@ -72,9 +136,55 @@ __libc_freeres (void)
> GLRO (dl_libc_freeres) ();
> #endif
>
> - for (p = symbol_set_first_element (__libc_freeres_ptrs);
> - !symbol_set_end_p (__libc_freeres_ptrs, p); ++p)
> - free (*p);
> + call_free_static_weak (__libc_fgetgrent_freemem_ptr);
> + call_free_static_weak (__libc_fgetsgent_freeres_ptr);
> + call_free_static_weak (__libc_getnetgrent_freemem_ptr);
> + call_free_static_weak (__libc_rcmd_freemem_ptr);
> + call_free_static_weak (__libc_rexec_freemem_ptr);
> + call_free_static_weak (__libc_mntent_freemem_ptr);
> + call_free_static_weak (__libc_fgetpwent_freemem_ptr);
> + call_free_static_weak (__libc_resolv_res_hconf_freemem_ptr);
> + call_free_static_weak (__libc_fgetspent_freemem_ptr);
> + call_free_static_weak (__libc_tzfile_freemem_ptr);
> + call_free_static_weak (__libc_getnameinfo_freemem_ptr);
> + call_free_static_weak (__libc_getutent_freemem_ptr);
> + call_free_static_weak (__libc_getutid_freemem_ptr);
> + call_free_static_weak (__libc_getutline_freemem_ptr);
> + call_free_static_weak (__libc_reg_printf_freemem_ptr);
> + call_free_static_weak (__libc_reg_type_freemem_ptr);
> +
> + call_free_static_weak (__libc_getgrgid_freemem_ptr);
> + call_free_static_weak (__libc_getgrnam_freemem_ptr);
> + call_free_static_weak (__libc_getpwnam_freemem_ptr);
> + call_free_static_weak (__libc_getpwuid_freemem_ptr);
> + call_free_static_weak (__libc_getspnam_freemem_ptr);
> + call_free_static_weak (__libc_getaliasbyname_freemem_ptr);
> + call_free_static_weak (__libc_gethostbyaddr_freemem_ptr);
> + call_free_static_weak (__libc_gethostbyname_freemem_ptr);
> + call_free_static_weak (__libc_gethostbyname2_freemem_ptr);
> + call_free_static_weak (__libc_getnetbyaddr_freemem_ptr);
> + call_free_static_weak (__libc_getnetbyname_freemem_ptr);
> + call_free_static_weak (__libc_getprotobynumber_freemem_ptr);
> + call_free_static_weak (__libc_getprotobyname_freemem_ptr);
> + call_free_static_weak (__libc_getrpcbyname_freemem_ptr);
> + call_free_static_weak (__libc_getrpcbynumber_freemem_ptr);
> + call_free_static_weak (__libc_getservbyname_freemem_ptr);
> + call_free_static_weak (__libc_getservbyport_freemem_ptr);
> +
> + call_free_static_weak (__libc_getgrent_freemem_ptr);
> + call_free_static_weak (__libc_getpwent_freemem_ptr);
> + call_free_static_weak (__libc_getspent_freemem_ptr);
> + call_free_static_weak (__libc_getaliasent_freemem_ptr);
> + call_free_static_weak (__libc_gethostent_freemem_ptr);
> + call_free_static_weak (__libc_getnetent_freemem_ptr);
> + call_free_static_weak (__libc_getprotoent_freemem_ptr);
> + call_free_static_weak (__libc_getrpcent_freemem_ptr);
> + call_free_static_weak (__libc_getservent_freemem_ptr);
> +
> + call_free_static_weak (__libc_efgcvt_freemem_ptr);
> + call_free_static_weak (__libc_qefgcvt_freemem_ptr);
OK.
> +
> + call_freeres_system_funcs;
> }
> }
> libc_hidden_def (__libc_freeres)
> diff --git a/malloc/thread-freeres.c b/malloc/thread-freeres.c
> index b22e1d789f..a4fbc890b3 100644
> --- a/malloc/thread-freeres.c
> +++ b/malloc/thread-freeres.c
> @@ -16,18 +16,15 @@
> License along with the GNU C Library; if not, see
> <https://www.gnu.org/licenses/>. */
>
> -#include <dlfcn/dlerror.h>
> #include <libc-internal.h>
> #include <malloc-internal.h>
> -#include <resolv/resolv-internal.h>
> -#include <rpc/rpc.h>
> -#include <string.h>
> -#include <tls-internal.h>
> +#include <set-freeres.h>
> #include <shlib-compat.h>
> +#include <tls-internal.h>
>
> /* Thread shutdown function. Note that this function must be called
> for threads during shutdown for correctness reasons. Unlike
> - __libc_subfreeres, skipping calls to it is not a valid optimization.
> + __libc_freeres, skipping calls to it is not a valid optimization.
> This is called directly from pthread_create as the thread exits. */
> void
> __libc_thread_freeres (void)
> diff --git a/misc/efgcvt-template.c b/misc/efgcvt-template.c
> index 87a90e78d4..816a13701d 100644
> --- a/misc/efgcvt-template.c
> +++ b/misc/efgcvt-template.c
> @@ -22,6 +22,7 @@
> #include <sys/param.h>
> #include <libc-lock.h>
> #include <math_ldbl_opt.h>
> +#include <set-freeres.h>
>
> #ifndef SPRINTF
> # define SPRINTF sprintf
> @@ -38,7 +39,7 @@
>
> static char FCVT_BUFFER[MAXDIG];
> static char ECVT_BUFFER[MAXDIG];
> -libc_freeres_ptr (static char *FCVT_BUFPTR);
> +static char *FCVT_BUFPTR;
>
> char *
> __FCVT (FLOAT_TYPE value, int ndigit, int *decpt, int *sign)
> @@ -73,3 +74,5 @@ __GCVT (FLOAT_TYPE value, int ndigit, char *buf)
> SPRINTF (buf, "%.*" FLOAT_FMT_FLAG "g", MIN (ndigit, NDIGIT_MAX), value);
> return buf;
> }
> +
> +weak_alias (FCVT_BUFPTR, __EFGCVT_FREEMEM_PTR);
> diff --git a/misc/efgcvt.c b/misc/efgcvt.c
> index 95f1443d60..e9a866ef19 100644
> --- a/misc/efgcvt.c
> +++ b/misc/efgcvt.c
> @@ -24,6 +24,7 @@
> #define __GCVT __gcvt
> #define __ECVT_R __ecvt_r
> #define __FCVT_R __fcvt_r
> +#define __EFGCVT_FREEMEM_PTR __libc_efgcvt_freemem_ptr
> #include <efgcvt-dbl-macros.h>
> #include <efgcvt-template.c>
>
> diff --git a/misc/fstab.c b/misc/fstab.c
> index 952f7adc36..f55657ee17 100644
> --- a/misc/fstab.c
> +++ b/misc/fstab.c
> @@ -177,7 +177,8 @@ 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. */
> -libc_freeres_fn (fstab_free)
> +void
> +__libc_fstab_freemem (void)
> {
> char *buffer;
>
> diff --git a/misc/hsearch.c b/misc/hsearch.c
> index 3b7be37f81..37994b053e 100644
> --- a/misc/hsearch.c
> +++ b/misc/hsearch.c
> @@ -46,7 +46,3 @@ __hdestroy (void)
> __hdestroy_r (&htab);
> }
> weak_alias (__hdestroy, hdestroy)
> -
> -/* Make sure the table is freed if we want to free everything before
> - exiting. */
> -text_set_element (__libc_subfreeres, __hdestroy);
> diff --git a/misc/mntent.c b/misc/mntent.c
> index 44e54df669..7511384c85 100644
> --- a/misc/mntent.c
> +++ b/misc/mntent.c
> @@ -19,6 +19,7 @@
> #include <mntent.h>
> #include <stdlib.h>
> #include <allocate_once.h>
> +#include <set-freeres.h>
>
> struct mntent_buffer
> {
> @@ -28,7 +29,7 @@ struct mntent_buffer
>
> /* We don't want to allocate the static buffer all the time since it
> is not always used (in fact, rather infrequently). */
> -libc_freeres_ptr (static void *mntent_buffer);
> +static void *mntent_buffer;
>
> static void *
> allocate (void *closure)
> @@ -56,3 +57,5 @@ getmntent (FILE *stream)
> return __getmntent_r (stream, &buffer->m,
> buffer->buffer, sizeof (buffer->buffer));
> }
> +
> +weak_alias (mntent_buffer, __libc_mntent_freemem_ptr)
> diff --git a/misc/qefgcvt.c b/misc/qefgcvt.c
> index f48e0b6016..0773987e63 100644
> --- a/misc/qefgcvt.c
> +++ b/misc/qefgcvt.c
> @@ -24,6 +24,7 @@
> #define __GCVT __qgcvt
> #define __ECVT_R __qecvt_r
> #define __FCVT_R __qfcvt_r
> +#define __EFGCVT_FREEMEM_PTR __libc_qefgcvt_freemem_ptr
> #include <efgcvt-ldbl-macros.h>
> #include <efgcvt-template.c>
>
> diff --git a/misc/unwind-link.c b/misc/unwind-link.c
> index e8653bbaf1..0e01eed7fc 100644
> --- a/misc/unwind-link.c
> +++ b/misc/unwind-link.c
> @@ -131,7 +131,7 @@ __libc_unwind_link_after_fork (void)
> }
> }
>
> -void __libc_freeres_fn_section
> +void
> __libc_unwind_link_freeres (void)
> {
> if (global_libgcc_handle != NULL)
> diff --git a/nptl/nptlfreeres.c b/nptl/nptlfreeres.c
> index c67456d9d3..90b7b13287 100644
> --- a/nptl/nptlfreeres.c
> +++ b/nptl/nptlfreeres.c
> @@ -16,7 +16,6 @@
> License along with the GNU C Library; if not, see
> <https://www.gnu.org/licenses/>. */
>
> -#include <set-hooks.h>
> #include <libc-symbols.h>
> #include <pthreadP.h>
> #include <nptl-stack.h>
> diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c
> index bde3b588a0..5afa258c19 100644
> --- a/nscd/nscd_getgr_r.c
> +++ b/nscd/nscd_getgr_r.c
> @@ -68,7 +68,8 @@ libc_locked_map_ptr (,__gr_map_handle) attribute_hidden;
> /* Note that we only free the structure if necessary. The memory
> mapping is not removed since it is not visible to the malloc
> handling. */
> -libc_freeres_fn (gr_map_free)
> +void
> +__nscd_gr_map_freemem (void)
> {
> if (__gr_map_handle.mapped != NO_MAPPING)
> {
> diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c
> index 5958f181db..5b10771167 100644
> --- a/nscd/nscd_gethst_r.c
> +++ b/nscd/nscd_gethst_r.c
> @@ -81,7 +81,8 @@ libc_locked_map_ptr (, __hst_map_handle) attribute_hidden;
> /* Note that we only free the structure if necessary. The memory
> mapping is not removed since it is not visible to the malloc
> handling. */
> -libc_freeres_fn (hst_map_free)
> +void
> +__nscd_hst_map_freemem (void)
> {
> if (__hst_map_handle.mapped != NO_MAPPING)
> {
> diff --git a/nscd/nscd_getpw_r.c b/nscd/nscd_getpw_r.c
> index 82fdd17d8c..52256b58c4 100644
> --- a/nscd/nscd_getpw_r.c
> +++ b/nscd/nscd_getpw_r.c
> @@ -67,7 +67,8 @@ libc_locked_map_ptr (static, map_handle);
> /* Note that we only free the structure if necessary. The memory
> mapping is not removed since it is not visible to the malloc
> handling. */
> -libc_freeres_fn (pw_map_free)
> +void
> +__nscd_pw_map_freemem (void)
> {
> if (map_handle.mapped != NO_MAPPING)
> {
> diff --git a/nscd/nscd_getserv_r.c b/nscd/nscd_getserv_r.c
> index de843b3363..92c80fe8fe 100644
> --- a/nscd/nscd_getserv_r.c
> +++ b/nscd/nscd_getserv_r.c
> @@ -62,7 +62,8 @@ libc_locked_map_ptr (, __serv_map_handle) attribute_hidden;
> /* Note that we only free the structure if necessary. The memory
> mapping is not removed since it is not visible to the malloc
> handling. */
> -libc_freeres_fn (serv_map_free)
> +void
> +__nscd_serv_map_freemem (void)
> {
> if (__serv_map_handle.mapped != NO_MAPPING)
> {
> diff --git a/nscd/nscd_netgroup.c b/nscd/nscd_netgroup.c
> index 11b7f3214c..33c0096f86 100644
> --- a/nscd/nscd_netgroup.c
> +++ b/nscd/nscd_netgroup.c
> @@ -31,7 +31,8 @@ libc_locked_map_ptr (static, map_handle);
> /* Note that we only free the structure if necessary. The memory
> mapping is not removed since it is not visible to the malloc
> handling. */
> -libc_freeres_fn (pw_map_free)
> +void
> +__nscd_group_map_freemem (void)
> {
> if (map_handle.mapped != NO_MAPPING)
> {
> diff --git a/nss/getXXbyYY.c b/nss/getXXbyYY.c
> index 35a3a81e2b..522030bddd 100644
> --- a/nss/getXXbyYY.c
> +++ b/nss/getXXbyYY.c
> @@ -20,6 +20,7 @@
> #include <libc-lock.h>
> #include <stdlib.h>
> #include <resolv.h>
> +#include <set-freeres.h>
>
> #include "nsswitch.h"
>
> @@ -58,6 +59,9 @@
> #define APPEND_R1(name) name##_r
> #define INTERNAL(name) INTERNAL1 (name)
> #define INTERNAL1(name) __##name
> +#define APPEND_FREEMEM_NAME1(name) __libc_##name##_freemem_ptr
> +#define APPEND_FREEMEM_NAME(name) APPEND_FREEMEM_NAME1(name)
> +#define FREEMEM_NAME APPEND_FREEMEM_NAME (FUNCTION_NAME)
>
> /* Sometimes we need to store error codes in the `h_errno' variable. */
> #ifdef NEED_H_ERRNO
> @@ -86,8 +90,9 @@ extern int INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf,
> __libc_lock_define_initialized (static, lock);
>
> /* This points to the static buffer used. */
> -libc_freeres_ptr (static char *buffer);
> +static char *buffer;
>
> +weak_alias (buffer, FREEMEM_NAME)
>
> LOOKUP_TYPE *
> FUNCTION_NAME (ADD_PARAMS)
> diff --git a/nss/getXXent.c b/nss/getXXent.c
> index 35720a05dd..ea3ca918b0 100644
> --- a/nss/getXXent.c
> +++ b/nss/getXXent.c
> @@ -18,6 +18,7 @@
> #include <errno.h>
> #include <libc-lock.h>
> #include <stdlib.h>
> +#include <set-freeres.h>
>
> #include "nsswitch.h"
>
> @@ -43,6 +44,9 @@
> #define APPEND_R1(name) name##_r
> #define INTERNAL(name) INTERNAL1 (name)
> #define INTERNAL1(name) __##name
> +#define APPEND_FREEMEM_NAME1(name) __libc_##name##_freemem_ptr
> +#define APPEND_FREEMEM_NAME(name) APPEND_FREEMEM_NAME1(name)
> +#define FREEMEM_NAME APPEND_FREEMEM_NAME (GETFUNC_NAME)
>
> /* Sometimes we need to store error codes in the `h_errno' variable. */
> #ifdef NEED_H_ERRNO
> @@ -62,8 +66,9 @@ extern int INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *resbuf, char *buffer,
> __libc_lock_define_initialized (static, lock);
>
> /* This points to the static buffer used. */
> -libc_freeres_ptr (static char *buffer);
> +static char *buffer;
>
> +weak_alias (buffer, FREEMEM_NAME)
>
> LOOKUP_TYPE *
> GETFUNC_NAME (void)
> diff --git a/nss/nss_action.c b/nss/nss_action.c
> index babea4e735..893880790f 100644
> --- a/nss/nss_action.c
> +++ b/nss/nss_action.c
> @@ -102,7 +102,7 @@ __nss_action_allocate (struct nss_action *actions, size_t count)
> return result;
> }
>
> -void __libc_freeres_fn_section
> +void
> __nss_action_freeres (void)
> {
> struct nss_action_list_wrapper *current = nss_actions;
> diff --git a/nss/nss_action.h b/nss/nss_action.h
> index 54c397c12f..d3da4f6617 100644
> --- a/nss/nss_action.h
> +++ b/nss/nss_action.h
> @@ -101,8 +101,5 @@ nss_action_list __nss_action_allocate (struct nss_action *actions,
> EINVAL means that LINE is syntactically invalid. */
> nss_action_list __nss_action_parse (const char *line);
>
> -/* Called from __libc_freeres. */
> -void __nss_action_freeres (void) attribute_hidden;
> -
>
> #endif /* _NSS_ACTION_H */
> diff --git a/nss/nss_database.c b/nss/nss_database.c
> index f2ed2f2c25..7e5b7f362b 100644
> --- a/nss/nss_database.c
> +++ b/nss/nss_database.c
> @@ -495,7 +495,7 @@ __nss_database_get_noreload (enum nss_database db)
> return result;
> }
>
> -void __libc_freeres_fn_section
> +void
> __nss_database_freeres (void)
> {
> free (global_database_state);
> diff --git a/nss/nss_database.h b/nss/nss_database.h
> index c28d6a861d..92ef189453 100644
> --- a/nss/nss_database.h
> +++ b/nss/nss_database.h
> @@ -64,9 +64,6 @@ libc_hidden_proto (__nss_database_get)
> nss_action_list __nss_database_get_noreload (enum nss_database db)
> attribute_hidden;
>
> -/* Called from __libc_freeres. */
> -void __nss_database_freeres (void) attribute_hidden;
> -
> /* Internal type. Exposed only for fork handling purposes. */
> struct nss_database_data
> {
> diff --git a/nss/nss_module.c b/nss/nss_module.c
> index 444facb9b8..ed224018b1 100644
> --- a/nss/nss_module.c
> +++ b/nss/nss_module.c
> @@ -416,7 +416,7 @@ __nss_module_disable_loading (void)
> __libc_lock_unlock (nss_module_list_lock);
> }
>
> -void __libc_freeres_fn_section
> +void
> __nss_module_freeres (void)
> {
> struct nss_module *current = nss_module_list;
> diff --git a/nss/nss_module.h b/nss/nss_module.h
> index b0eb067f2a..8cb76f1950 100644
> --- a/nss/nss_module.h
> +++ b/nss/nss_module.h
> @@ -100,7 +100,4 @@ void *__nss_module_get_function (struct nss_module *module, const char *name)
> /* Block attempts to dlopen any module we haven't already opened. */
> void __nss_module_disable_loading (void);
>
> -/* Called from __libc_freeres. */
> -void __nss_module_freeres (void) attribute_hidden;
> -
> #endif /* NSS_MODULE_H */
> diff --git a/posix/regcomp.c b/posix/regcomp.c
> index 84fc1cc82b..634dccf03f 100644
> --- a/posix/regcomp.c
> +++ b/posix/regcomp.c
> @@ -710,7 +710,8 @@ re_comp (const char *s)
> }
>
> #ifdef _LIBC
> -libc_freeres_fn (free_mem)
> +void
> +__libc_regcomp_freemem (void)
> {
> __regfree (&re_comp_buf);
> }
> diff --git a/posix/register-atfork.c b/posix/register-atfork.c
> index c039fb454f..d386731b92 100644
> --- a/posix/register-atfork.c
> +++ b/posix/register-atfork.c
> @@ -217,7 +217,8 @@ __run_postfork_handlers (enum __run_fork_handler_type who, _Bool do_locking,
> }
>
>
> -libc_freeres_fn (free_mem)
> +void
> +__libc_atfork_freemem (void)
> {
> lll_lock (atfork_lock, LLL_PRIVATE);
>
> diff --git a/pwd/fgetpwent.c b/pwd/fgetpwent.c
> index 1ddc98a0d0..806416d761 100644
> --- a/pwd/fgetpwent.c
> +++ b/pwd/fgetpwent.c
> @@ -20,12 +20,13 @@
> #include <pwd.h>
> #include <stdio.h>
> #include <stdlib.h>
> +#include <set-freeres.h>
>
>
> /* We need to protect the dynamic buffer handling. */
> __libc_lock_define_initialized (static, lock);
>
> -libc_freeres_ptr (static char *buffer);
> +static char *buffer;
>
> /* Read one entry from the given stream. */
> struct passwd *
> @@ -82,3 +83,5 @@ fgetpwent (FILE *stream)
>
> return result;
> }
> +
> +weak_alias (buffer, __libc_fgetpwent_freemem_ptr)
> diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c
> index 8ce3c778eb..b6fcd0f301 100644
> --- a/resolv/gai_misc.c
> +++ b/resolv/gai_misc.c
> @@ -434,7 +434,11 @@ handle_requests (void *arg)
>
>
> /* Free allocated resources. */
> -libc_freeres_fn (free_res)
> +#if !PTHREAD_IN_LIBC
> +__attribute__ ((__destructor__)) static
> +#endif
> +void
> +__gai_freemem (void)
> {
> size_t row;
>
> diff --git a/resolv/res-close.c b/resolv/res-close.c
> index dd116ea5c0..55e49b6db0 100644
> --- a/resolv/res-close.c
> +++ b/resolv/res-close.c
> @@ -140,5 +140,3 @@ __res_thread_freeres (void)
> /* Make sure we do a full re-initialization the next time. */
> _res.options = 0;
> }
> -/* Also must be called when the main thread exits. */
> -text_set_element (__libc_subfreeres, __res_thread_freeres);
> diff --git a/resolv/res_hconf.c b/resolv/res_hconf.c
> index dd09a2a255..5a995e74c1 100644
> --- a/resolv/res_hconf.c
> +++ b/resolv/res_hconf.c
> @@ -42,6 +42,7 @@
> #include "res_hconf.h"
> #include <wchar.h>
> #include <atomic.h>
> +#include <set-freeres.h>
>
> #if IS_IN (libc)
> # define fgets_unlocked __fgets_unlocked
> @@ -330,19 +331,8 @@ _res_hconf_init (void)
> #if IS_IN (libc)
> # if defined SIOCGIFCONF && defined SIOCGIFNETMASK
> /* List of known interfaces. */
> -libc_freeres_ptr (
> -static struct netaddr
> -{
> - int addrtype;
> - union
> - {
> - struct
> - {
> - uint32_t addr;
> - uint32_t mask;
> - } ipv4;
> - } u;
> -} *ifaddrs);
> +static struct netaddr *ifaddrs;
> +weak_alias (ifaddrs, __libc_resolv_res_hconf_freemem_ptr)
> # endif
>
> /* Reorder addresses returned in a hostent such that the first address
> diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h
> index bb12f474d2..d47004a780 100644
> --- a/resolv/resolv-internal.h
> +++ b/resolv/resolv-internal.h
> @@ -34,6 +34,20 @@
> loads and stores. */
> typedef HEADER __attribute__ ((__aligned__(1))) UHEADER;
>
> +/* List of known interfaces. */
> +struct netaddr
> +{
> + int addrtype;
> + union
> + {
> + struct
> + {
> + uint32_t addr;
> + uint32_t mask;
> + } ipv4;
> + } u;
> +};
> +
> /* Legacy function. This needs to be removed once all NSS modules
> have been adjusted. */
> static inline bool
> diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
> index 6dd552bb47..2fb6b36839 100644
> --- a/resolv/resolv_conf.c
> +++ b/resolv/resolv_conf.c
> @@ -654,7 +654,8 @@ __resolv_conf_detach (struct __res_state *resp)
> }
>
> /* Deallocate the global data. */
> -libc_freeres_fn (freeres)
> +void
> +__libc_resolv_conf_freemem (void)
> {
> /* No locking because this function is supposed to be called when
> the process has turned single-threaded. */
> diff --git a/resolv/tst-leaks2.c b/resolv/tst-leaks2.c
> index 160d4728d5..48d643dcde 100644
> --- a/resolv/tst-leaks2.c
> +++ b/resolv/tst-leaks2.c
> @@ -23,6 +23,8 @@
> #include <resolv.h>
> #include <support/check.h>
>
> +void __libc_freeres (void);
> +
> static int
> do_test (void)
> {
> diff --git a/rt/aio_misc.c b/rt/aio_misc.c
> index b4304d0a6f..2e62e80de2 100644
> --- a/rt/aio_misc.c
> +++ b/rt/aio_misc.c
> @@ -694,7 +694,11 @@ handle_fildes_io (void *arg)
>
>
> /* Free allocated resources. */
> -libc_freeres_fn (free_res)
> +#if !PTHREAD_IN_LIBC
> +__attribute__ ((__destructor__)) static
> +#endif
> +void
> +__aio_freemem (void)
> {
> size_t row;
>
> diff --git a/shadow/fgetspent.c b/shadow/fgetspent.c
> index 5f75e31c29..63b52c40be 100644
> --- a/shadow/fgetspent.c
> +++ b/shadow/fgetspent.c
> @@ -20,6 +20,7 @@
> #include <shadow.h>
> #include <stdio.h>
> #include <stdlib.h>
> +#include <set-freeres.h>
>
>
> /* A reasonable size for a buffer to start with. */
> @@ -28,7 +29,7 @@
> /* We need to protect the dynamic buffer handling. */
> __libc_lock_define_initialized (static, lock);
>
> -libc_freeres_ptr (static char *buffer);
> +static char *buffer;
>
> /* Read one shadow entry from the given stream. */
> struct spwd *
> @@ -85,3 +86,5 @@ fgetspent (FILE *stream)
>
> return result;
> }
> +
> +weak_alias (buffer, __libc_fgetspent_freemem_ptr);
> diff --git a/stdio-common/reg-modifier.c b/stdio-common/reg-modifier.c
> index fa1cd2ac3c..b8232b5ff8 100644
> --- a/stdio-common/reg-modifier.c
> +++ b/stdio-common/reg-modifier.c
> @@ -183,7 +183,8 @@ __handle_registered_modifier_wc (const unsigned int **format,
> }
>
>
> -libc_freeres_fn (free_mem)
> +void
> +__libc_printf_freemem (void)
> {
> if (__printf_modifier_table != NULL)
> {
> diff --git a/stdio-common/reg-printf.c b/stdio-common/reg-printf.c
> index 5f4c6a24c2..a9b6cbbb40 100644
> --- a/stdio-common/reg-printf.c
> +++ b/stdio-common/reg-printf.c
> @@ -21,11 +21,11 @@
> #include <stddef.h>
> #include <stdlib.h>
> #include <libc-lock.h>
> +#include <set-freeres.h>
>
>
> /* Array of functions indexed by format character. */
> -libc_freeres_ptr (printf_arginfo_size_function **__printf_arginfo_table)
> - attribute_hidden;
> +printf_arginfo_size_function **__printf_arginfo_table attribute_hidden;
> printf_function **__printf_function_table attribute_hidden;
>
> __libc_lock_define_initialized (static, lock)
> @@ -79,3 +79,5 @@ __register_printf_function (int spec, printf_function converter,
> (printf_arginfo_size_function*) arginfo);
> }
> weak_alias (__register_printf_function, register_printf_function)
> +
> +weak_alias (__printf_arginfo_table, __libc_reg_printf_freemem_ptr)
> diff --git a/stdio-common/reg-type.c b/stdio-common/reg-type.c
> index f308db6323..2d4f412fa5 100644
> --- a/stdio-common/reg-type.c
> +++ b/stdio-common/reg-type.c
> @@ -19,11 +19,11 @@
> #include <printf.h>
> #include <stdlib.h>
> #include <libc-lock.h>
> +#include <set-freeres.h>
>
>
> /* Array of functions indexed by format character. */
> -libc_freeres_ptr (printf_va_arg_function **__printf_va_arg_table)
> - attribute_hidden;
> +printf_va_arg_function **__printf_va_arg_table attribute_hidden;
>
> __libc_lock_define_initialized (static, lock);
>
> @@ -59,3 +59,5 @@ __register_printf_type (printf_va_arg_function fct)
> return result;
> }
> weak_alias (__register_printf_type, register_printf_type)
> +
> +weak_alias (__printf_va_arg_table, __libc_reg_type_freemem_ptr)
> diff --git a/stdlib/exit.c b/stdlib/exit.c
> index 98579fbda8..392b37259b 100644
> --- a/stdlib/exit.c
> +++ b/stdlib/exit.c
> @@ -20,7 +20,7 @@
> #include <unistd.h>
> #include <pointer_guard.h>
> #include <libc-lock.h>
> -#include <libio/libioP.h>
> +#include <set-freeres.h>
> #include "exit.h"
>
> /* Initialize the flag that indicates exit function processing
> diff --git a/stdlib/fmtmsg.c b/stdlib/fmtmsg.c
> index 787a263d63..7561a2936b 100644
> --- a/stdlib/fmtmsg.c
> +++ b/stdlib/fmtmsg.c
> @@ -361,7 +361,8 @@ __addseverity (int severity, const char *string)
> weak_alias (__addseverity, addseverity)
>
>
> -libc_freeres_fn (free_mem)
> +void
> +__libc_fmtmsg_freemem (void)
> {
> struct severity_info *runp = severity_list;
>
> diff --git a/stdlib/setenv.c b/stdlib/setenv.c
> index 2176cbac31..e44d41019c 100644
> --- a/stdlib/setenv.c
> +++ b/stdlib/setenv.c
> @@ -323,7 +323,8 @@ clearenv (void)
> return 0;
> }
> #ifdef _LIBC
> -libc_freeres_fn (free_mem)
> +void
> +__libc_setenv_freemem (void)
> {
> /* Remove all traces. */
> clearenv ();
> diff --git a/sunrpc/clnt_perr.c b/sunrpc/clnt_perr.c
> index 67499fd03f..c3d13722df 100644
> --- a/sunrpc/clnt_perr.c
> +++ b/sunrpc/clnt_perr.c
> @@ -389,8 +389,8 @@ auth_errmsg (enum auth_stat stat)
> }
>
>
> -libc_freeres_fn (free_mem)
> +void
> +__rpc_freemem (void)
> {
> - /* Not libc_freeres_ptr, since buf is a macro. */
> free (buf);
> }
> diff --git a/sunrpc/rpc_thread.c b/sunrpc/rpc_thread.c
> index 0abe6dc172..a04b7ec47f 100644
> --- a/sunrpc/rpc_thread.c
> +++ b/sunrpc/rpc_thread.c
> @@ -37,7 +37,6 @@ __rpc_thread_destroy (void)
> thread_rpc_vars = NULL;
> }
> }
> -text_set_element (__libc_subfreeres, __rpc_thread_destroy);
>
> /*
> * Initialize RPC multi-threaded operation
> diff --git a/sunrpc/tst-svc_register.c b/sunrpc/tst-svc_register.c
> index 41c5398ab6..4f3c31c504 100644
> --- a/sunrpc/tst-svc_register.c
> +++ b/sunrpc/tst-svc_register.c
> @@ -276,9 +276,9 @@ do_test (void)
> else
> /* This is arguably a bug: Regular process termination
> does not unregister the service with rpcbind. The
> - unset rpcbind call happens from a __libc_subfreeres
> - callback, and this only happens when running under
> - memory debuggers such as valgrind. */
> + unset rpcbind call happens from a __libc_freeres,
> + and this only happens when running under memory debuggers
> + such as valgrind. */
> TEST_VERIFY (!state.unset_called);
> }
> else
> diff --git a/sysdeps/generic/set-freeres-fp.h b/sysdeps/generic/set-freeres-fp.h
> new file mode 100644
> index 0000000000..f73ac747ad
> --- /dev/null
> +++ b/sysdeps/generic/set-freeres-fp.h
> @@ -0,0 +1,19 @@
> +/* System specific resource deallocation. Generic version.
> + Copyright (C) 2022 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
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#define call_freeres_fp_funcs
> diff --git a/sysdeps/generic/set-freeres-os.h b/sysdeps/generic/set-freeres-os.h
> new file mode 100644
> index 0000000000..6b17c8307a
> --- /dev/null
> +++ b/sysdeps/generic/set-freeres-os.h
> @@ -0,0 +1,19 @@
> +/* System specific resource deallocation. Generic version.
> + Copyright (C) 2020-2022 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
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#define call_freeres_os_funcs
> diff --git a/sysdeps/generic/set-freeres-system.h b/sysdeps/generic/set-freeres-system.h
> new file mode 100644
> index 0000000000..88701a657f
> --- /dev/null
> +++ b/sysdeps/generic/set-freeres-system.h
OK. Put this in a distinct header.
> @@ -0,0 +1,27 @@
> +/* System specific resource deallocation. Generic version.
> + Copyright (C) 2022 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
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +/* Each system may define weak functions to free any resource allocated with
> + malloc to avoid interfere with mtrace. */
> +
> +#include <set-freeres-os.h>
> +#include <set-freeres-fp.h>
> +
> +#define call_freeres_system_funcs \
> + call_freeres_os_funcs; \
> + call_freeres_fp_funcs
> diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-qefgcvt.c b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-qefgcvt.c
> index 9703069b95..ad83f5d8f3 100644
> --- a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-qefgcvt.c
> +++ b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-qefgcvt.c
> @@ -42,6 +42,7 @@ typeof (qfcvt_r) ___qfcvtieee128_r;
> #define __GCVT ___qgcvtieee128
> #define __ECVT_R ___qecvtieee128_r
> #define __FCVT_R ___qfcvtieee128_r
> +#define __EFGCVT_FREEMEM_PTR __libc_efgcvtieee128_freemem_ptr
> #include <efgcvt-ldbl-macros.h>
> #include <efgcvt-template.c>
>
> diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/set-freeres-fp.h b/sysdeps/ieee754/ldbl-128ibm-compat/set-freeres-fp.h
> new file mode 100644
> index 0000000000..3f6e17612a
> --- /dev/null
> +++ b/sysdeps/ieee754/ldbl-128ibm-compat/set-freeres-fp.h
> @@ -0,0 +1,22 @@
> +/* System specific resource deallocation. IBM long double 128 version.
> + Copyright (C) 2022 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
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +extern char * __libc_efgcvtieee128_freemem_ptr attribute_hidden;
> +
> +#define call_freeres_fp_funcs \
> + call_free_static_weak (__libc_efgcvtieee128_freemem_ptr)
> diff --git a/sysdeps/mach/hurd/bits/errno.h b/sysdeps/mach/hurd/bits/errno.h
> index 90c8897739..0d935e724a 100644
> --- a/sysdeps/mach/hurd/bits/errno.h
> +++ b/sysdeps/mach/hurd/bits/errno.h
> @@ -9,7 +9,6 @@
> mach/boolean.h
> mach/i386/boolean.h
> mach/i386/vm_types.h
> - mach/i386/stdint.h
> mach/mig_errors.h
> device/device_types.h
> mach/std_types.h
> diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
> index 5cda9bb072..bdc56d9781 100644
> --- a/sysdeps/posix/getaddrinfo.c
> +++ b/sysdeps/posix/getaddrinfo.c
> @@ -1761,7 +1761,8 @@ check_gaiconf_mtime (const struct __stat64_t64 *st)
> #endif
>
>
> -libc_freeres_fn(fini)
> +void
> +__libc_getaddrinfo_freemem (void)
> {
> if (labels != default_labels)
> {
> @@ -2233,7 +2234,7 @@ no_file:
>
> /* If we previously read the file but it is gone now, free the old data and
> use the builtin one. Leave the reload flag alone. */
> - fini ();
> + __libc_getaddrinfo_freemem ();
> }
>
>
> diff --git a/sysdeps/posix/ttyname.c b/sysdeps/posix/ttyname.c
> index fd41f7fb24..db83b584af 100644
> --- a/sysdeps/posix/ttyname.c
> +++ b/sysdeps/posix/ttyname.c
> @@ -24,6 +24,7 @@
> #include <unistd.h>
> #include <string.h>
> #include <stdlib.h>
> +#include <set-freeres.h>
>
> char *__ttyname;
>
> @@ -31,7 +32,8 @@ static char *getttyname (int fd, dev_t mydev, ino_t myino,
> int save, int *dostat);
>
>
> -libc_freeres_ptr (static char *getttyname_name);
> +static char *getttyname_name;
> +weak_alias (getttyname_name, __ttyname_freemem_ptr)
>
> static char *
> getttyname (int fd, dev_t mydev, ino_t myino, int save, int *dostat)
> diff --git a/sysdeps/unix/sysv/linux/check_pf.c b/sysdeps/unix/sysv/linux/check_pf.c
> index 0b77a2d897..bdda4e890d 100644
> --- a/sysdeps/unix/sysv/linux/check_pf.c
> +++ b/sysdeps/unix/sysv/linux/check_pf.c
> @@ -362,7 +362,8 @@ __check_pf (bool *seen_ipv4, bool *seen_ipv6,
> }
>
> /* Free the cache if it has been allocated. */
> -libc_freeres_fn (freecache)
> +void
> +__check_pf_freemem (void)
> {
> if (cache)
> __free_in6ai (cache->in6ai);
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutent.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutent.c
> index 6f8a06a0c8..699cea5125 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/getutent.c
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/getutent.c
> @@ -25,6 +25,7 @@
> # define weak_alias(n,a)
> #endif
> #include "login/getutent.c"
> +_weak_alias (buffer, __libc_getutent_freemem_ptr)
>
> #if defined SHARED
> default_symbol_version (__getutent, getutent, UTMP_COMPAT_BASE);
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutid.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutid.c
> index 6114582ed3..1af1aea5ab 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/getutid.c
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/getutid.c
> @@ -25,6 +25,7 @@
> # define weak_alias(n,a)
> #endif
> #include "login/getutid.c"
> +_weak_alias (buffer, __libc_getutid_freemem_ptr)
>
> #if defined SHARED
> default_symbol_version (__getutid, getutid, UTMP_COMPAT_BASE);
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getutline.c b/sysdeps/unix/sysv/linux/s390/s390-32/getutline.c
> index 88ac71e1f4..7a49bcf9db 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/getutline.c
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/getutline.c
> @@ -25,6 +25,7 @@
> # define weak_alias(n,a)
> #endif
> #include "login/getutline.c"
> +_weak_alias (buffer, __libc_getutline_freemem_ptr)
>
> #if defined SHARED
> default_symbol_version (__getutline, getutline, UTMP_COMPAT_BASE);
> diff --git a/sysdeps/unix/sysv/linux/set-freeres-os.h b/sysdeps/unix/sysv/linux/set-freeres-os.h
> new file mode 100644
> index 0000000000..964c9a4bfc
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/set-freeres-os.h
> @@ -0,0 +1,24 @@
> +/* System specific resource deallocation. Linux version.
> + Copyright (C) 2022 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
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +extern void __check_pf_freemem (void) attribute_hidden;
> +extern char * __ttyname_freemem_ptr attribute_hidden;
> +
> +#define call_freeres_os_funcs \
> + call_function_static_weak (__check_pf_freemem); \
> + call_free_static_weak (__ttyname_freemem_ptr)
> diff --git a/sysdeps/unix/sysv/linux/ttyname.c b/sysdeps/unix/sysv/linux/ttyname.c
> index 947c1f72a1..3b6e7ee2f2 100644
> --- a/sysdeps/unix/sysv/linux/ttyname.c
> +++ b/sysdeps/unix/sysv/linux/ttyname.c
> @@ -19,15 +19,11 @@
> #include <limits.h>
> #include <termios.h>
> #include <stdlib.h>
> -
> +#include <set-freeres.h>
> #include "ttyname.h"
>
> static char *ttyname_buf = NULL;
> -
> -libc_freeres_fn (free_mem)
> -{
> - free (ttyname_buf);
> -}
> +weak_alias (ttyname_buf, __ttyname_freemem_ptr)
>
> /* Return the pathname of the terminal FD is open on, or NULL on errors.
> The returned storage is good only until the next call to this function. */
> diff --git a/time/tzfile.c b/time/tzfile.c
> index 394b098856..f4f56e56ef 100644
> --- a/time/tzfile.c
> +++ b/time/tzfile.c
> @@ -26,6 +26,7 @@
> #include <sys/stat.h>
> #include <stdint.h>
> #include <alloc_buffer.h>
> +#include <set-freeres.h>
>
> #include <timezone/tzfile.h>
>
> @@ -50,7 +51,7 @@ struct leap
> };
>
> static size_t num_transitions;
> -libc_freeres_ptr (static __time64_t *transitions);
> +static __time64_t *transitions;
> static unsigned char *type_idxs;
> static size_t num_types;
> static struct ttinfo *types;
> @@ -777,3 +778,5 @@ __tzfile_compute (__time64_t timer, int use_localtime,
> }
> }
> }
> +
> +weak_alias (transitions, __libc_tzfile_freemem_ptr)
> diff --git a/time/tzset.c b/time/tzset.c
> index a06142bb58..b8b1ee2662 100644
> --- a/time/tzset.c
> +++ b/time/tzset.c
> @@ -610,7 +610,8 @@ __tz_convert (__time64_t timer, int use_localtime, struct tm *tp)
> }
>
>
> -libc_freeres_fn (free_mem)
> +void
> +__libc_tzset_freemem (void)
> {
> while (tzstring_list != NULL)
> {
--
Cheers,
Carlos.
next prev parent reply other threads:[~2023-03-04 17:37 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-27 21:11 [PATCH v3 0/4] Remove --with-default-link option Adhemerval Zanella
2022-12-27 21:11 ` [PATCH v3 1/4] Move libc_freeres_ptrs and libc_subfreeres to hidden/weak functions Adhemerval Zanella
2023-03-04 17:37 ` Carlos O'Donell [this message]
2022-12-27 21:11 ` [PATCH v3 2/4] libio: Remove the usage of __libc_IO_vtables Adhemerval Zanella
2023-03-04 17:37 ` Carlos O'Donell
2023-03-06 13:43 ` Adhemerval Zanella Netto
2023-03-27 12:53 ` Carlos O'Donell
2023-03-06 14:58 ` Arsen Arsenović
2023-03-06 16:01 ` Adhemerval Zanella Netto
2023-03-06 16:31 ` Andreas Schwab
2023-03-06 16:39 ` Adhemerval Zanella Netto
2023-03-06 16:53 ` Andreas Schwab
2023-03-06 17:24 ` Adhemerval Zanella Netto
2023-03-06 18:17 ` Adhemerval Zanella Netto
2023-03-06 18:47 ` Arsen Arsenović
2023-03-06 18:53 ` Adhemerval Zanella Netto
2023-03-06 19:10 ` Arsen Arsenović
2023-03-06 19:20 ` Adhemerval Zanella Netto
2023-03-06 19:26 ` Arsen Arsenović
2023-03-06 16:23 ` Andreas Schwab
2022-12-27 21:11 ` [PATCH v3 3/4] Remove --with-default-link configure option Adhemerval Zanella
2023-03-04 17:39 ` Carlos O'Donell
2022-12-27 21:11 ` [PATCH v3 4/4] Remove set-hooks.h from generic includes Adhemerval Zanella
2023-03-04 17:42 ` Carlos O'Donell
2023-03-04 17:37 ` [PATCH v3 0/4] Remove --with-default-link option Carlos O'Donell
2023-03-06 13:43 ` Adhemerval Zanella Netto
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=35cd3223-8766-3b6f-2126-ea99d90ec1cb@redhat.com \
--to=carlos@redhat.com \
--cc=adhemerval.zanella@linaro.org \
--cc=fweimer@redhat.com \
--cc=libc-alpha@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).