Update.
[glibc.git] / elf / dl-lookup.c
blob5fa50fc457f6d8b74be742db1b697a24ef932af1
1 /* Look up a symbol in the loaded objects.
2 Copyright (C) 1995,96,97,98,99,2000,2001 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>
30 #include <assert.h>
32 #define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
34 /* We need this string more than once. */
35 static const char undefined_msg[] = "undefined symbol: ";
38 struct sym_val
40 const ElfW(Sym) *s;
41 struct link_map *m;
45 #define make_string(string, rest...) \
46 ({ \
47 const char *all[] = { string, ## rest }; \
48 size_t len, cnt; \
49 char *result, *cp; \
51 len = 1; \
52 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
53 len += strlen (all[cnt]); \
55 cp = result = alloca (len); \
56 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
57 cp = __stpcpy (cp, all[cnt]); \
59 result; \
62 /* Statistics function. */
63 unsigned long int _dl_num_relocations;
66 /* We have two different situations when looking up a simple: with or
67 without versioning. gcc is not able to optimize a single function
68 definition serving for both purposes so we define two functions. */
69 #define VERSIONED 0
70 #include "do-lookup.h"
72 #define VERSIONED 1
73 #include "do-lookup.h"
76 /* Add extra dependency on MAP to UNDEF_MAP. */
77 static int
78 internal_function
79 add_dependency (struct link_map *undef_map, struct link_map *map)
81 struct link_map **list;
82 struct link_map *runp;
83 unsigned int act;
84 unsigned int i;
85 int result = 0;
87 /* Avoid self-references. */
88 if (undef_map == map)
89 return 0;
91 /* Make sure nobody can unload the object while we are at it. */
92 __libc_lock_lock_recursive (_dl_load_lock);
94 /* Determine whether UNDEF_MAP already has a reference to MAP. First
95 look in the normal dependencies. */
96 if (undef_map->l_searchlist.r_list != NULL)
98 list = undef_map->l_initfini;
100 for (i = 0; list[i] != NULL; ++i)
101 if (list[i] == map)
102 goto out;
105 /* No normal dependency. See whether we already had to add it
106 to the special list of dynamic dependencies. */
107 list = undef_map->l_reldeps;
108 act = undef_map->l_reldepsact;
110 for (i = 0; i < act; ++i)
111 if (list[i] == map)
112 goto out;
114 /* The object is not yet in the dependency list. Before we add
115 it make sure just one more time the object we are about to
116 reference is still available. There is a brief period in
117 which the object could have been removed since we found the
118 definition. */
119 runp = _dl_loaded;
120 while (runp != NULL && runp != map)
121 runp = runp->l_next;
123 if (runp != NULL)
125 /* The object is still available. Add the reference now. */
126 if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
128 /* Allocate more memory for the dependency list. Since this
129 can never happen during the startup phase we can use
130 `realloc'. */
131 void *newp;
133 undef_map->l_reldepsmax += 5;
134 newp = realloc (undef_map->l_reldeps,
135 undef_map->l_reldepsmax
136 * sizeof (struct link_map *));
138 if (__builtin_expect (newp != NULL, 1))
139 undef_map->l_reldeps = (struct link_map **) newp;
140 else
141 /* Correct the addition. */
142 undef_map->l_reldepsmax -= 5;
145 /* If we didn't manage to allocate memory for the list this is
146 no fatal mistake. We simply increment the use counter of the
147 referenced object and don't record the dependencies. This
148 means this increment can never be reverted and the object
149 will never be unloaded. This is semantically the correct
150 behaviour. */
151 if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
152 undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
154 if (map->l_searchlist.r_list != NULL)
155 /* And increment the counter in the referenced object. */
156 ++map->l_opencount;
157 else
158 /* We have to bump the counts for all dependencies since so far
159 this object was only a normal or transitive dependency.
160 Now it might be closed with _dl_close() directly. */
161 for (list = map->l_initfini; *list != NULL; ++list)
162 ++(*list)->l_opencount;
164 /* Display information if we are debugging. */
165 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
166 _dl_debug_printf ("\
167 \nfile=%s; needed by %s (relocation dependency)\n\n",
168 map->l_name[0] ? map->l_name : _dl_argv[0],
169 undef_map->l_name[0]
170 ? undef_map->l_name : _dl_argv[0]);
172 else
173 /* Whoa, that was bad luck. We have to search again. */
174 result = -1;
176 out:
177 /* Release the lock. */
178 __libc_lock_unlock_recursive (_dl_load_lock);
180 return result;
183 static int
184 internal_function
185 _dl_do_lookup (const char *undef_name, unsigned long int hash,
186 const ElfW(Sym) *ref, struct sym_val *result,
187 struct r_scope_elem *scope, size_t i,
188 struct link_map *skip, int type_class);
189 static int
190 internal_function
191 _dl_do_lookup_versioned (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 const struct r_found_version *const version,
195 struct link_map *skip, int type_class);
198 /* Search loaded objects' symbol tables for a definition of the symbol
199 UNDEF_NAME. */
201 lookup_t
202 internal_function
203 _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
204 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
205 int type_class, int explicit)
207 unsigned long int hash = _dl_elf_hash (undef_name);
208 struct sym_val current_value = { NULL, NULL };
209 struct r_scope_elem **scope;
210 int protected;
212 ++_dl_num_relocations;
214 /* Search the relevant loaded objects for a definition. */
215 for (scope = symbol_scope; *scope; ++scope)
216 if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL,
217 type_class))
219 /* We have to check whether this would bind UNDEF_MAP to an object
220 in the global scope which was dynamically loaded. In this case
221 we have to prevent the latter from being unloaded unless the
222 UNDEF_MAP object is also unloaded. */
223 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
224 /* Don't do this for explicit lookups as opposed to implicit
225 runtime lookups. */
226 && ! explicit
227 /* Add UNDEF_MAP to the dependencies. */
228 && add_dependency (undef_map, current_value.m) < 0)
229 /* Something went wrong. Perhaps the object we tried to reference
230 was just removed. Try finding another definition. */
231 return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope,
232 type_class, 0);
234 break;
237 if (__builtin_expect (current_value.s == NULL, 0))
239 const char *reference_name = undef_map ? undef_map->l_name : NULL;
241 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
242 /* We could find no value for a strong reference. */
243 /* XXX We cannot translate the messages. */
244 _dl_signal_cerror (0, (reference_name && reference_name[0]
245 ? reference_name
246 : (_dl_argv[0] ?: "<main program>")),
247 N_("relocation error"),
248 make_string (undefined_msg, undef_name));
249 *ref = NULL;
250 return 0;
253 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
255 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
257 const char *reference_name = undef_map ? undef_map->l_name : NULL;
259 _dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
260 (reference_name && reference_name[0]
261 ? reference_name : (_dl_argv[0] ?: "<main program>")),
262 current_value.m->l_name[0]
263 ? current_value.m->l_name : _dl_argv[0],
264 protected ? "protected" : "normal", undef_name);
267 if (__builtin_expect (protected == 0, 1))
269 *ref = current_value.s;
270 return LOOKUP_VALUE (current_value.m);
272 else
274 /* It is very tricky. We need to figure out what value to
275 return for the protected symbol */
276 struct sym_val protected_value = { NULL, NULL };
278 for (scope = symbol_scope; *scope; ++scope)
279 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
280 0, NULL, ELF_RTYPE_CLASS_PLT))
281 break;
283 if (protected_value.s == NULL || protected_value.m == undef_map)
285 *ref = current_value.s;
286 return LOOKUP_VALUE (current_value.m);
289 return LOOKUP_VALUE (undef_map);
294 /* This function is nearly the same as `_dl_lookup_symbol' but it
295 skips in the first list all objects until SKIP_MAP is found. I.e.,
296 it only considers objects which were loaded after the described
297 object. If there are more search lists the object described by
298 SKIP_MAP is only skipped. */
299 lookup_t
300 internal_function
301 _dl_lookup_symbol_skip (const char *undef_name,
302 struct link_map *undef_map, const ElfW(Sym) **ref,
303 struct r_scope_elem *symbol_scope[],
304 struct link_map *skip_map)
306 const char *reference_name = undef_map ? undef_map->l_name : NULL;
307 const unsigned long int hash = _dl_elf_hash (undef_name);
308 struct sym_val current_value = { NULL, NULL };
309 struct r_scope_elem **scope;
310 size_t i;
311 int protected;
313 ++_dl_num_relocations;
315 /* Search the relevant loaded objects for a definition. */
316 scope = symbol_scope;
317 for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
318 assert (i < (*scope)->r_nlist);
320 if (! _dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, i,
321 skip_map, 0))
322 while (*++scope)
323 if (_dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
324 skip_map, 0))
325 break;
327 if (__builtin_expect (current_value.s == NULL, 0))
329 *ref = NULL;
330 return 0;
333 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
335 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
336 _dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
337 (reference_name && reference_name[0]
338 ? reference_name : (_dl_argv[0] ?: "<main program>")),
339 current_value.m->l_name[0]
340 ? current_value.m->l_name : _dl_argv[0],
341 protected ? "protected" : "normal", undef_name);
343 if (__builtin_expect (protected == 0, 1))
345 *ref = current_value.s;
346 return LOOKUP_VALUE (current_value.m);
348 else
350 /* It is very tricky. We need to figure out what value to
351 return for the protected symbol. */
352 struct sym_val protected_value = { NULL, NULL };
354 if (i >= (*scope)->r_nlist
355 || !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
356 i, skip_map, ELF_RTYPE_CLASS_PLT))
357 while (*++scope)
358 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
359 0, skip_map, ELF_RTYPE_CLASS_PLT))
360 break;
362 if (protected_value.s == NULL || protected_value.m == undef_map)
364 *ref = current_value.s;
365 return LOOKUP_VALUE (current_value.m);
368 return LOOKUP_VALUE (undef_map);
373 /* This function works like _dl_lookup_symbol but it takes an
374 additional arguement with the version number of the requested
375 symbol.
377 XXX We'll see whether we need this separate function. */
378 lookup_t
379 internal_function
380 _dl_lookup_versioned_symbol (const char *undef_name,
381 struct link_map *undef_map, const ElfW(Sym) **ref,
382 struct r_scope_elem *symbol_scope[],
383 const struct r_found_version *version,
384 int type_class, int explicit)
386 unsigned long int hash = _dl_elf_hash (undef_name);
387 struct sym_val current_value = { NULL, NULL };
388 struct r_scope_elem **scope;
389 int protected;
391 ++_dl_num_relocations;
393 /* Search the relevant loaded objects for a definition. */
394 for (scope = symbol_scope; *scope; ++scope)
396 int res = do_lookup_versioned (undef_name, hash, *ref, &current_value,
397 *scope, 0, version, NULL, type_class);
398 if (res > 0)
400 /* We have to check whether this would bind UNDEF_MAP to an object
401 in the global scope which was dynamically loaded. In this case
402 we have to prevent the latter from being unloaded unless the
403 UNDEF_MAP object is also unloaded. */
404 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
405 /* Don't do this for explicit lookups as opposed to implicit
406 runtime lookups. */
407 && ! explicit
408 /* Add UNDEF_MAP to the dependencies. */
409 && add_dependency (undef_map, current_value.m) < 0)
410 /* Something went wrong. Perhaps the object we tried to reference
411 was just removed. Try finding another definition. */
412 return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
413 symbol_scope, version,
414 type_class, 0);
416 break;
419 if (__builtin_expect (res, 0) < 0)
421 /* Oh, oh. The file named in the relocation entry does not
422 contain the needed symbol. */
423 const char *reference_name = undef_map ? undef_map->l_name : NULL;
425 /* XXX We cannot translate the message. */
426 _dl_signal_cerror (0, (reference_name && reference_name[0]
427 ? reference_name
428 : (_dl_argv[0] ?: "<main program>")),
429 N_("relocation error"),
430 make_string ("symbol ", undef_name, ", version ",
431 version->name,
432 " not defined in file ",
433 version->filename,
434 " with link time reference",
435 res == -2
436 ? " (no version symbols)" : ""));
437 *ref = NULL;
438 return 0;
442 if (__builtin_expect (current_value.s == NULL, 0))
444 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
446 /* We could find no value for a strong reference. */
447 const char *reference_name = undef_map ? undef_map->l_name : NULL;
449 /* XXX We cannot translate the message. */
450 _dl_signal_cerror (0, (reference_name && reference_name[0]
451 ? reference_name
452 : (_dl_argv[0] ?: "<main program>")), NULL,
453 make_string (undefined_msg, undef_name,
454 ", version ",
455 version->name ?: NULL));
457 *ref = NULL;
458 return 0;
461 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
463 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
465 const char *reference_name = undef_map ? undef_map->l_name : NULL;
467 _dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
468 (reference_name && reference_name[0]
469 ? reference_name : (_dl_argv[0] ?: "<main program>")),
470 current_value.m->l_name[0]
471 ? current_value.m->l_name : _dl_argv[0],
472 protected ? "protected" : "normal",
473 undef_name, version->name);
476 if (__builtin_expect (protected == 0, 1))
478 *ref = current_value.s;
479 return LOOKUP_VALUE (current_value.m);
481 else
483 /* It is very tricky. We need to figure out what value to
484 return for the protected symbol */
485 struct sym_val protected_value = { NULL, NULL };
487 for (scope = symbol_scope; *scope; ++scope)
488 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value,
489 *scope, 0, version, NULL,
490 ELF_RTYPE_CLASS_PLT))
491 break;
493 if (protected_value.s == NULL || protected_value.m == undef_map)
495 *ref = current_value.s;
496 return LOOKUP_VALUE (current_value.m);
499 return LOOKUP_VALUE (undef_map);
504 /* Similar to _dl_lookup_symbol_skip but takes an additional argument
505 with the version we are looking for. */
506 lookup_t
507 internal_function
508 _dl_lookup_versioned_symbol_skip (const char *undef_name,
509 struct link_map *undef_map,
510 const ElfW(Sym) **ref,
511 struct r_scope_elem *symbol_scope[],
512 const struct r_found_version *version,
513 struct link_map *skip_map)
515 const char *reference_name = undef_map ? undef_map->l_name : NULL;
516 const unsigned long int hash = _dl_elf_hash (undef_name);
517 struct sym_val current_value = { NULL, NULL };
518 struct r_scope_elem **scope;
519 size_t i;
520 int protected;
522 ++_dl_num_relocations;
524 /* Search the relevant loaded objects for a definition. */
525 scope = symbol_scope;
526 for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
527 assert (i < (*scope)->r_nlist);
529 if (! _dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
530 *scope, i, version, skip_map, 0))
531 while (*++scope)
532 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
533 *scope, 0, version, skip_map, 0))
534 break;
536 if (__builtin_expect (current_value.s == NULL, 0))
538 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
540 /* We could find no value for a strong reference. */
541 const size_t len = strlen (undef_name);
542 char buf[sizeof undefined_msg + len];
543 __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
544 undef_name, len + 1);
545 /* XXX We cannot translate the messages. */
546 _dl_signal_cerror (0, (reference_name && reference_name[0]
547 ? reference_name
548 : (_dl_argv[0] ?: "<main program>")),
549 NULL, buf);
551 *ref = NULL;
552 return 0;
555 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
557 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
558 _dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
559 (reference_name && reference_name[0]
560 ? reference_name : (_dl_argv[0] ?: "<main program>")),
561 current_value.m->l_name[0]
562 ? current_value.m->l_name : _dl_argv[0],
563 protected ? "protected" : "normal",
564 undef_name, version->name);
566 if (__builtin_expect (protected == 0, 1))
568 *ref = current_value.s;
569 return LOOKUP_VALUE (current_value.m);
571 else
573 /* It is very tricky. We need to figure out what value to
574 return for the protected symbol */
575 struct sym_val protected_value = { NULL, NULL };
577 if (i >= (*scope)->r_nlist
578 || !_dl_do_lookup_versioned (undef_name, hash, *ref,
579 &protected_value, *scope, i, version,
580 skip_map, ELF_RTYPE_CLASS_PLT))
581 while (*++scope)
582 if (_dl_do_lookup_versioned (undef_name, hash, *ref,
583 &protected_value, *scope, 0, version,
584 skip_map, ELF_RTYPE_CLASS_PLT))
585 break;
587 if (protected_value.s == NULL || protected_value.m == undef_map)
589 *ref = current_value.s;
590 return LOOKUP_VALUE (current_value.m);
593 return LOOKUP_VALUE (undef_map);
598 /* Cache the location of MAP's hash table. */
600 void
601 internal_function
602 _dl_setup_hash (struct link_map *map)
604 Elf_Symndx *hash;
605 Elf_Symndx nchain;
607 if (!map->l_info[DT_HASH])
608 return;
609 hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr);
611 map->l_nbuckets = *hash++;
612 nchain = *hash++;
613 map->l_buckets = hash;
614 hash += map->l_nbuckets;
615 map->l_chain = hash;
618 /* These are here so that we only inline do_lookup{,_versioned} in the common
619 case, not everywhere. */
620 static int
621 internal_function
622 _dl_do_lookup (const char *undef_name, unsigned long int hash,
623 const ElfW(Sym) *ref, struct sym_val *result,
624 struct r_scope_elem *scope, size_t i,
625 struct link_map *skip, int type_class)
627 return do_lookup (undef_name, hash, ref, result, scope, i, skip,
628 type_class);
631 static int
632 internal_function
633 _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
634 const ElfW(Sym) *ref, struct sym_val *result,
635 struct r_scope_elem *scope, size_t i,
636 const struct r_found_version *const version,
637 struct link_map *skip, int type_class)
639 return do_lookup_versioned (undef_name, hash, ref, result, scope, i,
640 version, skip, type_class);