From patchwork Fri Jul 7 18:48:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 1805029 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.a=rsa-sha256 header.s=default header.b=S18aEl+i; dkim-atps=neutral Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QyMsm3SPmz20WT for ; Sat, 8 Jul 2023 04:50:36 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 63EBD386EAD7 for ; Fri, 7 Jul 2023 18:50:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 63EBD386EAD7 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1688755834; bh=EWb70HwnaavR9keG8nn14Gn4qfOkjQW2XawyN60zwyw=; h=To:Subject:In-Reply-To:References:Date:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=S18aEl+iRESbrlw6sZuZbGxbk84Be3P0WayxmwXuz3kp57t2M2BVLq6ANQc+UJgOA jzb+ef4SQtl0Ok3f/b7gyAbZtJPt9ftzoKh/Bbda4Sz51gE7LcZ31vAfq4oem3qPUo +Oz2lUqBjHvnFtT1fvjZiAgWuM09O1uBoSUXgV20= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org 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 4C3D9386EAD8 for ; Fri, 7 Jul 2023 18:48:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4C3D9386EAD8 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-584-LqT5CVKYMgOZudMV8QHSaQ-1; Fri, 07 Jul 2023 14:48:33 -0400 X-MC-Unique: LqT5CVKYMgOZudMV8QHSaQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id DA5073844FA9 for ; Fri, 7 Jul 2023 18:48:32 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.2.16.31]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0D3FA145414C for ; Fri, 7 Jul 2023 18:48:31 +0000 (UTC) To: libc-alpha@sourceware.org Subject: [PATCH v2 13/32] elf: Merge __dl_libc_freemem into __rtld_libc_freeres In-Reply-To: Message-ID: References: X-From-Line: b4c887759e6137b247ab0f0160ee4ca331608f04 Mon Sep 17 00:00:00 2001 Date: Fri, 07 Jul 2023 20:48:30 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE, 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 X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Florian Weimer via Libc-alpha From: Florian Weimer Reply-To: Florian Weimer Errors-To: libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org Sender: "Libc-alpha" The functions serve very similar purposes. The advantage of __rtld_libc_freeres is that it is locate within ld.so, so it is more natural to poke at link map internals there. This slightly regresses cleanup capabilities for statically linked binaries. If that becomes a problem, we should start calling __rtld_libc_freeres from __libc_freeres (perhaps after renaming it). --- elf/dl-libc.c | 107 ------------------------------------------ elf/dl-libc_freeres.c | 101 +++++++++++++++++++++++++++++++++++++++ include/set-freeres.h | 1 - malloc/set-freeres.c | 2 - 4 files changed, 101 insertions(+), 110 deletions(-) diff --git a/elf/dl-libc.c b/elf/dl-libc.c index c12e52f330..1d0ebd4793 100644 --- a/elf/dl-libc.c +++ b/elf/dl-libc.c @@ -226,110 +226,3 @@ __libc_dlclose (void *map) #endif return dlerror_run (do_dlclose, map); } - - -static bool -free_slotinfo (struct dtv_slotinfo_list **elemp) -{ - size_t cnt; - - if (*elemp == NULL) - /* Nothing here, all is removed (or there never was anything). */ - return true; - - if (!free_slotinfo (&(*elemp)->next)) - /* We cannot free the entry. */ - return false; - - /* That cleared our next pointer for us. */ - - for (cnt = 0; cnt < (*elemp)->len; ++cnt) - if ((*elemp)->slotinfo[cnt].map != NULL) - /* Still used. */ - return false; - - /* We can remove the list element. */ - free (*elemp); - *elemp = NULL; - - return true; -} - - -void -__dl_libc_freemem (void) -{ - struct link_map *l; - struct r_search_path_elem *d; - - /* Remove all search directories. */ - d = GL(dl_all_dirs); - while (d != GLRO(dl_init_all_dirs)) - { - struct r_search_path_elem *old = d; - d = d->next; - free (old); - } - - for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) - { - for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) - { - struct libname_list *lnp = l->l_libname->next; - - l->l_libname->next = NULL; - - /* Remove all additional names added to the objects. */ - while (lnp != NULL) - { - struct libname_list *old = lnp; - lnp = lnp->next; - if (! old->dont_free) - free (old); - } - - /* Free the initfini dependency list. */ - if (l->l_free_initfini) - free (l->l_initfini); - l->l_initfini = NULL; - } - - if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0 - && (GL(dl_ns)[ns]._ns_main_searchlist->r_nlist - // XXX Check whether we need NS-specific initial_searchlist - == GLRO(dl_initial_searchlist).r_nlist)) - { - /* All object dynamically loaded by the program are unloaded. Free - the memory allocated for the global scope variable. */ - struct link_map **old = GL(dl_ns)[ns]._ns_main_searchlist->r_list; - - /* Put the old map in. */ - GL(dl_ns)[ns]._ns_main_searchlist->r_list - // XXX Check whether we need NS-specific initial_searchlist - = GLRO(dl_initial_searchlist).r_list; - /* Signal that the original map is used. */ - GL(dl_ns)[ns]._ns_global_scope_alloc = 0; - - /* Now free the old map. */ - free (old); - } - } - - /* Free the memory allocated for the dtv slotinfo array. We can do - this only if all modules which used this memory are unloaded. */ -#ifdef SHARED - if (GL(dl_initial_dtv) == NULL) - /* There was no initial TLS setup, it was set up later when - it used the normal malloc. */ - free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)); - else -#endif - /* The first element of the list does not have to be deallocated. - It was allocated in the dynamic linker (i.e., with a different - malloc), and in the static library it's in .bss space. */ - free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next); - - void *scope_free_list = GL(dl_scope_free_list); - GL(dl_scope_free_list) = NULL; - free (scope_free_list); -} diff --git a/elf/dl-libc_freeres.c b/elf/dl-libc_freeres.c index d6d824acb5..d60c18d359 100644 --- a/elf/dl-libc_freeres.c +++ b/elf/dl-libc_freeres.c @@ -19,8 +19,109 @@ #include #include +static bool +free_slotinfo (struct dtv_slotinfo_list **elemp) +{ + size_t cnt; + + if (*elemp == NULL) + /* Nothing here, all is removed (or there never was anything). */ + return true; + + if (!free_slotinfo (&(*elemp)->next)) + /* We cannot free the entry. */ + return false; + + /* That cleared our next pointer for us. */ + + for (cnt = 0; cnt < (*elemp)->len; ++cnt) + if ((*elemp)->slotinfo[cnt].map != NULL) + /* Still used. */ + return false; + + /* We can remove the list element. */ + free (*elemp); + *elemp = NULL; + + return true; +} + void __rtld_libc_freeres (void) { + struct link_map *l; + struct r_search_path_elem *d; + + /* Remove all search directories. */ + d = GL(dl_all_dirs); + while (d != GLRO(dl_init_all_dirs)) + { + struct r_search_path_elem *old = d; + d = d->next; + free (old); + } + + for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) + { + for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) + { + struct libname_list *lnp = l->l_libname->next; + + l->l_libname->next = NULL; + + /* Remove all additional names added to the objects. */ + while (lnp != NULL) + { + struct libname_list *old = lnp; + lnp = lnp->next; + if (! old->dont_free) + free (old); + } + + /* Free the initfini dependency list. */ + if (l->l_free_initfini) + free (l->l_initfini); + l->l_initfini = NULL; + } + + if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0 + && (GL(dl_ns)[ns]._ns_main_searchlist->r_nlist + // XXX Check whether we need NS-specific initial_searchlist + == GLRO(dl_initial_searchlist).r_nlist)) + { + /* All object dynamically loaded by the program are unloaded. Free + the memory allocated for the global scope variable. */ + struct link_map **old = GL(dl_ns)[ns]._ns_main_searchlist->r_list; + + /* Put the old map in. */ + GL(dl_ns)[ns]._ns_main_searchlist->r_list + // XXX Check whether we need NS-specific initial_searchlist + = GLRO(dl_initial_searchlist).r_list; + /* Signal that the original map is used. */ + GL(dl_ns)[ns]._ns_global_scope_alloc = 0; + + /* Now free the old map. */ + free (old); + } + } + + /* Free the memory allocated for the dtv slotinfo array. We can do + this only if all modules which used this memory are unloaded. */ +#ifdef SHARED + if (GL(dl_initial_dtv) == NULL) + /* There was no initial TLS setup, it was set up later when + it used the normal malloc. */ + free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)); + else +#endif + /* The first element of the list does not have to be deallocated. + It was allocated in the dynamic linker (i.e., with a different + malloc), and in the static library it's in .bss space. */ + free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next); + + void *scope_free_list = GL(dl_scope_free_list); + GL(dl_scope_free_list) = NULL; + free (scope_free_list); + _dl_find_object_freeres (); } diff --git a/include/set-freeres.h b/include/set-freeres.h index 866d0e3717..4286710df9 100644 --- a/include/set-freeres.h +++ b/include/set-freeres.h @@ -38,7 +38,6 @@ 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; diff --git a/malloc/set-freeres.c b/malloc/set-freeres.c index 1aab34b586..d2ef073c75 100644 --- a/malloc/set-freeres.c +++ b/malloc/set-freeres.c @@ -28,7 +28,6 @@ # 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 @@ -90,7 +89,6 @@ __libc_freeres (void) _IO_cleanup (); /* We run the resource freeing after IO cleanup. */ - 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);