Update.
[glibc.git] / elf / dl-close.c
blobde4b91ac0325297ac5fc092243d7bc97ae5b96f5
1 /* Close a shared object opened by `_dl_open'.
2 Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #include <assert.h>
21 #include <dlfcn.h>
22 #include <libintl.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <bits/libc-lock.h>
26 #include <ldsodefs.h>
27 #include <sys/types.h>
28 #include <sys/mman.h>
31 /* Type of the constructor functions. */
32 typedef void (*fini_t) (void);
35 void
36 internal_function
37 _dl_close (void *_map)
39 struct reldep_list
41 struct link_map **rellist;
42 unsigned int nrellist;
43 struct reldep_list *next;
44 } *reldeps = NULL;
45 struct link_map **list;
46 struct link_map *map = _map;
47 unsigned int i;
48 unsigned int *new_opencount;
50 /* First see whether we can remove the object at all. */
51 if (__builtin_expect (map->l_flags_1 & DF_1_NODELETE, 0)
52 && map->l_init_called)
53 /* Nope. Do nothing. */
54 return;
56 if (__builtin_expect (map->l_opencount, 1) == 0)
57 _dl_signal_error (0, map->l_name, NULL, N_("shared object not open"));
59 /* Acquire the lock. */
60 __libc_lock_lock_recursive (_dl_load_lock);
62 /* Decrement the reference count. */
63 if (map->l_opencount > 1 || map->l_type != lt_loaded)
65 /* There are still references to this object. Do nothing more. */
66 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
67 _dl_debug_printf ("\nclosing file=%s; opencount == %u\n",
68 map->l_name, map->l_opencount);
70 /* One decrement the object itself, not the dependencies. */
71 --map->l_opencount;
73 __libc_lock_unlock_recursive (_dl_load_lock);
74 return;
77 list = map->l_initfini;
79 /* Compute the new l_opencount values. */
80 i = map->l_searchlist.r_nlist;
81 if (__builtin_expect (i == 0, 0))
82 /* This can happen if we handle relocation dependencies for an
83 object which wasn't loaded directly. */
84 for (i = 1; list[i] != NULL; ++i)
87 new_opencount = (unsigned int *) alloca (i * sizeof (unsigned int));
89 for (i = 0; list[i] != NULL; ++i)
91 list[i]->l_idx = i;
92 new_opencount[i] = list[i]->l_opencount;
94 --new_opencount[0];
95 for (i = 1; list[i] != NULL; ++i)
96 if ((! (list[i]->l_flags_1 & DF_1_NODELETE) || ! list[i]->l_init_called)
97 /* Decrement counter. */
98 && --new_opencount[i] == 0
99 /* Test whether this object was also loaded directly. */
100 && list[i]->l_searchlist.r_list != NULL)
102 /* In this case we have the decrement all the dependencies of
103 this object. They are all in MAP's dependency list. */
104 unsigned int j;
105 struct link_map **dep_list = list[i]->l_searchlist.r_list;
107 for (j = 1; j < list[i]->l_searchlist.r_nlist; ++j)
108 if (! (dep_list[j]->l_flags_1 & DF_1_NODELETE)
109 || ! dep_list[j]->l_init_called)
111 assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist);
112 --new_opencount[dep_list[j]->l_idx];
115 assert (new_opencount[0] == 0);
117 /* Call all termination functions at once. */
118 for (i = 0; list[i] != NULL; ++i)
120 struct link_map *imap = list[i];
121 if (new_opencount[i] == 0 && imap->l_type == lt_loaded
122 && (imap->l_info[DT_FINI] || imap->l_info[DT_FINI_ARRAY])
123 && (! (imap->l_flags_1 & DF_1_NODELETE) || ! imap->l_init_called)
124 /* Skip any half-cooked objects that were never initialized. */
125 && imap->l_init_called)
127 /* When debugging print a message first. */
128 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0))
129 _dl_debug_printf ("\ncalling fini: %s\n\n", imap->l_name);
131 /* Call its termination function. */
132 if (imap->l_info[DT_FINI_ARRAY] != NULL)
134 ElfW(Addr) *array =
135 (ElfW(Addr) *) (imap->l_addr
136 + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
137 unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
138 / sizeof (ElfW(Addr)));
139 unsigned int cnt;
141 for (cnt = 0; cnt < sz; ++cnt)
142 ((fini_t) (imap->l_addr + array[cnt])) ();
145 /* Next try the old-style destructor. */
146 if (imap->l_info[DT_FINI] != NULL)
147 (*(void (*) (void)) DL_DT_FINI_ADDRESS
148 (imap, (void *) imap->l_addr
149 + imap->l_info[DT_FINI]->d_un.d_ptr)) ();
151 else if (new_opencount[i] != 0 && imap->l_type == lt_loaded)
153 /* The object is still used. But the object we are unloading
154 right now is responsible for loading it and therefore we
155 have the search list of the current object in its scope.
156 Remove it. */
157 struct r_scope_elem **runp = imap->l_scope;
159 while (*runp != NULL)
160 if (*runp == &map->l_searchlist)
162 /* Copy all later elements. */
163 while ((runp[0] = runp[1]) != NULL)
164 ++runp;
165 break;
167 else
168 ++runp;
171 /* Store the new l_opencount value. */
172 imap->l_opencount = new_opencount[i];
173 /* Just a sanity check. */
174 assert (imap->l_type == lt_loaded || imap->l_opencount > 0);
177 /* Notify the debugger we are about to remove some loaded objects. */
178 _r_debug.r_state = RT_DELETE;
179 _dl_debug_state ();
181 /* Check each element of the search list to see if all references to
182 it are gone. */
183 for (i = 0; list[i] != NULL; ++i)
185 struct link_map *imap = list[i];
186 if (imap->l_opencount == 0 && imap->l_type == lt_loaded)
188 struct libname_list *lnp;
190 /* That was the last reference, and this was a dlopen-loaded
191 object. We can unmap it. */
192 if (__builtin_expect (imap->l_global, 0))
194 /* This object is in the global scope list. Remove it. */
195 unsigned int cnt = _dl_main_searchlist->r_nlist;
198 --cnt;
199 while (_dl_main_searchlist->r_list[cnt] != imap);
201 /* The object was already correctly registered. */
202 while (++cnt < _dl_main_searchlist->r_nlist)
203 _dl_main_searchlist->r_list[cnt - 1]
204 = _dl_main_searchlist->r_list[cnt];
206 --_dl_main_searchlist->r_nlist;
209 /* We can unmap all the maps at once. We determined the
210 start address and length when we loaded the object and
211 the `munmap' call does the rest. */
212 DL_UNMAP (imap);
214 /* Finally, unlink the data structure and free it. */
215 #ifdef SHARED
216 /* We will unlink the first object only if this is a statically
217 linked program. */
218 assert (imap->l_prev != NULL);
219 imap->l_prev->l_next = imap->l_next;
220 #else
221 if (imap->l_prev != NULL)
222 imap->l_prev->l_next = imap->l_next;
223 else
224 _dl_loaded = imap->l_next;
225 #endif
226 --_dl_nloaded;
227 if (imap->l_next)
228 imap->l_next->l_prev = imap->l_prev;
230 if (imap->l_versions != NULL)
231 free (imap->l_versions);
232 if (imap->l_origin != NULL && imap->l_origin != (char *) -1)
233 free ((char *) imap->l_origin);
235 /* If the object has relocation dependencies save this
236 information for latter. */
237 if (__builtin_expect (imap->l_reldeps != NULL, 0))
239 struct reldep_list *newrel;
241 newrel = (struct reldep_list *) alloca (sizeof (*reldeps));
242 newrel->rellist = imap->l_reldeps;
243 newrel->nrellist = imap->l_reldepsact;
244 newrel->next = reldeps;
246 reldeps = newrel;
249 /* This name always is allocated. */
250 free (imap->l_name);
251 /* Remove the list with all the names of the shared object. */
252 lnp = imap->l_libname;
255 struct libname_list *this = lnp;
256 lnp = lnp->next;
257 if (!this->dont_free)
258 free (this);
260 while (lnp != NULL);
262 /* Remove the searchlists. */
263 if (imap != map)
264 free (imap->l_initfini);
266 /* Remove the scope array if we allocated it. */
267 if (imap->l_scope != imap->l_scope_mem)
268 free (imap->l_scope);
270 if (imap->l_phdr_allocated)
271 free ((void *) imap->l_phdr);
273 if (imap->l_rpath_dirs.dirs != (void *) -1)
274 free (imap->l_rpath_dirs.dirs);
275 if (imap->l_runpath_dirs.dirs != (void *) -1)
276 free (imap->l_runpath_dirs.dirs);
278 free (imap);
282 /* Notify the debugger those objects are finalized and gone. */
283 _r_debug.r_state = RT_CONSISTENT;
284 _dl_debug_state ();
286 /* Now we can perhaps also remove the modules for which we had
287 dependencies because of symbol lookup. */
288 while (__builtin_expect (reldeps != NULL, 0))
290 while (reldeps->nrellist-- > 0)
291 _dl_close (reldeps->rellist[reldeps->nrellist]);
293 free (reldeps->rellist);
295 reldeps = reldeps->next;
298 free (list);
300 /* Release the lock. */
301 __libc_lock_unlock_recursive (_dl_load_lock);
305 static void
306 free_mem (void)
308 if (__builtin_expect (_dl_global_scope_alloc, 0) != 0
309 && _dl_main_searchlist->r_nlist == _dl_initial_searchlist.r_nlist)
311 /* All object dynamically loaded by the program are unloaded. Free
312 the memory allocated for the global scope variable. */
313 struct link_map **old = _dl_main_searchlist->r_list;
315 /* Put the old map in. */
316 _dl_main_searchlist->r_list = _dl_initial_searchlist.r_list;
317 /* Signal that the original map is used. */
318 _dl_global_scope_alloc = 0;
320 /* Now free the old map. */
321 free (old);
324 text_set_element (__libc_subfreeres, free_mem);