diff options
author | Florian Weimer <fweimer@redhat.com> | 2022-10-27 11:36:44 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2022-10-27 11:36:44 +0200 |
commit | 6f360366f7f76b158a0f4bf20d42f2854ad56264 (patch) | |
tree | 28f8951950311cfab96b60143e28ef96d9f9d036 /elf/dl-call_fini.c | |
parent | a65ff76c9a1811dd2396ab45563f645579c0e687 (diff) | |
download | glibc-6f360366f7f76b158a0f4bf20d42f2854ad56264.tar.gz glibc-6f360366f7f76b158a0f4bf20d42f2854ad56264.tar.xz glibc-6f360366f7f76b158a0f4bf20d42f2854ad56264.zip |
elf: Introduce to _dl_call_fini
This consolidates the destructor invocations from _dl_fini and dlclose. Remove the micro-optimization that avoids calling _dl_call_fini if they are no destructors (as dlclose is quite expensive anyway). The debug log message is now printed unconditionally. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'elf/dl-call_fini.c')
-rw-r--r-- | elf/dl-call_fini.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/elf/dl-call_fini.c b/elf/dl-call_fini.c new file mode 100644 index 0000000000..9e7ba10fa2 --- /dev/null +++ b/elf/dl-call_fini.c @@ -0,0 +1,50 @@ +/* Invoke DT_FINI and DT_FINI_ARRAY callbacks. + Copyright (C) 1996-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <ldsodefs.h> +#include <sysdep.h> + +void +_dl_call_fini (void *closure_map) +{ + struct link_map *map = closure_map; + + /* When debugging print a message first. */ + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS)) + _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n", map->l_name, map->l_ns); + + /* Make sure nothing happens if we are called twice. */ + map->l_init_called = 0; + + ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY]; + if (fini_array != NULL) + { + ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + + fini_array->d_un.d_ptr); + size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val + / sizeof (ElfW(Addr))); + + while (sz-- > 0) + ((fini_t) array[sz]) (); + } + + /* Next try the old-style destructor. */ + ElfW(Dyn) *fini = map->l_info[DT_FINI]; + if (fini != NULL) + DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr)); +} |