Update.
[glibc.git] / elf / dl-lookup.c
blob521f032b2bc03c60966a079a470e3f86408c2e7c
1 /* Look up a symbol in the loaded objects.
2 Copyright (C) 1995,96,97,98,99,2000,2001,2002 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 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.
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 Lesser General Public License for more details.
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. */
20 #include <alloca.h>
21 #include <libintl.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <ldsodefs.h>
26 #include "dl-hash.h"
27 #include <dl-machine.h>
28 #include <bits/libc-lock.h>
29 #include <tls.h>
31 #include <assert.h>
33 #define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
35 /* We need this string more than once. */
36 static const char undefined_msg[] = "undefined symbol: ";
39 struct sym_val
41 const ElfW(Sym) *s;
42 struct link_map *m;
46 #define make_string(string, rest...) \
47 ({ \
48 const char *all[] = { string, ## rest }; \
49 size_t len, cnt; \
50 char *result, *cp; \
52 len = 1; \
53 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
54 len += strlen (all[cnt]); \
56 cp = result = alloca (len); \
57 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
58 cp = __stpcpy (cp, all[cnt]); \
60 result; \
63 /* Statistics function. */
64 #ifdef SHARED
65 # define bump_num_relocations() ++GL(dl_num_relocations)
66 #else
67 # define bump_num_relocations() ((void) 0)
68 #endif
72 /* We have two different situations when looking up a simple: with or
73 without versioning. gcc is not able to optimize a single function
74 definition serving for both purposes so we define two functions. */
75 #define VERSIONED 0
76 #include "do-lookup.h"
78 #define VERSIONED 1
79 #include "do-lookup.h"
82 /* Add extra dependency on MAP to UNDEF_MAP. */
83 static int
84 internal_function
85 add_dependency (struct link_map *undef_map, struct link_map *map)
87 struct link_map **list;
88 struct link_map *runp;
89 unsigned int act;
90 unsigned int i;
91 int result = 0;
93 /* Avoid self-references. */
94 if (undef_map == map)
95 return 0;
97 /* Make sure nobody can unload the object while we are at it. */
98 __libc_lock_lock_recursive (GL(dl_load_lock));
100 /* Determine whether UNDEF_MAP already has a reference to MAP. First
101 look in the normal dependencies. */
102 if (undef_map->l_searchlist.r_list != NULL)
104 list = undef_map->l_initfini;
106 for (i = 0; list[i] != NULL; ++i)
107 if (list[i] == map)
108 goto out;
111 /* No normal dependency. See whether we already had to add it
112 to the special list of dynamic dependencies. */
113 list = undef_map->l_reldeps;
114 act = undef_map->l_reldepsact;
116 for (i = 0; i < act; ++i)
117 if (list[i] == map)
118 goto out;
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 runp = GL(dl_loaded);
126 while (runp != NULL && runp != map)
127 runp = runp->l_next;
129 if (runp != NULL)
131 /* The object is still available. Add the reference now. */
132 if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
134 /* Allocate more memory for the dependency list. Since this
135 can never happen during the startup phase we can use
136 `realloc'. */
137 void *newp;
139 undef_map->l_reldepsmax += 5;
140 newp = realloc (undef_map->l_reldeps,
141 undef_map->l_reldepsmax
142 * sizeof (struct link_map *));
144 if (__builtin_expect (newp != NULL, 1))
145 undef_map->l_reldeps = (struct link_map **) newp;
146 else
147 /* Correct the addition. */
148 undef_map->l_reldepsmax -= 5;
151 /* If we didn't manage to allocate memory for the list this is
152 no fatal mistake. We simply increment the use counter of the
153 referenced object and don't record the dependencies. This
154 means this increment can never be reverted and the object
155 will never be unloaded. This is semantically the correct
156 behaviour. */
157 if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
158 undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
160 if (map->l_searchlist.r_list != NULL)
161 /* And increment the counter in the referenced object. */
162 ++map->l_opencount;
163 else
164 /* We have to bump the counts for all dependencies since so far
165 this object was only a normal or transitive dependency.
166 Now it might be closed with _dl_close() directly. */
167 for (list = map->l_initfini; *list != NULL; ++list)
168 ++(*list)->l_opencount;
170 /* Display information if we are debugging. */
171 if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_FILES, 0))
172 INTUSE(_dl_debug_printf) ("\
173 \nfile=%s; needed by %s (relocation dependency)\n\n",
174 map->l_name[0] ? map->l_name : _dl_argv[0],
175 undef_map->l_name[0]
176 ? undef_map->l_name : _dl_argv[0]);
178 else
179 /* Whoa, that was bad luck. We have to search again. */
180 result = -1;
182 out:
183 /* Release the lock. */
184 __libc_lock_unlock_recursive (GL(dl_load_lock));
186 return result;
189 static int
190 internal_function
191 _dl_do_lookup (const char *undef_name, unsigned long int hash,
192 const ElfW(Sym) *ref, struct sym_val *result,
193 struct r_scope_elem *scope, size_t i,
194 struct link_map *skip, int type_class);
195 static int
196 internal_function
197 _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
198 const ElfW(Sym) *ref, struct sym_val *result,
199 struct r_scope_elem *scope, size_t i,
200 const struct r_found_version *const version,
201 struct link_map *skip, int type_class);
203 static void
204 internal_function
205 _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
206 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
207 struct sym_val *value,
208 const struct r_found_version *version, int type_class,
209 int protected);
211 /* Search loaded objects' symbol tables for a definition of the symbol
212 UNDEF_NAME. */
214 lookup_t
215 internal_function
216 _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
217 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
218 int type_class, int explicit)
220 const unsigned long int hash = _dl_elf_hash (undef_name);
221 struct sym_val current_value = { NULL, NULL };
222 struct r_scope_elem **scope;
223 int protected;
225 bump_num_relocations ();
227 /* Search the relevant loaded objects for a definition. */
228 for (scope = symbol_scope; *scope; ++scope)
229 if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL,
230 type_class))
232 /* We have to check whether this would bind UNDEF_MAP to an object
233 in the global scope which was dynamically loaded. In this case
234 we have to prevent the latter from being unloaded unless the
235 UNDEF_MAP object is also unloaded. */
236 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
237 /* Don't do this for explicit lookups as opposed to implicit
238 runtime lookups. */
239 && ! explicit
240 /* Add UNDEF_MAP to the dependencies. */
241 && add_dependency (undef_map, current_value.m) < 0)
242 /* Something went wrong. Perhaps the object we tried to reference
243 was just removed. Try finding another definition. */
244 return INTUSE(_dl_lookup_symbol) (undef_name, undef_map, ref,
245 symbol_scope, type_class, 0);
247 break;
250 if (__builtin_expect (current_value.s == NULL, 0))
252 const char *reference_name = undef_map ? undef_map->l_name : NULL;
254 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
255 /* We could find no value for a strong reference. */
256 /* XXX We cannot translate the messages. */
257 _dl_signal_cerror (0, (reference_name[0]
258 ? reference_name
259 : (_dl_argv[0] ?: "<main program>")),
260 N_("relocation error"),
261 make_string (undefined_msg, undef_name));
262 *ref = NULL;
263 return 0;
266 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
267 if (__builtin_expect (protected != 0, 0))
269 /* It is very tricky. We need to figure out what value to
270 return for the protected symbol */
271 struct sym_val protected_value = { NULL, NULL };
273 for (scope = symbol_scope; *scope; ++scope)
274 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
275 0, NULL, ELF_RTYPE_CLASS_PLT))
276 break;
278 if (protected_value.s != NULL && protected_value.m != undef_map)
280 current_value.s = *ref;
281 current_value.m = undef_map;
285 if (__builtin_expect (GL(dl_debug_mask)
286 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
287 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
288 &current_value, NULL, type_class, protected);
290 *ref = current_value.s;
291 return LOOKUP_VALUE (current_value.m);
293 INTDEF (_dl_lookup_symbol)
296 /* This function is nearly the same as `_dl_lookup_symbol' but it
297 skips in the first list all objects until SKIP_MAP is found. I.e.,
298 it only considers objects which were loaded after the described
299 object. If there are more search lists the object described by
300 SKIP_MAP is only skipped. */
301 lookup_t
302 internal_function
303 _dl_lookup_symbol_skip (const char *undef_name,
304 struct link_map *undef_map, const ElfW(Sym) **ref,
305 struct r_scope_elem *symbol_scope[],
306 struct link_map *skip_map)
308 const unsigned long int hash = _dl_elf_hash (undef_name);
309 struct sym_val current_value = { NULL, NULL };
310 struct r_scope_elem **scope;
311 size_t i;
312 int protected;
314 bump_num_relocations ();
316 /* Search the relevant loaded objects for a definition. */
317 scope = symbol_scope;
318 for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
319 assert (i < (*scope)->r_nlist);
321 if (! _dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, i,
322 skip_map, 0))
323 while (*++scope)
324 if (_dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
325 skip_map, 0))
326 break;
328 if (__builtin_expect (current_value.s == NULL, 0))
330 *ref = NULL;
331 return 0;
334 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
336 if (__builtin_expect (protected != 0, 0))
338 /* It is very tricky. We need to figure out what value to
339 return for the protected symbol. */
340 struct sym_val protected_value = { NULL, NULL };
342 if (i >= (*scope)->r_nlist
343 || !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
344 i, skip_map, ELF_RTYPE_CLASS_PLT))
345 while (*++scope)
346 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
347 0, skip_map, ELF_RTYPE_CLASS_PLT))
348 break;
350 if (protected_value.s != NULL && protected_value.m != undef_map)
352 current_value.s = *ref;
353 current_value.m = undef_map;
357 if (__builtin_expect (GL(dl_debug_mask)
358 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
359 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
360 &current_value, NULL, 0, protected);
362 *ref = current_value.s;
363 return LOOKUP_VALUE (current_value.m);
367 /* This function works like _dl_lookup_symbol but it takes an
368 additional arguement with the version number of the requested
369 symbol.
371 XXX We'll see whether we need this separate function. */
372 lookup_t
373 internal_function
374 _dl_lookup_versioned_symbol (const char *undef_name,
375 struct link_map *undef_map, const ElfW(Sym) **ref,
376 struct r_scope_elem *symbol_scope[],
377 const struct r_found_version *version,
378 int type_class, int explicit)
380 const unsigned long int hash = _dl_elf_hash (undef_name);
381 struct sym_val current_value = { NULL, NULL };
382 struct r_scope_elem **scope;
383 int protected;
385 bump_num_relocations ();
387 /* Search the relevant loaded objects for a definition. */
388 for (scope = symbol_scope; *scope; ++scope)
390 int res = do_lookup_versioned (undef_name, hash, *ref, &current_value,
391 *scope, 0, version, NULL, type_class);
392 if (res > 0)
394 /* We have to check whether this would bind UNDEF_MAP to an object
395 in the global scope which was dynamically loaded. In this case
396 we have to prevent the latter from being unloaded unless the
397 UNDEF_MAP object is also unloaded. */
398 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
399 /* Don't do this for explicit lookups as opposed to implicit
400 runtime lookups. */
401 && ! explicit
402 /* Add UNDEF_MAP to the dependencies. */
403 && add_dependency (undef_map, current_value.m) < 0)
404 /* Something went wrong. Perhaps the object we tried to reference
405 was just removed. Try finding another definition. */
406 return INTUSE(_dl_lookup_versioned_symbol) (undef_name, undef_map,
407 ref, symbol_scope,
408 version, type_class, 0);
410 break;
413 if (__builtin_expect (res, 0) < 0)
415 /* Oh, oh. The file named in the relocation entry does not
416 contain the needed symbol. */
417 const char *reference_name = undef_map ? undef_map->l_name : NULL;
419 /* XXX We cannot translate the message. */
420 _dl_signal_cerror (0, (reference_name[0]
421 ? reference_name
422 : (_dl_argv[0] ?: "<main program>")),
423 N_("relocation error"),
424 make_string ("symbol ", undef_name, ", version ",
425 version->name,
426 " not defined in file ",
427 version->filename,
428 " with link time reference",
429 res == -2
430 ? " (no version symbols)" : ""));
431 *ref = NULL;
432 return 0;
436 if (__builtin_expect (current_value.s == NULL, 0))
438 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
440 /* We could find no value for a strong reference. */
441 const char *reference_name = undef_map ? undef_map->l_name : NULL;
443 /* XXX We cannot translate the message. */
444 _dl_signal_cerror (0, (reference_name[0]
445 ? reference_name
446 : (_dl_argv[0] ?: "<main program>")), NULL,
447 make_string (undefined_msg, undef_name,
448 ", version ",
449 version->name ?: NULL));
451 *ref = NULL;
452 return 0;
455 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
457 if (__builtin_expect (protected != 0, 0))
459 /* It is very tricky. We need to figure out what value to
460 return for the protected symbol */
461 struct sym_val protected_value = { NULL, NULL };
463 for (scope = symbol_scope; *scope; ++scope)
464 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value,
465 *scope, 0, version, NULL,
466 ELF_RTYPE_CLASS_PLT))
467 break;
469 if (protected_value.s != NULL && protected_value.m != undef_map)
471 current_value.s = *ref;
472 current_value.m = undef_map;
476 if (__builtin_expect (GL(dl_debug_mask)
477 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
478 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
479 &current_value, version, type_class, protected);
481 *ref = current_value.s;
482 return LOOKUP_VALUE (current_value.m);
484 INTDEF (_dl_lookup_versioned_symbol)
487 /* Similar to _dl_lookup_symbol_skip but takes an additional argument
488 with the version we are looking for. */
489 lookup_t
490 internal_function
491 _dl_lookup_versioned_symbol_skip (const char *undef_name,
492 struct link_map *undef_map,
493 const ElfW(Sym) **ref,
494 struct r_scope_elem *symbol_scope[],
495 const struct r_found_version *version,
496 struct link_map *skip_map)
498 const char *reference_name = undef_map->l_name;
499 const unsigned long int hash = _dl_elf_hash (undef_name);
500 struct sym_val current_value = { NULL, NULL };
501 struct r_scope_elem **scope;
502 size_t i;
503 int protected;
505 bump_num_relocations ();
507 /* Search the relevant loaded objects for a definition. */
508 scope = symbol_scope;
509 for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
510 assert (i < (*scope)->r_nlist);
512 if (! _dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
513 *scope, i, version, skip_map, 0))
514 while (*++scope)
515 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
516 *scope, 0, version, skip_map, 0))
517 break;
519 if (__builtin_expect (current_value.s == NULL, 0))
521 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
523 /* We could find no value for a strong reference. */
524 const size_t len = strlen (undef_name);
525 char buf[sizeof undefined_msg + len];
526 __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
527 undef_name, len + 1);
528 /* XXX We cannot translate the messages. */
529 _dl_signal_cerror (0, (reference_name[0]
530 ? reference_name
531 : (_dl_argv[0] ?: "<main program>")),
532 NULL, buf);
534 *ref = NULL;
535 return 0;
538 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
540 if (__builtin_expect (protected != 0, 0))
542 /* It is very tricky. We need to figure out what value to
543 return for the protected symbol */
544 struct sym_val protected_value = { NULL, NULL };
546 if (i >= (*scope)->r_nlist
547 || !_dl_do_lookup_versioned (undef_name, hash, *ref,
548 &protected_value, *scope, i, version,
549 skip_map, ELF_RTYPE_CLASS_PLT))
550 while (*++scope)
551 if (_dl_do_lookup_versioned (undef_name, hash, *ref,
552 &protected_value, *scope, 0, version,
553 skip_map, ELF_RTYPE_CLASS_PLT))
554 break;
556 if (protected_value.s != NULL && protected_value.m != undef_map)
558 current_value.s = *ref;
559 current_value.m = undef_map;
563 if (__builtin_expect (GL(dl_debug_mask)
564 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
565 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
566 &current_value, version, 0, protected);
568 *ref = current_value.s;
569 return LOOKUP_VALUE (current_value.m);
573 /* Cache the location of MAP's hash table. */
575 void
576 internal_function
577 _dl_setup_hash (struct link_map *map)
579 Elf_Symndx *hash;
580 Elf_Symndx nchain;
582 if (!map->l_info[DT_HASH])
583 return;
584 hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr);
586 map->l_nbuckets = *hash++;
587 nchain = *hash++;
588 map->l_buckets = hash;
589 hash += map->l_nbuckets;
590 map->l_chain = hash;
593 static void
594 internal_function
595 _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
596 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
597 struct sym_val *value, const struct r_found_version *version,
598 int type_class, int protected)
600 const char *reference_name = undef_map->l_name;
602 if (GL(dl_debug_mask) & DL_DEBUG_BINDINGS)
604 INTUSE(_dl_debug_printf) ("binding file %s to %s: %s symbol `%s'",
605 (reference_name[0]
606 ? reference_name
607 : (_dl_argv[0] ?: "<main program>")),
608 value->m->l_name[0]
609 ? value->m->l_name : _dl_argv[0],
610 protected ? "protected" : "normal",
611 undef_name);
612 if (version)
613 _dl_debug_printf_c (" [%s]\n", version->name);
614 else
615 _dl_debug_printf_c ("\n");
617 #ifdef SHARED
618 if (GL(dl_debug_mask) & DL_DEBUG_PRELINK)
620 int conflict = 0;
621 struct sym_val val = { NULL, NULL };
623 if ((GL(dl_trace_prelink_map) == NULL
624 || GL(dl_trace_prelink_map) == GL(dl_loaded))
625 && undef_map != GL(dl_loaded))
627 const unsigned long int hash = _dl_elf_hash (undef_name);
629 if (version == 0)
630 _dl_do_lookup (undef_name, hash, *ref, &val,
631 undef_map->l_local_scope[0], 0, NULL, type_class);
632 else
633 _dl_do_lookup_versioned (undef_name, hash, *ref, &val,
634 undef_map->l_local_scope[0], 0, version,
635 NULL, type_class);
637 if (val.s != value->s || val.m != value->m)
638 conflict = 1;
641 if (conflict
642 || GL(dl_trace_prelink_map) == undef_map
643 || GL(dl_trace_prelink_map) == NULL)
645 _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
646 conflict ? "conflict" : "lookup",
647 (int) sizeof (ElfW(Addr)) * 2, undef_map->l_map_start,
648 (int) sizeof (ElfW(Addr)) * 2,
649 ((ElfW(Addr)) *ref) - undef_map->l_map_start,
650 (int) sizeof (ElfW(Addr)) * 2,
651 (ElfW(Addr)) (value->s ? value->m->l_map_start : 0),
652 (int) sizeof (ElfW(Addr)) * 2,
653 (ElfW(Addr)) (value->s ? value->s->st_value : 0));
655 if (conflict)
656 _dl_printf ("x 0x%0*Zx 0x%0*Zx ",
657 (int) sizeof (ElfW(Addr)) * 2,
658 (ElfW(Addr)) (val.s ? val.m->l_map_start : 0),
659 (int) sizeof (ElfW(Addr)) * 2,
660 (ElfW(Addr)) (val.s ? val.s->st_value : 0));
662 _dl_printf ("/%x %s\n", type_class, undef_name);
665 #endif
668 /* These are here so that we only inline do_lookup{,_versioned} in the common
669 case, not everywhere. */
670 static int __attribute_noinline__
671 internal_function
672 _dl_do_lookup (const char *undef_name, unsigned long int hash,
673 const ElfW(Sym) *ref, struct sym_val *result,
674 struct r_scope_elem *scope, size_t i,
675 struct link_map *skip, int type_class)
677 return do_lookup (undef_name, hash, ref, result, scope, i, skip,
678 type_class);
681 static int __attribute_noinline__
682 internal_function
683 _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
684 const ElfW(Sym) *ref, struct sym_val *result,
685 struct r_scope_elem *scope, size_t i,
686 const struct r_found_version *const version,
687 struct link_map *skip, int type_class)
689 return do_lookup_versioned (undef_name, hash, ref, result, scope, i,
690 version, skip, type_class);