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