From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 1B2123858025 for ; Sat, 4 Mar 2023 17:37:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1B2123858025 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1677951433; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OGeJa4m0aRmmko0IaWrgUYn+VDm3nxsRtvFHSPZPivM=; b=E8AiLBRlYRsMu40NUm7iJWDJtNQk4fnMfrfWpqAj5QLcv2/IBG2B+MggGbHcLSNXvgjbvP 4MKcvpF0oQyEj7xR4w06VUjf+92VoONJ0eY6fpJEzU3vujyRTisE7/hFlfoNruN6lTTV1k yfJB8zfAeQgTxwZsco96hccnq5UT3yQ= Received: from mail-io1-f69.google.com (mail-io1-f69.google.com [209.85.166.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-634-oPSBVMN9M3aoa0rNPz_GJA-1; Sat, 04 Mar 2023 12:37:12 -0500 X-MC-Unique: oPSBVMN9M3aoa0rNPz_GJA-1 Received: by mail-io1-f69.google.com with SMTP id b26-20020a5d805a000000b0074cfe3a44aeso3083866ior.10 for ; Sat, 04 Mar 2023 09:37:12 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1677951431; h=content-transfer-encoding:in-reply-to:organization:from:references :to:content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=OGeJa4m0aRmmko0IaWrgUYn+VDm3nxsRtvFHSPZPivM=; b=lYT/vHVixjlBdLiOr8Pvw7VHxQCKhlXYRAGt7AuIXtYe/HagIPw5+T8TVrmOqKn8Yu zsv7RBdE8Gkf7eovBiFyDNBG06/J22DiyBBlgClbUPSBVCj0MDQGXy1acFztJBHccO9e iDvUrmkemAorQ1cHZVE11rXVg99GzjIqtNTUvEihNUHDhvOnPjta4IrTEDs4mLps0iqQ eIJYa7wQqBwqPnYghtIrLoVMzgiyHjqd2SD234AMUocp+FKL8O2ZoH4pO6Ek8hOV0cHs A7CuXBKuDUOn92ypwhIlZTHOVDEwWawkbznV6JwNaP4cuLfkoBFU7KU/4sfQMRxVW5q/ kU3w== X-Gm-Message-State: AO0yUKVQo8u0/dQ3hPocPSAgsVeEqJLqtyof2W3s6z5VS8GvgMPNAvos BHzYtHg0dAM7vu51KBh1r9rgHvcASOLPtLhIKtiyswtJ5w6VGg/mM3lM/Hxn0gUCFDtxqMsiSo5 ZqyE3hqJL8fJ6iZl/bKMuvEUqpYsT X-Received: by 2002:a05:6e02:1686:b0:318:8674:bf3 with SMTP id f6-20020a056e02168600b0031886740bf3mr5540548ila.19.1677951429755; Sat, 04 Mar 2023 09:37:09 -0800 (PST) X-Google-Smtp-Source: AK7set/q4Va1+PhiuPDRBMxcx6189VFu1uQdUP6a7pHWMRIghZlY5tckkrJPVD7EUNP1K3CiAxKXGA== X-Received: by 2002:a05:6e02:1686:b0:318:8674:bf3 with SMTP id f6-20020a056e02168600b0031886740bf3mr5540525ila.19.1677951428726; Sat, 04 Mar 2023 09:37:08 -0800 (PST) Received: from [192.168.0.241] ([198.48.244.52]) by smtp.gmail.com with ESMTPSA id c17-20020a02a611000000b003eb1eee43a7sm1658180jam.112.2023.03.04.09.37.07 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 04 Mar 2023 09:37:08 -0800 (PST) Message-ID: <35cd3223-8766-3b6f-2126-ea99d90ec1cb@redhat.com> Date: Sat, 4 Mar 2023 12:37:07 -0500 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.8.0 Subject: Re: [PATCH v3 1/4] Move libc_freeres_ptrs and libc_subfreeres to hidden/weak functions To: Adhemerval Zanella , libc-alpha@sourceware.org, Florian Weimer References: <20221227211145.3765256-1-adhemerval.zanella@linaro.org> <20221227211145.3765256-2-adhemerval.zanella@linaro.org> From: Carlos O'Donell Organization: Red Hat In-Reply-To: <20221227211145.3765256-2-adhemerval.zanella@linaro.org> X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP,URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: 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 > > 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 > #include > #include > +#include > > > /* 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 > #include > #include > +#include > > > /* 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 > + . */ > + > +#ifndef _SET_FREERES_H > +#define _SET_FREERES_H 1 > + > +#include > +#include > +#include > +#include > + > +/* 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 > #include > #include > +#include > > #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 > #include > #include > +#include > > /* 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 > #include > #include > +#include > > > 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 > #include > #include > +#include > > 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 > +#include > > 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 > #include > +#include > > > /* 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 > #include > - > +#include > > /* 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 > #include > +#include > > > /* 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 > . */ > > +#include > #include > #include > -#include > #include > #include > -#include > #include > +#include > +#include > + > +#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 > . */ > > -#include > #include > #include > -#include > -#include > -#include > -#include > +#include > #include > +#include > > /* 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 > #include > #include > +#include > > #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 > #include > > 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 > #include > #include > +#include > > 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 > #include > > 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 > . */ > > -#include > #include > #include > #include > 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 > #include > #include > +#include > > #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 > #include > #include > +#include > > #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 > #include > #include > +#include > > > /* 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 > #include > +#include > > #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 > #include > > +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 > #include > #include > +#include > > > /* 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 > #include > #include > +#include > > > /* 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 > #include > #include > +#include > > > /* 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 > #include > #include > -#include > +#include > #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 > + . */ > + > +#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 > + . */ > + > +#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 > + . */ > + > +/* Each system may define weak functions to free any resource allocated with > + malloc to avoid interfere with mtrace. */ > + > +#include > +#include > + > +#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 > #include > > 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 > + . */ > + > +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 > #include > #include > +#include > > 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 > + . */ > + > +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 > #include > #include > - > +#include > #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 > #include > #include > +#include > > #include > > @@ -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.