Use INTERNAL_SYSCALL.
[glibc.git] / elf / dl-lookup.c
blob39b3a3d013f16eed309ec6b8e684dfe72886d625
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.
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>
29 #include <tls.h>
31 #include <assert.h>
33 #define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
35 /* We need this string more than once. */
36 static const char undefined_msg[] = "undefined symbol: ";
39 struct sym_val
41 const ElfW(Sym) *s;
42 struct link_map *m;
46 #define make_string(string, rest...) \
47 ({ \
48 const char *all[] = { string, ## rest }; \
49 size_t len, cnt; \
50 char *result, *cp; \
52 len = 1; \
53 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
54 len += strlen (all[cnt]); \
56 cp = result = alloca (len); \
57 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
58 cp = __stpcpy (cp, all[cnt]); \
60 result; \
63 /* Statistics function. */
64 #ifdef SHARED
65 # define bump_num_relocations() ++GL(dl_num_relocations)
66 #else
67 # define bump_num_relocations() ((void) 0)
68 #endif
72 /* We have two different situations when looking up a simple: with or
73 without versioning. gcc is not able to optimize a single function
74 definition serving for both purposes so we define two functions. */
75 #define VERSIONED 0
76 #include "do-lookup.h"
78 #define VERSIONED 1
79 #include "do-lookup.h"
82 /* Add extra dependency on MAP to UNDEF_MAP. */
83 static int
84 internal_function
85 add_dependency (struct link_map *undef_map, struct link_map *map)
87 struct link_map **list;
88 struct link_map *runp;
89 unsigned int act;
90 unsigned int i;
91 int result = 0;
93 /* Avoid self-references. */
94 if (undef_map == map)
95 return 0;
97 /* Don't create cross-reference between modules which are
98 dynamically loaded by the same dlopen() call. */
99 if (undef_map->l_opencount == 0 && map->l_opencount == 0)
100 return 0;
102 /* Make sure nobody can unload the object while we are at it. */
103 __rtld_lock_lock_recursive (GL(dl_load_lock));
105 /* Determine whether UNDEF_MAP already has a reference to MAP. First
106 look in the normal dependencies. */
107 if (undef_map->l_searchlist.r_list != NULL)
109 list = undef_map->l_initfini;
111 for (i = 0; list[i] != NULL; ++i)
112 if (list[i] == map)
113 goto out;
116 /* No normal dependency. See whether we already had to add it
117 to the special list of dynamic dependencies. */
118 list = undef_map->l_reldeps;
119 act = undef_map->l_reldepsact;
121 for (i = 0; i < act; ++i)
122 if (list[i] == map)
123 goto out;
125 /* The object is not yet in the dependency list. Before we add
126 it make sure just one more time the object we are about to
127 reference is still available. There is a brief period in
128 which the object could have been removed since we found the
129 definition. */
130 runp = GL(dl_loaded);
131 while (runp != NULL && runp != map)
132 runp = runp->l_next;
134 if (runp != NULL)
136 /* The object is still available. Add the reference now. */
137 if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
139 /* Allocate more memory for the dependency list. Since this
140 can never happen during the startup phase we can use
141 `realloc'. */
142 void *newp;
144 undef_map->l_reldepsmax += 5;
145 newp = realloc (undef_map->l_reldeps,
146 undef_map->l_reldepsmax
147 * sizeof (struct link_map *));
149 if (__builtin_expect (newp != NULL, 1))
150 undef_map->l_reldeps = (struct link_map **) newp;
151 else
152 /* Correct the addition. */
153 undef_map->l_reldepsmax -= 5;
156 /* If we didn't manage to allocate memory for the list this is
157 no fatal mistake. We simply increment the use counter of the
158 referenced object and don't record the dependencies. This
159 means this increment can never be reverted and the object
160 will never be unloaded. This is semantically the correct
161 behavior. */
162 if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
163 undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
165 if (map->l_searchlist.r_list != NULL)
166 /* And increment the counter in the referenced object. */
167 ++map->l_opencount;
168 else
169 /* We have to bump the counts for all dependencies since so far
170 this object was only a normal or transitive dependency.
171 Now it might be closed with _dl_close() directly. */
172 for (list = map->l_initfini; *list != NULL; ++list)
173 ++(*list)->l_opencount;
175 /* Display information if we are debugging. */
176 if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_FILES, 0))
177 INTUSE(_dl_debug_printf) ("\
178 \nfile=%s; needed by %s (relocation dependency)\n\n",
179 map->l_name[0] ? map->l_name : rtld_progname,
180 undef_map->l_name[0]
181 ? undef_map->l_name : rtld_progname);
183 else
184 /* Whoa, that was bad luck. We have to search again. */
185 result = -1;
187 out:
188 /* Release the lock. */
189 __rtld_lock_unlock_recursive (GL(dl_load_lock));
191 return result;
194 static int
195 internal_function
196 _dl_do_lookup (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, int flags,
199 struct link_map *skip, int type_class);
200 static int
201 internal_function
202 _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
203 const ElfW(Sym) *ref, struct sym_val *result,
204 struct r_scope_elem *scope, size_t i,
205 const struct r_found_version *const version,
206 struct link_map *skip, int type_class);
208 static void
209 internal_function
210 _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
211 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
212 struct sym_val *value,
213 const struct r_found_version *version, int type_class,
214 int protected);
216 /* Search loaded objects' symbol tables for a definition of the symbol
217 UNDEF_NAME. */
219 lookup_t
220 internal_function
221 _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
222 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
223 int type_class, int flags)
225 const unsigned long int hash = _dl_elf_hash (undef_name);
226 struct sym_val current_value = { NULL, NULL };
227 struct r_scope_elem **scope;
228 int protected;
230 bump_num_relocations ();
232 /* Search the relevant loaded objects for a definition. */
233 for (scope = symbol_scope; *scope; ++scope)
234 if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, flags,
235 NULL, type_class))
236 break;
238 if (__builtin_expect (current_value.s == NULL, 0))
240 const char *reference_name = undef_map ? undef_map->l_name : NULL;
242 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
243 /* We could find no value for a strong reference. */
244 /* XXX We cannot translate the messages. */
245 _dl_signal_cerror (0, (reference_name[0]
246 ? reference_name
247 : (rtld_progname ?: "<main program>")),
248 N_("relocation error"),
249 make_string (undefined_msg, undef_name));
250 *ref = NULL;
251 return 0;
254 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
255 if (__builtin_expect (protected != 0, 0))
257 /* It is very tricky. We need to figure out what value to
258 return for the protected symbol. */
259 struct sym_val protected_value = { NULL, NULL };
261 for (scope = symbol_scope; *scope; ++scope)
262 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
263 0, flags, NULL, ELF_RTYPE_CLASS_PLT))
264 break;
266 if (protected_value.s != NULL && protected_value.m != undef_map)
268 current_value.s = *ref;
269 current_value.m = undef_map;
273 /* We have to check whether this would bind UNDEF_MAP to an object
274 in the global scope which was dynamically loaded. In this case
275 we have to prevent the latter from being unloaded unless the
276 UNDEF_MAP object is also unloaded. */
277 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
278 /* Don't do this for explicit lookups as opposed to implicit
279 runtime lookups. */
280 && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
281 /* Add UNDEF_MAP to the dependencies. */
282 && add_dependency (undef_map, current_value.m) < 0)
283 /* Something went wrong. Perhaps the object we tried to reference
284 was just removed. Try finding another definition. */
285 return INTUSE(_dl_lookup_symbol) (undef_name, undef_map, ref,
286 symbol_scope, type_class, flags);
288 if (__builtin_expect (GL(dl_debug_mask)
289 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
290 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
291 &current_value, NULL, type_class, protected);
293 *ref = current_value.s;
294 return LOOKUP_VALUE (current_value.m);
296 INTDEF (_dl_lookup_symbol)
299 /* This function is nearly the same as `_dl_lookup_symbol' but it
300 skips in the first list all objects until SKIP_MAP is found. I.e.,
301 it only considers objects which were loaded after the described
302 object. If there are more search lists the object described by
303 SKIP_MAP is only skipped. */
304 lookup_t
305 internal_function
306 _dl_lookup_symbol_skip (const char *undef_name,
307 struct link_map *undef_map, const ElfW(Sym) **ref,
308 struct r_scope_elem *symbol_scope[],
309 struct link_map *skip_map)
311 const unsigned long int hash = _dl_elf_hash (undef_name);
312 struct sym_val current_value = { NULL, NULL };
313 struct r_scope_elem **scope;
314 size_t i;
315 int protected;
317 bump_num_relocations ();
319 /* Search the relevant loaded objects for a definition. */
320 scope = symbol_scope;
321 for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
322 assert (i < (*scope)->r_nlist);
324 if (! _dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, i,
325 DL_LOOKUP_RETURN_NEWEST, skip_map, 0))
326 while (*++scope)
327 if (_dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
328 DL_LOOKUP_RETURN_NEWEST, skip_map, 0))
329 break;
331 if (__builtin_expect (current_value.s == NULL, 0))
333 *ref = NULL;
334 return 0;
337 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
339 if (__builtin_expect (protected != 0, 0))
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, DL_LOOKUP_RETURN_NEWEST, skip_map,
348 ELF_RTYPE_CLASS_PLT))
349 while (*++scope)
350 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
351 0, DL_LOOKUP_RETURN_NEWEST, skip_map,
352 ELF_RTYPE_CLASS_PLT))
353 break;
355 if (protected_value.s != NULL && protected_value.m != undef_map)
357 current_value.s = *ref;
358 current_value.m = undef_map;
362 if (__builtin_expect (GL(dl_debug_mask)
363 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
364 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
365 &current_value, NULL, 0, protected);
367 *ref = current_value.s;
368 return LOOKUP_VALUE (current_value.m);
372 /* This function works like _dl_lookup_symbol but it takes an
373 additional arguement with the version number of the requested
374 symbol.
376 XXX We'll see whether we need this separate function. */
377 lookup_t
378 internal_function
379 _dl_lookup_versioned_symbol (const char *undef_name,
380 struct link_map *undef_map, const ElfW(Sym) **ref,
381 struct r_scope_elem *symbol_scope[],
382 const struct r_found_version *version,
383 int type_class, int flags)
385 const unsigned long int hash = _dl_elf_hash (undef_name);
386 struct sym_val current_value = { NULL, NULL };
387 struct r_scope_elem **scope;
388 int protected;
390 bump_num_relocations ();
392 /* No other flag than DL_LOOKUP_ADD_DEPENDENCY is allowed. */
393 assert (flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY);
395 /* Search the relevant loaded objects for a definition. */
396 for (scope = symbol_scope; *scope; ++scope)
398 int res = do_lookup_versioned (undef_name, hash, *ref, &current_value,
399 *scope, 0, version, NULL, type_class);
400 if (res > 0)
401 break;
403 if (__builtin_expect (res, 0) < 0)
405 /* Oh, oh. The file named in the relocation entry does not
406 contain the needed symbol. */
407 const char *reference_name = undef_map ? undef_map->l_name : NULL;
409 /* XXX We cannot translate the message. */
410 _dl_signal_cerror (0, (reference_name[0]
411 ? reference_name
412 : (rtld_progname ?: "<main program>")),
413 N_("relocation error"),
414 make_string ("symbol ", undef_name, ", version ",
415 version->name,
416 " not defined in file ",
417 version->filename,
418 " with link time reference",
419 res == -2
420 ? " (no version symbols)" : ""));
421 *ref = NULL;
422 return 0;
426 if (__builtin_expect (current_value.s == NULL, 0))
428 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
430 /* We could find no value for a strong reference. */
431 const char *reference_name = undef_map ? undef_map->l_name : NULL;
433 /* XXX We cannot translate the message. */
434 _dl_signal_cerror (0, (reference_name[0]
435 ? reference_name
436 : (rtld_progname ?: "<main program>")), NULL,
437 make_string (undefined_msg, undef_name,
438 ", version ",
439 version->name ?: NULL));
441 *ref = NULL;
442 return 0;
445 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
447 if (__builtin_expect (protected != 0, 0))
449 /* It is very tricky. We need to figure out what value to
450 return for the protected symbol. */
451 struct sym_val protected_value = { NULL, NULL };
453 for (scope = symbol_scope; *scope; ++scope)
454 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value,
455 *scope, 0, version, NULL,
456 ELF_RTYPE_CLASS_PLT))
457 break;
459 if (protected_value.s != NULL && protected_value.m != undef_map)
461 current_value.s = *ref;
462 current_value.m = undef_map;
466 /* We have to check whether this would bind UNDEF_MAP to an object
467 in the global scope which was dynamically loaded. In this case
468 we have to prevent the latter from being unloaded unless the
469 UNDEF_MAP object is also unloaded. */
470 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
471 /* Don't do this for explicit lookups as opposed to implicit
472 runtime lookups. */
473 && flags != 0
474 /* Add UNDEF_MAP to the dependencies. */
475 && add_dependency (undef_map, current_value.m) < 0)
476 /* Something went wrong. Perhaps the object we tried to reference
477 was just removed. Try finding another definition. */
478 return INTUSE(_dl_lookup_versioned_symbol) (undef_name, undef_map,
479 ref, symbol_scope,
480 version, type_class, flags);
482 if (__builtin_expect (GL(dl_debug_mask)
483 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
484 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
485 &current_value, version, type_class, protected);
487 *ref = current_value.s;
488 return LOOKUP_VALUE (current_value.m);
490 INTDEF (_dl_lookup_versioned_symbol)
493 /* Similar to _dl_lookup_symbol_skip but takes an additional argument
494 with the version we are looking for. */
495 lookup_t
496 internal_function
497 _dl_lookup_versioned_symbol_skip (const char *undef_name,
498 struct link_map *undef_map,
499 const ElfW(Sym) **ref,
500 struct r_scope_elem *symbol_scope[],
501 const struct r_found_version *version,
502 struct link_map *skip_map)
504 const char *reference_name = undef_map->l_name;
505 const unsigned long int hash = _dl_elf_hash (undef_name);
506 struct sym_val current_value = { NULL, NULL };
507 struct r_scope_elem **scope;
508 size_t i;
509 int protected;
511 bump_num_relocations ();
513 /* Search the relevant loaded objects for a definition. */
514 scope = symbol_scope;
515 for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
516 assert (i < (*scope)->r_nlist);
518 if (! _dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
519 *scope, i, version, skip_map, 0))
520 while (*++scope)
521 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
522 *scope, 0, version, skip_map, 0))
523 break;
525 if (__builtin_expect (current_value.s == NULL, 0))
527 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
529 /* We could find no value for a strong reference. */
530 const size_t len = strlen (undef_name);
531 char buf[sizeof undefined_msg + len];
532 __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
533 undef_name, len + 1);
534 /* XXX We cannot translate the messages. */
535 _dl_signal_cerror (0, (reference_name[0]
536 ? reference_name
537 : (rtld_progname ?: "<main program>")),
538 NULL, buf);
540 *ref = NULL;
541 return 0;
544 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
546 if (__builtin_expect (protected != 0, 0))
548 /* It is very tricky. We need to figure out what value to
549 return for the protected symbol. */
550 struct sym_val protected_value = { NULL, NULL };
552 if (i >= (*scope)->r_nlist
553 || !_dl_do_lookup_versioned (undef_name, hash, *ref,
554 &protected_value, *scope, i, version,
555 skip_map, ELF_RTYPE_CLASS_PLT))
556 while (*++scope)
557 if (_dl_do_lookup_versioned (undef_name, hash, *ref,
558 &protected_value, *scope, 0, version,
559 skip_map, ELF_RTYPE_CLASS_PLT))
560 break;
562 if (protected_value.s != NULL && protected_value.m != undef_map)
564 current_value.s = *ref;
565 current_value.m = undef_map;
569 if (__builtin_expect (GL(dl_debug_mask)
570 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
571 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
572 &current_value, version, 0, protected);
574 *ref = current_value.s;
575 return LOOKUP_VALUE (current_value.m);
579 /* Cache the location of MAP's hash table. */
581 void
582 internal_function
583 _dl_setup_hash (struct link_map *map)
585 Elf_Symndx *hash;
586 Elf_Symndx nchain;
588 if (!map->l_info[DT_HASH])
589 return;
590 hash = (void *) D_PTR (map, l_info[DT_HASH]);
592 map->l_nbuckets = *hash++;
593 nchain = *hash++;
594 map->l_buckets = hash;
595 hash += map->l_nbuckets;
596 map->l_chain = hash;
600 static void
601 internal_function
602 _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
603 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
604 struct sym_val *value,
605 const struct r_found_version *version, int type_class,
606 int protected)
608 const char *reference_name = undef_map->l_name;
610 if (GL(dl_debug_mask) & DL_DEBUG_BINDINGS)
612 INTUSE(_dl_debug_printf) ("binding file %s to %s: %s symbol `%s'",
613 (reference_name[0]
614 ? reference_name
615 : (rtld_progname ?: "<main program>")),
616 value->m->l_name[0]
617 ? value->m->l_name : rtld_progname,
618 protected ? "protected" : "normal",
619 undef_name);
620 if (version)
621 _dl_debug_printf_c (" [%s]\n", version->name);
622 else
623 _dl_debug_printf_c ("\n");
625 #ifdef SHARED
626 if (GL(dl_debug_mask) & DL_DEBUG_PRELINK)
628 int conflict = 0;
629 struct sym_val val = { NULL, NULL };
631 if ((GL(dl_trace_prelink_map) == NULL
632 || GL(dl_trace_prelink_map) == GL(dl_loaded))
633 && undef_map != GL(dl_loaded))
635 const unsigned long int hash = _dl_elf_hash (undef_name);
637 if (version == 0)
638 _dl_do_lookup (undef_name, hash, *ref, &val,
639 undef_map->l_local_scope[0], 0, 0, NULL,
640 type_class);
641 else
642 _dl_do_lookup_versioned (undef_name, hash, *ref, &val,
643 undef_map->l_local_scope[0], 0, version,
644 NULL, type_class);
646 if (val.s != value->s || val.m != value->m)
647 conflict = 1;
650 #ifdef USE_TLS
651 if (value->s
652 && (__builtin_expect (ELFW(ST_TYPE) (value->s->st_info)
653 == STT_TLS, 0)))
654 type_class = 4;
655 #endif
657 if (conflict
658 || GL(dl_trace_prelink_map) == undef_map
659 || GL(dl_trace_prelink_map) == NULL
660 || type_class == 4)
662 _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
663 conflict ? "conflict" : "lookup",
664 (int) sizeof (ElfW(Addr)) * 2, undef_map->l_map_start,
665 (int) sizeof (ElfW(Addr)) * 2,
666 ((ElfW(Addr)) *ref) - undef_map->l_map_start,
667 (int) sizeof (ElfW(Addr)) * 2,
668 (ElfW(Addr)) (value->s ? value->m->l_map_start : 0),
669 (int) sizeof (ElfW(Addr)) * 2,
670 (ElfW(Addr)) (value->s ? value->s->st_value : 0));
672 if (conflict)
673 _dl_printf ("x 0x%0*Zx 0x%0*Zx ",
674 (int) sizeof (ElfW(Addr)) * 2,
675 (ElfW(Addr)) (val.s ? val.m->l_map_start : 0),
676 (int) sizeof (ElfW(Addr)) * 2,
677 (ElfW(Addr)) (val.s ? val.s->st_value : 0));
679 _dl_printf ("/%x %s\n", type_class, undef_name);
682 #endif
685 /* These are here so that we only inline do_lookup{,_versioned} in the common
686 case, not everywhere. */
687 static int __attribute_noinline__
688 internal_function
689 _dl_do_lookup (const char *undef_name, unsigned long int hash,
690 const ElfW(Sym) *ref, struct sym_val *result,
691 struct r_scope_elem *scope, size_t i, int flags,
692 struct link_map *skip, int type_class)
694 return do_lookup (undef_name, hash, ref, result, scope, i, flags, skip,
695 type_class);
698 static int __attribute_noinline__
699 internal_function
700 _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
701 const ElfW(Sym) *ref, struct sym_val *result,
702 struct r_scope_elem *scope, size_t i,
703 const struct r_found_version *const version,
704 struct link_map *skip, int type_class)
706 return do_lookup_versioned (undef_name, hash, ref, result, scope, i,
707 version, skip, type_class);