]> git.ipfire.org Git - thirdparty/glibc.git/blob - elf/dl-lookup.c
Update.
[thirdparty/glibc.git] / elf / dl-lookup.c
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.
4
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.
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 Lesser General Public License for more details.
14
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. */
19
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
30 #include <assert.h>
31
32 #define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
33
34 /* We need this string more than once. */
35 static const char undefined_msg[] = "undefined symbol: ";
36
37
38 struct sym_val
39 {
40 const ElfW(Sym) *s;
41 struct link_map *m;
42 };
43
44
45 #define make_string(string, rest...) \
46 ({ \
47 const char *all[] = { string, ## rest }; \
48 size_t len, cnt; \
49 char *result, *cp; \
50 \
51 len = 1; \
52 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
53 len += strlen (all[cnt]); \
54 \
55 cp = result = alloca (len); \
56 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
57 cp = __stpcpy (cp, all[cnt]); \
58 \
59 result; \
60 })
61
62 /* Statistics function. */
63 #ifdef SHARED
64 # define bump_num_relocations() ++GL(dl_num_relocations)
65 #else
66 # define bump_num_relocations() ((void) 0)
67 #endif
68
69
70
71 /* We have two different situations when looking up a simple: with or
72 without versioning. gcc is not able to optimize a single function
73 definition serving for both purposes so we define two functions. */
74 #define VERSIONED 0
75 #include "do-lookup.h"
76
77 #define VERSIONED 1
78 #include "do-lookup.h"
79
80
81 /* Add extra dependency on MAP to UNDEF_MAP. */
82 static int
83 internal_function
84 add_dependency (struct link_map *undef_map, struct link_map *map)
85 {
86 struct link_map **list;
87 struct link_map *runp;
88 unsigned int act;
89 unsigned int i;
90 int result = 0;
91
92 /* Avoid self-references. */
93 if (undef_map == map)
94 return 0;
95
96 /* Make sure nobody can unload the object while we are at it. */
97 __libc_lock_lock_recursive (GL(dl_load_lock));
98
99 /* Determine whether UNDEF_MAP already has a reference to MAP. First
100 look in the normal dependencies. */
101 if (undef_map->l_searchlist.r_list != NULL)
102 {
103 list = undef_map->l_initfini;
104
105 for (i = 0; list[i] != NULL; ++i)
106 if (list[i] == map)
107 goto out;
108 }
109
110 /* No normal dependency. See whether we already had to add it
111 to the special list of dynamic dependencies. */
112 list = undef_map->l_reldeps;
113 act = undef_map->l_reldepsact;
114
115 for (i = 0; i < act; ++i)
116 if (list[i] == map)
117 goto out;
118
119 /* The object is not yet in the dependency list. Before we add
120 it make sure just one more time the object we are about to
121 reference is still available. There is a brief period in
122 which the object could have been removed since we found the
123 definition. */
124 runp = GL(dl_loaded);
125 while (runp != NULL && runp != map)
126 runp = runp->l_next;
127
128 if (runp != NULL)
129 {
130 /* The object is still available. Add the reference now. */
131 if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
132 {
133 /* Allocate more memory for the dependency list. Since this
134 can never happen during the startup phase we can use
135 `realloc'. */
136 void *newp;
137
138 undef_map->l_reldepsmax += 5;
139 newp = realloc (undef_map->l_reldeps,
140 undef_map->l_reldepsmax
141 * sizeof (struct link_map *));
142
143 if (__builtin_expect (newp != NULL, 1))
144 undef_map->l_reldeps = (struct link_map **) newp;
145 else
146 /* Correct the addition. */
147 undef_map->l_reldepsmax -= 5;
148 }
149
150 /* If we didn't manage to allocate memory for the list this is
151 no fatal mistake. We simply increment the use counter of the
152 referenced object and don't record the dependencies. This
153 means this increment can never be reverted and the object
154 will never be unloaded. This is semantically the correct
155 behaviour. */
156 if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
157 undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
158
159 if (map->l_searchlist.r_list != NULL)
160 /* And increment the counter in the referenced object. */
161 ++map->l_opencount;
162 else
163 /* We have to bump the counts for all dependencies since so far
164 this object was only a normal or transitive dependency.
165 Now it might be closed with _dl_close() directly. */
166 for (list = map->l_initfini; *list != NULL; ++list)
167 ++(*list)->l_opencount;
168
169 /* Display information if we are debugging. */
170 if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_FILES, 0))
171 INTUSE(_dl_debug_printf) ("\
172 \nfile=%s; needed by %s (relocation dependency)\n\n",
173 map->l_name[0] ? map->l_name : _dl_argv[0],
174 undef_map->l_name[0]
175 ? undef_map->l_name : _dl_argv[0]);
176 }
177 else
178 /* Whoa, that was bad luck. We have to search again. */
179 result = -1;
180
181 out:
182 /* Release the lock. */
183 __libc_lock_unlock_recursive (GL(dl_load_lock));
184
185 return result;
186 }
187
188 static int
189 internal_function
190 _dl_do_lookup (const char *undef_name, unsigned long int hash,
191 const ElfW(Sym) *ref, struct sym_val *result,
192 struct r_scope_elem *scope, size_t i,
193 struct link_map *skip, int type_class);
194 static int
195 internal_function
196 _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
197 const ElfW(Sym) *ref, struct sym_val *result,
198 struct r_scope_elem *scope, size_t i,
199 const struct r_found_version *const version,
200 struct link_map *skip, int type_class);
201
202 static void
203 internal_function
204 _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
205 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
206 struct sym_val *value,
207 const struct r_found_version *version, int type_class,
208 int protected);
209
210 /* Search loaded objects' symbol tables for a definition of the symbol
211 UNDEF_NAME. */
212
213 lookup_t
214 internal_function
215 _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
216 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
217 int type_class, int explicit)
218 {
219 const unsigned long int hash = _dl_elf_hash (undef_name);
220 struct sym_val current_value = { NULL, NULL };
221 struct r_scope_elem **scope;
222 int protected;
223
224 bump_num_relocations ();
225
226 /* Search the relevant loaded objects for a definition. */
227 for (scope = symbol_scope; *scope; ++scope)
228 if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL,
229 type_class))
230 {
231 /* We have to check whether this would bind UNDEF_MAP to an object
232 in the global scope which was dynamically loaded. In this case
233 we have to prevent the latter from being unloaded unless the
234 UNDEF_MAP object is also unloaded. */
235 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
236 /* Don't do this for explicit lookups as opposed to implicit
237 runtime lookups. */
238 && ! explicit
239 /* Add UNDEF_MAP to the dependencies. */
240 && add_dependency (undef_map, current_value.m) < 0)
241 /* Something went wrong. Perhaps the object we tried to reference
242 was just removed. Try finding another definition. */
243 return INTUSE(_dl_lookup_symbol) (undef_name, undef_map, ref,
244 symbol_scope, type_class, 0);
245
246 break;
247 }
248
249 if (__builtin_expect (current_value.s == NULL, 0))
250 {
251 const char *reference_name = undef_map ? undef_map->l_name : NULL;
252
253 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
254 /* We could find no value for a strong reference. */
255 /* XXX We cannot translate the messages. */
256 _dl_signal_cerror (0, (reference_name[0]
257 ? reference_name
258 : (_dl_argv[0] ?: "<main program>")),
259 N_("relocation error"),
260 make_string (undefined_msg, undef_name));
261 *ref = NULL;
262 return 0;
263 }
264
265 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
266 if (__builtin_expect (protected != 0, 0))
267 {
268 /* It is very tricky. We need to figure out what value to
269 return for the protected symbol */
270 struct sym_val protected_value = { NULL, NULL };
271
272 for (scope = symbol_scope; *scope; ++scope)
273 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
274 0, NULL, ELF_RTYPE_CLASS_PLT))
275 break;
276
277 if (protected_value.s != NULL && protected_value.m != undef_map)
278 {
279 current_value.s = *ref;
280 current_value.m = undef_map;
281 }
282 }
283
284 if (__builtin_expect (GL(dl_debug_mask)
285 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
286 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
287 &current_value, NULL, type_class, protected);
288
289 *ref = current_value.s;
290 return LOOKUP_VALUE (current_value.m);
291 }
292 INTDEF (_dl_lookup_symbol)
293
294
295 /* This function is nearly the same as `_dl_lookup_symbol' but it
296 skips in the first list all objects until SKIP_MAP is found. I.e.,
297 it only considers objects which were loaded after the described
298 object. If there are more search lists the object described by
299 SKIP_MAP is only skipped. */
300 lookup_t
301 internal_function
302 _dl_lookup_symbol_skip (const char *undef_name,
303 struct link_map *undef_map, const ElfW(Sym) **ref,
304 struct r_scope_elem *symbol_scope[],
305 struct link_map *skip_map)
306 {
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;
312
313 bump_num_relocations ();
314
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);
319
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;
326
327 if (__builtin_expect (current_value.s == NULL, 0))
328 {
329 *ref = NULL;
330 return 0;
331 }
332
333 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
334
335 if (__builtin_expect (protected != 0, 0))
336 {
337 /* It is very tricky. We need to figure out what value to
338 return for the protected symbol. */
339 struct sym_val protected_value = { NULL, NULL };
340
341 if (i >= (*scope)->r_nlist
342 || !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
343 i, skip_map, ELF_RTYPE_CLASS_PLT))
344 while (*++scope)
345 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
346 0, skip_map, ELF_RTYPE_CLASS_PLT))
347 break;
348
349 if (protected_value.s != NULL && protected_value.m != undef_map)
350 {
351 current_value.s = *ref;
352 current_value.m = undef_map;
353 }
354 }
355
356 if (__builtin_expect (GL(dl_debug_mask)
357 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
358 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
359 &current_value, NULL, 0, protected);
360
361 *ref = current_value.s;
362 return LOOKUP_VALUE (current_value.m);
363 }
364
365
366 /* This function works like _dl_lookup_symbol but it takes an
367 additional arguement with the version number of the requested
368 symbol.
369
370 XXX We'll see whether we need this separate function. */
371 lookup_t
372 internal_function
373 _dl_lookup_versioned_symbol (const char *undef_name,
374 struct link_map *undef_map, const ElfW(Sym) **ref,
375 struct r_scope_elem *symbol_scope[],
376 const struct r_found_version *version,
377 int type_class, int explicit)
378 {
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
384 bump_num_relocations ();
385
386 /* Search the relevant loaded objects for a definition. */
387 for (scope = symbol_scope; *scope; ++scope)
388 {
389 int res = do_lookup_versioned (undef_name, hash, *ref, &current_value,
390 *scope, 0, version, NULL, type_class);
391 if (res > 0)
392 {
393 /* We have to check whether this would bind UNDEF_MAP to an object
394 in the global scope which was dynamically loaded. In this case
395 we have to prevent the latter from being unloaded unless the
396 UNDEF_MAP object is also unloaded. */
397 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
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 INTUSE(_dl_lookup_versioned_symbol) (undef_name, undef_map,
406 ref, symbol_scope,
407 version, type_class, 0);
408
409 break;
410 }
411
412 if (__builtin_expect (res, 0) < 0)
413 {
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;
417
418 /* XXX We cannot translate the message. */
419 _dl_signal_cerror (0, (reference_name[0]
420 ? reference_name
421 : (_dl_argv[0] ?: "<main program>")),
422 N_("relocation error"),
423 make_string ("symbol ", undef_name, ", version ",
424 version->name,
425 " not defined in file ",
426 version->filename,
427 " with link time reference",
428 res == -2
429 ? " (no version symbols)" : ""));
430 *ref = NULL;
431 return 0;
432 }
433 }
434
435 if (__builtin_expect (current_value.s == NULL, 0))
436 {
437 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
438 {
439 /* We could find no value for a strong reference. */
440 const char *reference_name = undef_map ? undef_map->l_name : NULL;
441
442 /* XXX We cannot translate the message. */
443 _dl_signal_cerror (0, (reference_name[0]
444 ? reference_name
445 : (_dl_argv[0] ?: "<main program>")), NULL,
446 make_string (undefined_msg, undef_name,
447 ", version ",
448 version->name ?: NULL));
449 }
450 *ref = NULL;
451 return 0;
452 }
453
454 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
455
456 if (__builtin_expect (protected != 0, 0))
457 {
458 /* It is very tricky. We need to figure out what value to
459 return for the protected symbol */
460 struct sym_val protected_value = { NULL, NULL };
461
462 for (scope = symbol_scope; *scope; ++scope)
463 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value,
464 *scope, 0, version, NULL,
465 ELF_RTYPE_CLASS_PLT))
466 break;
467
468 if (protected_value.s != NULL && protected_value.m != undef_map)
469 {
470 current_value.s = *ref;
471 current_value.m = undef_map;
472 }
473 }
474
475 if (__builtin_expect (GL(dl_debug_mask)
476 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
477 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
478 &current_value, version, type_class, protected);
479
480 *ref = current_value.s;
481 return LOOKUP_VALUE (current_value.m);
482 }
483 INTDEF (_dl_lookup_versioned_symbol)
484
485
486 /* Similar to _dl_lookup_symbol_skip but takes an additional argument
487 with the version we are looking for. */
488 lookup_t
489 internal_function
490 _dl_lookup_versioned_symbol_skip (const char *undef_name,
491 struct link_map *undef_map,
492 const ElfW(Sym) **ref,
493 struct r_scope_elem *symbol_scope[],
494 const struct r_found_version *version,
495 struct link_map *skip_map)
496 {
497 const char *reference_name = undef_map->l_name;
498 const unsigned long int hash = _dl_elf_hash (undef_name);
499 struct sym_val current_value = { NULL, NULL };
500 struct r_scope_elem **scope;
501 size_t i;
502 int protected;
503
504 bump_num_relocations ();
505
506 /* Search the relevant loaded objects for a definition. */
507 scope = symbol_scope;
508 for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
509 assert (i < (*scope)->r_nlist);
510
511 if (! _dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
512 *scope, i, version, skip_map, 0))
513 while (*++scope)
514 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
515 *scope, 0, version, skip_map, 0))
516 break;
517
518 if (__builtin_expect (current_value.s == NULL, 0))
519 {
520 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
521 {
522 /* We could find no value for a strong reference. */
523 const size_t len = strlen (undef_name);
524 char buf[sizeof undefined_msg + len];
525 __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
526 undef_name, len + 1);
527 /* XXX We cannot translate the messages. */
528 _dl_signal_cerror (0, (reference_name[0]
529 ? reference_name
530 : (_dl_argv[0] ?: "<main program>")),
531 NULL, buf);
532 }
533 *ref = NULL;
534 return 0;
535 }
536
537 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
538
539 if (__builtin_expect (protected != 0, 0))
540 {
541 /* It is very tricky. We need to figure out what value to
542 return for the protected symbol */
543 struct sym_val protected_value = { NULL, NULL };
544
545 if (i >= (*scope)->r_nlist
546 || !_dl_do_lookup_versioned (undef_name, hash, *ref,
547 &protected_value, *scope, i, version,
548 skip_map, ELF_RTYPE_CLASS_PLT))
549 while (*++scope)
550 if (_dl_do_lookup_versioned (undef_name, hash, *ref,
551 &protected_value, *scope, 0, version,
552 skip_map, ELF_RTYPE_CLASS_PLT))
553 break;
554
555 if (protected_value.s != NULL && protected_value.m != undef_map)
556 {
557 current_value.s = *ref;
558 current_value.m = undef_map;
559 }
560 }
561
562 if (__builtin_expect (GL(dl_debug_mask)
563 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
564 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
565 &current_value, version, 0, protected);
566
567 *ref = current_value.s;
568 return LOOKUP_VALUE (current_value.m);
569 }
570
571
572 /* Cache the location of MAP's hash table. */
573
574 void
575 internal_function
576 _dl_setup_hash (struct link_map *map)
577 {
578 Elf_Symndx *hash;
579 Elf_Symndx nchain;
580
581 if (!map->l_info[DT_HASH])
582 return;
583 hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr);
584
585 map->l_nbuckets = *hash++;
586 nchain = *hash++;
587 map->l_buckets = hash;
588 hash += map->l_nbuckets;
589 map->l_chain = hash;
590 }
591
592 static void
593 internal_function
594 _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
595 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
596 struct sym_val *value, const struct r_found_version *version,
597 int type_class, int protected)
598 {
599 const char *reference_name = undef_map->l_name;
600
601 if (GL(dl_debug_mask) & DL_DEBUG_BINDINGS)
602 {
603 INTUSE(_dl_debug_printf) ("binding file %s to %s: %s symbol `%s'",
604 (reference_name[0]
605 ? reference_name
606 : (_dl_argv[0] ?: "<main program>")),
607 value->m->l_name[0]
608 ? value->m->l_name : _dl_argv[0],
609 protected ? "protected" : "normal",
610 undef_name);
611 if (version)
612 _dl_debug_printf_c (" [%s]\n", version->name);
613 else
614 _dl_debug_printf_c ("\n");
615 }
616 #ifdef SHARED
617 if (GL(dl_debug_mask) & DL_DEBUG_PRELINK)
618 {
619 int conflict = 0;
620 struct sym_val val = { NULL, NULL };
621
622 if ((GL(dl_trace_prelink_map) == NULL
623 || GL(dl_trace_prelink_map) == GL(dl_loaded))
624 && undef_map != GL(dl_loaded))
625 {
626 const unsigned long int hash = _dl_elf_hash (undef_name);
627
628 if (version == 0)
629 _dl_do_lookup (undef_name, hash, *ref, &val,
630 undef_map->l_local_scope[0], 0, NULL, type_class);
631 else
632 _dl_do_lookup_versioned (undef_name, hash, *ref, &val,
633 undef_map->l_local_scope[0], 0, version,
634 NULL, type_class);
635
636 if (val.s != value->s || val.m != value->m)
637 conflict = 1;
638 }
639
640 if (conflict
641 || GL(dl_trace_prelink_map) == undef_map
642 || GL(dl_trace_prelink_map) == NULL)
643 {
644 _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
645 conflict ? "conflict" : "lookup",
646 (int) sizeof (ElfW(Addr)) * 2, undef_map->l_map_start,
647 (int) sizeof (ElfW(Addr)) * 2,
648 ((ElfW(Addr)) *ref) - undef_map->l_map_start,
649 (int) sizeof (ElfW(Addr)) * 2,
650 (ElfW(Addr)) (value->s ? value->m->l_map_start : 0),
651 (int) sizeof (ElfW(Addr)) * 2,
652 (ElfW(Addr)) (value->s ? value->s->st_value : 0));
653
654 if (conflict)
655 _dl_printf ("x 0x%0*Zx 0x%0*Zx ",
656 (int) sizeof (ElfW(Addr)) * 2,
657 (ElfW(Addr)) (val.s ? val.m->l_map_start : 0),
658 (int) sizeof (ElfW(Addr)) * 2,
659 (ElfW(Addr)) (val.s ? val.s->st_value : 0));
660
661 _dl_printf ("/%x %s\n", type_class, undef_name);
662 }
663 }
664 #endif
665 }
666
667 /* These are here so that we only inline do_lookup{,_versioned} in the common
668 case, not everywhere. */
669 static int __attribute_noinline__
670 internal_function
671 _dl_do_lookup (const char *undef_name, unsigned long int hash,
672 const ElfW(Sym) *ref, struct sym_val *result,
673 struct r_scope_elem *scope, size_t i,
674 struct link_map *skip, int type_class)
675 {
676 return do_lookup (undef_name, hash, ref, result, scope, i, skip,
677 type_class);
678 }
679
680 static int __attribute_noinline__
681 internal_function
682 _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
683 const ElfW(Sym) *ref, struct sym_val *result,
684 struct r_scope_elem *scope, size_t i,
685 const struct r_found_version *const version,
686 struct link_map *skip, int type_class)
687 {
688 return do_lookup_versioned (undef_name, hash, ref, result, scope, i,
689 version, skip, type_class);
690 }