1 /* Close a shared object opened by `_dl_open'.
2 Copyright (C) 1996-2001, 2002 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
25 #include <bits/libc-lock.h>
27 #include <sys/types.h>
31 /* Type of the constructor functions. */
32 typedef void (*fini_t
) (void);
37 _dl_close (void *_map
)
41 struct link_map
**rellist
;
42 unsigned int nrellist
;
43 struct reldep_list
*next
;
45 struct link_map
**list
;
46 struct link_map
*map
= _map
;
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. */
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 (GL(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 (GL(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. */
73 __libc_lock_unlock_recursive (GL(dl_load_lock
));
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
)
92 new_opencount
[i
] = list
[i
]->l_opencount
;
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. */
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 (GL(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
)
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
)));
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.
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
)
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
;
181 /* Check each element of the search list to see if all references to
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
= GL(dl_main_searchlist
)->r_nlist
;
199 while (GL(dl_main_searchlist
)->r_list
[cnt
] != imap
);
201 /* The object was already correctly registered. */
202 while (++cnt
< GL(dl_main_searchlist
)->r_nlist
)
203 GL(dl_main_searchlist
)->r_list
[cnt
- 1]
204 = GL(dl_main_searchlist
)->r_list
[cnt
];
206 --GL(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. */
214 /* Finally, unlink the data structure and free it. */
216 /* We will unlink the first object only if this is a statically
218 assert (imap
->l_prev
!= NULL
);
219 imap
->l_prev
->l_next
= imap
->l_next
;
221 if (imap
->l_prev
!= NULL
)
222 imap
->l_prev
->l_next
= imap
->l_next
;
224 GL(dl_loaded
) = 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
;
249 /* This name always is allocated. */
251 /* Remove the list with all the names of the shared object. */
252 lnp
= imap
->l_libname
;
255 struct libname_list
*this = lnp
;
257 if (!this->dont_free
)
262 /* Remove the searchlists. */
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
);
282 /* Notify the debugger those objects are finalized and gone. */
283 _r_debug
.r_state
= RT_CONSISTENT
;
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
;
300 /* Release the lock. */
301 __libc_lock_unlock_recursive (GL(dl_load_lock
));
308 if (__builtin_expect (GL(dl_global_scope_alloc
), 0) != 0
309 && GL(dl_main_searchlist
)->r_nlist
== GL(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
= GL(dl_main_searchlist
)->r_list
;
315 /* Put the old map in. */
316 GL(dl_main_searchlist
)->r_list
= GL(dl_initial_searchlist
).r_list
;
317 /* Signal that the original map is used. */
318 GL(dl_global_scope_alloc
) = 0;
320 /* Now free the old map. */
324 text_set_element (__libc_subfreeres
, free_mem
);