Update.
[glibc.git] / elf / dl-lookup.c
blobf1ec98e74b9dedac223a86326e93cbee8b70a0ec
1 /* Look up a symbol in the loaded objects.
2 Copyright (C) 1995,96,97,98,99,2000 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 Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 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 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <alloca.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <ldsodefs.h>
25 #include "dl-hash.h"
26 #include <dl-machine.h>
27 #include <bits/libc-lock.h>
29 #include <assert.h>
31 #define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
33 /* We need this string more than once. */
34 static const char undefined_msg[] = "undefined symbol: ";
37 struct sym_val
39 const ElfW(Sym) *s;
40 struct link_map *m;
44 #define make_string(string, rest...) \
45 ({ \
46 const char *all[] = { string, ## rest }; \
47 size_t len, cnt; \
48 char *result, *cp; \
50 len = 1; \
51 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
52 len += strlen (all[cnt]); \
54 cp = result = alloca (len); \
55 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
56 cp = __stpcpy (cp, all[cnt]); \
58 result; \
61 /* Statistics function. */
62 unsigned long int _dl_num_relocations;
64 /* During the program run we must not modify the global data of
65 loaded shared object simultanously in two threads. Therefore we
66 protect `_dl_open' and `_dl_close' in dl-close.c.
68 This must be a recursive lock since the initializer function of
69 the loaded object might as well require a call to this function.
70 At this time it is not anymore a problem to modify the tables. */
71 __libc_lock_define (extern, _dl_load_lock)
74 /* We have two different situations when looking up a simple: with or
75 without versioning. gcc is not able to optimize a single function
76 definition serving for both purposes so we define two functions. */
77 #define VERSIONED 0
78 #define PROTECTED 0
79 #include "do-lookup.h"
81 #define VERSIONED 1
82 #define PROTECTED 0
83 #include "do-lookup.h"
86 /* Add extra dependency on MAP to UNDEF_MAP. */
87 static int
88 add_dependency (struct link_map *undef_map, struct link_map *map)
90 struct link_map **list;
91 unsigned int act;
92 unsigned int i;
93 int result = 0;
95 /* Make sure nobody can unload the object while we are at it. */
96 __libc_lock_lock (_dl_load_lock);
98 /* Determine whether UNDEF_MAP already has a reference to MAP. First
99 look in the normal dependencies. */
100 list = undef_map->l_searchlist.r_list;
101 act = undef_map->l_searchlist.r_nlist;
103 for (i = 0; i < act; ++i)
104 if (list[i] == map)
105 break;
107 if (__builtin_expect (i == act, 1))
109 /* No normal dependency. See whether we already had to add it
110 to the special list of dynamic dependencies. */
111 list = undef_map->l_reldeps;
112 act = undef_map->l_reldepsact;
114 for (i = 0; i < act; ++i)
115 if (list[i] == map)
116 break;
118 if (i == act)
120 /* The object is not yet in the dependency list. Before we add
121 it make sure just one more time the object we are about to
122 reference is still available. There is a brief period in
123 which the object could have been removed since we found the
124 definition. */
125 struct link_map *runp = _dl_loaded;
127 while (runp != NULL && runp != map)
128 runp = runp->l_next;
130 if (runp != NULL)
132 /* The object is still available. Add the reference now. */
133 if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
135 /* Allocate more memory for the dependency list. Since
136 this can never happen during the startup phase we can
137 use `realloc'. */
138 void *newp;
140 undef_map->l_reldepsmax += 5;
141 newp = realloc (undef_map->l_reldeps,
142 undef_map->l_reldepsmax
143 * sizeof(struct link_map *));
145 if (__builtin_expect (newp != NULL, 1))
146 undef_map->l_reldeps = (struct link_map **) newp;
147 else
148 /* Correct the addition. */
149 undef_map->l_reldepsmax -= 5;
152 /* If we didn't manage to allocate memory for the list this
153 is no fatal mistake. We simply increment the use counter
154 of the referenced object and don't record the dependencies.
155 This means this increment can never be reverted and the
156 object will never be unloaded. This is semantically the
157 correct behaviour. */
158 if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
159 undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
161 /* And increment the counter in the referenced object. */
162 ++map->l_opencount;
164 /* Display information if we are debugging. */
165 if (__builtin_expect (_dl_debug_files, 0))
166 _dl_debug_message (1, "\nfile=",
167 map->l_name[0] ? map->l_name : _dl_argv[0],
168 "; needed by ",
169 undef_map->l_name[0]
170 ? undef_map->l_name : _dl_argv[0],
171 " (relocation dependency)\n\n", NULL);
173 else
174 /* Whoa, that was bad luck. We have to search again. */
175 result = -1;
179 /* Release the lock. */
180 __libc_lock_unlock (_dl_load_lock);
182 return result;
186 /* Search loaded objects' symbol tables for a definition of the symbol
187 UNDEF_NAME. */
189 lookup_t
190 internal_function
191 _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
192 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
193 int reloc_type)
195 const char *reference_name = undef_map ? undef_map->l_name : NULL;
196 const unsigned long int hash = _dl_elf_hash (undef_name);
197 struct sym_val current_value = { NULL, NULL };
198 struct r_scope_elem **scope;
199 int protected;
200 int noexec = elf_machine_lookup_noexec_p (reloc_type);
201 int noplt = elf_machine_lookup_noplt_p (reloc_type);
203 ++_dl_num_relocations;
205 /* Search the relevant loaded objects for a definition. */
206 for (scope = symbol_scope; *scope; ++scope)
207 if (do_lookup (undef_name, undef_map, hash, *ref, &current_value,
208 *scope, 0, NULL, noexec, noplt))
210 /* We have to check whether this would bind UNDEF_MAP to an object
211 in the global scope which was dynamically loaded. In this case
212 we have to prevent the latter from being unloaded unless the
213 UNDEF_MAP object is also unloaded. */
214 if (__builtin_expect (current_value.m->l_global, 0)
215 && (__builtin_expect (current_value.m->l_type, lt_library)
216 == lt_loaded)
217 && undef_map != current_value.m
218 /* Add UNDEF_MAP to the dependencies. */
219 && add_dependency (undef_map, current_value.m) < 0)
220 /* Something went wrong. Perhaps the object we tried to reference
221 was just removed. Try finding another definition. */
222 return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope,
223 reloc_type);
225 break;
228 if (__builtin_expect (current_value.s == NULL, 0))
230 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
231 /* We could find no value for a strong reference. */
232 /* XXX We cannot translate the messages. */
233 _dl_signal_cerror (0, (reference_name && reference_name[0]
234 ? reference_name
235 : (_dl_argv[0] ?: "<main program>")),
236 make_string (undefined_msg, undef_name));
237 *ref = NULL;
238 return 0;
241 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
243 if (__builtin_expect (_dl_debug_bindings, 0))
244 _dl_debug_message (1, "binding file ",
245 (reference_name && reference_name[0]
246 ? reference_name
247 : (_dl_argv[0] ?: "<main program>")),
248 " to ", current_value.m->l_name[0]
249 ? current_value.m->l_name : _dl_argv[0],
250 ": ", protected ? "protected" : "normal",
251 " symbol `", undef_name, "'\n", NULL);
253 if (__builtin_expect (protected == 0, 1))
255 *ref = current_value.s;
256 return LOOKUP_VALUE (current_value.m);
258 else
260 /* It is very tricky. We need to figure out what value to
261 return for the protected symbol */
262 struct sym_val protected_value = { NULL, NULL };
264 for (scope = symbol_scope; *scope; ++scope)
265 if (do_lookup (undef_name, undef_map, hash, *ref,
266 &protected_value, *scope, 0, NULL, 0, 1))
267 break;
269 if (protected_value.s == NULL || protected_value.m == undef_map)
271 *ref = current_value.s;
272 return LOOKUP_VALUE (current_value.m);
275 return LOOKUP_VALUE (undef_map);
280 /* This function is nearly the same as `_dl_lookup_symbol' but it
281 skips in the first list all objects until SKIP_MAP is found. I.e.,
282 it only considers objects which were loaded after the described
283 object. If there are more search lists the object described by
284 SKIP_MAP is only skipped. */
285 lookup_t
286 internal_function
287 _dl_lookup_symbol_skip (const char *undef_name,
288 struct link_map *undef_map, const ElfW(Sym) **ref,
289 struct r_scope_elem *symbol_scope[],
290 struct link_map *skip_map)
292 const char *reference_name = undef_map ? undef_map->l_name : NULL;
293 const unsigned long int hash = _dl_elf_hash (undef_name);
294 struct sym_val current_value = { NULL, NULL };
295 struct r_scope_elem **scope;
296 size_t i;
297 int protected;
299 ++_dl_num_relocations;
301 /* Search the relevant loaded objects for a definition. */
302 scope = symbol_scope;
303 for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
304 assert (i < (*scope)->r_nduplist);
306 if (i < (*scope)->r_nlist
307 && do_lookup (undef_name, undef_map, hash, *ref, &current_value,
308 *scope, i, skip_map, 0, 0))
310 /* We have to check whether this would bind UNDEF_MAP to an object
311 in the global scope which was dynamically loaded. In this case
312 we have to prevent the latter from being unloaded unless the
313 UNDEF_MAP object is also unloaded. */
314 if (current_value.m->l_global
315 && (__builtin_expect (current_value.m->l_type, lt_library)
316 == lt_loaded)
317 && undef_map != current_value.m
318 /* Add UNDEF_MAP to the dependencies. */
319 && add_dependency (undef_map, current_value.m) < 0)
320 /* Something went wrong. Perhaps the object we tried to reference
321 was just removed. Try finding another definition. */
322 return _dl_lookup_symbol_skip (undef_name, undef_map, ref,
323 symbol_scope, skip_map);
325 else
326 while (*++scope)
327 if (do_lookup (undef_name, undef_map, hash, *ref, &current_value,
328 *scope, 0, skip_map, 0, 0))
330 /* We have to check whether this would bind UNDEF_MAP to an object
331 in the global scope which was dynamically loaded. In this case
332 we have to prevent the latter from being unloaded unless the
333 UNDEF_MAP object is also unloaded. */
334 if (__builtin_expect (current_value.m->l_global, 0)
335 && (__builtin_expect (current_value.m->l_type, lt_library)
336 == lt_loaded)
337 && undef_map != current_value.m
338 /* Add UNDEF_MAP to the dependencies. */
339 && add_dependency (undef_map, current_value.m) < 0)
340 /* Something went wrong. Perhaps the object we tried to reference
341 was just removed. Try finding another definition. */
342 return _dl_lookup_symbol_skip (undef_name, undef_map, ref,
343 symbol_scope, skip_map);
345 break;
348 if (__builtin_expect (current_value.s == NULL, 0))
350 *ref = NULL;
351 return 0;
354 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
356 if (__builtin_expect (_dl_debug_bindings, 0))
357 _dl_debug_message (1, "binding file ",
358 (reference_name && reference_name[0]
359 ? reference_name
360 : (_dl_argv[0] ?: "<main program>")),
361 " to ", current_value.m->l_name[0]
362 ? current_value.m->l_name : _dl_argv[0],
363 ": ", protected ? "protected" : "normal",
364 " symbol `", undef_name, "'\n", NULL);
366 if (__builtin_expect (protected == 0, 1))
368 *ref = current_value.s;
369 return LOOKUP_VALUE (current_value.m);
371 else
373 /* It is very tricky. We need to figure out what value to
374 return for the protected symbol */
375 struct sym_val protected_value = { NULL, NULL };
377 if (i >= (*scope)->r_nlist
378 || !do_lookup (undef_name, undef_map, hash, *ref, &protected_value,
379 *scope, i, skip_map, 0, 1))
380 while (*++scope)
381 if (do_lookup (undef_name, undef_map, hash, *ref, &protected_value,
382 *scope, 0, skip_map, 0, 1))
383 break;
385 if (protected_value.s == NULL || protected_value.m == undef_map)
387 *ref = current_value.s;
388 return LOOKUP_VALUE (current_value.m);
391 return LOOKUP_VALUE (undef_map);
396 /* This function works like _dl_lookup_symbol but it takes an
397 additional arguement with the version number of the requested
398 symbol.
400 XXX We'll see whether we need this separate function. */
401 lookup_t
402 internal_function
403 _dl_lookup_versioned_symbol (const char *undef_name,
404 struct link_map *undef_map, const ElfW(Sym) **ref,
405 struct r_scope_elem *symbol_scope[],
406 const struct r_found_version *version,
407 int reloc_type)
409 const char *reference_name = undef_map ? undef_map->l_name : NULL;
410 const unsigned long int hash = _dl_elf_hash (undef_name);
411 struct sym_val current_value = { NULL, NULL };
412 struct r_scope_elem **scope;
413 int protected;
414 int noexec = elf_machine_lookup_noexec_p (reloc_type);
415 int noplt = elf_machine_lookup_noplt_p (reloc_type);
417 ++_dl_num_relocations;
419 /* Search the relevant loaded objects for a definition. */
420 for (scope = symbol_scope; *scope; ++scope)
422 int res = do_lookup_versioned (undef_name, undef_map, hash, *ref,
423 &current_value, *scope, 0, version, NULL,
424 noexec, noplt);
425 if (res > 0)
427 /* We have to check whether this would bind UNDEF_MAP to an object
428 in the global scope which was dynamically loaded. In this case
429 we have to prevent the latter from being unloaded unless the
430 UNDEF_MAP object is also unloaded. */
431 if (__builtin_expect (current_value.m->l_global, 0)
432 && (__builtin_expect (current_value.m->l_type, lt_library)
433 == lt_loaded)
434 && undef_map != current_value.m
435 /* Add UNDEF_MAP to the dependencies. */
436 && add_dependency (undef_map, current_value.m) < 0)
437 /* Something went wrong. Perhaps the object we tried to reference
438 was just removed. Try finding another definition. */
439 return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
440 symbol_scope, version,
441 reloc_type);
443 break;
446 if (__builtin_expect (res, 0) < 0)
448 /* Oh, oh. The file named in the relocation entry does not
449 contain the needed symbol. */
450 /* XXX We cannot translate the message. */
451 _dl_signal_cerror (0, (reference_name && reference_name[0]
452 ? reference_name
453 : (_dl_argv[0] ?: "<main program>")),
454 make_string ("symbol ", undef_name, ", version ",
455 version->name,
456 " not defined in file ",
457 version->filename,
458 " with link time reference",
459 res == -2
460 ? " (no version symbols)" : ""));
461 *ref = NULL;
462 return 0;
466 if (__builtin_expect (current_value.s == NULL, 0))
468 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
469 /* We could find no value for a strong reference. */
470 /* XXX We cannot translate the message. */
471 _dl_signal_cerror (0, (reference_name && reference_name[0]
472 ? reference_name
473 : (_dl_argv[0] ?: "<main program>")),
474 make_string (undefined_msg, undef_name,
475 ", version ", version->name ?: NULL));
476 *ref = NULL;
477 return 0;
480 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
482 if (__builtin_expect (_dl_debug_bindings, 0))
483 _dl_debug_message (1, "binding file ",
484 (reference_name && reference_name[0]
485 ? reference_name
486 : (_dl_argv[0] ?: "<main program>")),
487 " to ", current_value.m->l_name[0]
488 ? current_value.m->l_name : _dl_argv[0],
489 ": ", protected ? "protected" : "normal",
490 " symbol `", undef_name, "' [", version->name,
491 "]\n", NULL);
493 if (__builtin_expect (protected == 0, 1))
495 *ref = current_value.s;
496 return LOOKUP_VALUE (current_value.m);
498 else
500 /* It is very tricky. We need to figure out what value to
501 return for the protected symbol */
502 struct sym_val protected_value = { NULL, NULL };
504 for (scope = symbol_scope; *scope; ++scope)
505 if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
506 &protected_value, *scope, 0, version, NULL,
507 0, 1))
508 break;
510 if (protected_value.s == NULL || protected_value.m == undef_map)
512 *ref = current_value.s;
513 return LOOKUP_VALUE (current_value.m);
516 return LOOKUP_VALUE (undef_map);
521 /* Similar to _dl_lookup_symbol_skip but takes an additional argument
522 with the version we are looking for. */
523 lookup_t
524 internal_function
525 _dl_lookup_versioned_symbol_skip (const char *undef_name,
526 struct link_map *undef_map,
527 const ElfW(Sym) **ref,
528 struct r_scope_elem *symbol_scope[],
529 const struct r_found_version *version,
530 struct link_map *skip_map)
532 const char *reference_name = undef_map ? undef_map->l_name : NULL;
533 const unsigned long int hash = _dl_elf_hash (undef_name);
534 struct sym_val current_value = { NULL, NULL };
535 struct r_scope_elem **scope;
536 size_t i;
537 int protected;
539 ++_dl_num_relocations;
541 /* Search the relevant loaded objects for a definition. */
542 scope = symbol_scope;
543 for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
544 assert (i < (*scope)->r_nduplist);
546 if (i < (*scope)->r_nlist
547 && do_lookup_versioned (undef_name, undef_map, hash, *ref,
548 &current_value, *scope, i, version, skip_map,
549 0, 0))
551 /* We have to check whether this would bind UNDEF_MAP to an object
552 in the global scope which was dynamically loaded. In this case
553 we have to prevent the latter from being unloaded unless the
554 UNDEF_MAP object is also unloaded. */
555 if (__builtin_expect (current_value.m->l_global, 0)
556 && (__builtin_expect (current_value.m->l_type, lt_library)
557 == lt_loaded)
558 && undef_map != current_value.m
559 /* Add UNDEF_MAP to the dependencies. */
560 && add_dependency (undef_map, current_value.m) < 0)
561 /* Something went wrong. Perhaps the object we tried to reference
562 was just removed. Try finding another definition. */
563 return _dl_lookup_versioned_symbol_skip (undef_name, undef_map, ref,
564 symbol_scope, version,
565 skip_map);
567 else
568 while (*++scope)
569 if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
570 &current_value, *scope, 0, version, skip_map,
571 0, 0))
573 /* We have to check whether this would bind UNDEF_MAP to an object
574 in the global scope which was dynamically loaded. In this case
575 we have to prevent the latter from being unloaded unless the
576 UNDEF_MAP object is also unloaded. */
577 if (current_value.m->l_global
578 && (__builtin_expect (current_value.m->l_type, lt_library)
579 == lt_loaded)
580 && undef_map != current_value.m
581 /* Add UNDEF_MAP to the dependencies. */
582 && add_dependency (undef_map, current_value.m) < 0)
583 /* Something went wrong. Perhaps the object we tried to reference
584 was just removed. Try finding another definition. */
585 return _dl_lookup_versioned_symbol_skip (undef_name, undef_map,
586 ref, symbol_scope,
587 version, skip_map);
588 break;
591 if (__builtin_expect (current_value.s == NULL, 0))
593 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
595 /* We could find no value for a strong reference. */
596 const size_t len = strlen (undef_name);
597 char buf[sizeof undefined_msg + len];
598 __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
599 undef_name, len + 1);
600 /* XXX We cannot translate the messages. */
601 _dl_signal_cerror (0, (reference_name && reference_name[0]
602 ? reference_name
603 : (_dl_argv[0] ?: "<main program>")), buf);
605 *ref = NULL;
606 return 0;
609 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
611 if (__builtin_expect (_dl_debug_bindings, 0))
612 _dl_debug_message (1, "binding file ",
613 (reference_name && reference_name[0]
614 ? reference_name
615 : (_dl_argv[0] ?: "<main program>")),
616 " to ", current_value.m->l_name[0]
617 ? current_value.m->l_name : _dl_argv[0],
618 ": ", protected ? "protected" : "normal",
619 " symbol `", undef_name, "' [", version->name,
620 "]\n", NULL);
622 if (__builtin_expect (protected == 0, 1))
624 *ref = current_value.s;
625 return LOOKUP_VALUE (current_value.m);
627 else
629 /* It is very tricky. We need to figure out what value to
630 return for the protected symbol */
631 struct sym_val protected_value = { NULL, NULL };
633 if (i >= (*scope)->r_nlist
634 || !do_lookup_versioned (undef_name, undef_map, hash, *ref,
635 &protected_value, *scope, i, version,
636 skip_map, 0, 1))
637 while (*++scope)
638 if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
639 &protected_value, *scope, 0, version,
640 skip_map, 0, 1))
641 break;
643 if (protected_value.s == NULL || protected_value.m == undef_map)
645 *ref = current_value.s;
646 return LOOKUP_VALUE (current_value.m);
649 return LOOKUP_VALUE (undef_map);
654 /* Cache the location of MAP's hash table. */
656 void
657 internal_function
658 _dl_setup_hash (struct link_map *map)
660 Elf_Symndx *hash;
661 Elf_Symndx nchain;
663 if (!map->l_info[DT_HASH])
664 return;
665 hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr);
667 map->l_nbuckets = *hash++;
668 nchain = *hash++;
669 map->l_buckets = hash;
670 hash += map->l_nbuckets;
671 map->l_chain = hash;