1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <assert.h>
21: #include <dlfcn.h>
22: #include <errno.h>
23: #include <libintl.h>
24: #include <stddef.h>
25: #include <stdio.h>
26: #include <stdlib.h>
27: #include <string.h>
28: #include <unistd.h>
29: #include <bits/libc-lock.h>
30: #include <ldsodefs.h>
31: #include <sys/types.h>
32: #include <sys/mman.h>
33: #include <sysdep-cancel.h>
34: #include <tls.h>
35:
36:
37:
38: typedef void (*fini_t) (void);
39:
40:
41:
42: #define IDX_STILL_USED -1
43:
44:
45:
46: static bool
47: remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
48: bool should_be_there)
49: {
50: if (idx - disp >= listp->len)
51: {
52: if (listp->next == NULL)
53: {
54:
55:
56:
57: assert (! should_be_there);
58: }
59: else
60: {
61: if (remove_slotinfo (idx, listp->next, disp + listp->len,
62: should_be_there))
63: return true;
64:
65:
66:
67: idx = disp + listp->len;
68: }
69: }
70: else
71: {
72: struct link_map *old_map = listp->slotinfo[idx - disp].map;
73:
74:
75:
76: if (__builtin_expect (old_map != NULL, 1))
77: {
78: assert (old_map->l_tls_modid == idx);
79:
80:
81: listp->slotinfo[idx - disp].gen = GL(dl_tls_generation) + 1;
82: listp->slotinfo[idx - disp].map = NULL;
83: }
84:
85:
86:
87: if (idx != GL(dl_tls_max_dtv_idx))
88: return true;
89: }
90:
91: while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0))
92: {
93: --idx;
94:
95: if (listp->slotinfo[idx - disp].map != NULL)
96: {
97:
98: GL(dl_tls_max_dtv_idx) = idx;
99: return true;
100: }
101: }
102:
103:
104: return false;
105: }
106:
107:
108: void
109: _dl_close_worker (struct link_map *map)
110: {
111:
112: --map->l_direct_opencount;
113:
114:
115:
116:
117: static enum { not_pending, pending, rerun } dl_close_state;
118:
119: if (map->l_direct_opencount > 0 || map->l_type != lt_loaded
120: || dl_close_state != not_pending)
121: {
122: if (map->l_direct_opencount == 0 && map->l_type == lt_loaded)
123: dl_close_state = rerun;
124:
125:
126: if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
127: _dl_debug_printf ("\nclosing file=%s; direct_opencount=%u\n",
128: map->l_name, map->l_direct_opencount);
129:
130: return;
131: }
132:
133: Lmid_t nsid = map->l_ns;
134: struct link_namespaces *ns = &GL(dl_ns)[nsid];
135:
136: retry:
137: dl_close_state = pending;
138:
139: bool any_tls = false;
140: const unsigned int nloaded = ns->_ns_nloaded;
141: char used[nloaded];
142: char done[nloaded];
143: struct link_map *maps[nloaded];
144:
145:
146:
147: int idx = 0;
148: for (struct link_map *l = ns->_ns_loaded; l != NULL; l = l->l_next)
149: {
150: l->l_idx = idx;
151: maps[idx] = l;
152: ++idx;
153: }
154: assert (idx == nloaded);
155:
156:
157: memset (used, '\0', sizeof (used));
158: memset (done, '\0', sizeof (done));
159:
160:
161: int done_index = -1;
162: while (++done_index < nloaded)
163: {
164: struct link_map *l = maps[done_index];
165:
166: if (done[done_index])
167:
168: continue;
169:
170:
171: if (l->l_type == lt_loaded
172: && l->l_direct_opencount == 0
173: && (l->l_flags_1 & DF_1_NODELETE) == 0
174: && !used[done_index])
175: continue;
176:
177:
178: done[done_index] = 1;
179: used[done_index] = 1;
180:
181: l->l_idx = IDX_STILL_USED;
182:
183:
184: if (l->l_initfini != NULL)
185: {
186: struct link_map **lp = &l->l_initfini[1];
187: while (*lp != NULL)
188: {
189: if ((*lp)->l_idx != IDX_STILL_USED)
190: {
191: assert ((*lp)->l_idx >= 0 && (*lp)->l_idx < nloaded);
192:
193: if (!used[(*lp)->l_idx])
194: {
195: used[(*lp)->l_idx] = 1;
196: if ((*lp)->l_idx - 1 < done_index)
197: done_index = (*lp)->l_idx - 1;
198: }
199: }
200:
201: ++lp;
202: }
203: }
204:
205: if (l->l_reldeps != NULL)
206: for (unsigned int j = 0; j < l->l_reldeps->act; ++j)
207: {
208: struct link_map *jmap = l->l_reldeps->list[j];
209:
210: if (jmap->l_idx != IDX_STILL_USED)
211: {
212: assert (jmap->l_idx >= 0 && jmap->l_idx < nloaded);
213:
214: if (!used[jmap->l_idx])
215: {
216: used[jmap->l_idx] = 1;
217: if (jmap->l_idx - 1 < done_index)
218: done_index = jmap->l_idx - 1;
219: }
220: }
221: }
222: }
223:
224:
225: _dl_sort_fini (ns->_ns_loaded, maps, nloaded, used, nsid);
226:
227:
228: #ifdef SHARED
229: bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing;
230: #endif
231: bool unload_any = false;
232: bool scope_mem_left = false;
233: unsigned int unload_global = 0;
234: unsigned int first_loaded = ~0;
235: for (unsigned int i = 0; i < nloaded; ++i)
236: {
237: struct link_map *imap = maps[i];
238:
239:
240: assert (imap->l_ns == nsid);
241:
242: if (!used[i])
243: {
244: assert (imap->l_type == lt_loaded
245: && (imap->l_flags_1 & DF_1_NODELETE) == 0);
246:
247:
248:
249: if (imap->l_init_called)
250: {
251:
252: if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS,
253: 0))
254: _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
255: imap->l_name, nsid);
256:
257: if (imap->l_info[DT_FINI_ARRAY] != NULL)
258: {
259: ElfW(Addr) *array =
260: (ElfW(Addr) *) (imap->l_addr
261: + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
262: unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
263: / sizeof (ElfW(Addr)));
264:
265: while (sz-- > 0)
266: ((fini_t) array[sz]) ();
267: }
268:
269:
270: if (imap->l_info[DT_FINI] != NULL)
271: (*(void (*) (void)) DL_DT_FINI_ADDRESS
272: (imap, ((void *) imap->l_addr
273: + imap->l_info[DT_FINI]->d_un.d_ptr))) ();
274: }
275:
276: #ifdef SHARED
277:
278: if (__builtin_expect (do_audit, 0))
279: {
280: struct audit_ifaces *afct = GLRO(dl_audit);
281: for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
282: {
283: if (afct->objclose != NULL)
284:
285: (void) afct->objclose (&imap->l_audit[cnt].cookie);
286:
287: afct = afct->next;
288: }
289: }
290: #endif
291:
292:
293: imap->l_removed = 1;
294:
295:
296: unload_any = true;
297:
298: if (imap->l_global)
299: ++unload_global;
300:
301:
302: if (i < first_loaded)
303: first_loaded = i;
304: }
305:
306: else if (imap->l_type == lt_loaded)
307: {
308: struct r_scope_elem *new_list = NULL;
309:
310: if (imap->l_searchlist.r_list == NULL && imap->l_initfini != NULL)
311: {
312:
313:
314:
315:
316:
317:
318:
319: unsigned int cnt;
320: for (cnt = 1; imap->l_initfini[cnt] != NULL; ++cnt)
321: ;
322:
323:
324: imap->l_searchlist.r_list = &imap->l_initfini[cnt + 1];
325: imap->l_searchlist.r_nlist = cnt;
326:
327: new_list = &imap->l_searchlist;
328: }
329:
330:
331:
332:
333: size_t remain = (new_list != NULL) + 1;
334: bool removed_any = false;
335: for (size_t cnt = 0; imap->l_scope[cnt] != NULL; ++cnt)
336:
337:
338:
339: if (imap->l_scope[cnt] != &imap->l_symbolic_searchlist)
340: {
341: struct link_map *tmap = (struct link_map *)
342: ((char *) imap->l_scope[cnt]
343: - offsetof (struct link_map, l_searchlist));
344: assert (tmap->l_ns == nsid);
345: if (tmap->l_idx == IDX_STILL_USED)
346: ++remain;
347: else
348: removed_any = true;
349: }
350: else
351: ++remain;
352:
353: if (removed_any)
354: {
355:
356:
357:
358:
359: size_t new_size;
360: struct r_scope_elem **newp;
361:
362: #define SCOPE_ELEMS(imap) \
363: (sizeof (imap->l_scope_mem) / sizeof (imap->l_scope_mem[0]))
364:
365: if (imap->l_scope != imap->l_scope_mem
366: && remain < SCOPE_ELEMS (imap))
367: {
368: new_size = SCOPE_ELEMS (imap);
369: newp = imap->l_scope_mem;
370: }
371: else
372: {
373: new_size = imap->l_scope_max;
374: newp = (struct r_scope_elem **)
375: malloc (new_size * sizeof (struct r_scope_elem *));
376: if (newp == NULL)
377: _dl_signal_error (ENOMEM, "dlclose", NULL,
378: N_("cannot create scope list"));
379: }
380:
381:
382: remain = 0;
383: for (size_t cnt = 0; imap->l_scope[cnt] != NULL; ++cnt)
384: {
385: if (imap->l_scope[cnt] != &imap->l_symbolic_searchlist)
386: {
387: struct link_map *tmap = (struct link_map *)
388: ((char *) imap->l_scope[cnt]
389: - offsetof (struct link_map, l_searchlist));
390: if (tmap->l_idx != IDX_STILL_USED)
391: {
392:
393:
394: if (new_list != NULL)
395: {
396: newp[remain++] = new_list;
397: new_list = NULL;
398: }
399: continue;
400: }
401: }
402:
403: newp[remain++] = imap->l_scope[cnt];
404: }
405: newp[remain] = NULL;
406:
407: struct r_scope_elem **old = imap->l_scope;
408:
409: imap->l_scope = newp;
410:
411:
412: if (old != imap->l_scope_mem)
413: {
414: if (_dl_scope_free (old))
415:
416:
417: scope_mem_left = false;
418: }
419: else
420: scope_mem_left = true;
421:
422: imap->l_scope_max = new_size;
423: }
424:
425:
426:
427: if (imap->l_loader != NULL
428: && imap->l_loader->l_idx != IDX_STILL_USED)
429: imap->l_loader = NULL;
430:
431:
432: if (i < first_loaded)
433: first_loaded = i;
434: }
435: }
436:
437:
438: if (!unload_any)
439: goto out;
440:
441: #ifdef SHARED
442:
443: if (__builtin_expect (do_audit, 0))
444: {
445: struct link_map *head = ns->_ns_loaded;
446: struct audit_ifaces *afct = GLRO(dl_audit);
447:
448: if (head->l_auditing == 0)
449: {
450: for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
451: {
452: if (afct->activity != NULL)
453: afct->activity (&head->l_audit[cnt].cookie, LA_ACT_DELETE);
454:
455: afct = afct->next;
456: }
457: }
458: }
459: #endif
460:
461:
462: struct r_debug *r = _dl_debug_initialize (0, nsid);
463: r->r_state = RT_DELETE;
464: _dl_debug_state ();
465:
466: if (unload_global)
467: {
468:
469: struct r_scope_elem *ns_msl = ns->_ns_main_searchlist;
470: unsigned int i;
471: unsigned int j = 0;
472: unsigned int cnt = ns_msl->r_nlist;
473:
474: while (cnt > 0 && ns_msl->r_list[cnt - 1]->l_removed)
475: --cnt;
476:
477: if (cnt + unload_global == ns_msl->r_nlist)
478:
479: j = cnt;
480: else
481: for (i = 0; i < cnt; i++)
482: if (ns_msl->r_list[i]->l_removed == 0)
483: {
484: if (i != j)
485: ns_msl->r_list[j] = ns_msl->r_list[i];
486: j++;
487: }
488: ns_msl->r_nlist = j;
489: }
490:
491: if (!RTLD_SINGLE_THREAD_P
492: && (unload_global
493: || scope_mem_left
494: || (GL(dl_scope_free_list) != NULL
495: && GL(dl_scope_free_list)->count)))
496: {
497: THREAD_GSCOPE_WAIT ();
498:
499:
500: struct dl_scope_free_list *fsl = GL(dl_scope_free_list);
501: if (fsl != NULL)
502: while (fsl->count > 0)
503: free (fsl->list[--fsl->count]);
504: }
505:
506: size_t tls_free_start;
507: size_t tls_free_end;
508: tls_free_start = tls_free_end = NO_TLS_OFFSET;
509:
510:
511:
512: for (unsigned int i = first_loaded; i < nloaded; ++i)
513: {
514: struct link_map *imap = maps[i];
515: if (!used[i])
516: {
517: assert (imap->l_type == lt_loaded);
518:
519:
520:
521:
522:
523: if (__builtin_expect (imap->l_tls_blocksize > 0, 0))
524: {
525: any_tls = true;
526:
527: if (GL(dl_tls_dtv_slotinfo_list) != NULL
528: && ! remove_slotinfo (imap->l_tls_modid,
529: GL(dl_tls_dtv_slotinfo_list), 0,
530: imap->l_init_called))
531:
532: GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem);
533:
534: if (imap->l_tls_offset != NO_TLS_OFFSET)
535: {
536:
537:
538:
539:
540: #if TLS_TCB_AT_TP
541: if (tls_free_start == NO_TLS_OFFSET
542: || (size_t) imap->l_tls_offset == tls_free_start)
543: {
544:
545: tls_free_start
546: = imap->l_tls_offset - imap->l_tls_blocksize;
547:
548: if (tls_free_end == NO_TLS_OFFSET)
549: tls_free_end = imap->l_tls_offset;
550: }
551: else if (imap->l_tls_offset - imap->l_tls_blocksize
552: == tls_free_end)
553:
554: tls_free_end = imap->l_tls_offset;
555: else
556: {
557:
558:
559:
560: if (tls_free_end == GL(dl_tls_static_used))
561: {
562: GL(dl_tls_static_used) = tls_free_start;
563: tls_free_end = imap->l_tls_offset;
564: tls_free_start
565: = tls_free_end - imap->l_tls_blocksize;
566: }
567: else if ((size_t) imap->l_tls_offset
568: == GL(dl_tls_static_used))
569: GL(dl_tls_static_used)
570: = imap->l_tls_offset - imap->l_tls_blocksize;
571: else if (tls_free_end < (size_t) imap->l_tls_offset)
572: {
573:
574:
575: tls_free_end = imap->