]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-deps.c
Update to LGPL v2.1.
[thirdparty/glibc.git] / elf / dl-deps.c
CommitLineData
efec1d0c 1/* Load the dependencies of a mapped object.
62dcee57 2 Copyright (C) 1996,1997,1998,1999,2000,2001 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. */
efec1d0c 19
dc5efe83 20#include <assert.h>
efec1d0c 21#include <dlfcn.h>
a853022c 22#include <errno.h>
8e17ea58 23#include <libintl.h>
efec1d0c 24#include <stdlib.h>
ca34d7a7 25#include <string.h>
06535ae9 26#include <unistd.h>
dc5efe83 27#include <sys/param.h>
a42195db 28#include <ldsodefs.h>
a853022c 29
dc5efe83 30#include <dl-dst.h>
1522c368
UD
31
32/* Whether an shared object references one or more auxiliary objects
33 is signaled by the AUXTAG entry in l_info. */
b0982c4a 34#define AUXTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
1522c368 35 + DT_EXTRATAGIDX (DT_AUXILIARY))
f41c8091
UD
36/* Whether an shared object references one or more auxiliary objects
37 is signaled by the AUXTAG entry in l_info. */
b0982c4a 38#define FILTERTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
f41c8091 39 + DT_EXTRATAGIDX (DT_FILTER))
1522c368 40
e3e35cfc
UD
41/* This is zero at program start to signal that the global scope map is
42 allocated by rtld. Later it keeps the size of the map. It might be
43 reset if in _dl_close if the last global object is removed. */
44size_t _dl_global_scope_alloc;
45
dc5efe83 46extern size_t _dl_platformlen;
1522c368
UD
47
48/* When loading auxiliary objects we must ignore errors. It's ok if
49 an object is missing. */
993b3242 50struct openaux_args
1522c368
UD
51 {
52 /* The arguments to openaux. */
53 struct link_map *map;
54 int trace_mode;
55 const char *strtab;
dc5efe83 56 const char *name;
993b3242 57
1522c368
UD
58 /* The return value of openaux. */
59 struct link_map *aux;
60 };
993b3242
UD
61
62static void
63openaux (void *a)
64{
65 struct openaux_args *args = (struct openaux_args *) a;
66
dc5efe83 67 args->aux = _dl_map_object (args->map, args->name, 0,
993b3242
UD
68 (args->map->l_type == lt_executable
69 ? lt_library : args->map->l_type),
bf8b3e74 70 args->trace_mode, 0);
993b3242
UD
71}
72
1522c368
UD
73
74
80d9c5f0 75/* We use a very special kind of list to track the path
1522c368 76 through the list of loaded shared objects. We have to
80d9c5f0 77 produce a flat list with unique members of all involved objects.
1522c368
UD
78*/
79struct list
80 {
81 int done; /* Nonzero if this map was processed. */
82 struct link_map *map; /* The data. */
80d9c5f0 83 struct list *next; /* Elements for normal list. */
1522c368
UD
84 };
85
86
dc5efe83
UD
87/* Macro to expand DST. It is an macro since we use `alloca'. */
88#define expand_dst(l, str, fatal) \
89 ({ \
90 const char *__str = (str); \
91 const char *__result = __str; \
92 size_t __cnt = DL_DST_COUNT(__str, 0); \
93 \
94 if (__cnt != 0) \
95 { \
06535ae9
UD
96 char *__newp; \
97 \
98 /* DST must not appear in SUID/SGID programs. */ \
99 if (__libc_enable_secure) \
100 _dl_signal_error (0, __str, \
8e17ea58 101 N_("DST not allowed in SUID/SGID programs")); \
06535ae9
UD
102 \
103 __newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str), \
104 __cnt)); \
dc5efe83
UD
105 \
106 __result = DL_DST_SUBSTITUTE (l, __str, __newp, 0); \
107 \
108 if (*__result == '\0') \
109 { \
110 /* The replacement for the DST is not known. We can't \
111 processed. */ \
112 if (fatal) \
8e17ea58
UD
113 _dl_signal_error (0, __str, N_("\
114empty dynamics string token substitution")); \
dc5efe83
UD
115 else \
116 { \
117 /* This is for DT_AUXILIARY. */ \
62dcee57 118 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0)) \
35fc382a
UD
119 _dl_debug_printf ("cannot load auxiliary `%s' because of" \
120 "empty dynamic string token " \
121 "substitution\n", __str); \
dc5efe83
UD
122 continue; \
123 } \
124 } \
125 } \
126 \
127 __result; })
128
129
d9cb1a7d 130void
d0fc4041 131internal_function
2064087b 132_dl_map_object_deps (struct link_map *map,
46ec036d 133 struct link_map **preloads, unsigned int npreloads,
d9cb1a7d 134 int trace_mode)
efec1d0c 135{
1522c368 136 struct list known[1 + npreloads + 1];
80d9c5f0
UD
137 struct list *runp, *tail;
138 unsigned int nlist, i;
c77a4478
UD
139 /* Object name. */
140 const char *name;
141 int errno_saved;
142 int errno_reason;
951d5dd8 143 const char *errstring;
64b7897d 144 const char *objname;
1522c368 145
938c669e
AJ
146 auto inline void preload (struct link_map *map);
147
df4ef2ab
UD
148 inline void preload (struct link_map *map)
149 {
1522c368
UD
150 known[nlist].done = 0;
151 known[nlist].map = map;
80d9c5f0 152 known[nlist].next = &known[nlist + 1];
efec1d0c 153
1522c368 154 ++nlist;
df4ef2ab
UD
155 /* We use `l_reserved' as a mark bit to detect objects we have
156 already put in the search list and avoid adding duplicate
157 elements later in the list. */
158 map->l_reserved = 1;
159 }
2064087b 160
1522c368
UD
161 /* No loaded object so far. */
162 nlist = 0;
2064087b 163
1522c368 164 /* First load MAP itself. */
df4ef2ab
UD
165 preload (map);
166
167 /* Add the preloaded items after MAP but before any of its dependencies. */
168 for (i = 0; i < npreloads; ++i)
169 preload (preloads[i]);
170
8a523922 171 /* Terminate the lists. */
80d9c5f0 172 known[nlist - 1].next = NULL;
1522c368 173
1522c368 174 /* Pointer to last unique object. */
80d9c5f0 175 tail = &known[nlist - 1];
efec1d0c 176
1522c368
UD
177 /* Process each element of the search list, loading each of its
178 auxiliary objects and immediate dependencies. Auxiliary objects
179 will be added in the list before the object itself and
180 dependencies will be appended to the list as we step through it.
181 This produces a flat, ordered list that represents a
182 breadth-first search of the dependency tree.
183
184 The whole process is complicated by the fact that we better
185 should use alloca for the temporary list elements. But using
186 alloca means we cannot use recursive function calls. */
c77a4478
UD
187 errno_saved = errno;
188 errno_reason = 0;
951d5dd8 189 errstring = NULL;
c77a4478
UD
190 errno = 0;
191 name = NULL;
1522c368 192 for (runp = known; runp; )
efec1d0c 193 {
1522c368 194 struct link_map *l = runp->map;
dacc8ffa
UD
195 struct link_map **needed = NULL;
196 unsigned int nneeded = 0;
197
198 /* Unless otherwise stated, this object is handled. */
199 runp->done = 1;
200
201 /* Allocate a temporary record to contain the references to the
202 dependencies of this object. */
07a3d63e
UD
203 if (l->l_searchlist.r_list == NULL && l->l_initfini == NULL
204 && l != map && l->l_ldnum > 0)
dacc8ffa
UD
205 needed = (struct link_map **) alloca (l->l_ldnum
206 * sizeof (struct link_map *));
f68b86cc 207
8193034b 208 if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG])
efec1d0c 209 {
a42195db 210 const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
1522c368
UD
211 struct openaux_args args;
212 struct list *orig;
266180eb 213 const ElfW(Dyn) *d;
1522c368 214
1522c368
UD
215 args.strtab = strtab;
216 args.map = l;
217 args.trace_mode = trace_mode;
218 orig = runp;
219
efec1d0c 220 for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
e3e35cfc 221 if (__builtin_expect (d->d_tag, DT_NEEDED) == DT_NEEDED)
efec1d0c 222 {
f68b86cc 223 /* Map in the needed object. */
dc5efe83 224 struct link_map *dep;
505d4b24 225 int err;
dc5efe83
UD
226
227 /* Recognize DSTs. */
228 name = expand_dst (l, strtab + d->d_un.d_val, 0);
c77a4478
UD
229 /* Store the tag in the argument structure. */
230 args.name = name;
dc5efe83 231
505d4b24
UD
232 err = _dl_catch_error (&objname, &errstring, openaux, &args);
233 if (__builtin_expect (errstring != NULL, 0))
c77a4478 234 {
505d4b24
UD
235 if (err)
236 errno_reason = err;
c77a4478
UD
237 else
238 errno_reason = -1;
239 goto out;
240 }
241 else
242 dep = args.aux;
1522c368 243
42c4f32a 244 if (! dep->l_reserved)
efec1d0c 245 {
80d9c5f0
UD
246 /* Allocate new entry. */
247 struct list *newp;
248
249 newp = alloca (sizeof (struct list));
250
251 /* Append DEP to the list. */
252 newp->map = dep;
1522c368 253 newp->done = 0;
80d9c5f0
UD
254 newp->next = NULL;
255 tail->next = newp;
256 tail = newp;
f68b86cc 257 ++nlist;
f9496a7b
RM
258 /* Set the mark bit that says it's already in the list. */
259 dep->l_reserved = 1;
efec1d0c 260 }
dacc8ffa
UD
261
262 /* Remember this dependency. */
263 if (needed != NULL)
264 needed[nneeded++] = dep;
1522c368 265 }
f41c8091 266 else if (d->d_tag == DT_AUXILIARY || d->d_tag == DT_FILTER)
1522c368 267 {
f41c8091 268 struct list *newp;
dc5efe83
UD
269
270 /* Recognize DSTs. */
271 name = expand_dst (l, strtab + d->d_un.d_val,
272 d->d_tag == DT_AUXILIARY);
c77a4478
UD
273 /* Store the tag in the argument structure. */
274 args.name = name;
84384f5b 275
f41c8091 276 if (d->d_tag == DT_AUXILIARY)
1522c368 277 {
505d4b24
UD
278 int err;
279
8d9618b7 280 /* Say that we are about to load an auxiliary library. */
62dcee57 281 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0))
35fc382a
UD
282 _dl_debug_printf ("load auxiliary object=%s"
283 " requested by file=%s\n", name,
284 l->l_name[0]
285 ? l->l_name : _dl_argv[0]);
8d9618b7 286
f41c8091
UD
287 /* We must be prepared that the addressed shared
288 object is not available. */
505d4b24
UD
289 err = _dl_catch_error (&objname, &errstring, openaux,
290 &args);
291 if (__builtin_expect (errstring != NULL, 0))
f41c8091
UD
292 {
293 /* We are not interested in the error message. */
294 assert (errstring != NULL);
ca3c0135
UD
295 if (errstring != _dl_out_of_memory)
296 free ((char *) errstring);
f41c8091
UD
297
298 /* Simply ignore this error and continue the work. */
299 continue;
300 }
1522c368
UD
301 }
302 else
8d9618b7 303 {
505d4b24
UD
304 int err;
305
8d9618b7 306 /* Say that we are about to load an auxiliary library. */
62dcee57 307 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0))
35fc382a
UD
308 _dl_debug_printf ("load filtered object=%s"
309 " requested by file=%s\n", name,
310 l->l_name[0]
311 ? l->l_name : _dl_argv[0]);
8d9618b7
UD
312
313 /* For filter objects the dependency must be available. */
505d4b24
UD
314 err = _dl_catch_error (&objname, &errstring, openaux,
315 &args);
316 if (__builtin_expect (errstring != NULL, 0))
c77a4478 317 {
505d4b24
UD
318 if (err)
319 errno_reason = err;
c77a4478
UD
320 else
321 errno_reason = -1;
322 goto out;
323 }
8d9618b7 324 }
f41c8091
UD
325
326 /* The auxiliary object is actually available.
327 Incorporate the map in all the lists. */
328
329 /* Allocate new entry. This always has to be done. */
330 newp = alloca (sizeof (struct list));
331
ee0f7bd6
UD
332 /* We want to insert the new map before the current one,
333 but we have no back links. So we copy the contents of
334 the current entry over. Note that ORIG and NEWP now
335 have switched their meanings. */
80d9c5f0 336 memcpy (newp, orig, sizeof (*newp));
f41c8091
UD
337
338 /* Initialize new entry. */
339 orig->done = 0;
340 orig->map = args.aux;
f41c8091 341
dacc8ffa
UD
342 /* Remember this dependency. */
343 if (needed != NULL)
344 needed[nneeded++] = args.aux;
345
f41c8091
UD
346 /* We must handle two situations here: the map is new,
347 so we must add it in all three lists. If the map
348 is already known, we have two further possibilities:
349 - if the object is before the current map in the
350 search list, we do nothing. It is already found
351 early
352 - if the object is after the current one, we must
353 move it just before the current map to make sure
354 the symbols are found early enough
355 */
356 if (args.aux->l_reserved)
1522c368 357 {
f41c8091
UD
358 /* The object is already somewhere in the list.
359 Locate it first. */
360 struct list *late;
361
362 /* This object is already in the search list we
363 are building. Don't add a duplicate pointer.
42c4f32a 364 Just added by _dl_map_object. */
80d9c5f0
UD
365 for (late = newp; late->next; late = late->next)
366 if (late->next->map == args.aux)
f41c8091
UD
367 break;
368
80d9c5f0 369 if (late->next)
1522c368 370 {
f41c8091
UD
371 /* The object is somewhere behind the current
372 position in the search path. We have to
373 move it to this earlier position. */
80d9c5f0 374 orig->next = newp;
f41c8091 375
80d9c5f0 376 /* Now remove the later entry from the list
ee0f7bd6 377 and adjust the tail pointer. */
80d9c5f0
UD
378 if (tail == late->next)
379 tail = late;
380 late->next = late->next->next;
f41c8091 381
ee0f7bd6 382 /* We must move the object earlier in the chain. */
1522c368
UD
383 if (args.aux->l_prev)
384 args.aux->l_prev->l_next = args.aux->l_next;
385 if (args.aux->l_next)
386 args.aux->l_next->l_prev = args.aux->l_prev;
387
388 args.aux->l_prev = newp->map->l_prev;
389 newp->map->l_prev = args.aux;
390 if (args.aux->l_prev != NULL)
391 args.aux->l_prev->l_next = args.aux;
392 args.aux->l_next = newp->map;
393 }
f41c8091
UD
394 else
395 {
396 /* The object must be somewhere earlier in the
397 list. That's good, we only have to insert
398 an entry for the duplicate list. */
80d9c5f0 399 orig->next = NULL; /* Never used. */
f41c8091
UD
400
401 /* Now we have a problem. The element
80d9c5f0 402 pointing to ORIG in the list must
f41c8091
UD
403 point to NEWP now. This is the only place
404 where we need this backreference and this
405 situation is really not that frequent. So
406 we don't use a double-linked list but
407 instead search for the preceding element. */
26b4d766 408 late = known;
80d9c5f0
UD
409 while (late->next != orig)
410 late = late->next;
411 late->next = newp;
f41c8091
UD
412 }
413 }
414 else
415 {
416 /* This is easy. We just add the symbol right here. */
80d9c5f0 417 orig->next = newp;
f41c8091
UD
418 ++nlist;
419 /* Set the mark bit that says it's already in the list. */
420 args.aux->l_reserved = 1;
421
422 /* The only problem is that in the double linked
423 list of all objects we don't have this new
424 object at the correct place. Correct this here. */
425 if (args.aux->l_prev)
426 args.aux->l_prev->l_next = args.aux->l_next;
427 if (args.aux->l_next)
428 args.aux->l_next->l_prev = args.aux->l_prev;
429
430 args.aux->l_prev = newp->map->l_prev;
431 newp->map->l_prev = args.aux;
432 if (args.aux->l_prev != NULL)
433 args.aux->l_prev->l_next = args.aux;
434 args.aux->l_next = newp->map;
435 }
1522c368 436
80d9c5f0
UD
437 /* Move the tail pointer if necessary. */
438 if (orig == tail)
439 tail = newp;
1522c368 440
f41c8091
UD
441 /* Move on the insert point. */
442 orig = newp;
efec1d0c
RM
443 }
444 }
dacc8ffa
UD
445
446 /* Terminate the list of dependencies and store the array address. */
447 if (needed != NULL)
448 {
449 needed[nneeded++] = NULL;
450
c6d80202 451 l->l_initfini = malloc (nneeded * sizeof needed[0]);
dacc8ffa
UD
452 if (l->l_initfini == NULL)
453 _dl_signal_error (ENOMEM, map->l_name,
8e17ea58 454 N_("cannot allocate dependency list"));
c6d80202 455 memcpy (l->l_initfini, needed, nneeded * sizeof needed[0]);
dacc8ffa 456 }
1522c368
UD
457
458 /* If we have no auxiliary objects just go on to the next map. */
459 if (runp->done)
460 do
80d9c5f0 461 runp = runp->next;
8193034b 462 while (runp != NULL && runp->done);
efec1d0c
RM
463 }
464
c77a4478
UD
465out:
466 if (errno == 0 && errno_saved != 0)
467 __set_errno (errno_saved);
468
752a2a50
UD
469 if (map->l_initfini != NULL && map->l_type == lt_loaded)
470 {
471 /* This object was previously loaded as a dependency and we have
472 a separate l_initfini list. We don't need it anymore. */
473 assert (map->l_searchlist.r_list == NULL);
474 free (map->l_initfini);
475 }
476
f68b86cc
RM
477 /* Store the search list we built in the object. It will be used for
478 searches in the scope of this object. */
2e93b4a4 479 map->l_initfini =
80d9c5f0 480 (struct link_map **) malloc ((2 * nlist + 1)
2e93b4a4
UD
481 * sizeof (struct link_map *));
482 if (map->l_initfini == NULL)
df4ef2ab 483 _dl_signal_error (ENOMEM, map->l_name,
8e17ea58 484 N_("cannot allocate symbol search list"));
2e93b4a4
UD
485
486
487 map->l_searchlist.r_list = &map->l_initfini[nlist + 1];
be935610 488 map->l_searchlist.r_nlist = nlist;
f68b86cc 489
80d9c5f0 490 for (nlist = 0, runp = known; runp; runp = runp->next)
f68b86cc 491 {
a881e0a0 492 if (trace_mode && runp->map->l_faked)
ad9570d7
UD
493 /* This can happen when we trace the loading. */
494 --map->l_searchlist.r_nlist;
495 else
496 map->l_searchlist.r_list[nlist++] = runp->map;
f68b86cc
RM
497
498 /* Now clear all the mark bits we set in the objects on the search list
499 to avoid duplicates, so the next call starts fresh. */
1522c368 500 runp->map->l_reserved = 0;
f68b86cc 501 }
84384f5b 502
dacc8ffa 503 /* Now determine the order in which the initialization has to happen. */
2e93b4a4
UD
504 memcpy (map->l_initfini, map->l_searchlist.r_list,
505 nlist * sizeof (struct link_map *));
dacc8ffa
UD
506 /* We can skip looking for the binary itself which is at the front
507 of the search list. Look through the list backward so that circular
508 dependencies are not changing the order. */
509 for (i = 1; i < nlist; ++i)
510 {
511 struct link_map *l = map->l_searchlist.r_list[i];
512 unsigned int j;
513 unsigned int k;
514
515 /* Find the place in the initfini list where the map is currently
516 located. */
517 for (j = 1; map->l_initfini[j] != l; ++j)
518 ;
519
520 /* Find all object for which the current one is a dependency and
521 move the found object (if necessary) in front. */
522 for (k = j + 1; k < nlist; ++k)
523 {
524 struct link_map **runp;
525
526 runp = map->l_initfini[k]->l_initfini;
527 if (runp != NULL)
528 {
529 while (*runp != NULL)
530 if (*runp == l)
531 {
532 struct link_map *here = map->l_initfini[k];
533
534 /* Move it now. */
535 memmove (&map->l_initfini[j] + 1,
536 &map->l_initfini[j],
537 (k - j) * sizeof (struct link_map *));
538 map->l_initfini[j] = here;
539
540 break;
541 }
542 else
543 ++runp;
544 }
545 }
546 }
a8571d37
AJ
547 /* Terminate the list of dependencies. */
548 map->l_initfini[nlist] = NULL;
c77a4478
UD
549
550 if (errno_reason)
551 _dl_signal_error (errno_reason == -1 ? 0 : errno_reason,
64b7897d 552 objname, errstring);
efec1d0c 553}