1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <alloca.h>
21: #include <assert.h>
22: #include <string.h>
23: #include <ldsodefs.h>
24:
25:
26:
27: typedef void (*fini_t) (void);
28:
29:
30: void
31: internal_function
32: _dl_sort_fini (struct link_map *l, struct link_map **maps, size_t nmaps,
33: char *used, Lmid_t ns)
34: {
35: if (ns == LM_ID_BASE)
36:
37: l = l->l_next;
38:
39: for (; l != NULL; l = l->l_next)
40:
41:
42: if (l == l->l_real && l->l_idx != -1)
43: {
44:
45: unsigned int j;
46: for (j = ns == LM_ID_BASE ? 1 : 0; maps[j] != l; ++j)
47: assert (j < nmaps);
48:
49:
50:
51: for (unsigned int k = j + 1; k < nmaps; ++k)
52: {
53: struct link_map **runp = maps[k]->l_initfini;
54: if (runp != NULL)
55: {
56: while (*runp != NULL)
57: if (*runp == l)
58: {
59: struct link_map *here = maps[k];
60:
61:
62: memmove (&maps[j] + 1,
63: &maps[j], (k - j) * sizeof (struct link_map *));
64: maps[j] = here;
65:
66: if (used != NULL)
67: {
68: char here_used = used[k];
69:
70: memmove (&used[j] + 1,
71: &used[j], (k - j) * sizeof (char));
72: used[j] = here_used;
73: }
74:
75: ++j;
76:
77: break;
78: }
79: else
80: ++runp;
81: }
82:
83: if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
84: {
85: unsigned int m = maps[k]->l_reldeps->act;
86: struct link_map **relmaps = &maps[k]->l_reldeps->list[0];
87:
88: while (m-- > 0)
89: {
90: if (relmaps[m] == l)
91: {
92: struct link_map *here = maps[k];
93:
94:
95: memmove (&maps[j] + 1,
96: &maps[j],
97: (k - j) * sizeof (struct link_map *));
98: maps[j] = here;
99:
100: if (used != NULL)
101: {
102: char here_used = used[k];
103:
104: memmove (&used[j] + 1,
105: &used[j], (k - j) * sizeof (char));
106: used[j] = here_used;
107: }
108:
109: break;
110: }
111: }
112: }
113: }
114: }
115: }
116:
117:
118: void
119: internal_function
120: _dl_fini (void)
121: {
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133: struct link_map **maps = NULL;
134: size_t maps_size = 0;
135:
136:
137:
138:
139: #ifdef SHARED
140: int do_audit = 0;
141: again:
142: #endif
143: for (Lmid_t ns = DL_NNS - 1; ns >= 0; --ns)
144: {
145:
146: __rtld_lock_lock_recursive (GL(dl_load_lock));
147:
148: unsigned int nmaps = 0;
149: unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
150:
151:
152: if (nloaded == 0
153: #ifdef SHARED
154: || GL(dl_ns)[ns]._ns_loaded->l_auditing != do_audit
155: #endif
156: )
157: goto out;
158:
159:
160:
161: assert (ns != LM_ID_BASE || nloaded > 0);
162:
163:
164:
165: if (maps_size < nloaded * sizeof (struct link_map *))
166: {
167: if (maps_size == 0)
168: {
169: maps_size = nloaded * sizeof (struct link_map *);
170: maps = (struct link_map **) alloca (maps_size);
171: }
172: else
173: maps = (struct link_map **)
174: extend_alloca (maps, maps_size,
175: nloaded * sizeof (struct link_map *));
176: }
177:
178: unsigned int i;
179: struct link_map *l;
180: assert (nloaded != 0 || GL(dl_ns)[ns]._ns_loaded == NULL);
181: for (l = GL(dl_ns)[ns]._ns_loaded, i = 0; l != NULL; l = l->l_next)
182:
183: if (l == l->l_real)
184: {
185: assert (i < nloaded);
186:
187: maps[i] = l;
188: l->l_idx = i;
189: ++i;
190:
191:
192:
193: ++l->l_direct_opencount;
194: }
195: assert (ns != LM_ID_BASE || i == nloaded);
196: assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1);
197: nmaps = i;
198:
199: if (nmaps != 0)
200:
201: _dl_sort_fini (GL(dl_ns)[ns]._ns_loaded, maps, nmaps, NULL, ns);
202:
203:
204:
205:
206:
207:
208:
209: out:
210: __rtld_lock_unlock_recursive (GL(dl_load_lock));
211:
212:
213:
214: for (i = 0; i < nmaps; ++i)
215: {
216: l = maps[i];
217:
218: if (l->l_init_called)
219: {
220:
221: l->l_init_called = 0;
222:
223:
224: if (l->l_info[DT_FINI_ARRAY] != NULL
225: || l->l_info[DT_FINI] != NULL)
226: {
227:
228: if (__builtin_expect (GLRO(dl_debug_mask)
229: & DL_DEBUG_IMPCALLS, 0))
230: _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
231: l->l_name[0] ? l->l_name : rtld_progname,
232: ns);
233:
234:
235: if (l->l_info[DT_FINI_ARRAY] != NULL)
236: {
237: ElfW(Addr) *array =
238: (ElfW(Addr) *) (l->l_addr
239: + l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
240: unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
241: / sizeof (ElfW(Addr)));
242: while (i-- > 0)
243: ((fini_t) array[i]) ();
244: }
245:
246:
247: if (l->l_info[DT_FINI] != NULL)
248: ((fini_t) DL_DT_FINI_ADDRESS (l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
249: }
250:
251: #ifdef SHARED
252:
253: if (!do_audit && __builtin_expect (GLRO(dl_naudit) > 0, 0))
254: {
255: struct audit_ifaces *afct = GLRO(dl_audit);
256: for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
257: {
258: if (afct->objclose != NULL)
259:
260: (void) afct->objclose (&l->l_audit[cnt].cookie);
261:
262: afct = afct->next;
263: }
264: }
265: #endif
266: }
267:
268:
269: --l->l_direct_opencount;
270: }
271: }
272:
273: #ifdef SHARED
274: if (! do_audit && GLRO(dl_naudit) > 0)
275: {
276: do_audit = 1;
277: goto again;
278: }
279:
280: if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS, 0))
281: _dl_debug_printf ("\nruntime linker statistics:\n"
282: " final number of relocations: %lu\n"
283: "final number of relocations from cache: %lu\n",
284: GL(dl_num_relocations),
285: GL(dl_num_cache_relocations));
286: #endif
287: }