diff options
Diffstat (limited to 'newlib/libc/sys/linux/dl/dl-close.c')
-rw-r--r-- | newlib/libc/sys/linux/dl/dl-close.c | 334 |
1 files changed, 0 insertions, 334 deletions
diff --git a/newlib/libc/sys/linux/dl/dl-close.c b/newlib/libc/sys/linux/dl/dl-close.c deleted file mode 100644 index ef53868d9..000000000 --- a/newlib/libc/sys/linux/dl/dl-close.c +++ /dev/null @@ -1,334 +0,0 @@ -/* Close a shared object opened by `_dl_open'. - Copyright (C) 1996,1997,1998,1999,2000,2001 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <assert.h> -#include <dlfcn.h> -#include <libintl.h> -#include <stdlib.h> -#include <string.h> -#include <bits/libc-lock.h> -#include <ldsodefs.h> -#include <sys/types.h> -#include <sys/mman.h> - - -/* Type of the constructor functions. */ -typedef void (*fini_t) (void); - - -void -internal_function -_dl_close (void *_map) -{ - struct reldep_list - { - struct link_map **rellist; - unsigned int nrellist; - struct reldep_list *next; - } *reldeps = NULL; - struct link_map **list; - struct link_map *map = _map; - unsigned int i; - unsigned int *new_opencount; - - /* First see whether we can remove the object at all. */ - if (__builtin_expect (map->l_flags_1 & DF_1_NODELETE, 0) - && map->l_init_called) - /* Nope. Do nothing. */ - return; - - if (__builtin_expect (map->l_opencount, 1) == 0) - _dl_signal_error (0, map->l_name, NULL, N_("shared object not open")); - - /* Acquire the lock. */ -#ifdef HAVE_DD_LOCK - __lock_acquire(_dl_load_lock); -#endif - - - /* Decrement the reference count. */ - if (map->l_opencount > 1 || map->l_type != lt_loaded) - { - /* There are still references to this object. Do nothing more. */ - if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0)) - _dl_debug_printf ("\nclosing file=%s; opencount == %u\n", - map->l_name, map->l_opencount); - - /* One decrement the object itself, not the dependencies. */ - --map->l_opencount; - -#ifdef HAVE_DD_LOCK - __lock_release(_dl_load_lock); -#endif - - return; - } - - list = map->l_initfini; - - /* Compute the new l_opencount values. */ - i = map->l_searchlist.r_nlist; - if (__builtin_expect (i == 0, 0)) - /* This can happen if we handle relocation dependencies for an - object which wasn't loaded directly. */ - for (i = 1; list[i] != NULL; ++i) - ; - - new_opencount = (unsigned int *) alloca (i * sizeof (unsigned int)); - - for (i = 0; list[i] != NULL; ++i) - { - list[i]->l_idx = i; - new_opencount[i] = list[i]->l_opencount; - } - --new_opencount[0]; - for (i = 1; list[i] != NULL; ++i) - if ((! (list[i]->l_flags_1 & DF_1_NODELETE) || ! list[i]->l_init_called) - /* Decrement counter. */ - && --new_opencount[i] == 0 - /* Test whether this object was also loaded directly. */ - && list[i]->l_searchlist.r_list != NULL) - { - /* In this case we have the decrement all the dependencies of - this object. They are all in MAP's dependency list. */ - unsigned int j; - struct link_map **dep_list = list[i]->l_searchlist.r_list; - - for (j = 1; j < list[i]->l_searchlist.r_nlist; ++j) - if (! (dep_list[j]->l_flags_1 & DF_1_NODELETE) - || ! dep_list[j]->l_init_called) - { - assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist); - --new_opencount[dep_list[j]->l_idx]; - } - } - assert (new_opencount[0] == 0); - - /* Call all termination functions at once. */ - for (i = 0; list[i] != NULL; ++i) - { - struct link_map *imap = list[i]; - if (new_opencount[i] == 0 && imap->l_type == lt_loaded - && (imap->l_info[DT_FINI] || imap->l_info[DT_FINI_ARRAY]) - && (! (imap->l_flags_1 & DF_1_NODELETE) || ! imap->l_init_called) - /* Skip any half-cooked objects that were never initialized. */ - && imap->l_init_called) - { - /* When debugging print a message first. */ - if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0)) - _dl_debug_printf ("\ncalling fini: %s\n\n", imap->l_name); - - /* Call its termination function. */ - if (imap->l_info[DT_FINI_ARRAY] != NULL) - { - ElfW(Addr) *array = - (ElfW(Addr) *) (imap->l_addr - + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr); - unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val - / sizeof (ElfW(Addr))); - unsigned int cnt; - - for (cnt = 0; cnt < sz; ++cnt) - ((fini_t) (imap->l_addr + array[cnt])) (); - } - - /* Next try the old-style destructor. */ - if (imap->l_info[DT_FINI] != NULL) - (*(void (*) (void)) DL_DT_FINI_ADDRESS - (imap, (void *) imap->l_addr - + imap->l_info[DT_FINI]->d_un.d_ptr)) (); - } - else if (new_opencount[i] != 0 && imap->l_type == lt_loaded) - { - /* The object is still used. But the object we are unloading - right now is responsible for loading it and therefore we - have the search list of the current object in its scope. - Remove it. */ - struct r_scope_elem **runp = imap->l_scope; - - while (*runp != NULL) - if (*runp == &map->l_searchlist) - { - /* Copy all later elements. */ - while ((runp[0] = runp[1]) != NULL) - ++runp; - break; - } - else - ++runp; - } - - /* Store the new l_opencount value. */ - imap->l_opencount = new_opencount[i]; - /* Just a sanity check. */ - assert (imap->l_type == lt_loaded || imap->l_opencount > 0); - } - - /* Notify the debugger we are about to remove some loaded objects. */ - _r_debug.r_state = RT_DELETE; - _dl_debug_state (); - - /* Check each element of the search list to see if all references to - it are gone. */ - for (i = 0; list[i] != NULL; ++i) - { - struct link_map *imap = list[i]; - if (imap->l_opencount == 0 && imap->l_type == lt_loaded) - { - struct libname_list *lnp; - - /* That was the last reference, and this was a dlopen-loaded - object. We can unmap it. */ - if (__builtin_expect (imap->l_global, 0)) - { - /* This object is in the global scope list. Remove it. */ - unsigned int cnt = _dl_main_searchlist->r_nlist; - - do - --cnt; - while (_dl_main_searchlist->r_list[cnt] != imap); - - /* The object was already correctly registered. */ - while (++cnt < _dl_main_searchlist->r_nlist) - _dl_main_searchlist->r_list[cnt - 1] - = _dl_main_searchlist->r_list[cnt]; - - --_dl_main_searchlist->r_nlist; - } - - /* We can unmap all the maps at once. We determined the - start address and length when we loaded the object and - the `munmap' call does the rest. */ - DL_UNMAP (imap); - - /* Finally, unlink the data structure and free it. */ -#ifdef SHARED - /* We will unlink the first object only if this is a statically - linked program. */ - assert (imap->l_prev != NULL); - imap->l_prev->l_next = imap->l_next; -#else - if (imap->l_prev != NULL) - imap->l_prev->l_next = imap->l_next; - else - _dl_loaded = imap->l_next; -#endif - --_dl_nloaded; - if (imap->l_next) - imap->l_next->l_prev = imap->l_prev; - - if (imap->l_versions != NULL) - free (imap->l_versions); - if (imap->l_origin != NULL && imap->l_origin != (char *) -1) - free ((char *) imap->l_origin); - - /* If the object has relocation dependencies save this - information for latter. */ - if (__builtin_expect (imap->l_reldeps != NULL, 0)) - { - struct reldep_list *newrel; - - newrel = (struct reldep_list *) alloca (sizeof (*reldeps)); - newrel->rellist = imap->l_reldeps; - newrel->nrellist = imap->l_reldepsact; - newrel->next = reldeps; - - reldeps = newrel; - } - - /* This name always is allocated. */ - free (imap->l_name); - /* Remove the list with all the names of the shared object. */ - lnp = imap->l_libname; - do - { - struct libname_list *this = lnp; - lnp = lnp->next; - if (!this->dont_free) - free (this); - } - while (lnp != NULL); - - /* Remove the searchlists. */ - if (imap != map) - free (imap->l_initfini); - - /* Remove the scope array if we allocated it. */ - if (imap->l_scope != imap->l_scope_mem) - free (imap->l_scope); - - if (imap->l_phdr_allocated) - free ((void *) imap->l_phdr); - - if (imap->l_rpath_dirs.dirs != (void *) -1) - free (imap->l_rpath_dirs.dirs); - if (imap->l_runpath_dirs.dirs != (void *) -1) - free (imap->l_runpath_dirs.dirs); - - free (imap); - } - } - - /* Notify the debugger those objects are finalized and gone. */ - _r_debug.r_state = RT_CONSISTENT; - _dl_debug_state (); - - /* Now we can perhaps also remove the modules for which we had - dependencies because of symbol lookup. */ - while (__builtin_expect (reldeps != NULL, 0)) - { - while (reldeps->nrellist-- > 0) - _dl_close (reldeps->rellist[reldeps->nrellist]); - - free (reldeps->rellist); - - reldeps = reldeps->next; - } - - free (list); - - /* Release the lock. */ -#ifdef HAVE_DD_LOCK - __lock_release(_dl_load_lock); -#endif - - -} - - -static void -free_mem (void) -{ - if (__builtin_expect (_dl_global_scope_alloc, 0) != 0 - && _dl_main_searchlist->r_nlist == _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 = _dl_main_searchlist->r_list; - - /* Put the old map in. */ - _dl_main_searchlist->r_list = _dl_initial_searchlist.r_list; - /* Signal that the original map is used. */ - _dl_global_scope_alloc = 0; - - /* Now free the old map. */ - free (old); - } -} -text_set_element (__libc_subfreeres, free_mem); |