aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2025-02-02 20:10:09 +0100
committerFlorian Weimer <fweimer@redhat.com>2025-02-02 20:10:09 +0100
commitd12cb8e45232f11ee77f8b6d8cd71cc96fbff4a4 (patch)
tree9a8183abdca87c4043bfb63add0533042442d47c /elf
parent749310c61b66aa2af0422db25686440b64a14800 (diff)
downloadglibc-d12cb8e45232f11ee77f8b6d8cd71cc96fbff4a4.tar.xz
glibc-d12cb8e45232f11ee77f8b6d8cd71cc96fbff4a4.zip
elf: Merge __dl_libc_freemem into __rtld_libc_freeres
The functions serve very similar purposes. The advantage of __rtld_libc_freeres is that it is located 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).
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-libc.c107
-rw-r--r--elf/dl-libc_freeres.c101
2 files changed, 101 insertions, 107 deletions
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 <ldsodefs.h>
#include <dl-find_object.h>
+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 ();
}