]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-close.c
Update.
[thirdparty/glibc.git] / elf / dl-close.c
CommitLineData
26b4d766 1/* Close a shared object opened by `_dl_open'.
aff4519d 2 Copyright (C) 1996-2002, 2003 Free Software Foundation, Inc.
afd4eb37
UD
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
afd4eb37
UD
9
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
41bdb6e2 13 Lesser General Public License for more details.
afd4eb37 14
41bdb6e2
AJ
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. */
ba79d61b 19
7afab53d 20#include <assert.h>
ba79d61b 21#include <dlfcn.h>
8e17ea58 22#include <libintl.h>
b209e34a 23#include <stdio.h>
ba79d61b 24#include <stdlib.h>
8d6468d0 25#include <string.h>
a853022c 26#include <bits/libc-lock.h>
b8445829 27#include <ldsodefs.h>
ba79d61b
RM
28#include <sys/types.h>
29#include <sys/mman.h>
30
31
dacc8ffa
UD
32/* Type of the constructor functions. */
33typedef void (*fini_t) (void);
34
35
fc093be1
UD
36#ifdef USE_TLS
37/* Returns true we an non-empty was found. */
38static bool
1f0c4a10
RM
39remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
40 bool should_be_there)
fc093be1
UD
41{
42 if (idx - disp >= listp->len)
43 {
1f0c4a10
RM
44 if (listp->next == NULL)
45 {
46 /* The index is not actually valid in the slotinfo list,
8265947d
RM
47 because this object was closed before it was fully set
48 up due to some error. */
1f0c4a10
RM
49 assert (! should_be_there);
50 }
51 else
52 {
53 if (remove_slotinfo (idx, listp->next, disp + listp->len,
54 should_be_there))
55 return true;
fc093be1 56
1f0c4a10
RM
57 /* No non-empty entry. Search from the end of this element's
58 slotinfo array. */
59 idx = disp + listp->len;
60 }
fc093be1
UD
61 }
62 else
63 {
64 struct link_map *old_map = listp->slotinfo[idx - disp].map;
fc093be1 65
2430d57a
RM
66 /* The entry might still be in its unused state if we are closing an
67 object that wasn't fully set up. */
68 if (__builtin_expect (old_map != NULL, 1))
69 {
70 assert (old_map->l_tls_modid == idx);
71
72 /* Mark the entry as unused. */
73 listp->slotinfo[idx - disp].gen = GL(dl_tls_generation) + 1;
74 listp->slotinfo[idx - disp].map = NULL;
75 }
fc093be1
UD
76
77 /* If this is not the last currently used entry no need to look
78 further. */
2430d57a 79 if (idx != GL(dl_tls_max_dtv_idx))
fc093be1 80 return true;
fc093be1
UD
81 }
82
83 while (idx - disp > disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0)
84 {
85 --idx;
86
87 if (listp->slotinfo[idx - disp].map != NULL)
88 {
89 /* Found a new last used index. */
90 GL(dl_tls_max_dtv_idx) = idx;
91 return true;
92 }
93 }
94
95 /* No non-entry in this list element. */
96 return false;
97}
98#endif
99
100
ba79d61b 101void
d0fc4041 102internal_function
94e365c6 103_dl_close (void *_map)
ba79d61b 104{
4b4fcf99
UD
105 struct reldep_list
106 {
107 struct link_map **rellist;
108 unsigned int nrellist;
556224ab 109 unsigned int nhandled;
4b4fcf99 110 struct reldep_list *next;
556224ab 111 bool handled[0];
4b4fcf99 112 } *reldeps = NULL;
ba79d61b 113 struct link_map **list;
94e365c6 114 struct link_map *map = _map;
ba79d61b 115 unsigned int i;
42c4f32a 116 unsigned int *new_opencount;
a04586d8
UD
117#ifdef USE_TLS
118 bool any_tls = false;
119#endif
ba79d61b 120
bf8b3e74 121 /* First see whether we can remove the object at all. */
c4bb124a
UD
122 if (__builtin_expect (map->l_flags_1 & DF_1_NODELETE, 0)
123 && map->l_init_called)
bf8b3e74
UD
124 /* Nope. Do nothing. */
125 return;
126
c41c89d3 127 if (__builtin_expect (map->l_opencount, 1) == 0)
407fe3bb 128 _dl_signal_error (0, map->l_name, NULL, N_("shared object not open"));
ba79d61b 129
26b4d766 130 /* Acquire the lock. */
d3c9f895 131 __rtld_lock_lock_recursive (GL(dl_load_lock));
26b4d766 132
ba79d61b 133 /* Decrement the reference count. */
a709dd43 134 if (map->l_opencount > 1 || map->l_type != lt_loaded)
26b4d766
UD
135 {
136 /* There are still references to this object. Do nothing more. */
d6b5d570 137 if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_FILES, 0))
c4bb124a
UD
138 _dl_debug_printf ("\nclosing file=%s; opencount == %u\n",
139 map->l_name, map->l_opencount);
b35e21f4 140
aff4519d 141 /* Decrement the object's reference counter, not the dependencies'. */
42c4f32a 142 --map->l_opencount;
8699e7b1 143
d3c9f895 144 __rtld_lock_unlock_recursive (GL(dl_load_lock));
26b4d766
UD
145 return;
146 }
ba79d61b 147
2e93b4a4 148 list = map->l_initfini;
42c4f32a
UD
149
150 /* Compute the new l_opencount values. */
c4bb124a
UD
151 i = map->l_searchlist.r_nlist;
152 if (__builtin_expect (i == 0, 0))
153 /* This can happen if we handle relocation dependencies for an
154 object which wasn't loaded directly. */
155 for (i = 1; list[i] != NULL; ++i)
156 ;
157
556224ab 158 unsigned int nopencount = i;
c4bb124a
UD
159 new_opencount = (unsigned int *) alloca (i * sizeof (unsigned int));
160
7e036a01 161 for (i = 0; list[i] != NULL; ++i)
42c4f32a 162 {
2e93b4a4
UD
163 list[i]->l_idx = i;
164 new_opencount[i] = list[i]->l_opencount;
42c4f32a
UD
165 }
166 --new_opencount[0];
7e036a01 167 for (i = 1; list[i] != NULL; ++i)
aff4519d 168 if ((list[i]->l_flags_1 & DF_1_NODELETE) == 0
42c4f32a 169 /* Decrement counter. */
556224ab 170 && --new_opencount[i] == 0)
42c4f32a 171 {
556224ab
UD
172 void mark_removed (struct link_map *remmap)
173 {
174 /* Test whether this object was also loaded directly. */
175 if (remmap->l_searchlist.r_list != NULL)
176 {
177 /* In this case we have to decrement all the dependencies of
178 this object. They are all in MAP's dependency list. */
179 unsigned int j;
180 struct link_map **dep_list = remmap->l_searchlist.r_list;
181
182 for (j = 1; j < remmap->l_searchlist.r_nlist; ++j)
183 if (! (dep_list[j]->l_flags_1 & DF_1_NODELETE)
184 || ! dep_list[j]->l_init_called)
185 {
186 assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist);
187 if (--new_opencount[dep_list[j]->l_idx] == 0)
aff4519d
UD
188 {
189 assert (dep_list[j]->l_type == lt_loaded);
190 mark_removed (dep_list[j]);
191 }
556224ab
UD
192 }
193 }
194
195 if (remmap->l_reldeps != NULL)
196 {
197 unsigned int j;
198 for (j = 0; j < remmap->l_reldepsact; ++j)
199 {
200 /* Find out whether this object is in our list. */
201 if (remmap->l_reldeps[j]->l_idx < nopencount
202 && (list[remmap->l_reldeps[j]->l_idx]
203 == remmap->l_reldeps[j]))
204 /* Yes, it is. */
205 if (--new_opencount[remmap->l_reldeps[j]->l_idx] == 0)
aff4519d
UD
206 {
207 /* This one is now gone, too. */
208 assert (remmap->l_reldeps[j]->l_type == lt_loaded);
209 mark_removed (remmap->l_reldeps[j]);
210 }
556224ab
UD
211 }
212 }
213 }
214
215 mark_removed (list[i]);
42c4f32a
UD
216 }
217 assert (new_opencount[0] == 0);
218
a709dd43 219 /* Call all termination functions at once. */
7e036a01 220 for (i = 0; list[i] != NULL; ++i)
a709dd43 221 {
2e93b4a4 222 struct link_map *imap = list[i];
42c4f32a 223 if (new_opencount[i] == 0 && imap->l_type == lt_loaded
aff4519d 224 && (imap->l_flags_1 & DF_1_NODELETE) == 0)
a709dd43 225 {
b48abe3c 226 /* When debugging print a message first. */
d6b5d570 227 if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
35fc382a 228 _dl_debug_printf ("\ncalling fini: %s\n\n", imap->l_name);
dacc8ffa 229
aff4519d
UD
230 /* Call its termination function. Do not do it for
231 half-cooked objects. */
232 if (imap->l_init_called)
dacc8ffa 233 {
aff4519d
UD
234 if (imap->l_info[DT_FINI_ARRAY] != NULL)
235 {
236 ElfW(Addr) *array =
237 (ElfW(Addr) *) (imap->l_addr
238 + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
239 unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
240 / sizeof (ElfW(Addr)));
aff4519d 241
62f29da7
UD
242 while (sz-- > 0)
243 ((fini_t) array[sz]) ();
aff4519d
UD
244 }
245
246 /* Next try the old-style destructor. */
247 if (imap->l_info[DT_FINI] != NULL)
248 (*(void (*) (void)) DL_DT_FINI_ADDRESS
249 (imap, ((void *) imap->l_addr
250 + imap->l_info[DT_FINI]->d_un.d_ptr))) ();
dacc8ffa
UD
251 }
252
aff4519d
UD
253 /* This object must not be used anymore. We must remove the
254 reference from the scope. */
255 unsigned int j;
256 struct link_map **searchlist = map->l_searchlist.r_list;
257 unsigned int nsearchlist = map->l_searchlist.r_nlist;
258
259#ifndef NDEBUG
260 bool found = false;
261#endif
262 for (j = 0; j < nsearchlist; ++j)
263 if (imap == searchlist[j])
264 {
265 /* This is the object to remove. Copy all the
266 following ones. */
267 while (++j < nsearchlist)
268 searchlist[j - 1] = searchlist[j];
269
270 searchlist[j - 1] = NULL;
271
272 --map->l_searchlist.r_nlist;
273
274#ifndef NDEBUG
275 found = true;
276#endif
277 break;
278 }
279 assert (found);
a709dd43 280 }
aff4519d
UD
281 else if (new_opencount[i] != 0 && imap->l_type == lt_loaded
282 && imap->l_searchlist.r_list == NULL
283 && imap->l_initfini != NULL)
5a21d307 284 {
aff4519d
UD
285 /* The object is still used. But the object we are
286 unloading right now is responsible for loading it. If
287 the current object does not have it's own scope yet we
288 have to create one. This has to be done before running
289 the finalizers.
290
291 To do this count the number of dependencies. */
292 unsigned int cnt;
293 for (cnt = 1; imap->l_initfini[cnt] != NULL; ++cnt)
294 if (imap->l_initfini[cnt]->l_idx >= i
295 && imap->l_initfini[cnt]->l_idx < nopencount)
296 ++new_opencount[imap->l_initfini[cnt]->l_idx];
297 else
298 ++imap->l_initfini[cnt]->l_opencount;
299
300 /* We simply reuse the l_initfini list. */
301 imap->l_searchlist.r_list = &imap->l_initfini[cnt + 1];
302 imap->l_searchlist.r_nlist = cnt;
303
304 for (cnt = 0; imap->l_scope[cnt] != NULL; ++cnt)
1376cd8c 305 if (imap->l_scope[cnt] == &map->l_searchlist)
5a21d307 306 {
aff4519d 307 imap->l_scope[cnt] = &imap->l_searchlist;
5a21d307
UD
308 break;
309 }
5a21d307 310 }
42c4f32a
UD
311
312 /* Store the new l_opencount value. */
313 imap->l_opencount = new_opencount[i];
aff4519d 314
42c4f32a
UD
315 /* Just a sanity check. */
316 assert (imap->l_type == lt_loaded || imap->l_opencount > 0);
a709dd43
UD
317 }
318
4d6acc61
RM
319 /* Notify the debugger we are about to remove some loaded objects. */
320 _r_debug.r_state = RT_DELETE;
321 _dl_debug_state ();
322
c877418f
RM
323#ifdef USE_TLS
324 size_t tls_free_start, tls_free_end;
325 tls_free_start = tls_free_end = GL(dl_tls_static_used);
326#endif
327
ba79d61b
RM
328 /* Check each element of the search list to see if all references to
329 it are gone. */
7e036a01 330 for (i = 0; list[i] != NULL; ++i)
ba79d61b 331 {
af69217f
UD
332 struct link_map *imap = list[i];
333 if (imap->l_opencount == 0 && imap->l_type == lt_loaded)
ba79d61b 334 {
a8a1269d
UD
335 struct libname_list *lnp;
336
ba79d61b
RM
337 /* That was the last reference, and this was a dlopen-loaded
338 object. We can unmap it. */
c41c89d3 339 if (__builtin_expect (imap->l_global, 0))
ba79d61b
RM
340 {
341 /* This object is in the global scope list. Remove it. */
d6b5d570 342 unsigned int cnt = GL(dl_main_searchlist)->r_nlist;
be935610 343
ba79d61b 344 do
50b65db1 345 --cnt;
d6b5d570 346 while (GL(dl_main_searchlist)->r_list[cnt] != imap);
482eec0d 347
50b65db1 348 /* The object was already correctly registered. */
d6b5d570
UD
349 while (++cnt < GL(dl_main_searchlist)->r_nlist)
350 GL(dl_main_searchlist)->r_list[cnt - 1]
351 = GL(dl_main_searchlist)->r_list[cnt];
50b65db1 352
d6b5d570 353 --GL(dl_main_searchlist)->r_nlist;
ba79d61b
RM
354 }
355
a04586d8 356#ifdef USE_TLS
1f0c4a10 357 /* Remove the object from the dtv slotinfo array if it uses TLS. */
a04586d8
UD
358 if (__builtin_expect (imap->l_tls_blocksize > 0, 0))
359 {
a04586d8 360 any_tls = true;
bb4cb252 361
fc093be1 362 if (! remove_slotinfo (imap->l_tls_modid,
1f0c4a10
RM
363 GL(dl_tls_dtv_slotinfo_list), 0,
364 imap->l_init_called))
fc093be1
UD
365 /* All dynamically loaded modules with TLS are unloaded. */
366 GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem);
c877418f
RM
367
368 if (imap->l_tls_offset != 0)
369 {
370 /* Collect a contiguous chunk built from the objects in
371 this search list, going in either direction. When the
372 whole chunk is at the end of the used area then we can
373 reclaim it. */
374 if (imap->l_tls_offset == tls_free_end)
375 /* Extend the contiguous chunk being reclaimed. */
376 tls_free_end += imap->l_tls_blocksize;
377 else if (imap->l_tls_offset + imap->l_tls_blocksize
378 == tls_free_start)
379 /* Extend the chunk backwards. */
380 tls_free_start = imap->l_tls_offset;
381 else
382 {
383 /* This isn't contiguous with the last chunk freed.
384 One of them will be leaked. */
385 if (tls_free_end == GL(dl_tls_static_used))
386 GL(dl_tls_static_used) = tls_free_start;
387 tls_free_start = imap->l_tls_offset;
388 tls_free_end = tls_free_start + imap->l_tls_blocksize;
389 }
390 }
a04586d8
UD
391 }
392#endif
393
a8a1269d 394 /* We can unmap all the maps at once. We determined the
4ce636da
UD
395 start address and length when we loaded the object and
396 the `munmap' call does the rest. */
09bf6406 397 DL_UNMAP (imap);
22bc7978 398
ba79d61b 399 /* Finally, unlink the data structure and free it. */
b5567b2a 400#ifdef SHARED
7afab53d
UD
401 /* We will unlink the first object only if this is a statically
402 linked program. */
403 assert (imap->l_prev != NULL);
6a805a0b 404 imap->l_prev->l_next = imap->l_next;
7afab53d
UD
405#else
406 if (imap->l_prev != NULL)
af69217f 407 imap->l_prev->l_next = imap->l_next;
7afab53d 408 else
d6b5d570 409 GL(dl_loaded) = imap->l_next;
7afab53d 410#endif
d6b5d570 411 --GL(dl_nloaded);
af69217f
UD
412 if (imap->l_next)
413 imap->l_next->l_prev = imap->l_prev;
a8a1269d 414
556224ab
UD
415 free (imap->l_versions);
416 if (imap->l_origin != (char *) -1)
a8a1269d
UD
417 free ((char *) imap->l_origin);
418
4b4fcf99
UD
419 /* If the object has relocation dependencies save this
420 information for latter. */
421 if (__builtin_expect (imap->l_reldeps != NULL, 0))
422 {
423 struct reldep_list *newrel;
424
556224ab
UD
425 newrel = (struct reldep_list *) alloca (sizeof (*reldeps)
426 + (imap->l_reldepsact
427 * sizeof (bool)));
1826d793
UD
428 newrel->rellist = imap->l_reldeps;
429 newrel->nrellist = imap->l_reldepsact;
4b4fcf99
UD
430 newrel->next = reldeps;
431
556224ab
UD
432 newrel->nhandled = imap->l_reldepsact;
433 unsigned int j;
434 for (j = 0; j < imap->l_reldepsact; ++j)
435 {
436 /* Find out whether this object is in our list. */
437 if (imap->l_reldeps[j]->l_idx < nopencount
438 && list[imap->l_reldeps[j]->l_idx] == imap->l_reldeps[j])
439 /* Yes, it is. */
440 newrel->handled[j] = true;
441 else
442 newrel->handled[j] = false;
443 }
444
4b4fcf99
UD
445 reldeps = newrel;
446 }
447
4ce636da 448 /* This name always is allocated. */
a8a1269d 449 free (imap->l_name);
4ce636da 450 /* Remove the list with all the names of the shared object. */
a8a1269d
UD
451 lnp = imap->l_libname;
452 do
453 {
76156ea1 454 struct libname_list *this = lnp;
a8a1269d 455 lnp = lnp->next;
11810621
UD
456 if (!this->dont_free)
457 free (this);
a8a1269d
UD
458 }
459 while (lnp != NULL);
a8a1269d 460
4ce636da 461 /* Remove the searchlists. */
dacc8ffa 462 if (imap != map)
556224ab 463 free (imap->l_initfini);
4ce636da 464
5a21d307
UD
465 /* Remove the scope array if we allocated it. */
466 if (imap->l_scope != imap->l_scope_mem)
467 free (imap->l_scope);
468
7bcaca43 469 if (imap->l_phdr_allocated)
15925412 470 free ((void *) imap->l_phdr);
7bcaca43 471
f55727ca
UD
472 if (imap->l_rpath_dirs.dirs != (void *) -1)
473 free (imap->l_rpath_dirs.dirs);
474 if (imap->l_runpath_dirs.dirs != (void *) -1)
475 free (imap->l_runpath_dirs.dirs);
476
af69217f 477 free (imap);
ba79d61b
RM
478 }
479 }
480
a04586d8 481#ifdef USE_TLS
c877418f 482 /* If we removed any object which uses TLS bump the generation counter. */
bb4cb252 483 if (any_tls)
c877418f
RM
484 {
485 if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
486 __libc_fatal (_("TLS generation counter wrapped! Please send report with the 'glibcbug' script."));
487
488 if (tls_free_end == GL(dl_tls_static_used))
489 GL(dl_tls_static_used) = tls_free_start;
490 }
a04586d8
UD
491#endif
492
e3e5f672
UD
493 /* Notify the debugger those objects are finalized and gone. */
494 _r_debug.r_state = RT_CONSISTENT;
495 _dl_debug_state ();
496
cf197e41
UD
497 /* Now we can perhaps also remove the modules for which we had
498 dependencies because of symbol lookup. */
4b4fcf99 499 while (__builtin_expect (reldeps != NULL, 0))
cf197e41 500 {
4b4fcf99 501 while (reldeps->nrellist-- > 0)
556224ab
UD
502 /* Some of the relocation dependencies might be on the
503 dependency list of the object we are closing right now.
504 They were already handled. Do not close them again. */
505 if (reldeps->nrellist < reldeps->nhandled
506 && ! reldeps->handled[reldeps->nrellist])
507 _dl_close (reldeps->rellist[reldeps->nrellist]);
4b4fcf99
UD
508
509 free (reldeps->rellist);
cf197e41 510
4b4fcf99 511 reldeps = reldeps->next;
cf197e41
UD
512 }
513
ba79d61b 514 free (list);
4d6acc61 515
e3e5f672 516 /* Release the lock. */
d3c9f895 517 __rtld_lock_unlock_recursive (GL(dl_load_lock));
e3e5f672 518}
cc7e7a26 519libc_hidden_def (_dl_close)
e3e5f672
UD
520
521
100e184f 522#ifdef USE_TLS
a04586d8 523static bool
216455bc 524free_slotinfo (struct dtv_slotinfo_list **elemp)
a04586d8
UD
525{
526 size_t cnt;
527
216455bc 528 if (*elemp == NULL)
69f0c4d8
UD
529 /* Nothing here, all is removed (or there never was anything). */
530 return true;
531
216455bc 532 if (!free_slotinfo (&(*elemp)->next))
a04586d8
UD
533 /* We cannot free the entry. */
534 return false;
535
216455bc 536 /* That cleared our next pointer for us. */
a04586d8 537
216455bc
RM
538 for (cnt = 0; cnt < (*elemp)->len; ++cnt)
539 if ((*elemp)->slotinfo[cnt].map != NULL)
a04586d8
UD
540 /* Still used. */
541 return false;
542
543 /* We can remove the list element. */
216455bc
RM
544 free (*elemp);
545 *elemp = NULL;
a04586d8
UD
546
547 return true;
548}
100e184f 549#endif
a04586d8
UD
550
551
c877418f 552libc_freeres_fn (free_mem)
e3e5f672 553{
d6b5d570
UD
554 if (__builtin_expect (GL(dl_global_scope_alloc), 0) != 0
555 && GL(dl_main_searchlist)->r_nlist == GL(dl_initial_searchlist).r_nlist)
d3556ac9
UD
556 {
557 /* All object dynamically loaded by the program are unloaded. Free
558 the memory allocated for the global scope variable. */
d6b5d570 559 struct link_map **old = GL(dl_main_searchlist)->r_list;
d3556ac9
UD
560
561 /* Put the old map in. */
d6b5d570 562 GL(dl_main_searchlist)->r_list = GL(dl_initial_searchlist).r_list;
d3556ac9 563 /* Signal that the original map is used. */
d6b5d570 564 GL(dl_global_scope_alloc) = 0;
d3556ac9
UD
565
566 /* Now free the old map. */
567 free (old);
568 }
a04586d8
UD
569
570#ifdef USE_TLS
2d148689
RM
571 if (USE___THREAD || GL(dl_tls_dtv_slotinfo_list) != NULL)
572 {
573 /* Free the memory allocated for the dtv slotinfo array. We can do
216455bc
RM
574 this only if all modules which used this memory are unloaded. */
575# ifdef SHARED
576 if (GL(dl_initial_dtv) == NULL)
577 /* There was no initial TLS setup, it was set up later when
578 it used the normal malloc. */
579 free_slotinfo (&GL(dl_tls_dtv_slotinfo_list));
580# endif
581 /* The first element of the list does not have to be deallocated.
582 It was allocated in the dynamic linker (i.e., with a different
583 malloc), and in the static library it's in .bss space. */
584 free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
2d148689 585 }
a04586d8 586#endif
ba79d61b 587}