diff --git a/elf/dl-libc.c b/elf/dl-libc.c index d55f94e40d..760cb955f7 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 0231e0fef2..e8bd7a4b98 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 bb1d0a8f72..0fb25827ec 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 c1809d3af7..2ac1df3c1c 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 @@ -136,7 +135,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);