Updated.
[glibc.git] / elf / dl-lookup.c
blob5fa6b73b50e2de8f8affe5671f175b3037e20a50
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 <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;
65 /* We have two different situations when looking up a simple: with or
66 without versioning. gcc is not able to optimize a single function
67 definition serving for both purposes so we define two functions. */
68 #define VERSIONED 0
69 #include "do-lookup.h"
71 #define VERSIONED 1
72 #include "do-lookup.h"
75 /* Add extra dependency on MAP to UNDEF_MAP. */
76 static int
77 internal_function
78 add_dependency (struct link_map *undef_map, struct link_map *map)
80 struct link_map **list;
81 unsigned int act;
82 unsigned int i;
83 int result = 0;
85 /* Make sure nobody can unload the object while we are at it. */
86 __libc_lock_lock_recursive (_dl_load_lock);
88 /* Determine whether UNDEF_MAP already has a reference to MAP. First
89 look in the normal dependencies. */
90 list = undef_map->l_initfini;
92 for (i = 0; list[i] != NULL; ++i)
93 if (list[i] == map)
94 break;
96 if (__builtin_expect (list[i] == NULL, 1))
98 /* No normal dependency. See whether we already had to add it
99 to the special list of dynamic dependencies. */
100 list = undef_map->l_reldeps;
101 act = undef_map->l_reldepsact;
103 for (i = 0; i < act; ++i)
104 if (list[i] == map)
105 break;
107 if (i == act)
109 /* The object is not yet in the dependency list. Before we add
110 it make sure just one more time the object we are about to
111 reference is still available. There is a brief period in
112 which the object could have been removed since we found the
113 definition. */
114 struct link_map *runp = _dl_loaded;
116 while (runp != NULL && runp != map)
117 runp = runp->l_next;
119 if (runp != NULL)
121 /* The object is still available. Add the reference now. */
122 if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
124 /* Allocate more memory for the dependency list. Since
125 this can never happen during the startup phase we can
126 use `realloc'. */
127 void *newp;
129 undef_map->l_reldepsmax += 5;
130 newp = realloc (undef_map->l_reldeps,
131 undef_map->l_reldepsmax
132 * sizeof(struct link_map *));
134 if (__builtin_expect (newp != NULL, 1))
135 undef_map->l_reldeps = (struct link_map **) newp;
136 else
137 /* Correct the addition. */
138 undef_map->l_reldepsmax -= 5;
141 /* If we didn't manage to allocate memory for the list this
142 is no fatal mistake. We simply increment the use counter
143 of the referenced object and don't record the dependencies.
144 This means this increment can never be reverted and the
145 object will never be unloaded. This is semantically the
146 correct behaviour. */
147 if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
148 undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
150 /* And increment the counter in the referenced object. */
151 ++map->l_opencount;
153 /* Display information if we are debugging. */
154 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
155 _dl_debug_printf ("\
156 \nfile=%s; needed by %s (relocation dependency)\n\n",
157 map->l_name[0] ? map->l_name : _dl_argv[0],
158 undef_map->l_name[0]
159 ? undef_map->l_name : _dl_argv[0]);
161 else
162 /* Whoa, that was bad luck. We have to search again. */
163 result = -1;
167 /* Release the lock. */
168 __libc_lock_unlock_recursive (_dl_load_lock);
170 return result;
173 static int
174 internal_function
175 _dl_do_lookup (const char *undef_name, unsigned long int hash,
176 const ElfW(Sym) *ref, struct sym_val *result,
177 struct r_scope_elem *scope, size_t i,
178 struct link_map *skip, int type_class);
179 static int
180 internal_function
181 _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
182 const ElfW(Sym) *ref, struct sym_val *result,
183 struct r_scope_elem *scope, size_t i,
184 const struct r_found_version *const version,
185 struct link_map *skip, int type_class);
188 /* Search loaded objects' symbol tables for a definition of the symbol
189 UNDEF_NAME. */
191 lookup_t
192 internal_function
193 _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
194 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
195 int type_class, int explicit)
197 unsigned long int hash = _dl_elf_hash (undef_name);
198 struct sym_val current_value = { NULL, NULL };
199 struct r_scope_elem **scope;
200 int protected;
202 ++_dl_num_relocations;
204 /* Search the relevant loaded objects for a definition. */
205 for (scope = symbol_scope; *scope; ++scope)
206 if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL,
207 type_class))
209 /* We have to check whether this would bind UNDEF_MAP to an object
210 in the global scope which was dynamically loaded. In this case
211 we have to prevent the latter from being unloaded unless the
212 UNDEF_MAP object is also unloaded. */
213 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
214 && current_value.m->l_global
215 && undef_map != current_value.m
216 /* Don't do this for explicit lookups as opposed to implicit
217 runtime lookups. */
218 && ! explicit
219 /* Add UNDEF_MAP to the dependencies. */
220 && add_dependency (undef_map, current_value.m) < 0)
221 /* Something went wrong. Perhaps the object we tried to reference
222 was just removed. Try finding another definition. */
223 return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope,
224 type_class, 0);
226 break;
229 if (__builtin_expect (current_value.s == NULL, 0))
231 const char *reference_name = undef_map ? undef_map->l_name : NULL;
233 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
234 /* We could find no value for a strong reference. */
235 /* XXX We cannot translate the messages. */
236 _dl_signal_cerror (0, (reference_name && reference_name[0]
237 ? reference_name
238 : (_dl_argv[0] ?: "<main program>")),
239 make_string (undefined_msg, undef_name));
240 *ref = NULL;
241 return 0;
244 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
246 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
248 const char *reference_name = undef_map ? undef_map->l_name : NULL;
250 _dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
251 (reference_name && reference_name[0]
252 ? reference_name : (_dl_argv[0] ?: "<main program>")),
253 current_value.m->l_name[0]
254 ? current_value.m->l_name : _dl_argv[0],
255 protected ? "protected" : "normal", undef_name);
258 if (__builtin_expect (protected == 0, 1))
260 *ref = current_value.s;
261 return LOOKUP_VALUE (current_value.m);
263 else
265 /* It is very tricky. We need to figure out what value to
266 return for the protected symbol */
267 struct sym_val protected_value = { NULL, NULL };
269 for (scope = symbol_scope; *scope; ++scope)
270 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
271 0, NULL, ELF_RTYPE_CLASS_PLT))
272 break;
274 if (protected_value.s == NULL || protected_value.m == undef_map)
276 *ref = current_value.s;
277 return LOOKUP_VALUE (current_value.m);
280 return LOOKUP_VALUE (undef_map);
285 /* This function is nearly the same as `_dl_lookup_symbol' but it
286 skips in the first list all objects until SKIP_MAP is found. I.e.,
287 it only considers objects which were loaded after the described
288 object. If there are more search lists the object described by
289 SKIP_MAP is only skipped. */
290 lookup_t
291 internal_function
292 _dl_lookup_symbol_skip (const char *undef_name,
293 struct link_map *undef_map, const ElfW(Sym) **ref,
294 struct r_scope_elem *symbol_scope[],
295 struct link_map *skip_map)
297 const char *reference_name = undef_map ? undef_map->l_name : NULL;
298 const unsigned long int hash = _dl_elf_hash (undef_name);
299 struct sym_val current_value = { NULL, NULL };
300 struct r_scope_elem **scope;
301 size_t i;
302 int protected;
304 ++_dl_num_relocations;
306 /* Search the relevant loaded objects for a definition. */
307 scope = symbol_scope;
308 for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
309 assert (i < (*scope)->r_nlist);
311 if (! _dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, i,
312 skip_map, 0))
313 while (*++scope)
314 if (_dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
315 skip_map, 0))
316 break;
318 if (__builtin_expect (current_value.s == NULL, 0))
320 *ref = NULL;
321 return 0;
324 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
326 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
327 _dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
328 (reference_name && reference_name[0]
329 ? reference_name : (_dl_argv[0] ?: "<main program>")),
330 current_value.m->l_name[0]
331 ? current_value.m->l_name : _dl_argv[0],
332 protected ? "protected" : "normal", undef_name);
334 if (__builtin_expect (protected == 0, 1))
336 *ref = current_value.s;
337 return LOOKUP_VALUE (current_value.m);
339 else
341 /* It is very tricky. We need to figure out what value to
342 return for the protected symbol. */
343 struct sym_val protected_value = { NULL, NULL };
345 if (i >= (*scope)->r_nlist
346 || !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
347 i, skip_map, ELF_RTYPE_CLASS_PLT))
348 while (*++scope)
349 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
350 0, skip_map, ELF_RTYPE_CLASS_PLT))
351 break;
353 if (protected_value.s == NULL || protected_value.m == undef_map)
355 *ref = current_value.s;
356 return LOOKUP_VALUE (current_value.m);
359 return LOOKUP_VALUE (undef_map);
364 /* This function works like _dl_lookup_symbol but it takes an
365 additional arguement with the version number of the requested
366 symbol.
368 XXX We'll see whether we need this separate function. */
369 lookup_t
370 internal_function
371 _dl_lookup_versioned_symbol (const char *undef_name,
372 struct link_map *undef_map, const ElfW(Sym) **ref,
373 struct r_scope_elem *symbol_scope[],
374 const struct r_found_version *version,
375 int type_class, int explicit)
377 unsigned long int hash = _dl_elf_hash (undef_name);
378 struct sym_val current_value = { NULL, NULL };
379 struct r_scope_elem **scope;
380 int protected;
382 ++_dl_num_relocations;
384 /* Search the relevant loaded objects for a definition. */
385 for (scope = symbol_scope; *scope; ++scope)
387 int res = do_lookup_versioned (undef_name, hash, *ref, &current_value,
388 *scope, 0, version, NULL, type_class);
389 if (res > 0)
391 /* We have to check whether this would bind UNDEF_MAP to an object
392 in the global scope which was dynamically loaded. In this case
393 we have to prevent the latter from being unloaded unless the
394 UNDEF_MAP object is also unloaded. */
395 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
396 && current_value.m->l_global
397 && undef_map != current_value.m
398 /* Don't do this for explicit lookups as opposed to implicit
399 runtime lookups. */
400 && ! explicit
401 /* Add UNDEF_MAP to the dependencies. */
402 && add_dependency (undef_map, current_value.m) < 0)
403 /* Something went wrong. Perhaps the object we tried to reference
404 was just removed. Try finding another definition. */
405 return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
406 symbol_scope, version,
407 type_class, 0);
409 break;
412 if (__builtin_expect (res, 0) < 0)
414 /* Oh, oh. The file named in the relocation entry does not
415 contain the needed symbol. */
416 const char *reference_name = undef_map ? undef_map->l_name : NULL;
418 /* XXX We cannot translate the message. */
419 _dl_signal_cerror (0, (reference_name && reference_name[0]
420 ? reference_name
421 : (_dl_argv[0] ?: "<main program>")),
422 make_string ("symbol ", undef_name, ", version ",
423 version->name,
424 " not defined in file ",
425 version->filename,
426 " with link time reference",
427 res == -2
428 ? " (no version symbols)" : ""));
429 *ref = NULL;
430 return 0;
434 if (__builtin_expect (current_value.s == NULL, 0))
436 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
438 /* We could find no value for a strong reference. */
439 const char *reference_name = undef_map ? undef_map->l_name : NULL;
441 /* XXX We cannot translate the message. */
442 _dl_signal_cerror (0, (reference_name && reference_name[0]
443 ? reference_name
444 : (_dl_argv[0] ?: "<main program>")),
445 make_string (undefined_msg, undef_name,
446 ", version ",
447 version->name ?: NULL));
449 *ref = NULL;
450 return 0;
453 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
455 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
457 const char *reference_name = undef_map ? undef_map->l_name : NULL;
459 _dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
460 (reference_name && reference_name[0]
461 ? reference_name : (_dl_argv[0] ?: "<main program>")),
462 current_value.m->l_name[0]
463 ? current_value.m->l_name : _dl_argv[0],
464 protected ? "protected" : "normal",
465 undef_name, version->name);
468 if (__builtin_expect (protected == 0, 1))
470 *ref = current_value.s;
471 return LOOKUP_VALUE (current_value.m);
473 else
475 /* It is very tricky. We need to figure out what value to
476 return for the protected symbol */
477 struct sym_val protected_value = { NULL, NULL };
479 for (scope = symbol_scope; *scope; ++scope)
480 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value,
481 *scope, 0, version, NULL,
482 ELF_RTYPE_CLASS_PLT))
483 break;
485 if (protected_value.s == NULL || protected_value.m == undef_map)
487 *ref = current_value.s;
488 return LOOKUP_VALUE (current_value.m);
491 return LOOKUP_VALUE (undef_map);
496 /* Similar to _dl_lookup_symbol_skip but takes an additional argument
497 with the version we are looking for. */
498 lookup_t
499 internal_function
500 _dl_lookup_versioned_symbol_skip (const char *undef_name,
501 struct link_map *undef_map,
502 const ElfW(Sym) **ref,
503 struct r_scope_elem *symbol_scope[],
504 const struct r_found_version *version,
505 struct link_map *skip_map)
507 const char *reference_name = undef_map ? undef_map->l_name : NULL;
508 const unsigned long int hash = _dl_elf_hash (undef_name);
509 struct sym_val current_value = { NULL, NULL };
510 struct r_scope_elem **scope;
511 size_t i;
512 int protected;
514 ++_dl_num_relocations;
516 /* Search the relevant loaded objects for a definition. */
517 scope = symbol_scope;
518 for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
519 assert (i < (*scope)->r_nlist);
521 if (! _dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
522 *scope, i, version, skip_map, 0))
523 while (*++scope)
524 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
525 *scope, 0, version, skip_map, 0))
526 break;
528 if (__builtin_expect (current_value.s == NULL, 0))
530 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
532 /* We could find no value for a strong reference. */
533 const size_t len = strlen (undef_name);
534 char buf[sizeof undefined_msg + len];
535 __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
536 undef_name, len + 1);
537 /* XXX We cannot translate the messages. */
538 _dl_signal_cerror (0, (reference_name && reference_name[0]
539 ? reference_name
540 : (_dl_argv[0] ?: "<main program>")), buf);
542 *ref = NULL;
543 return 0;
546 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
548 if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
549 _dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
550 (reference_name && reference_name[0]
551 ? reference_name : (_dl_argv[0] ?: "<main program>")),
552 current_value.m->l_name[0]
553 ? current_value.m->l_name : _dl_argv[0],
554 protected ? "protected" : "normal",
555 undef_name, version->name);
557 if (__builtin_expect (protected == 0, 1))
559 *ref = current_value.s;
560 return LOOKUP_VALUE (current_value.m);
562 else
564 /* It is very tricky. We need to figure out what value to
565 return for the protected symbol */
566 struct sym_val protected_value = { NULL, NULL };
568 if (i >= (*scope)->r_nlist
569 || !_dl_do_lookup_versioned (undef_name, hash, *ref,
570 &protected_value, *scope, i, version,
571 skip_map, ELF_RTYPE_CLASS_PLT))
572 while (*++scope)
573 if (_dl_do_lookup_versioned (undef_name, hash, *ref,
574 &protected_value, *scope, 0, version,
575 skip_map, ELF_RTYPE_CLASS_PLT))
576 break;
578 if (protected_value.s == NULL || protected_value.m == undef_map)
580 *ref = current_value.s;
581 return LOOKUP_VALUE (current_value.m);
584 return LOOKUP_VALUE (undef_map);
589 /* Cache the location of MAP's hash table. */
591 void
592 internal_function
593 _dl_setup_hash (struct link_map *map)
595 Elf_Symndx *hash;
596 Elf_Symndx nchain;
598 if (!map->l_info[DT_HASH])
599 return;
600 hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr);
602 map->l_nbuckets = *hash++;
603 nchain = *hash++;
604 map->l_buckets = hash;
605 hash += map->l_nbuckets;
606 map->l_chain = hash;
609 /* These are here so that we only inline do_lookup{,_versioned} in the common
610 case, not everywhere. */
611 static int
612 internal_function
613 _dl_do_lookup (const char *undef_name, unsigned long int hash,
614 const ElfW(Sym) *ref, struct sym_val *result,
615 struct r_scope_elem *scope, size_t i,
616 struct link_map *skip, int type_class)
618 return do_lookup (undef_name, hash, ref, result, scope, i, skip,
619 type_class);
622 static int
623 internal_function
624 _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
625 const ElfW(Sym) *ref, struct sym_val *result,
626 struct r_scope_elem *scope, size_t i,
627 const struct r_found_version *const version,
628 struct link_map *skip, int type_class)
630 return do_lookup_versioned (undef_name, hash, ref, result, scope, i,
631 version, skip, type_class);