]> sourceware.org Git - glibc.git/blob - elf/dl-lookup.c
(_dl_lookup_symbol_skip): Fix a typo.
[glibc.git] / elf / dl-lookup.c
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.
4
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.
9
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.
14
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. */
19
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>
28
29 #include <assert.h>
30
31 #define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
32
33 /* We need this string more than once. */
34 static const char undefined_msg[] = "undefined symbol: ";
35
36
37 struct sym_val
38 {
39 const ElfW(Sym) *s;
40 struct link_map *m;
41 };
42
43
44 #define make_string(string, rest...) \
45 ({ \
46 const char *all[] = { string, ## rest }; \
47 size_t len, cnt; \
48 char *result, *cp; \
49 \
50 len = 1; \
51 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
52 len += strlen (all[cnt]); \
53 \
54 cp = result = alloca (len); \
55 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
56 cp = __stpcpy (cp, all[cnt]); \
57 \
58 result; \
59 })
60
61 /* Statistics function. */
62 unsigned long int _dl_num_relocations;
63
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.
67
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)
72
73
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"
80
81 #define VERSIONED 1
82 #define PROTECTED 0
83 #include "do-lookup.h"
84
85
86 /* Add extra dependency on MAP to UNDEF_MAP. */
87 static int
88 add_dependency (struct link_map *undef_map, struct link_map *map)
89 {
90 struct link_map **list;
91 unsigned int act;
92 unsigned int i;
93 int result = 0;
94
95 /* Make sure nobody can unload the object while we are at it. */
96 __libc_lock_lock (_dl_load_lock);
97
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;
102
103 for (i = 0; i < act; ++i)
104 if (list[i] == map)
105 break;
106
107 if (__builtin_expect (i == act, 1))
108 {
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;
113
114 for (i = 0; i < act; ++i)
115 if (list[i] == map)
116 break;
117
118 if (i == act)
119 {
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;
126
127 while (runp != NULL && runp != map)
128 runp = runp->l_next;
129
130 if (runp != NULL)
131 {
132 /* The object is still available. Add the reference now. */
133 if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
134 {
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;
139
140 undef_map->l_reldepsmax += 5;
141 newp = realloc (undef_map->l_reldeps,
142 undef_map->l_reldepsmax
143 * sizeof(struct link_map *));
144
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;
150 }
151
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;
160
161 /* And increment the counter in the referenced object. */
162 ++map->l_opencount;
163
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);
172 }
173 else
174 /* Whoa, that was bad luck. We have to search again. */
175 result = -1;
176 }
177 }
178
179 /* Release the lock. */
180 __libc_lock_unlock (_dl_load_lock);
181
182 return result;
183 }
184
185
186 /* Search loaded objects' symbol tables for a definition of the symbol
187 UNDEF_NAME. */
188
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, int explicit)
194 {
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);
202
203 ++_dl_num_relocations;
204
205 /* Search the relevant loaded objects for a definition. */
206 for (scope = symbol_scope; *scope; ++scope)
207 if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL,
208 noexec, noplt))
209 {
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 /* Don't do this for explicit lookups as opposed to implicit
219 runtime lookups. */
220 && __builtin_expect (! explicit, 1)
221 /* Add UNDEF_MAP to the dependencies. */
222 && add_dependency (undef_map, current_value.m) < 0)
223 /* Something went wrong. Perhaps the object we tried to reference
224 was just removed. Try finding another definition. */
225 return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope,
226 reloc_type, 0);
227
228 break;
229 }
230
231 if (__builtin_expect (current_value.s == NULL, 0))
232 {
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;
242 }
243
244 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
245
246 if (__builtin_expect (_dl_debug_bindings, 0))
247 _dl_debug_message (1, "binding file ",
248 (reference_name && reference_name[0]
249 ? reference_name
250 : (_dl_argv[0] ?: "<main program>")),
251 " to ", current_value.m->l_name[0]
252 ? current_value.m->l_name : _dl_argv[0],
253 ": ", protected ? "protected" : "normal",
254 " symbol `", undef_name, "'\n", NULL);
255
256 if (__builtin_expect (protected == 0, 1))
257 {
258 *ref = current_value.s;
259 return LOOKUP_VALUE (current_value.m);
260 }
261 else
262 {
263 /* It is very tricky. We need to figure out what value to
264 return for the protected symbol */
265 struct sym_val protected_value = { NULL, NULL };
266
267 for (scope = symbol_scope; *scope; ++scope)
268 if (do_lookup (undef_name, hash, *ref, &protected_value, *scope, 0,
269 NULL, 0, 1))
270 break;
271
272 if (protected_value.s == NULL || protected_value.m == undef_map)
273 {
274 *ref = current_value.s;
275 return LOOKUP_VALUE (current_value.m);
276 }
277
278 return LOOKUP_VALUE (undef_map);
279 }
280 }
281
282
283 /* This function is nearly the same as `_dl_lookup_symbol' but it
284 skips in the first list all objects until SKIP_MAP is found. I.e.,
285 it only considers objects which were loaded after the described
286 object. If there are more search lists the object described by
287 SKIP_MAP is only skipped. */
288 lookup_t
289 internal_function
290 _dl_lookup_symbol_skip (const char *undef_name,
291 struct link_map *undef_map, const ElfW(Sym) **ref,
292 struct r_scope_elem *symbol_scope[],
293 struct link_map *skip_map)
294 {
295 const char *reference_name = undef_map ? undef_map->l_name : NULL;
296 const unsigned long int hash = _dl_elf_hash (undef_name);
297 struct sym_val current_value = { NULL, NULL };
298 struct r_scope_elem **scope;
299 size_t i;
300 int protected;
301
302 ++_dl_num_relocations;
303
304 /* Search the relevant loaded objects for a definition. */
305 scope = symbol_scope;
306 for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
307 assert (i < (*scope)->r_nduplist);
308
309 if (i >= (*scope)->r_nlist
310 || ! do_lookup (undef_name, hash, *ref, &current_value, *scope, i,
311 skip_map, 0, 0))
312 while (*++scope)
313 if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
314 skip_map, 0, 0))
315 break;
316
317 if (__builtin_expect (current_value.s == NULL, 0))
318 {
319 *ref = NULL;
320 return 0;
321 }
322
323 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
324
325 if (__builtin_expect (_dl_debug_bindings, 0))
326 _dl_debug_message (1, "binding file ",
327 (reference_name && reference_name[0]
328 ? reference_name
329 : (_dl_argv[0] ?: "<main program>")),
330 " to ", current_value.m->l_name[0]
331 ? current_value.m->l_name : _dl_argv[0],
332 ": ", protected ? "protected" : "normal",
333 " symbol `", undef_name, "'\n", NULL);
334
335 if (__builtin_expect (protected == 0, 1))
336 {
337 *ref = current_value.s;
338 return LOOKUP_VALUE (current_value.m);
339 }
340 else
341 {
342 /* It is very tricky. We need to figure out what value to
343 return for the protected symbol. */
344 struct sym_val protected_value = { NULL, NULL };
345
346 if (i >= (*scope)->r_nlist
347 || !do_lookup (undef_name, hash, *ref, &protected_value, *scope, i,
348 skip_map, 0, 1))
349 while (*++scope)
350 if (do_lookup (undef_name, hash, *ref, &protected_value, *scope, 0,
351 skip_map, 0, 1))
352 break;
353
354 if (protected_value.s == NULL || protected_value.m == undef_map)
355 {
356 *ref = current_value.s;
357 return LOOKUP_VALUE (current_value.m);
358 }
359
360 return LOOKUP_VALUE (undef_map);
361 }
362 }
363
364
365 /* This function works like _dl_lookup_symbol but it takes an
366 additional arguement with the version number of the requested
367 symbol.
368
369 XXX We'll see whether we need this separate function. */
370 lookup_t
371 internal_function
372 _dl_lookup_versioned_symbol (const char *undef_name,
373 struct link_map *undef_map, const ElfW(Sym) **ref,
374 struct r_scope_elem *symbol_scope[],
375 const struct r_found_version *version,
376 int reloc_type, int explicit)
377 {
378 const char *reference_name = undef_map ? undef_map->l_name : NULL;
379 const unsigned long int hash = _dl_elf_hash (undef_name);
380 struct sym_val current_value = { NULL, NULL };
381 struct r_scope_elem **scope;
382 int protected;
383 int noexec = elf_machine_lookup_noexec_p (reloc_type);
384 int noplt = elf_machine_lookup_noplt_p (reloc_type);
385
386 ++_dl_num_relocations;
387
388 /* Search the relevant loaded objects for a definition. */
389 for (scope = symbol_scope; *scope; ++scope)
390 {
391 int res = do_lookup_versioned (undef_name, hash, *ref, &current_value,
392 *scope, 0, version, NULL, noexec, noplt);
393 if (res > 0)
394 {
395 /* We have to check whether this would bind UNDEF_MAP to an object
396 in the global scope which was dynamically loaded. In this case
397 we have to prevent the latter from being unloaded unless the
398 UNDEF_MAP object is also unloaded. */
399 if (__builtin_expect (current_value.m->l_global, 0)
400 && (__builtin_expect (current_value.m->l_type, lt_library)
401 == lt_loaded)
402 && undef_map != current_value.m
403 /* Don't do this for explicit lookups as opposed to implicit
404 runtime lookups. */
405 && __builtin_expect (! explicit, 1)
406 /* Add UNDEF_MAP to the dependencies. */
407 && add_dependency (undef_map, current_value.m) < 0)
408 /* Something went wrong. Perhaps the object we tried to reference
409 was just removed. Try finding another definition. */
410 return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
411 symbol_scope, version,
412 reloc_type, 0);
413
414 break;
415 }
416
417 if (__builtin_expect (res, 0) < 0)
418 {
419 /* Oh, oh. The file named in the relocation entry does not
420 contain the needed symbol. */
421 /* XXX We cannot translate the message. */
422 _dl_signal_cerror (0, (reference_name && reference_name[0]
423 ? reference_name
424 : (_dl_argv[0] ?: "<main program>")),
425 make_string ("symbol ", undef_name, ", version ",
426 version->name,
427 " not defined in file ",
428 version->filename,
429 " with link time reference",
430 res == -2
431 ? " (no version symbols)" : ""));
432 *ref = NULL;
433 return 0;
434 }
435 }
436
437 if (__builtin_expect (current_value.s == NULL, 0))
438 {
439 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
440 /* We could find no value for a strong reference. */
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 ", version->name ?: NULL));
447 *ref = NULL;
448 return 0;
449 }
450
451 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
452
453 if (__builtin_expect (_dl_debug_bindings, 0))
454 _dl_debug_message (1, "binding file ",
455 (reference_name && reference_name[0]
456 ? reference_name
457 : (_dl_argv[0] ?: "<main program>")),
458 " to ", current_value.m->l_name[0]
459 ? current_value.m->l_name : _dl_argv[0],
460 ": ", protected ? "protected" : "normal",
461 " symbol `", undef_name, "' [", version->name,
462 "]\n", NULL);
463
464 if (__builtin_expect (protected == 0, 1))
465 {
466 *ref = current_value.s;
467 return LOOKUP_VALUE (current_value.m);
468 }
469 else
470 {
471 /* It is very tricky. We need to figure out what value to
472 return for the protected symbol */
473 struct sym_val protected_value = { NULL, NULL };
474
475 for (scope = symbol_scope; *scope; ++scope)
476 if (do_lookup_versioned (undef_name, hash, *ref, &protected_value,
477 *scope, 0, version, NULL, 0, 1))
478 break;
479
480 if (protected_value.s == NULL || protected_value.m == undef_map)
481 {
482 *ref = current_value.s;
483 return LOOKUP_VALUE (current_value.m);
484 }
485
486 return LOOKUP_VALUE (undef_map);
487 }
488 }
489
490
491 /* Similar to _dl_lookup_symbol_skip but takes an additional argument
492 with the version we are looking for. */
493 lookup_t
494 internal_function
495 _dl_lookup_versioned_symbol_skip (const char *undef_name,
496 struct link_map *undef_map,
497 const ElfW(Sym) **ref,
498 struct r_scope_elem *symbol_scope[],
499 const struct r_found_version *version,
500 struct link_map *skip_map)
501 {
502 const char *reference_name = undef_map ? undef_map->l_name : NULL;
503 const unsigned long int hash = _dl_elf_hash (undef_name);
504 struct sym_val current_value = { NULL, NULL };
505 struct r_scope_elem **scope;
506 size_t i;
507 int protected;
508
509 ++_dl_num_relocations;
510
511 /* Search the relevant loaded objects for a definition. */
512 scope = symbol_scope;
513 for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
514 assert (i < (*scope)->r_nduplist);
515
516 if (i >= (*scope)->r_nlist
517 || ! do_lookup_versioned (undef_name, hash, *ref, &current_value,
518 *scope, i, version, skip_map, 0, 0))
519 while (*++scope)
520 if (do_lookup_versioned (undef_name, hash, *ref, &current_value, *scope,
521 0, version, skip_map, 0, 0))
522 break;
523
524 if (__builtin_expect (current_value.s == NULL, 0))
525 {
526 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
527 {
528 /* We could find no value for a strong reference. */
529 const size_t len = strlen (undef_name);
530 char buf[sizeof undefined_msg + len];
531 __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
532 undef_name, len + 1);
533 /* XXX We cannot translate the messages. */
534 _dl_signal_cerror (0, (reference_name && reference_name[0]
535 ? reference_name
536 : (_dl_argv[0] ?: "<main program>")), buf);
537 }
538 *ref = NULL;
539 return 0;
540 }
541
542 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
543
544 if (__builtin_expect (_dl_debug_bindings, 0))
545 _dl_debug_message (1, "binding file ",
546 (reference_name && reference_name[0]
547 ? reference_name
548 : (_dl_argv[0] ?: "<main program>")),
549 " to ", current_value.m->l_name[0]
550 ? current_value.m->l_name : _dl_argv[0],
551 ": ", protected ? "protected" : "normal",
552 " symbol `", undef_name, "' [", version->name,
553 "]\n", NULL);
554
555 if (__builtin_expect (protected == 0, 1))
556 {
557 *ref = current_value.s;
558 return LOOKUP_VALUE (current_value.m);
559 }
560 else
561 {
562 /* It is very tricky. We need to figure out what value to
563 return for the protected symbol */
564 struct sym_val protected_value = { NULL, NULL };
565
566 if (i >= (*scope)->r_nlist
567 || !do_lookup_versioned (undef_name, hash, *ref, &protected_value,
568 *scope, i, version, skip_map, 0, 1))
569 while (*++scope)
570 if (do_lookup_versioned (undef_name, hash, *ref, &protected_value,
571 *scope, 0, version, skip_map, 0, 1))
572 break;
573
574 if (protected_value.s == NULL || protected_value.m == undef_map)
575 {
576 *ref = current_value.s;
577 return LOOKUP_VALUE (current_value.m);
578 }
579
580 return LOOKUP_VALUE (undef_map);
581 }
582 }
583
584
585 /* Cache the location of MAP's hash table. */
586
587 void
588 internal_function
589 _dl_setup_hash (struct link_map *map)
590 {
591 Elf_Symndx *hash;
592 Elf_Symndx nchain;
593
594 if (!map->l_info[DT_HASH])
595 return;
596 hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr);
597
598 map->l_nbuckets = *hash++;
599 nchain = *hash++;
600 map->l_buckets = hash;
601 hash += map->l_nbuckets;
602 map->l_chain = hash;
603 }
This page took 0.067045 seconds and 6 git commands to generate.