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