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