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
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 ((map
->l_flags_1
& DF_1_NODELETE
) && map
->l_init_called
)
52 /* Nope. Do nothing. */
55 if (__builtin_expect (map
->l_opencount
, 1) == 0)
56 _dl_signal_error (0, map
->l_name
, N_("shared object not open"));
58 /* Acquire the lock. */
59 __libc_lock_lock_recursive (_dl_load_lock
);
61 /* Decrement the reference count. */
62 if (map
->l_opencount
> 1 || map
->l_type
!= lt_loaded
)
64 /* There are still references to this object. Do nothing more. */
65 if (__builtin_expect (_dl_debug_mask
& DL_DEBUG_FILES
, 0))
69 buf
[sizeof buf
- 1] = '\0';
71 _dl_debug_printf ("\nclosing file=%s; opencount == %u\n",
72 map
->l_name
, map
->l_opencount
);
75 /* One decrement the object itself, not the dependencies. */
78 __libc_lock_unlock_recursive (_dl_load_lock
);
82 list
= map
->l_initfini
;
84 /* Compute the new l_opencount values. */
85 new_opencount
= (unsigned int *) alloca (map
->l_searchlist
.r_nlist
86 * sizeof (unsigned int));
87 for (i
= 0; list
[i
] != NULL
; ++i
)
90 new_opencount
[i
] = list
[i
]->l_opencount
;
93 for (i
= 1; list
[i
] != NULL
; ++i
)
94 if ((! (list
[i
]->l_flags_1
& DF_1_NODELETE
) || ! list
[i
]->l_init_called
)
95 /* Decrement counter. */
96 && --new_opencount
[i
] == 0
97 /* Test whether this object was also loaded directly. */
98 && list
[i
]->l_searchlist
.r_list
!= NULL
)
100 /* In this case we have the decrement all the dependencies of
101 this object. They are all in MAP's dependency list. */
103 struct link_map
**dep_list
= list
[i
]->l_searchlist
.r_list
;
105 for (j
= 1; j
< list
[i
]->l_searchlist
.r_nlist
; ++j
)
106 if (! (dep_list
[j
]->l_flags_1
& DF_1_NODELETE
)
107 || ! dep_list
[j
]->l_init_called
)
109 assert (dep_list
[j
]->l_idx
< map
->l_searchlist
.r_nlist
);
110 --new_opencount
[dep_list
[j
]->l_idx
];
113 assert (new_opencount
[0] == 0);
115 /* Call all termination functions at once. */
116 for (i
= 0; list
[i
] != NULL
; ++i
)
118 struct link_map
*imap
= list
[i
];
119 if (new_opencount
[i
] == 0 && imap
->l_type
== lt_loaded
120 && (imap
->l_info
[DT_FINI
] || imap
->l_info
[DT_FINI_ARRAY
])
121 && (! (imap
->l_flags_1
& DF_1_NODELETE
) || ! imap
->l_init_called
)
122 /* Skip any half-cooked objects that were never initialized. */
123 && imap
->l_init_called
)
125 /* When debugging print a message first. */
126 if (__builtin_expect (_dl_debug_mask
& DL_DEBUG_IMPCALLS
, 0))
127 _dl_debug_printf ("\ncalling fini: %s\n\n", imap
->l_name
);
129 /* Call its termination function. */
130 if (imap
->l_info
[DT_FINI_ARRAY
] != NULL
)
133 (ElfW(Addr
) *) (imap
->l_addr
134 + imap
->l_info
[DT_FINI_ARRAY
]->d_un
.d_ptr
);
135 unsigned int sz
= (imap
->l_info
[DT_FINI_ARRAYSZ
]->d_un
.d_val
136 / sizeof (ElfW(Addr
)));
139 for (cnt
= 0; cnt
< sz
; ++cnt
)
140 ((fini_t
) (imap
->l_addr
+ array
[cnt
])) ();
143 /* Next try the old-style destructor. */
144 if (imap
->l_info
[DT_FINI
] != NULL
)
145 (*(void (*) (void)) DL_DT_FINI_ADDRESS
146 (imap
, (void *) imap
->l_addr
147 + imap
->l_info
[DT_FINI
]->d_un
.d_ptr
)) ();
150 /* Store the new l_opencount value. */
151 imap
->l_opencount
= new_opencount
[i
];
152 /* Just a sanity check. */
153 assert (imap
->l_type
== lt_loaded
|| imap
->l_opencount
> 0);
156 /* Notify the debugger we are about to remove some loaded objects. */
157 _r_debug
.r_state
= RT_DELETE
;
160 /* Check each element of the search list to see if all references to
162 for (i
= 0; list
[i
] != NULL
; ++i
)
164 struct link_map
*imap
= list
[i
];
165 if (imap
->l_opencount
== 0 && imap
->l_type
== lt_loaded
)
167 struct libname_list
*lnp
;
169 /* That was the last reference, and this was a dlopen-loaded
170 object. We can unmap it. */
171 if (__builtin_expect (imap
->l_global
, 0))
173 /* This object is in the global scope list. Remove it. */
174 unsigned int cnt
= _dl_main_searchlist
->r_nlist
;
178 while (_dl_main_searchlist
->r_list
[cnt
] != imap
);
180 /* The object was already correctly registered. */
181 while (++cnt
< _dl_main_searchlist
->r_nlist
)
182 _dl_main_searchlist
->r_list
[cnt
- 1]
183 = _dl_main_searchlist
->r_list
[cnt
];
185 --_dl_main_searchlist
->r_nlist
;
188 /* We can unmap all the maps at once. We determined the
189 start address and length when we loaded the object and
190 the `munmap' call does the rest. */
193 /* Finally, unlink the data structure and free it. */
195 /* We will unlink the first object only if this is a statically
197 assert (imap
->l_prev
!= NULL
);
198 imap
->l_prev
->l_next
= imap
->l_next
;
200 if (imap
->l_prev
!= NULL
)
201 imap
->l_prev
->l_next
= imap
->l_next
;
203 _dl_loaded
= imap
->l_next
;
207 imap
->l_next
->l_prev
= imap
->l_prev
;
209 if (imap
->l_versions
!= NULL
)
210 free (imap
->l_versions
);
211 if (imap
->l_origin
!= NULL
&& imap
->l_origin
!= (char *) -1)
212 free ((char *) imap
->l_origin
);
214 /* If the object has relocation dependencies save this
215 information for latter. */
216 if (__builtin_expect (imap
->l_reldeps
!= NULL
, 0))
218 struct reldep_list
*newrel
;
220 newrel
= (struct reldep_list
*) alloca (sizeof (*reldeps
));
221 newrel
->rellist
= imap
->l_reldeps
;
222 newrel
->nrellist
= imap
->l_reldepsact
;
223 newrel
->next
= reldeps
;
228 /* This name always is allocated. */
230 /* Remove the list with all the names of the shared object. */
231 lnp
= imap
->l_libname
;
234 struct libname_list
*this = lnp
;
240 /* Remove the searchlists. */
242 free (imap
->l_initfini
);
244 if (imap
->l_phdr_allocated
)
245 free ((void *) imap
->l_phdr
);
247 if (imap
->l_rpath_dirs
.dirs
!= (void *) -1)
248 free (imap
->l_rpath_dirs
.dirs
);
249 if (imap
->l_runpath_dirs
.dirs
!= (void *) -1)
250 free (imap
->l_runpath_dirs
.dirs
);
256 /* Notify the debugger those objects are finalized and gone. */
257 _r_debug
.r_state
= RT_CONSISTENT
;
260 /* Now we can perhaps also remove the modules for which we had
261 dependencies because of symbol lookup. */
262 while (__builtin_expect (reldeps
!= NULL
, 0))
264 while (reldeps
->nrellist
-- > 0)
265 _dl_close (reldeps
->rellist
[reldeps
->nrellist
]);
267 free (reldeps
->rellist
);
269 reldeps
= reldeps
->next
;
274 /* Release the lock. */
275 __libc_lock_unlock_recursive (_dl_load_lock
);
282 if (__builtin_expect (_dl_global_scope_alloc
, 0) != 0
283 && _dl_main_searchlist
->r_nlist
== _dl_initial_searchlist
.r_nlist
)
285 /* All object dynamically loaded by the program are unloaded. Free
286 the memory allocated for the global scope variable. */
287 struct link_map
**old
= _dl_main_searchlist
->r_list
;
289 /* Put the old map in. */
290 _dl_main_searchlist
->r_list
= _dl_initial_searchlist
.r_list
;
291 /* Signal that the original map is used. */
292 _dl_global_scope_alloc
= 0;
294 /* Now free the old map. */
298 text_set_element (__libc_subfreeres
, free_mem
);