Update.
[glibc.git] / elf / dl-lookup.c
blob09f34f9f4a4e77561eb82a9c99a1b1cc9234dc86
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_PROCNUM + 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 _dl_signal_cerror (0, (reference_name && reference_name[0]
233 ? reference_name
234 : (_dl_argv[0] ?: "<main program>")),
235 make_string (undefined_msg, undef_name));
236 *ref = NULL;
237 return 0;
240 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
242 if (__builtin_expect (_dl_debug_bindings, 0))
243 _dl_debug_message (1, "binding file ",
244 (reference_name && reference_name[0]
245 ? reference_name
246 : (_dl_argv[0] ?: "<main program>")),
247 " to ", current_value.m->l_name[0]
248 ? current_value.m->l_name : _dl_argv[0],
249 ": ", protected ? "protected" : "normal",
250 " symbol `", undef_name, "'\n", NULL);
252 if (__builtin_expect (protected == 0, 1))
254 *ref = current_value.s;
255 return LOOKUP_VALUE (current_value.m);
257 else
259 /* It is very tricky. We need to figure out what value to
260 return for the protected symbol */
261 struct sym_val protected_value = { NULL, NULL };
263 for (scope = symbol_scope; *scope; ++scope)
264 if (do_lookup (undef_name, undef_map, hash, *ref,
265 &protected_value, *scope, 0, NULL, 0, 1))
266 break;
268 if (protected_value.s == NULL || protected_value.m == undef_map)
270 *ref = current_value.s;
271 return LOOKUP_VALUE (current_value.m);
274 return LOOKUP_VALUE (undef_map);
279 /* This function is nearly the same as `_dl_lookup_symbol' but it
280 skips in the first list all objects until SKIP_MAP is found. I.e.,
281 it only considers objects which were loaded after the described
282 object. If there are more search lists the object described by
283 SKIP_MAP is only skipped. */
284 lookup_t
285 internal_function
286 _dl_lookup_symbol_skip (const char *undef_name,
287 struct link_map *undef_map, const ElfW(Sym) **ref,
288 struct r_scope_elem *symbol_scope[],
289 struct link_map *skip_map)
291 const char *reference_name = undef_map ? undef_map->l_name : NULL;
292 const unsigned long int hash = _dl_elf_hash (undef_name);
293 struct sym_val current_value = { NULL, NULL };
294 struct r_scope_elem **scope;
295 size_t i;
296 int protected;
298 ++_dl_num_relocations;
300 /* Search the relevant loaded objects for a definition. */
301 scope = symbol_scope;
302 for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
303 assert (i < (*scope)->r_nduplist);
305 if (i < (*scope)->r_nlist
306 && do_lookup (undef_name, undef_map, hash, *ref, &current_value,
307 *scope, i, skip_map, 0, 0))
309 /* We have to check whether this would bind UNDEF_MAP to an object
310 in the global scope which was dynamically loaded. In this case
311 we have to prevent the latter from being unloaded unless the
312 UNDEF_MAP object is also unloaded. */
313 if (current_value.m->l_global
314 && (__builtin_expect (current_value.m->l_type, lt_library)
315 == lt_loaded)
316 && undef_map != current_value.m
317 /* Add UNDEF_MAP to the dependencies. */
318 && add_dependency (undef_map, current_value.m) < 0)
319 /* Something went wrong. Perhaps the object we tried to reference
320 was just removed. Try finding another definition. */
321 return _dl_lookup_symbol_skip (undef_name, undef_map, ref,
322 symbol_scope, skip_map);
324 else
325 while (*++scope)
326 if (do_lookup (undef_name, undef_map, hash, *ref, &current_value,
327 *scope, 0, skip_map, 0, 0))
329 /* We have to check whether this would bind UNDEF_MAP to an object
330 in the global scope which was dynamically loaded. In this case
331 we have to prevent the latter from being unloaded unless the
332 UNDEF_MAP object is also unloaded. */
333 if (__builtin_expect (current_value.m->l_global, 0)
334 && (__builtin_expect (current_value.m->l_type, lt_library)
335 == lt_loaded)
336 && undef_map != current_value.m
337 /* Add UNDEF_MAP to the dependencies. */
338 && add_dependency (undef_map, current_value.m) < 0)
339 /* Something went wrong. Perhaps the object we tried to reference
340 was just removed. Try finding another definition. */
341 return _dl_lookup_symbol_skip (undef_name, undef_map, ref,
342 symbol_scope, skip_map);
344 break;
347 if (__builtin_expect (current_value.s == NULL, 0))
349 *ref = NULL;
350 return 0;
353 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
355 if (__builtin_expect (_dl_debug_bindings, 0))
356 _dl_debug_message (1, "binding file ",
357 (reference_name && reference_name[0]
358 ? reference_name
359 : (_dl_argv[0] ?: "<main program>")),
360 " to ", current_value.m->l_name[0]
361 ? current_value.m->l_name : _dl_argv[0],
362 ": ", protected ? "protected" : "normal",
363 " symbol `", undef_name, "'\n", NULL);
365 if (__builtin_expect (protected == 0, 1))
367 *ref = current_value.s;
368 return LOOKUP_VALUE (current_value.m);
370 else
372 /* It is very tricky. We need to figure out what value to
373 return for the protected symbol */
374 struct sym_val protected_value = { NULL, NULL };
376 if (i >= (*scope)->r_nlist
377 || !do_lookup (undef_name, undef_map, hash, *ref, &protected_value,
378 *scope, i, skip_map, 0, 1))
379 while (*++scope)
380 if (do_lookup (undef_name, undef_map, hash, *ref, &protected_value,
381 *scope, 0, skip_map, 0, 1))
382 break;
384 if (protected_value.s == NULL || protected_value.m == undef_map)
386 *ref = current_value.s;
387 return LOOKUP_VALUE (current_value.m);
390 return LOOKUP_VALUE (undef_map);
395 /* This function works like _dl_lookup_symbol but it takes an
396 additional arguement with the version number of the requested
397 symbol.
399 XXX We'll see whether we need this separate function. */
400 lookup_t
401 internal_function
402 _dl_lookup_versioned_symbol (const char *undef_name,
403 struct link_map *undef_map, const ElfW(Sym) **ref,
404 struct r_scope_elem *symbol_scope[],
405 const struct r_found_version *version,
406 int reloc_type)
408 const char *reference_name = undef_map ? undef_map->l_name : NULL;
409 const unsigned long int hash = _dl_elf_hash (undef_name);
410 struct sym_val current_value = { NULL, NULL };
411 struct r_scope_elem **scope;
412 int protected;
413 int noexec = elf_machine_lookup_noexec_p (reloc_type);
414 int noplt = elf_machine_lookup_noplt_p (reloc_type);
416 ++_dl_num_relocations;
418 /* Search the relevant loaded objects for a definition. */
419 for (scope = symbol_scope; *scope; ++scope)
421 int res = do_lookup_versioned (undef_name, undef_map, hash, *ref,
422 &current_value, *scope, 0, version, NULL,
423 noexec, noplt);
424 if (res > 0)
426 /* We have to check whether this would bind UNDEF_MAP to an object
427 in the global scope which was dynamically loaded. In this case
428 we have to prevent the latter from being unloaded unless the
429 UNDEF_MAP object is also unloaded. */
430 if (__builtin_expect (current_value.m->l_global, 0)
431 && (__builtin_expect (current_value.m->l_type, lt_library)
432 == lt_loaded)
433 && undef_map != current_value.m
434 /* Add UNDEF_MAP to the dependencies. */
435 && add_dependency (undef_map, current_value.m) < 0)
436 /* Something went wrong. Perhaps the object we tried to reference
437 was just removed. Try finding another definition. */
438 return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
439 symbol_scope, version,
440 reloc_type);
442 break;
445 if (__builtin_expect (res, 0) < 0)
447 /* Oh, oh. The file named in the relocation entry does not
448 contain the needed symbol. */
449 _dl_signal_cerror (0, (reference_name && reference_name[0]
450 ? reference_name
451 : (_dl_argv[0] ?: "<main program>")),
452 make_string ("symbol ", undef_name, ", version ",
453 version->name,
454 " not defined in file ",
455 version->filename,
456 " with link time reference",
457 res == -2
458 ? " (no version symbols)" : ""));
459 *ref = NULL;
460 return 0;
464 if (__builtin_expect (current_value.s == NULL, 0))
466 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
467 /* We could find no value for a strong reference. */
468 _dl_signal_cerror (0, (reference_name && reference_name[0]
469 ? reference_name
470 : (_dl_argv[0] ?: "<main program>")),
471 make_string (undefined_msg, undef_name,
472 ", version ", version->name ?: NULL));
473 *ref = NULL;
474 return 0;
477 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
479 if (__builtin_expect (_dl_debug_bindings, 0))
480 _dl_debug_message (1, "binding file ",
481 (reference_name && reference_name[0]
482 ? reference_name
483 : (_dl_argv[0] ?: "<main program>")),
484 " to ", current_value.m->l_name[0]
485 ? current_value.m->l_name : _dl_argv[0],
486 ": ", protected ? "protected" : "normal",
487 " symbol `", undef_name, "' [", version->name,
488 "]\n", NULL);
490 if (__builtin_expect (protected == 0, 1))
492 *ref = current_value.s;
493 return LOOKUP_VALUE (current_value.m);
495 else
497 /* It is very tricky. We need to figure out what value to
498 return for the protected symbol */
499 struct sym_val protected_value = { NULL, NULL };
501 for (scope = symbol_scope; *scope; ++scope)
502 if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
503 &protected_value, *scope, 0, version, NULL,
504 0, 1))
505 break;
507 if (protected_value.s == NULL || protected_value.m == undef_map)
509 *ref = current_value.s;
510 return LOOKUP_VALUE (current_value.m);
513 return LOOKUP_VALUE (undef_map);
518 /* Similar to _dl_lookup_symbol_skip but takes an additional argument
519 with the version we are looking for. */
520 lookup_t
521 internal_function
522 _dl_lookup_versioned_symbol_skip (const char *undef_name,
523 struct link_map *undef_map,
524 const ElfW(Sym) **ref,
525 struct r_scope_elem *symbol_scope[],
526 const struct r_found_version *version,
527 struct link_map *skip_map)
529 const char *reference_name = undef_map ? undef_map->l_name : NULL;
530 const unsigned long int hash = _dl_elf_hash (undef_name);
531 struct sym_val current_value = { NULL, NULL };
532 struct r_scope_elem **scope;
533 size_t i;
534 int protected;
536 ++_dl_num_relocations;
538 /* Search the relevant loaded objects for a definition. */
539 scope = symbol_scope;
540 for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
541 assert (i < (*scope)->r_nduplist);
543 if (i < (*scope)->r_nlist
544 && do_lookup_versioned (undef_name, undef_map, hash, *ref,
545 &current_value, *scope, i, version, skip_map,
546 0, 0))
548 /* We have to check whether this would bind UNDEF_MAP to an object
549 in the global scope which was dynamically loaded. In this case
550 we have to prevent the latter from being unloaded unless the
551 UNDEF_MAP object is also unloaded. */
552 if (__builtin_expect (current_value.m->l_global, 0)
553 && (__builtin_expect (current_value.m->l_type, lt_library)
554 == lt_loaded)
555 && undef_map != current_value.m
556 /* Add UNDEF_MAP to the dependencies. */
557 && add_dependency (undef_map, current_value.m) < 0)
558 /* Something went wrong. Perhaps the object we tried to reference
559 was just removed. Try finding another definition. */
560 return _dl_lookup_versioned_symbol_skip (undef_name, undef_map, ref,
561 symbol_scope, version,
562 skip_map);
564 else
565 while (*++scope)
566 if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
567 &current_value, *scope, 0, version, skip_map,
568 0, 0))
570 /* We have to check whether this would bind UNDEF_MAP to an object
571 in the global scope which was dynamically loaded. In this case
572 we have to prevent the latter from being unloaded unless the
573 UNDEF_MAP object is also unloaded. */
574 if (current_value.m->l_global
575 && (__builtin_expect (current_value.m->l_type, lt_library)
576 == lt_loaded)
577 && undef_map != current_value.m
578 /* Add UNDEF_MAP to the dependencies. */
579 && add_dependency (undef_map, current_value.m) < 0)
580 /* Something went wrong. Perhaps the object we tried to reference
581 was just removed. Try finding another definition. */
582 return _dl_lookup_versioned_symbol_skip (undef_name, undef_map,
583 ref, symbol_scope,
584 version, skip_map);
585 break;
588 if (__builtin_expect (current_value.s == NULL, 0))
590 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
592 /* We could find no value for a strong reference. */
593 const size_t len = strlen (undef_name);
594 char buf[sizeof undefined_msg + len];
595 __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
596 undef_name, len + 1);
597 _dl_signal_cerror (0, (reference_name && reference_name[0]
598 ? reference_name
599 : (_dl_argv[0] ?: "<main program>")), buf);
601 *ref = NULL;
602 return 0;
605 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
607 if (__builtin_expect (_dl_debug_bindings, 0))
608 _dl_debug_message (1, "binding file ",
609 (reference_name && reference_name[0]
610 ? reference_name
611 : (_dl_argv[0] ?: "<main program>")),
612 " to ", current_value.m->l_name[0]
613 ? current_value.m->l_name : _dl_argv[0],
614 ": ", protected ? "protected" : "normal",
615 " symbol `", undef_name, "' [", version->name,
616 "]\n", NULL);
618 if (__builtin_expect (protected == 0, 1))
620 *ref = current_value.s;
621 return LOOKUP_VALUE (current_value.m);
623 else
625 /* It is very tricky. We need to figure out what value to
626 return for the protected symbol */
627 struct sym_val protected_value = { NULL, NULL };
629 if (i >= (*scope)->r_nlist
630 || !do_lookup_versioned (undef_name, undef_map, hash, *ref,
631 &protected_value, *scope, i, version,
632 skip_map, 0, 1))
633 while (*++scope)
634 if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
635 &protected_value, *scope, 0, version,
636 skip_map, 0, 1))
637 break;
639 if (protected_value.s == NULL || protected_value.m == undef_map)
641 *ref = current_value.s;
642 return LOOKUP_VALUE (current_value.m);
645 return LOOKUP_VALUE (undef_map);
650 /* Cache the location of MAP's hash table. */
652 void
653 internal_function
654 _dl_setup_hash (struct link_map *map)
656 Elf_Symndx *hash;
657 Elf_Symndx nchain;
659 if (!map->l_info[DT_HASH])
660 return;
661 hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr);
663 map->l_nbuckets = *hash++;
664 nchain = *hash++;
665 map->l_buckets = hash;
666 hash += map->l_nbuckets;
667 map->l_chain = hash;