]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-lookup.c
Update.
[thirdparty/glibc.git] / elf / dl-lookup.c
CommitLineData
d66e34cd 1/* Look up a symbol in the loaded objects.
be4b5a95 2 Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc.
afd4eb37 3 This file is part of the GNU C Library.
d66e34cd 4
afd4eb37 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
d66e34cd 9
afd4eb37
UD
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
41bdb6e2 13 Lesser General Public License for more details.
d66e34cd 14
41bdb6e2
AJ
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. */
d66e34cd 19
f671aeab 20#include <alloca.h>
407fe3bb 21#include <libintl.h>
cf197e41 22#include <stdlib.h>
8d6468d0 23#include <string.h>
3db52d94 24#include <unistd.h>
a42195db 25#include <ldsodefs.h>
bc9f6000
UD
26#include "dl-hash.h"
27#include <dl-machine.h>
cf197e41 28#include <bits/libc-lock.h>
c84142e8 29
a853022c
UD
30#include <assert.h>
31
b0982c4a 32#define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
266180eb 33
714a562f
UD
34/* We need this string more than once. */
35static const char undefined_msg[] = "undefined symbol: ";
36
37
84384f5b
UD
38struct sym_val
39 {
84384f5b 40 const ElfW(Sym) *s;
0c367d92 41 struct link_map *m;
84384f5b
UD
42 };
43
44
1fb05e3d
UD
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) \
da832465 57 cp = __stpcpy (cp, all[cnt]); \
1fb05e3d
UD
58 \
59 result; \
60 })
61
8352b484 62/* Statistics function. */
d6b5d570
UD
63#ifdef SHARED
64# define bump_num_relocations() ++GL(dl_num_relocations)
be4b5a95 65#else
d6b5d570 66# define bump_num_relocations() ((void) 0)
be4b5a95
UD
67#endif
68
8352b484 69
1fb05e3d 70
a0e3f6f4
UD
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"
84384f5b 76
a0e3f6f4
UD
77#define VERSIONED 1
78#include "do-lookup.h"
84384f5b 79
84384f5b 80
cf197e41
UD
81/* Add extra dependency on MAP to UNDEF_MAP. */
82static int
80d9c5f0 83internal_function
cf197e41
UD
84add_dependency (struct link_map *undef_map, struct link_map *map)
85{
86 struct link_map **list;
c4bb124a 87 struct link_map *runp;
c0282c06 88 unsigned int act;
cf197e41
UD
89 unsigned int i;
90 int result = 0;
91
c4bb124a
UD
92 /* Avoid self-references. */
93 if (undef_map == map)
94 return 0;
95
cf197e41 96 /* Make sure nobody can unload the object while we are at it. */
5688da55 97 __libc_lock_lock_recursive (GL(dl_load_lock));
cf197e41
UD
98
99 /* Determine whether UNDEF_MAP already has a reference to MAP. First
100 look in the normal dependencies. */
c4bb124a 101 if (undef_map->l_searchlist.r_list != NULL)
cf197e41 102 {
c4bb124a 103 list = undef_map->l_initfini;
cf197e41 104
c4bb124a 105 for (i = 0; list[i] != NULL; ++i)
cf197e41 106 if (list[i] == map)
c4bb124a
UD
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;
cf197e41 114
c4bb124a
UD
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. */
d6b5d570 124 runp = GL(dl_loaded);
c4bb124a
UD
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))
cf197e41 132 {
c4bb124a
UD
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;
cf197e41 145 else
c4bb124a
UD
146 /* Correct the addition. */
147 undef_map->l_reldepsmax -= 5;
cf197e41 148 }
c4bb124a
UD
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
84aafa91
UD
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;
c4bb124a
UD
168
169 /* Display information if we are debugging. */
d6b5d570 170 if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_FILES, 0))
c4bb124a
UD
171 _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]);
cf197e41 176 }
c4bb124a
UD
177 else
178 /* Whoa, that was bad luck. We have to search again. */
179 result = -1;
cf197e41 180
c4bb124a 181 out:
cf197e41 182 /* Release the lock. */
5688da55 183 __libc_lock_unlock_recursive (GL(dl_load_lock));
cf197e41
UD
184
185 return result;
186}
187
80d9c5f0
UD
188static int
189internal_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,
cf5a372e 193 struct link_map *skip, int type_class);
80d9c5f0
UD
194static int
195internal_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,
cf5a372e 200 struct link_map *skip, int type_class);
cf197e41 201
32e6df36
UD
202static void
203internal_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, const struct r_found_version *version,
207 int type_class, int protected);
647eb037 208
6c03c2cf 209/* Search loaded objects' symbol tables for a definition of the symbol
bc9f6000 210 UNDEF_NAME. */
d66e34cd 211
c0282c06 212lookup_t
d0fc4041 213internal_function
06535ae9
UD
214_dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
215 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
cf5a372e 216 int type_class, int explicit)
d66e34cd 217{
32e6df36 218 const unsigned long int hash = _dl_elf_hash (undef_name);
680254fe 219 struct sym_val current_value = { NULL, NULL };
be935610 220 struct r_scope_elem **scope;
6aa29abe 221 int protected;
d66e34cd 222
be4b5a95 223 bump_num_relocations ();
48f6496e 224
d66e34cd 225 /* Search the relevant loaded objects for a definition. */
ba79d61b 226 for (scope = symbol_scope; *scope; ++scope)
2b7238dd 227 if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL,
cf5a372e 228 type_class))
cf197e41
UD
229 {
230 /* We have to check whether this would bind UNDEF_MAP to an object
231 in the global scope which was dynamically loaded. In this case
232 we have to prevent the latter from being unloaded unless the
233 UNDEF_MAP object is also unloaded. */
680254fe 234 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
2b7238dd
UD
235 /* Don't do this for explicit lookups as opposed to implicit
236 runtime lookups. */
680254fe 237 && ! explicit
cf197e41
UD
238 /* Add UNDEF_MAP to the dependencies. */
239 && add_dependency (undef_map, current_value.m) < 0)
240 /* Something went wrong. Perhaps the object we tried to reference
241 was just removed. Try finding another definition. */
242 return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope,
cf5a372e 243 type_class, 0);
cf197e41
UD
244
245 break;
246 }
ba79d61b 247
466a0ec9 248 if (__builtin_expect (current_value.s == NULL, 0))
0c367d92 249 {
c90b5d28
UD
250 const char *reference_name = undef_map ? undef_map->l_name : NULL;
251
0c367d92
UD
252 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
253 /* We could find no value for a strong reference. */
8e17ea58 254 /* XXX We cannot translate the messages. */
32e6df36 255 _dl_signal_cerror (0, (reference_name[0]
3f933dc2
UD
256 ? reference_name
257 : (_dl_argv[0] ?: "<main program>")),
407fe3bb 258 N_("relocation error"),
3f933dc2 259 make_string (undefined_msg, undef_name));
0c367d92
UD
260 *ref = NULL;
261 return 0;
262 }
263
6aa29abe 264 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
32e6df36 265 if (__builtin_expect (protected != 0, 0))
6aa29abe
UD
266 {
267 /* It is very tricky. We need to figure out what value to
268 return for the protected symbol */
269 struct sym_val protected_value = { NULL, NULL };
270
271 for (scope = symbol_scope; *scope; ++scope)
80d9c5f0 272 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
cf5a372e 273 0, NULL, ELF_RTYPE_CLASS_PLT))
6aa29abe
UD
274 break;
275
32e6df36 276 if (protected_value.s != NULL && protected_value.m != undef_map)
6aa29abe 277 {
32e6df36
UD
278 current_value.s = *ref;
279 current_value.m = undef_map;
6aa29abe 280 }
6aa29abe 281 }
32e6df36 282
d6b5d570 283 if (__builtin_expect (GL(dl_debug_mask)
32e6df36
UD
284 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
285 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
286 &current_value, NULL, type_class, protected);
287
288 *ref = current_value.s;
289 return LOOKUP_VALUE (current_value.m);
84384f5b
UD
290}
291
292
293/* This function is nearly the same as `_dl_lookup_symbol' but it
294 skips in the first list all objects until SKIP_MAP is found. I.e.,
295 it only considers objects which were loaded after the described
296 object. If there are more search lists the object described by
297 SKIP_MAP is only skipped. */
c0282c06 298lookup_t
d0fc4041 299internal_function
06535ae9
UD
300_dl_lookup_symbol_skip (const char *undef_name,
301 struct link_map *undef_map, const ElfW(Sym) **ref,
be935610 302 struct r_scope_elem *symbol_scope[],
bc9f6000 303 struct link_map *skip_map)
84384f5b 304{
84384f5b 305 const unsigned long int hash = _dl_elf_hash (undef_name);
0c367d92 306 struct sym_val current_value = { NULL, NULL };
be935610 307 struct r_scope_elem **scope;
84384f5b 308 size_t i;
6aa29abe 309 int protected;
84384f5b 310
be4b5a95 311 bump_num_relocations ();
48f6496e 312
84384f5b
UD
313 /* Search the relevant loaded objects for a definition. */
314 scope = symbol_scope;
80d9c5f0
UD
315 for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
316 assert (i < (*scope)->r_nlist);
84384f5b 317
80d9c5f0 318 if (! _dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, i,
cf5a372e 319 skip_map, 0))
c84142e8 320 while (*++scope)
80d9c5f0 321 if (_dl_do_lookup (undef_name, hash, *ref, &current_value, *scope, 0,
cf5a372e 322 skip_map, 0))
2b7238dd 323 break;
c84142e8 324
466a0ec9 325 if (__builtin_expect (current_value.s == NULL, 0))
0c367d92
UD
326 {
327 *ref = NULL;
328 return 0;
329 }
330
6aa29abe
UD
331 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
332
32e6df36 333 if (__builtin_expect (protected != 0, 0))
6aa29abe 334 {
2b7238dd
UD
335 /* It is very tricky. We need to figure out what value to
336 return for the protected symbol. */
6aa29abe
UD
337 struct sym_val protected_value = { NULL, NULL };
338
339 if (i >= (*scope)->r_nlist
80d9c5f0 340 || !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
cf5a372e 341 i, skip_map, ELF_RTYPE_CLASS_PLT))
6aa29abe 342 while (*++scope)
80d9c5f0 343 if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
cf5a372e 344 0, skip_map, ELF_RTYPE_CLASS_PLT))
6aa29abe
UD
345 break;
346
32e6df36 347 if (protected_value.s != NULL && protected_value.m != undef_map)
6aa29abe 348 {
32e6df36
UD
349 current_value.s = *ref;
350 current_value.m = undef_map;
6aa29abe 351 }
6aa29abe 352 }
32e6df36 353
d6b5d570 354 if (__builtin_expect (GL(dl_debug_mask)
32e6df36
UD
355 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
356 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
357 &current_value, NULL, 0, protected);
358
359 *ref = current_value.s;
360 return LOOKUP_VALUE (current_value.m);
c84142e8
UD
361}
362
363
364/* This function works like _dl_lookup_symbol but it takes an
365 additional arguement with the version number of the requested
366 symbol.
367
368 XXX We'll see whether we need this separate function. */
c0282c06 369lookup_t
d0fc4041 370internal_function
06535ae9
UD
371_dl_lookup_versioned_symbol (const char *undef_name,
372 struct link_map *undef_map, const ElfW(Sym) **ref,
be935610 373 struct r_scope_elem *symbol_scope[],
bc9f6000 374 const struct r_found_version *version,
cf5a372e 375 int type_class, int explicit)
c84142e8 376{
32e6df36 377 const unsigned long int hash = _dl_elf_hash (undef_name);
680254fe 378 struct sym_val current_value = { NULL, NULL };
be935610 379 struct r_scope_elem **scope;
6aa29abe 380 int protected;
c84142e8 381
be4b5a95 382 bump_num_relocations ();
48f6496e 383
c84142e8
UD
384 /* Search the relevant loaded objects for a definition. */
385 for (scope = symbol_scope; *scope; ++scope)
1fb05e3d 386 {
2b7238dd 387 int res = do_lookup_versioned (undef_name, hash, *ref, &current_value,
cf5a372e 388 *scope, 0, version, NULL, type_class);
1fb05e3d 389 if (res > 0)
cf197e41
UD
390 {
391 /* We have to check whether this would bind UNDEF_MAP to an object
392 in the global scope which was dynamically loaded. In this case
393 we have to prevent the latter from being unloaded unless the
394 UNDEF_MAP object is also unloaded. */
680254fe 395 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
2b7238dd
UD
396 /* Don't do this for explicit lookups as opposed to implicit
397 runtime lookups. */
680254fe 398 && ! explicit
cf197e41
UD
399 /* Add UNDEF_MAP to the dependencies. */
400 && add_dependency (undef_map, current_value.m) < 0)
401 /* Something went wrong. Perhaps the object we tried to reference
402 was just removed. Try finding another definition. */
403 return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
404 symbol_scope, version,
cf5a372e 405 type_class, 0);
cf197e41
UD
406
407 break;
408 }
1fb05e3d 409
466a0ec9 410 if (__builtin_expect (res, 0) < 0)
3f933dc2
UD
411 {
412 /* Oh, oh. The file named in the relocation entry does not
413 contain the needed symbol. */
c90b5d28
UD
414 const char *reference_name = undef_map ? undef_map->l_name : NULL;
415
8e17ea58 416 /* XXX We cannot translate the message. */
32e6df36 417 _dl_signal_cerror (0, (reference_name[0]
3f933dc2
UD
418 ? reference_name
419 : (_dl_argv[0] ?: "<main program>")),
407fe3bb 420 N_("relocation error"),
3f933dc2
UD
421 make_string ("symbol ", undef_name, ", version ",
422 version->name,
423 " not defined in file ",
424 version->filename,
425 " with link time reference",
426 res == -2
427 ? " (no version symbols)" : ""));
428 *ref = NULL;
429 return 0;
430 }
1fb05e3d 431 }
c84142e8 432
466a0ec9 433 if (__builtin_expect (current_value.s == NULL, 0))
0c367d92
UD
434 {
435 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
c90b5d28
UD
436 {
437 /* We could find no value for a strong reference. */
438 const char *reference_name = undef_map ? undef_map->l_name : NULL;
439
440 /* XXX We cannot translate the message. */
32e6df36 441 _dl_signal_cerror (0, (reference_name[0]
c90b5d28 442 ? reference_name
407fe3bb 443 : (_dl_argv[0] ?: "<main program>")), NULL,
c90b5d28
UD
444 make_string (undefined_msg, undef_name,
445 ", version ",
446 version->name ?: NULL));
447 }
0c367d92
UD
448 *ref = NULL;
449 return 0;
450 }
451
6aa29abe
UD
452 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
453
32e6df36 454 if (__builtin_expect (protected != 0, 0))
6aa29abe
UD
455 {
456 /* It is very tricky. We need to figure out what value to
457 return for the protected symbol */
458 struct sym_val protected_value = { NULL, NULL };
459
460 for (scope = symbol_scope; *scope; ++scope)
80d9c5f0 461 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value,
cf5a372e
UD
462 *scope, 0, version, NULL,
463 ELF_RTYPE_CLASS_PLT))
6aa29abe
UD
464 break;
465
32e6df36 466 if (protected_value.s != NULL && protected_value.m != undef_map)
6aa29abe 467 {
32e6df36
UD
468 current_value.s = *ref;
469 current_value.m = undef_map;
6aa29abe 470 }
6aa29abe 471 }
32e6df36 472
d6b5d570 473 if (__builtin_expect (GL(dl_debug_mask)
32e6df36
UD
474 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
475 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
476 &current_value, version, type_class, protected);
477
478 *ref = current_value.s;
479 return LOOKUP_VALUE (current_value.m);
c84142e8
UD
480}
481
482
483/* Similar to _dl_lookup_symbol_skip but takes an additional argument
484 with the version we are looking for. */
c0282c06 485lookup_t
d0fc4041 486internal_function
c84142e8 487_dl_lookup_versioned_symbol_skip (const char *undef_name,
06535ae9 488 struct link_map *undef_map,
c84142e8 489 const ElfW(Sym) **ref,
be935610 490 struct r_scope_elem *symbol_scope[],
1fb05e3d 491 const struct r_found_version *version,
bc9f6000 492 struct link_map *skip_map)
c84142e8 493{
32e6df36 494 const char *reference_name = undef_map->l_name;
c84142e8 495 const unsigned long int hash = _dl_elf_hash (undef_name);
0c367d92 496 struct sym_val current_value = { NULL, NULL };
be935610 497 struct r_scope_elem **scope;
c84142e8 498 size_t i;
6aa29abe 499 int protected;
c84142e8 500
be4b5a95 501 bump_num_relocations ();
48f6496e 502
c84142e8
UD
503 /* Search the relevant loaded objects for a definition. */
504 scope = symbol_scope;
80d9c5f0
UD
505 for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
506 assert (i < (*scope)->r_nlist);
c84142e8 507
80d9c5f0 508 if (! _dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
cf5a372e 509 *scope, i, version, skip_map, 0))
84384f5b 510 while (*++scope)
80d9c5f0 511 if (_dl_do_lookup_versioned (undef_name, hash, *ref, &current_value,
cf5a372e 512 *scope, 0, version, skip_map, 0))
2b7238dd 513 break;
84384f5b 514
466a0ec9 515 if (__builtin_expect (current_value.s == NULL, 0))
1f205a47 516 {
0c367d92
UD
517 if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
518 {
519 /* We could find no value for a strong reference. */
520 const size_t len = strlen (undef_name);
521 char buf[sizeof undefined_msg + len];
522 __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
523 undef_name, len + 1);
8e17ea58 524 /* XXX We cannot translate the messages. */
32e6df36 525 _dl_signal_cerror (0, (reference_name[0]
3f933dc2 526 ? reference_name
407fe3bb
UD
527 : (_dl_argv[0] ?: "<main program>")),
528 NULL, buf);
0c367d92
UD
529 }
530 *ref = NULL;
531 return 0;
1f205a47
UD
532 }
533
6aa29abe
UD
534 protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
535
32e6df36 536 if (__builtin_expect (protected != 0, 0))
6aa29abe
UD
537 {
538 /* It is very tricky. We need to figure out what value to
539 return for the protected symbol */
540 struct sym_val protected_value = { NULL, NULL };
541
542 if (i >= (*scope)->r_nlist
80d9c5f0
UD
543 || !_dl_do_lookup_versioned (undef_name, hash, *ref,
544 &protected_value, *scope, i, version,
cf5a372e 545 skip_map, ELF_RTYPE_CLASS_PLT))
6aa29abe 546 while (*++scope)
80d9c5f0
UD
547 if (_dl_do_lookup_versioned (undef_name, hash, *ref,
548 &protected_value, *scope, 0, version,
cf5a372e 549 skip_map, ELF_RTYPE_CLASS_PLT))
6aa29abe
UD
550 break;
551
32e6df36 552 if (protected_value.s != NULL && protected_value.m != undef_map)
6aa29abe 553 {
32e6df36
UD
554 current_value.s = *ref;
555 current_value.m = undef_map;
6aa29abe 556 }
6aa29abe 557 }
32e6df36 558
d6b5d570 559 if (__builtin_expect (GL(dl_debug_mask)
32e6df36
UD
560 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
561 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
562 &current_value, version, 0, protected);
563
564 *ref = current_value.s;
565 return LOOKUP_VALUE (current_value.m);
d66e34cd
RM
566}
567
568
569/* Cache the location of MAP's hash table. */
570
571void
d0fc4041 572internal_function
d66e34cd
RM
573_dl_setup_hash (struct link_map *map)
574{
a1eca9f3
UD
575 Elf_Symndx *hash;
576 Elf_Symndx nchain;
f41c8091
UD
577
578 if (!map->l_info[DT_HASH])
579 return;
580 hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr);
581
d66e34cd
RM
582 map->l_nbuckets = *hash++;
583 nchain = *hash++;
584 map->l_buckets = hash;
585 hash += map->l_nbuckets;
586 map->l_chain = hash;
587}
80d9c5f0 588
32e6df36
UD
589static void
590internal_function
591_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
592 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
593 struct sym_val *value, const struct r_found_version *version,
594 int type_class, int protected)
595{
596 const char *reference_name = undef_map->l_name;
597
d6b5d570 598 if (GL(dl_debug_mask) & DL_DEBUG_BINDINGS)
32e6df36
UD
599 {
600 _dl_debug_printf ("binding file %s to %s: %s symbol `%s'",
601 (reference_name[0]
602 ? reference_name : (_dl_argv[0] ?: "<main program>")),
603 value->m->l_name[0] ? value->m->l_name : _dl_argv[0],
604 protected ? "protected" : "normal",
605 undef_name);
606 if (version)
607 _dl_debug_printf_c (" [%s]\n", version->name);
608 else
609 _dl_debug_printf_c ("\n");
610 }
611#ifdef SHARED
d6b5d570 612 if (GL(dl_debug_mask) & DL_DEBUG_PRELINK)
32e6df36
UD
613 {
614 int conflict = 0;
615 struct sym_val val = { NULL, NULL };
616
d6b5d570
UD
617 if ((GL(dl_trace_prelink_map) == NULL
618 || GL(dl_trace_prelink_map) == GL(dl_loaded))
619 && undef_map != GL(dl_loaded))
32e6df36
UD
620 {
621 const unsigned long int hash = _dl_elf_hash (undef_name);
622
623 if (version == 0)
624 _dl_do_lookup (undef_name, hash, *ref, &val,
625 undef_map->l_local_scope[0], 0, NULL, type_class);
626 else
627 _dl_do_lookup_versioned (undef_name, hash, *ref, &val,
628 undef_map->l_local_scope[0], 0, version,
629 NULL, type_class);
630
631 if (val.s != value->s || val.m != value->m)
632 conflict = 1;
633 }
634
635 if (conflict
d6b5d570
UD
636 || GL(dl_trace_prelink_map) == undef_map
637 || GL(dl_trace_prelink_map) == NULL)
32e6df36
UD
638 {
639 _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
640 conflict ? "conflict" : "lookup",
641 (int) sizeof (ElfW(Addr)) * 2, undef_map->l_map_start,
642 (int) sizeof (ElfW(Addr)) * 2,
643 ((ElfW(Addr)) *ref) - undef_map->l_map_start,
644 (int) sizeof (ElfW(Addr)) * 2,
645 (ElfW(Addr)) (value->s ? value->m->l_map_start : 0),
646 (int) sizeof (ElfW(Addr)) * 2,
647 (ElfW(Addr)) (value->s ? value->s->st_value : 0));
648
649 if (conflict)
650 _dl_printf ("x 0x%0*Zx 0x%0*Zx ",
651 (int) sizeof (ElfW(Addr)) * 2,
652 (ElfW(Addr)) (val.s ? val.m->l_map_start : 0),
653 (int) sizeof (ElfW(Addr)) * 2,
654 (ElfW(Addr)) (val.s ? val.s->st_value : 0));
655
656 _dl_printf ("/%x %s\n", type_class, undef_name);
657 }
658 }
659#endif
660}
661
80d9c5f0
UD
662/* These are here so that we only inline do_lookup{,_versioned} in the common
663 case, not everywhere. */
fb23eb25 664static int __attribute_noinline__
80d9c5f0
UD
665internal_function
666_dl_do_lookup (const char *undef_name, unsigned long int hash,
667 const ElfW(Sym) *ref, struct sym_val *result,
668 struct r_scope_elem *scope, size_t i,
cf5a372e 669 struct link_map *skip, int type_class)
80d9c5f0 670{
cf5a372e
UD
671 return do_lookup (undef_name, hash, ref, result, scope, i, skip,
672 type_class);
80d9c5f0
UD
673}
674
fb23eb25 675static int __attribute_noinline__
80d9c5f0
UD
676internal_function
677_dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
678 const ElfW(Sym) *ref, struct sym_val *result,
679 struct r_scope_elem *scope, size_t i,
680 const struct r_found_version *const version,
cf5a372e 681 struct link_map *skip, int type_class)
80d9c5f0
UD
682{
683 return do_lookup_versioned (undef_name, hash, ref, result, scope, i,
cf5a372e 684 version, skip, type_class);
80d9c5f0 685}