1/* Look up a symbol in the loaded objects.
2 Copyright (C) 1995-2024 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, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <libintl.h>
20#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
23#include <ldsodefs.h>
24#include <dl-hash.h>
25#include <dl-machine.h>
26#include <dl-new-hash.h>
27#include <dl-protected.h>
28#include <sysdep-cancel.h>
29#include <libc-lock.h>
30#include <tls.h>
31#include <atomic.h>
32#include <elf_machine_sym_no_match.h>
33
34#include <assert.h>
35
36#define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
37
38struct sym_val
39 {
40 const ElfW(Sym) *s;
41 struct link_map *m;
42 };
43
44
45/* Statistics function. */
46#ifdef SHARED
47# define bump_num_relocations() ++GL(dl_num_relocations)
48#else
49# define bump_num_relocations() ((void) 0)
50#endif
51
52/* Utility function for do_lookup_x. The caller is called with undef_name,
53 ref, version, flags and type_class, and those are passed as the first
54 five arguments. The caller then computes sym, symidx, strtab, and map
55 and passes them as the next four arguments. Lastly the caller passes in
56 versioned_sym and num_versions which are modified by check_match during
57 the checking process. */
58static const ElfW(Sym) *
59check_match (const char *const undef_name,
60 const ElfW(Sym) *const ref,
61 const struct r_found_version *const version,
62 const int flags,
63 const int type_class,
64 const ElfW(Sym) *const sym,
65 const Elf_Symndx symidx,
66 const char *const strtab,
67 const struct link_map *const map,
68 const ElfW(Sym) **const versioned_sym,
69 int *const num_versions)
70{
71 unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
72 assert (ELF_RTYPE_CLASS_PLT == 1);
73 if (__glibc_unlikely ((sym->st_value == 0 /* No value. */
74 && sym->st_shndx != SHN_ABS
75 && stt != STT_TLS)
76 || elf_machine_sym_no_match (sym)
77 || (type_class & (sym->st_shndx == SHN_UNDEF))))
78 return NULL;
79
80 /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
81 STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
82 code/data definitions. */
83#define ALLOWED_STT \
84 ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
85 | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
86 if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0))
87 return NULL;
88
89 if (sym != ref && strcmp (strtab + sym->st_name, undef_name))
90 /* Not the symbol we are looking for. */
91 return NULL;
92
93 const ElfW(Half) *verstab = map->l_versyms;
94 if (version != NULL)
95 {
96 if (__glibc_unlikely (verstab == NULL))
97 {
98 /* We need a versioned symbol but haven't found any. If
99 this is the object which is referenced in the verneed
100 entry it is a bug in the library since a symbol must
101 not simply disappear.
102
103 It would also be a bug in the object since it means that
104 the list of required versions is incomplete and so the
105 tests in dl-version.c haven't found a problem.*/
106 assert (version->filename == NULL
107 || ! _dl_name_match_p (version->filename, map));
108
109 /* Otherwise we accept the symbol. */
110 }
111 else
112 {
113 /* We can match the version information or use the
114 default one if it is not hidden. */
115 ElfW(Half) ndx = verstab[symidx] & 0x7fff;
116 if (map->l_versions[ndx].hash == version->hash
117 && strcmp (map->l_versions[ndx].name, version->name) == 0)
118 /* This is an exact version match. Return the symbol below. */
119 ;
120 else
121 {
122 if (!version->hidden
123 && map->l_versions[ndx].name[0] == '\0'
124 && (verstab[symidx] & 0x8000) == 0
125 && (*num_versions)++ == 0)
126 /* This is the global default version. Store it as a
127 fallback match. */
128 *versioned_sym = sym;
129
130 return NULL;
131 }
132 }
133 }
134 else
135 {
136 /* No specific version is selected. There are two ways we
137 can got here:
138
139 - a binary which does not include versioning information
140 is loaded
141
142 - dlsym() instead of dlvsym() is used to get a symbol which
143 might exist in more than one form
144
145 If the library does not provide symbol version information
146 there is no problem at all: we simply use the symbol if it
147 is defined.
148
149 These two lookups need to be handled differently if the
150 library defines versions. In the case of the old
151 unversioned application the oldest (default) version
152 should be used. In case of a dlsym() call the latest and
153 public interface should be returned. */
154 if (verstab != NULL)
155 {
156 if ((verstab[symidx] & 0x7fff)
157 >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3))
158 {
159 /* Don't accept hidden symbols. */
160 if ((verstab[symidx] & 0x8000) == 0
161 && (*num_versions)++ == 0)
162 /* No version so far. */
163 *versioned_sym = sym;
164
165 return NULL;
166 }
167 }
168 }
169
170 /* There cannot be another entry for this symbol so stop here. */
171 return sym;
172}
173
174/* Utility function for do_lookup_unique. Add a symbol to TABLE. */
175static void
176enter_unique_sym (struct unique_sym *table, size_t size,
177 unsigned int hash, const char *name,
178 const ElfW(Sym) *sym, const struct link_map *map)
179{
180 size_t idx = hash % size;
181 size_t hash2 = 1 + hash % (size - 2);
182 while (table[idx].name != NULL)
183 {
184 idx += hash2;
185 if (idx >= size)
186 idx -= size;
187 }
188
189 table[idx].hashval = hash;
190 table[idx].name = name;
191 table[idx].sym = sym;
192 table[idx].map = map;
193}
194
195/* Mark MAP as NODELETE according to the lookup mode in FLAGS. During
196 initial relocation, NODELETE state is pending only. */
197static void
198mark_nodelete (struct link_map *map, int flags)
199{
200 if (flags & DL_LOOKUP_FOR_RELOCATE)
201 map->l_nodelete_pending = true;
202 else
203 map->l_nodelete_active = true;
204}
205
206/* Return true if MAP is marked as NODELETE according to the lookup
207 mode in FLAGS> */
208static bool
209is_nodelete (struct link_map *map, int flags)
210{
211 /* Non-pending NODELETE always counts. Pending NODELETE only counts
212 during initial relocation processing. */
213 return map->l_nodelete_active
214 || ((flags & DL_LOOKUP_FOR_RELOCATE) && map->l_nodelete_pending);
215}
216
217/* Utility function for do_lookup_x. Lookup an STB_GNU_UNIQUE symbol
218 in the unique symbol table, creating a new entry if necessary.
219 Return the matching symbol in RESULT. */
220static void
221do_lookup_unique (const char *undef_name, unsigned int new_hash,
222 struct link_map *map, struct sym_val *result,
223 int type_class, const ElfW(Sym) *sym, const char *strtab,
224 const ElfW(Sym) *ref, const struct link_map *undef_map,
225 int flags)
226{
227 /* We have to determine whether we already found a symbol with this
228 name before. If not then we have to add it to the search table.
229 If we already found a definition we have to use it. */
230
231 struct unique_sym_table *tab
232 = &GL(dl_ns)[map->l_ns]._ns_unique_sym_table;
233
234 __rtld_lock_lock_recursive (tab->lock);
235
236 struct unique_sym *entries = tab->entries;
237 size_t size = tab->size;
238 if (entries != NULL)
239 {
240 size_t idx = new_hash % size;
241 size_t hash2 = 1 + new_hash % (size - 2);
242 while (1)
243 {
244 if (entries[idx].hashval == new_hash
245 && strcmp (entries[idx].name, undef_name) == 0)
246 {
247 if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
248 {
249 /* We possibly have to initialize the central
250 copy from the copy addressed through the
251 relocation. */
252 result->s = sym;
253 result->m = map;
254 }
255 else
256 {
257 result->s = entries[idx].sym;
258 result->m = (struct link_map *) entries[idx].map;
259 }
260 __rtld_lock_unlock_recursive (tab->lock);
261 return;
262 }
263
264 if (entries[idx].name == NULL)
265 break;
266
267 idx += hash2;
268 if (idx >= size)
269 idx -= size;
270 }
271
272 if (size * 3 <= tab->n_elements * 4)
273 {
274 /* Expand the table. */
275#ifdef RTLD_CHECK_FOREIGN_CALL
276 /* This must not happen during runtime relocations. */
277 assert (!RTLD_CHECK_FOREIGN_CALL);
278#endif
279 size_t newsize = _dl_higher_prime_number (n: size + 1);
280 struct unique_sym *newentries
281 = calloc (nmemb: sizeof (struct unique_sym), size: newsize);
282 if (newentries == NULL)
283 {
284 nomem:
285 __rtld_lock_unlock_recursive (tab->lock);
286 _dl_fatal_printf (fmt: "out of memory\n");
287 }
288
289 for (idx = 0; idx < size; ++idx)
290 if (entries[idx].name != NULL)
291 enter_unique_sym (table: newentries, size: newsize, hash: entries[idx].hashval,
292 name: entries[idx].name, sym: entries[idx].sym,
293 map: entries[idx].map);
294
295 tab->free (entries);
296 tab->size = newsize;
297 size = newsize;
298 entries = tab->entries = newentries;
299 tab->free = __rtld_free;
300 }
301 }
302 else
303 {
304#ifdef RTLD_CHECK_FOREIGN_CALL
305 /* This must not happen during runtime relocations. */
306 assert (!RTLD_CHECK_FOREIGN_CALL);
307#endif
308
309#define INITIAL_NUNIQUE_SYM_TABLE 31
310 size = INITIAL_NUNIQUE_SYM_TABLE;
311 entries = calloc (nmemb: sizeof (struct unique_sym), size: size);
312 if (entries == NULL)
313 goto nomem;
314
315 tab->entries = entries;
316 tab->size = size;
317 tab->free = __rtld_free;
318 }
319
320 if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
321 enter_unique_sym (table: entries, size, hash: new_hash, name: strtab + sym->st_name, sym: ref,
322 map: undef_map);
323 else
324 {
325 enter_unique_sym (table: entries, size,
326 hash: new_hash, name: strtab + sym->st_name, sym, map);
327
328 if (map->l_type == lt_loaded && !is_nodelete (map, flags))
329 {
330 /* Make sure we don't unload this object by
331 setting the appropriate flag. */
332 if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS))
333 _dl_debug_printf (fmt: "\
334marking %s [%lu] as NODELETE due to unique symbol\n",
335 map->l_name, map->l_ns);
336 mark_nodelete (map, flags);
337 }
338 }
339 ++tab->n_elements;
340
341 __rtld_lock_unlock_recursive (tab->lock);
342
343 result->s = sym;
344 result->m = (struct link_map *) map;
345}
346
347/* Inner part of the lookup functions. We return a value > 0 if we
348 found the symbol, the value 0 if nothing is found and < 0 if
349 something bad happened. */
350static int
351__attribute_noinline__
352do_lookup_x (const char *undef_name, unsigned int new_hash,
353 unsigned long int *old_hash, const ElfW(Sym) *ref,
354 struct sym_val *result, struct r_scope_elem *scope, size_t i,
355 const struct r_found_version *const version, int flags,
356 struct link_map *skip, int type_class, struct link_map *undef_map)
357{
358 size_t n = scope->r_nlist;
359 /* Make sure we read the value before proceeding. Otherwise we
360 might use r_list pointing to the initial scope and r_nlist being
361 the value after a resize. That is the only path in dl-open.c not
362 protected by GSCOPE. A read barrier here might be to expensive. */
363 __asm volatile ("" : "+r" (n), "+m" (scope->r_list));
364 struct link_map **list = scope->r_list;
365
366 do
367 {
368 const struct link_map *map = list[i]->l_real;
369
370 /* Here come the extra test needed for `_dl_lookup_symbol_skip'. */
371 if (map == skip)
372 continue;
373
374 /* Don't search the executable when resolving a copy reloc. */
375 if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
376 continue;
377
378 /* Do not look into objects which are going to be removed,
379 except when the referencing object itself is being removed.
380
381 The second part covers the situation when an object lazily
382 binds to another object while running its destructor, but the
383 destructor of the other object has already run, so that
384 dlclose has set l_removed. It may not always be obvious how
385 to avoid such a scenario to programmers creating DSOs,
386 particularly if C++ vague linkage is involved and triggers
387 symbol interposition.
388
389 Accepting these to-be-removed objects makes the lazy and
390 BIND_NOW cases more similar. (With BIND_NOW, the symbol is
391 resolved early, before the destructor call, so the issue does
392 not arise.). Behavior matches the constructor scenario: the
393 implementation allows binding to symbols of objects whose
394 constructors have not run. In fact, not doing this would be
395 mostly incompatible with symbol interposition. */
396 if (map->l_removed && !(undef_map != NULL && undef_map->l_removed))
397 continue;
398
399 /* Print some debugging info if wanted. */
400 if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS))
401 _dl_debug_printf (fmt: "symbol=%s; lookup in file=%s [%lu]\n",
402 undef_name, DSO_FILENAME (map->l_name),
403 map->l_ns);
404
405 /* If the hash table is empty there is nothing to do here. */
406 if (map->l_nbuckets == 0)
407 continue;
408
409 Elf_Symndx symidx;
410 int num_versions = 0;
411 const ElfW(Sym) *versioned_sym = NULL;
412
413 /* The tables for this map. */
414 const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
415 const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
416
417 const ElfW(Sym) *sym;
418 const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
419 if (__glibc_likely (bitmask != NULL))
420 {
421 ElfW(Addr) bitmask_word
422 = bitmask[(new_hash / __ELF_NATIVE_CLASS)
423 & map->l_gnu_bitmask_idxbits];
424
425 unsigned int hashbit1 = new_hash & (__ELF_NATIVE_CLASS - 1);
426 unsigned int hashbit2 = ((new_hash >> map->l_gnu_shift)
427 & (__ELF_NATIVE_CLASS - 1));
428
429 if (__glibc_unlikely ((bitmask_word >> hashbit1)
430 & (bitmask_word >> hashbit2) & 1))
431 {
432 Elf32_Word bucket = map->l_gnu_buckets[new_hash
433 % map->l_nbuckets];
434 if (bucket != 0)
435 {
436 const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket];
437
438 do
439 if (((*hasharr ^ new_hash) >> 1) == 0)
440 {
441 symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr);
442 sym = check_match (undef_name, ref, version, flags,
443 type_class, sym: &symtab[symidx], symidx,
444 strtab, map, versioned_sym: &versioned_sym,
445 num_versions: &num_versions);
446 if (sym != NULL)
447 goto found_it;
448 }
449 while ((*hasharr++ & 1u) == 0);
450 }
451 }
452 /* No symbol found. */
453 symidx = SHN_UNDEF;
454 }
455 else
456 {
457 if (*old_hash == 0xffffffff)
458 *old_hash = _dl_elf_hash (name_arg: undef_name);
459
460 /* Use the old SysV-style hash table. Search the appropriate
461 hash bucket in this object's symbol table for a definition
462 for the same symbol name. */
463 for (symidx = map->l_buckets[*old_hash % map->l_nbuckets];
464 symidx != STN_UNDEF;
465 symidx = map->l_chain[symidx])
466 {
467 sym = check_match (undef_name, ref, version, flags,
468 type_class, sym: &symtab[symidx], symidx,
469 strtab, map, versioned_sym: &versioned_sym,
470 num_versions: &num_versions);
471 if (sym != NULL)
472 goto found_it;
473 }
474 }
475
476 /* If we have seen exactly one versioned symbol while we are
477 looking for an unversioned symbol and the version is not the
478 default version we still accept this symbol since there are
479 no possible ambiguities. */
480 sym = num_versions == 1 ? versioned_sym : NULL;
481
482 if (sym != NULL)
483 {
484 found_it:
485 /* Hidden and internal symbols are local, ignore them. */
486 if (__glibc_unlikely (dl_symbol_visibility_binds_local_p (sym)))
487 goto skip;
488
489 if (ELFW(ST_VISIBILITY) (sym->st_other) == STV_PROTECTED)
490 _dl_check_protected_symbol (undef_name, undef_map, ref, map,
491 type_class);
492
493 switch (ELFW(ST_BIND) (sym->st_info))
494 {
495 case STB_WEAK:
496 /* Weak definition. Use this value if we don't find another. */
497 if (__glibc_unlikely (GLRO(dl_dynamic_weak)))
498 {
499 if (! result->s)
500 {
501 result->s = sym;
502 result->m = (struct link_map *) map;
503 }
504 break;
505 }
506 /* FALLTHROUGH */
507 case STB_GLOBAL:
508 /* Global definition. Just what we need. */
509 result->s = sym;
510 result->m = (struct link_map *) map;
511 return 1;
512
513 case STB_GNU_UNIQUE:;
514 do_lookup_unique (undef_name, new_hash, map: (struct link_map *) map,
515 result, type_class, sym, strtab, ref,
516 undef_map, flags);
517 return 1;
518
519 default:
520 /* Local symbols are ignored. */
521 break;
522 }
523 }
524
525skip:
526 ;
527 }
528 while (++i < n);
529
530 /* We have not found anything until now. */
531 return 0;
532}
533
534
535/* Add extra dependency on MAP to UNDEF_MAP. */
536static int
537add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
538{
539 struct link_map *runp;
540 unsigned int i;
541 int result = 0;
542
543 /* Avoid self-references and references to objects which cannot be
544 unloaded anyway. */
545 if (undef_map == map)
546 return 0;
547
548 /* Avoid references to objects which cannot be unloaded anyway. We
549 do not need to record dependencies if this object goes away
550 during dlopen failure, either. IFUNC resolvers with relocation
551 dependencies may pick an dependency which can be dlclose'd, but
552 such IFUNC resolvers are undefined anyway. */
553 assert (map->l_type == lt_loaded);
554 if (is_nodelete (map, flags))
555 return 0;
556
557 struct link_map_reldeps *l_reldeps
558 = atomic_forced_read (undef_map->l_reldeps);
559
560 /* Make sure l_reldeps is read before l_initfini. */
561 atomic_read_barrier ();
562
563 /* Determine whether UNDEF_MAP already has a reference to MAP. First
564 look in the normal dependencies. */
565 struct link_map **l_initfini = atomic_forced_read (undef_map->l_initfini);
566 if (l_initfini != NULL)
567 {
568 for (i = 0; l_initfini[i] != NULL; ++i)
569 if (l_initfini[i] == map)
570 return 0;
571 }
572
573 /* No normal dependency. See whether we already had to add it
574 to the special list of dynamic dependencies. */
575 unsigned int l_reldepsact = 0;
576 if (l_reldeps != NULL)
577 {
578 struct link_map **list = &l_reldeps->list[0];
579 l_reldepsact = l_reldeps->act;
580 for (i = 0; i < l_reldepsact; ++i)
581 if (list[i] == map)
582 return 0;
583 }
584
585 /* Save serial number of the target MAP. */
586 unsigned long long serial = map->l_serial;
587
588 /* Make sure nobody can unload the object while we are at it. */
589 if (__glibc_unlikely (flags & DL_LOOKUP_GSCOPE_LOCK))
590 {
591 /* We can't just call __rtld_lock_lock_recursive (GL(dl_load_lock))
592 here, that can result in ABBA deadlock. */
593 THREAD_GSCOPE_RESET_FLAG ();
594 __rtld_lock_lock_recursive (GL(dl_load_lock));
595 /* While MAP value won't change, after THREAD_GSCOPE_RESET_FLAG ()
596 it can e.g. point to unallocated memory. So avoid the optimizer
597 treating the above read from MAP->l_serial as ensurance it
598 can safely dereference it. */
599 map = atomic_forced_read (map);
600
601 /* From this point on it is unsafe to dereference MAP, until it
602 has been found in one of the lists. */
603
604 /* Redo the l_initfini check in case undef_map's l_initfini
605 changed in the mean time. */
606 if (undef_map->l_initfini != l_initfini
607 && undef_map->l_initfini != NULL)
608 {
609 l_initfini = undef_map->l_initfini;
610 for (i = 0; l_initfini[i] != NULL; ++i)
611 if (l_initfini[i] == map)
612 goto out_check;
613 }
614
615 /* Redo the l_reldeps check if undef_map's l_reldeps changed in
616 the mean time. */
617 if (undef_map->l_reldeps != NULL)
618 {
619 if (undef_map->l_reldeps != l_reldeps)
620 {
621 struct link_map **list = &undef_map->l_reldeps->list[0];
622 l_reldepsact = undef_map->l_reldeps->act;
623 for (i = 0; i < l_reldepsact; ++i)
624 if (list[i] == map)
625 goto out_check;
626 }
627 else if (undef_map->l_reldeps->act > l_reldepsact)
628 {
629 struct link_map **list
630 = &undef_map->l_reldeps->list[0];
631 i = l_reldepsact;
632 l_reldepsact = undef_map->l_reldeps->act;
633 for (; i < l_reldepsact; ++i)
634 if (list[i] == map)
635 goto out_check;
636 }
637 }
638 }
639 else
640 __rtld_lock_lock_recursive (GL(dl_load_lock));
641
642 /* The object is not yet in the dependency list. Before we add
643 it make sure just one more time the object we are about to
644 reference is still available. There is a brief period in
645 which the object could have been removed since we found the
646 definition. */
647 runp = GL(dl_ns)[undef_map->l_ns]._ns_loaded;
648 while (runp != NULL && runp != map)
649 runp = runp->l_next;
650
651 if (runp != NULL)
652 {
653 /* The object is still available. */
654
655 /* MAP could have been dlclosed, freed and then some other dlopened
656 library could have the same link_map pointer. */
657 if (map->l_serial != serial)
658 goto out_check;
659
660 /* Redo the NODELETE check, as when dl_load_lock wasn't held
661 yet this could have changed. */
662 if (is_nodelete (map, flags))
663 goto out;
664
665 /* If the object with the undefined reference cannot be removed ever
666 just make sure the same is true for the object which contains the
667 definition. */
668 if (undef_map->l_type != lt_loaded || is_nodelete (map, flags))
669 {
670 if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
671 && !is_nodelete (map, flags))
672 {
673 if (undef_map->l_name[0] == '\0')
674 _dl_debug_printf (fmt: "\
675marking %s [%lu] as NODELETE due to reference from main program\n",
676 map->l_name, map->l_ns);
677 else
678 _dl_debug_printf (fmt: "\
679marking %s [%lu] as NODELETE due to reference from %s [%lu]\n",
680 map->l_name, map->l_ns,
681 undef_map->l_name, undef_map->l_ns);
682 }
683 mark_nodelete (map, flags);
684 goto out;
685 }
686
687 /* Add the reference now. */
688 if (__glibc_unlikely (l_reldepsact >= undef_map->l_reldepsmax))
689 {
690 /* Allocate more memory for the dependency list. Since this
691 can never happen during the startup phase we can use
692 `realloc'. */
693 struct link_map_reldeps *newp;
694 unsigned int max
695 = undef_map->l_reldepsmax ? undef_map->l_reldepsmax * 2 : 10;
696
697#ifdef RTLD_PREPARE_FOREIGN_CALL
698 RTLD_PREPARE_FOREIGN_CALL;
699#endif
700
701 newp = malloc (size: sizeof (*newp) + max * sizeof (struct link_map *));
702 if (newp == NULL)
703 {
704 /* If we didn't manage to allocate memory for the list this is
705 no fatal problem. We simply make sure the referenced object
706 cannot be unloaded. This is semantically the correct
707 behavior. */
708 if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
709 && !is_nodelete (map, flags))
710 _dl_debug_printf (fmt: "\
711marking %s [%lu] as NODELETE due to memory allocation failure\n",
712 map->l_name, map->l_ns);
713 /* In case of non-lazy binding, we could actually report
714 the memory allocation error, but for now, we use the
715 conservative approximation as well. */
716 mark_nodelete (map, flags);
717 goto out;
718 }
719 else
720 {
721 if (l_reldepsact)
722 memcpy (&newp->list[0], &undef_map->l_reldeps->list[0],
723 l_reldepsact * sizeof (struct link_map *));
724 newp->list[l_reldepsact] = map;
725 newp->act = l_reldepsact + 1;
726 atomic_write_barrier ();
727 void *old = undef_map->l_reldeps;
728 undef_map->l_reldeps = newp;
729 undef_map->l_reldepsmax = max;
730 if (old)
731 _dl_scope_free (old);
732 }
733 }
734 else
735 {
736 undef_map->l_reldeps->list[l_reldepsact] = map;
737 atomic_write_barrier ();
738 undef_map->l_reldeps->act = l_reldepsact + 1;
739 }
740
741 /* Display information if we are debugging. */
742 if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
743 _dl_debug_printf (fmt: "\
744\nfile=%s [%lu]; needed by %s [%lu] (relocation dependency)\n\n",
745 DSO_FILENAME (map->l_name),
746 map->l_ns,
747 DSO_FILENAME (undef_map->l_name),
748 undef_map->l_ns);
749 }
750 else
751 /* Whoa, that was bad luck. We have to search again. */
752 result = -1;
753
754 out:
755 /* Release the lock. */
756 __rtld_lock_unlock_recursive (GL(dl_load_lock));
757
758 if (__glibc_unlikely (flags & DL_LOOKUP_GSCOPE_LOCK))
759 THREAD_GSCOPE_SET_FLAG ();
760
761 return result;
762
763 out_check:
764 if (map->l_serial != serial)
765 result = -1;
766 goto out;
767}
768
769
770/* Search loaded objects' symbol tables for a definition of the symbol
771 UNDEF_NAME, perhaps with a requested version for the symbol.
772
773 We must never have calls to the audit functions inside this function
774 or in any function which gets called. If this would happen the audit
775 code might create a thread which can throw off all the scope locking. */
776lookup_t
777_dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
778 const ElfW(Sym) **ref,
779 struct r_scope_elem *symbol_scope[],
780 const struct r_found_version *version,
781 int type_class, int flags, struct link_map *skip_map)
782{
783 const unsigned int new_hash = _dl_new_hash (str: undef_name);
784 unsigned long int old_hash = 0xffffffff;
785 struct sym_val current_value = { NULL, NULL };
786 struct r_scope_elem **scope = symbol_scope;
787
788 bump_num_relocations ();
789
790 /* DL_LOOKUP_RETURN_NEWEST does not make sense for versioned
791 lookups. */
792 assert (version == NULL || !(flags & DL_LOOKUP_RETURN_NEWEST));
793
794 size_t i = 0;
795 if (__glibc_unlikely (skip_map != NULL))
796 /* Search the relevant loaded objects for a definition. */
797 while ((*scope)->r_list[i] != skip_map)
798 ++i;
799
800 /* Search the relevant loaded objects for a definition. */
801 for (size_t start = i; *scope != NULL; start = 0, ++scope)
802 if (do_lookup_x (undef_name, new_hash, old_hash: &old_hash, ref: *ref,
803 result: &current_value, scope: *scope, i: start, version, flags,
804 skip: skip_map, type_class, undef_map) != 0)
805 break;
806
807 if (__glibc_unlikely (current_value.s == NULL))
808 {
809 if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
810 && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED))
811 {
812 /* We could find no value for a strong reference. */
813 const char *reference_name = undef_map ? undef_map->l_name : "";
814 const char *versionstr = version ? ", version " : "";
815 const char *versionname = (version && version->name
816 ? version->name : "");
817 struct dl_exception exception;
818 /* XXX We cannot translate the message. */
819 _dl_exception_create_format
820 (&exception, DSO_FILENAME (reference_name),
821 fmt: "undefined symbol: %s%s%s",
822 undef_name, versionstr, versionname);
823 _dl_signal_cexception (errcode: 0, exception: &exception, N_("symbol lookup error"));
824 _dl_exception_free (&exception);
825 }
826 *ref = NULL;
827 return 0;
828 }
829
830 int protected = (*ref
831 && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED);
832 if (__glibc_unlikely (protected != 0))
833 {
834 /* It is very tricky. We need to figure out what value to
835 return for the protected symbol. */
836 if (type_class == ELF_RTYPE_CLASS_PLT)
837 {
838 if (current_value.s != NULL && current_value.m != undef_map)
839 {
840 current_value.s = *ref;
841 current_value.m = undef_map;
842 }
843 }
844 else
845 {
846 struct sym_val protected_value = { NULL, NULL };
847
848 for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
849 if (do_lookup_x (undef_name, new_hash, old_hash: &old_hash, ref: *ref,
850 result: &protected_value, scope: *scope, i, version, flags,
851 skip: skip_map, ELF_RTYPE_CLASS_PLT, NULL) != 0)
852 break;
853
854 if (protected_value.s != NULL && protected_value.m != undef_map)
855 {
856 current_value.s = *ref;
857 current_value.m = undef_map;
858 }
859 }
860 }
861
862 /* We have to check whether this would bind UNDEF_MAP to an object
863 in the global scope which was dynamically loaded. In this case
864 we have to prevent the latter from being unloaded unless the
865 UNDEF_MAP object is also unloaded. */
866 if (__glibc_unlikely (current_value.m->l_type == lt_loaded)
867 /* Don't do this for explicit lookups as opposed to implicit
868 runtime lookups. */
869 && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
870 /* Add UNDEF_MAP to the dependencies. */
871 && add_dependency (undef_map, map: current_value.m, flags) < 0)
872 /* Something went wrong. Perhaps the object we tried to reference
873 was just removed. Try finding another definition. */
874 return _dl_lookup_symbol_x (undef_name, undef_map, ref,
875 symbol_scope: (flags & DL_LOOKUP_GSCOPE_LOCK)
876 ? undef_map->l_scope : symbol_scope,
877 version, type_class, flags, skip_map);
878
879 /* The object is used. */
880 if (__glibc_unlikely (current_value.m->l_used == 0))
881 current_value.m->l_used = 1;
882
883 if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS))
884 {
885 const char *reference_name = undef_map->l_name;
886
887 _dl_debug_printf (fmt: "binding file %s [%lu] to %s [%lu]: %s symbol `%s'",
888 DSO_FILENAME (reference_name),
889 undef_map->l_ns,
890 DSO_FILENAME (current_value.m->l_name),
891 current_value.m->l_ns,
892 protected ? "protected" : "normal", undef_name);
893 if (version)
894 _dl_debug_printf_c (fmt: " [%s]\n", version->name);
895 else
896 _dl_debug_printf_c (fmt: "\n");
897 }
898
899
900 *ref = current_value.s;
901 return LOOKUP_VALUE (current_value.m);
902}
903

source code of glibc/elf/dl-lookup.c