1 /* Look up a symbol in the loaded objects.
2 Copyright (C) 1995,96,97,98,99,2000 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
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 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
26 #include <dl-machine.h>
27 #include <bits/libc-lock.h>
31 #define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
33 /* We need this string more than once. */
34 static const char undefined_msg
[] = "undefined symbol: ";
44 #define make_string(string, rest...) \
46 const char *all[] = { string, ## rest }; \
51 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
52 len += strlen (all[cnt]); \
54 cp = result = alloca (len); \
55 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
56 cp = __stpcpy (cp, all[cnt]); \
61 /* Statistics function. */
62 unsigned long int _dl_num_relocations
;
64 /* During the program run we must not modify the global data of
65 loaded shared object simultanously in two threads. Therefore we
66 protect `_dl_open' and `_dl_close' in dl-close.c.
68 This must be a recursive lock since the initializer function of
69 the loaded object might as well require a call to this function.
70 At this time it is not anymore a problem to modify the tables. */
71 __libc_lock_define (extern, _dl_load_lock
)
74 /* We have two different situations when looking up a simple: with or
75 without versioning. gcc is not able to optimize a single function
76 definition serving for both purposes so we define two functions. */
79 #include "do-lookup.h"
83 #include "do-lookup.h"
86 /* Add extra dependency on MAP to UNDEF_MAP. */
88 add_dependency (struct link_map
*undef_map
, struct link_map
*map
)
90 struct link_map
**list
;
95 /* Make sure nobody can unload the object while we are at it. */
96 __libc_lock_lock (_dl_load_lock
);
98 /* Determine whether UNDEF_MAP already has a reference to MAP. First
99 look in the normal dependencies. */
100 list
= undef_map
->l_searchlist
.r_list
;
101 act
= undef_map
->l_searchlist
.r_nlist
;
103 for (i
= 0; i
< act
; ++i
)
107 if (__builtin_expect (i
== act
, 1))
109 /* No normal dependency. See whether we already had to add it
110 to the special list of dynamic dependencies. */
111 list
= undef_map
->l_reldeps
;
112 act
= undef_map
->l_reldepsact
;
114 for (i
= 0; i
< act
; ++i
)
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
125 struct link_map
*runp
= _dl_loaded
;
127 while (runp
!= NULL
&& runp
!= map
)
132 /* The object is still available. Add the reference now. */
133 if (__builtin_expect (act
>= undef_map
->l_reldepsmax
, 0))
135 /* Allocate more memory for the dependency list. Since
136 this can never happen during the startup phase we can
140 undef_map
->l_reldepsmax
+= 5;
141 newp
= realloc (undef_map
->l_reldeps
,
142 undef_map
->l_reldepsmax
143 * sizeof(struct link_map
*));
145 if (__builtin_expect (newp
!= NULL
, 1))
146 undef_map
->l_reldeps
= (struct link_map
**) newp
;
148 /* Correct the addition. */
149 undef_map
->l_reldepsmax
-= 5;
152 /* If we didn't manage to allocate memory for the list this
153 is no fatal mistake. We simply increment the use counter
154 of the referenced object and don't record the dependencies.
155 This means this increment can never be reverted and the
156 object will never be unloaded. This is semantically the
157 correct behaviour. */
158 if (__builtin_expect (act
< undef_map
->l_reldepsmax
, 1))
159 undef_map
->l_reldeps
[undef_map
->l_reldepsact
++] = map
;
161 /* And increment the counter in the referenced object. */
164 /* Display information if we are debugging. */
165 if (__builtin_expect (_dl_debug_files
, 0))
166 _dl_debug_message (1, "\nfile=",
167 map
->l_name
[0] ? map
->l_name
: _dl_argv
[0],
170 ? undef_map
->l_name
: _dl_argv
[0],
171 " (relocation dependency)\n\n", NULL
);
174 /* Whoa, that was bad luck. We have to search again. */
179 /* Release the lock. */
180 __libc_lock_unlock (_dl_load_lock
);
186 /* Search loaded objects' symbol tables for a definition of the symbol
191 _dl_lookup_symbol (const char *undef_name
, struct link_map
*undef_map
,
192 const ElfW(Sym
) **ref
, struct r_scope_elem
*symbol_scope
[],
195 const char *reference_name
= undef_map
? undef_map
->l_name
: NULL
;
196 const unsigned long int hash
= _dl_elf_hash (undef_name
);
197 struct sym_val current_value
= { NULL
, NULL
};
198 struct r_scope_elem
**scope
;
200 int noexec
= elf_machine_lookup_noexec_p (reloc_type
);
201 int noplt
= elf_machine_lookup_noplt_p (reloc_type
);
203 ++_dl_num_relocations
;
205 /* Search the relevant loaded objects for a definition. */
206 for (scope
= symbol_scope
; *scope
; ++scope
)
207 if (do_lookup (undef_name
, undef_map
, hash
, *ref
, ¤t_value
,
208 *scope
, 0, NULL
, noexec
, noplt
))
210 /* We have to check whether this would bind UNDEF_MAP to an object
211 in the global scope which was dynamically loaded. In this case
212 we have to prevent the latter from being unloaded unless the
213 UNDEF_MAP object is also unloaded. */
214 if (__builtin_expect (current_value
.m
->l_global
, 0)
215 && (__builtin_expect (current_value
.m
->l_type
, lt_library
)
217 && undef_map
!= current_value
.m
218 /* Add UNDEF_MAP to the dependencies. */
219 && add_dependency (undef_map
, current_value
.m
) < 0)
220 /* Something went wrong. Perhaps the object we tried to reference
221 was just removed. Try finding another definition. */
222 return _dl_lookup_symbol (undef_name
, undef_map
, ref
, symbol_scope
,
228 if (__builtin_expect (current_value
.s
== NULL
, 0))
230 if (*ref
== NULL
|| ELFW(ST_BIND
) ((*ref
)->st_info
) != STB_WEAK
)
231 /* We could find no value for a strong reference. */
232 _dl_signal_cerror (0, (reference_name
&& reference_name
[0]
234 : (_dl_argv
[0] ?: "<main program>")),
235 make_string (undefined_msg
, undef_name
));
240 protected = *ref
&& ELFW(ST_VISIBILITY
) ((*ref
)->st_other
) == STV_PROTECTED
;
242 if (__builtin_expect (_dl_debug_bindings
, 0))
243 _dl_debug_message (1, "binding file ",
244 (reference_name
&& reference_name
[0]
246 : (_dl_argv
[0] ?: "<main program>")),
247 " to ", current_value
.m
->l_name
[0]
248 ? current_value
.m
->l_name
: _dl_argv
[0],
249 ": ", protected ? "protected" : "normal",
250 " symbol `", undef_name
, "'\n", NULL
);
252 if (__builtin_expect (protected == 0, 1))
254 *ref
= current_value
.s
;
255 return LOOKUP_VALUE (current_value
.m
);
259 /* It is very tricky. We need to figure out what value to
260 return for the protected symbol */
261 struct sym_val protected_value
= { NULL
, NULL
};
263 for (scope
= symbol_scope
; *scope
; ++scope
)
264 if (do_lookup (undef_name
, undef_map
, hash
, *ref
,
265 &protected_value
, *scope
, 0, NULL
, 0, 1))
268 if (protected_value
.s
== NULL
|| protected_value
.m
== undef_map
)
270 *ref
= current_value
.s
;
271 return LOOKUP_VALUE (current_value
.m
);
274 return LOOKUP_VALUE (undef_map
);
279 /* This function is nearly the same as `_dl_lookup_symbol' but it
280 skips in the first list all objects until SKIP_MAP is found. I.e.,
281 it only considers objects which were loaded after the described
282 object. If there are more search lists the object described by
283 SKIP_MAP is only skipped. */
286 _dl_lookup_symbol_skip (const char *undef_name
,
287 struct link_map
*undef_map
, const ElfW(Sym
) **ref
,
288 struct r_scope_elem
*symbol_scope
[],
289 struct link_map
*skip_map
)
291 const char *reference_name
= undef_map
? undef_map
->l_name
: NULL
;
292 const unsigned long int hash
= _dl_elf_hash (undef_name
);
293 struct sym_val current_value
= { NULL
, NULL
};
294 struct r_scope_elem
**scope
;
298 ++_dl_num_relocations
;
300 /* Search the relevant loaded objects for a definition. */
301 scope
= symbol_scope
;
302 for (i
= 0; (*scope
)->r_duplist
[i
] != skip_map
; ++i
)
303 assert (i
< (*scope
)->r_nduplist
);
305 if (i
< (*scope
)->r_nlist
306 && do_lookup (undef_name
, undef_map
, hash
, *ref
, ¤t_value
,
307 *scope
, i
, skip_map
, 0, 0))
309 /* We have to check whether this would bind UNDEF_MAP to an object
310 in the global scope which was dynamically loaded. In this case
311 we have to prevent the latter from being unloaded unless the
312 UNDEF_MAP object is also unloaded. */
313 if (current_value
.m
->l_global
314 && (__builtin_expect (current_value
.m
->l_type
, lt_library
)
316 && undef_map
!= current_value
.m
317 /* Add UNDEF_MAP to the dependencies. */
318 && add_dependency (undef_map
, current_value
.m
) < 0)
319 /* Something went wrong. Perhaps the object we tried to reference
320 was just removed. Try finding another definition. */
321 return _dl_lookup_symbol_skip (undef_name
, undef_map
, ref
,
322 symbol_scope
, skip_map
);
326 if (do_lookup (undef_name
, undef_map
, hash
, *ref
, ¤t_value
,
327 *scope
, 0, skip_map
, 0, 0))
329 /* We have to check whether this would bind UNDEF_MAP to an object
330 in the global scope which was dynamically loaded. In this case
331 we have to prevent the latter from being unloaded unless the
332 UNDEF_MAP object is also unloaded. */
333 if (__builtin_expect (current_value
.m
->l_global
, 0)
334 && (__builtin_expect (current_value
.m
->l_type
, lt_library
)
336 && undef_map
!= current_value
.m
337 /* Add UNDEF_MAP to the dependencies. */
338 && add_dependency (undef_map
, current_value
.m
) < 0)
339 /* Something went wrong. Perhaps the object we tried to reference
340 was just removed. Try finding another definition. */
341 return _dl_lookup_symbol_skip (undef_name
, undef_map
, ref
,
342 symbol_scope
, skip_map
);
347 if (__builtin_expect (current_value
.s
== NULL
, 0))
353 protected = *ref
&& ELFW(ST_VISIBILITY
) ((*ref
)->st_other
) == STV_PROTECTED
;
355 if (__builtin_expect (_dl_debug_bindings
, 0))
356 _dl_debug_message (1, "binding file ",
357 (reference_name
&& reference_name
[0]
359 : (_dl_argv
[0] ?: "<main program>")),
360 " to ", current_value
.m
->l_name
[0]
361 ? current_value
.m
->l_name
: _dl_argv
[0],
362 ": ", protected ? "protected" : "normal",
363 " symbol `", undef_name
, "'\n", NULL
);
365 if (__builtin_expect (protected == 0, 1))
367 *ref
= current_value
.s
;
368 return LOOKUP_VALUE (current_value
.m
);
372 /* It is very tricky. We need to figure out what value to
373 return for the protected symbol */
374 struct sym_val protected_value
= { NULL
, NULL
};
376 if (i
>= (*scope
)->r_nlist
377 || !do_lookup (undef_name
, undef_map
, hash
, *ref
, &protected_value
,
378 *scope
, i
, skip_map
, 0, 1))
380 if (do_lookup (undef_name
, undef_map
, hash
, *ref
, &protected_value
,
381 *scope
, 0, skip_map
, 0, 1))
384 if (protected_value
.s
== NULL
|| protected_value
.m
== undef_map
)
386 *ref
= current_value
.s
;
387 return LOOKUP_VALUE (current_value
.m
);
390 return LOOKUP_VALUE (undef_map
);
395 /* This function works like _dl_lookup_symbol but it takes an
396 additional arguement with the version number of the requested
399 XXX We'll see whether we need this separate function. */
402 _dl_lookup_versioned_symbol (const char *undef_name
,
403 struct link_map
*undef_map
, const ElfW(Sym
) **ref
,
404 struct r_scope_elem
*symbol_scope
[],
405 const struct r_found_version
*version
,
408 const char *reference_name
= undef_map
? undef_map
->l_name
: NULL
;
409 const unsigned long int hash
= _dl_elf_hash (undef_name
);
410 struct sym_val current_value
= { NULL
, NULL
};
411 struct r_scope_elem
**scope
;
413 int noexec
= elf_machine_lookup_noexec_p (reloc_type
);
414 int noplt
= elf_machine_lookup_noplt_p (reloc_type
);
416 ++_dl_num_relocations
;
418 /* Search the relevant loaded objects for a definition. */
419 for (scope
= symbol_scope
; *scope
; ++scope
)
421 int res
= do_lookup_versioned (undef_name
, undef_map
, hash
, *ref
,
422 ¤t_value
, *scope
, 0, version
, NULL
,
426 /* We have to check whether this would bind UNDEF_MAP to an object
427 in the global scope which was dynamically loaded. In this case
428 we have to prevent the latter from being unloaded unless the
429 UNDEF_MAP object is also unloaded. */
430 if (__builtin_expect (current_value
.m
->l_global
, 0)
431 && (__builtin_expect (current_value
.m
->l_type
, lt_library
)
433 && undef_map
!= current_value
.m
434 /* Add UNDEF_MAP to the dependencies. */
435 && add_dependency (undef_map
, current_value
.m
) < 0)
436 /* Something went wrong. Perhaps the object we tried to reference
437 was just removed. Try finding another definition. */
438 return _dl_lookup_versioned_symbol (undef_name
, undef_map
, ref
,
439 symbol_scope
, version
,
445 if (__builtin_expect (res
, 0) < 0)
447 /* Oh, oh. The file named in the relocation entry does not
448 contain the needed symbol. */
449 _dl_signal_cerror (0, (reference_name
&& reference_name
[0]
451 : (_dl_argv
[0] ?: "<main program>")),
452 make_string ("symbol ", undef_name
, ", version ",
454 " not defined in file ",
456 " with link time reference",
458 ? " (no version symbols)" : ""));
464 if (__builtin_expect (current_value
.s
== NULL
, 0))
466 if (*ref
== NULL
|| ELFW(ST_BIND
) ((*ref
)->st_info
) != STB_WEAK
)
467 /* We could find no value for a strong reference. */
468 _dl_signal_cerror (0, (reference_name
&& reference_name
[0]
470 : (_dl_argv
[0] ?: "<main program>")),
471 make_string (undefined_msg
, undef_name
,
472 ", version ", version
->name
?: NULL
));
477 protected = *ref
&& ELFW(ST_VISIBILITY
) ((*ref
)->st_other
) == STV_PROTECTED
;
479 if (__builtin_expect (_dl_debug_bindings
, 0))
480 _dl_debug_message (1, "binding file ",
481 (reference_name
&& reference_name
[0]
483 : (_dl_argv
[0] ?: "<main program>")),
484 " to ", current_value
.m
->l_name
[0]
485 ? current_value
.m
->l_name
: _dl_argv
[0],
486 ": ", protected ? "protected" : "normal",
487 " symbol `", undef_name
, "' [", version
->name
,
490 if (__builtin_expect (protected == 0, 1))
492 *ref
= current_value
.s
;
493 return LOOKUP_VALUE (current_value
.m
);
497 /* It is very tricky. We need to figure out what value to
498 return for the protected symbol */
499 struct sym_val protected_value
= { NULL
, NULL
};
501 for (scope
= symbol_scope
; *scope
; ++scope
)
502 if (do_lookup_versioned (undef_name
, undef_map
, hash
, *ref
,
503 &protected_value
, *scope
, 0, version
, NULL
,
507 if (protected_value
.s
== NULL
|| protected_value
.m
== undef_map
)
509 *ref
= current_value
.s
;
510 return LOOKUP_VALUE (current_value
.m
);
513 return LOOKUP_VALUE (undef_map
);
518 /* Similar to _dl_lookup_symbol_skip but takes an additional argument
519 with the version we are looking for. */
522 _dl_lookup_versioned_symbol_skip (const char *undef_name
,
523 struct link_map
*undef_map
,
524 const ElfW(Sym
) **ref
,
525 struct r_scope_elem
*symbol_scope
[],
526 const struct r_found_version
*version
,
527 struct link_map
*skip_map
)
529 const char *reference_name
= undef_map
? undef_map
->l_name
: NULL
;
530 const unsigned long int hash
= _dl_elf_hash (undef_name
);
531 struct sym_val current_value
= { NULL
, NULL
};
532 struct r_scope_elem
**scope
;
536 ++_dl_num_relocations
;
538 /* Search the relevant loaded objects for a definition. */
539 scope
= symbol_scope
;
540 for (i
= 0; (*scope
)->r_duplist
[i
] != skip_map
; ++i
)
541 assert (i
< (*scope
)->r_nduplist
);
543 if (i
< (*scope
)->r_nlist
544 && do_lookup_versioned (undef_name
, undef_map
, hash
, *ref
,
545 ¤t_value
, *scope
, i
, version
, skip_map
,
548 /* We have to check whether this would bind UNDEF_MAP to an object
549 in the global scope which was dynamically loaded. In this case
550 we have to prevent the latter from being unloaded unless the
551 UNDEF_MAP object is also unloaded. */
552 if (__builtin_expect (current_value
.m
->l_global
, 0)
553 && (__builtin_expect (current_value
.m
->l_type
, lt_library
)
555 && undef_map
!= current_value
.m
556 /* Add UNDEF_MAP to the dependencies. */
557 && add_dependency (undef_map
, current_value
.m
) < 0)
558 /* Something went wrong. Perhaps the object we tried to reference
559 was just removed. Try finding another definition. */
560 return _dl_lookup_versioned_symbol_skip (undef_name
, undef_map
, ref
,
561 symbol_scope
, version
,
566 if (do_lookup_versioned (undef_name
, undef_map
, hash
, *ref
,
567 ¤t_value
, *scope
, 0, version
, skip_map
,
570 /* We have to check whether this would bind UNDEF_MAP to an object
571 in the global scope which was dynamically loaded. In this case
572 we have to prevent the latter from being unloaded unless the
573 UNDEF_MAP object is also unloaded. */
574 if (current_value
.m
->l_global
575 && (__builtin_expect (current_value
.m
->l_type
, lt_library
)
577 && undef_map
!= current_value
.m
578 /* Add UNDEF_MAP to the dependencies. */
579 && add_dependency (undef_map
, current_value
.m
) < 0)
580 /* Something went wrong. Perhaps the object we tried to reference
581 was just removed. Try finding another definition. */
582 return _dl_lookup_versioned_symbol_skip (undef_name
, undef_map
,
588 if (__builtin_expect (current_value
.s
== NULL
, 0))
590 if (*ref
== NULL
|| ELFW(ST_BIND
) ((*ref
)->st_info
) != STB_WEAK
)
592 /* We could find no value for a strong reference. */
593 const size_t len
= strlen (undef_name
);
594 char buf
[sizeof undefined_msg
+ len
];
595 __mempcpy (__mempcpy (buf
, undefined_msg
, sizeof undefined_msg
- 1),
596 undef_name
, len
+ 1);
597 _dl_signal_cerror (0, (reference_name
&& reference_name
[0]
599 : (_dl_argv
[0] ?: "<main program>")), buf
);
605 protected = *ref
&& ELFW(ST_VISIBILITY
) ((*ref
)->st_other
) == STV_PROTECTED
;
607 if (__builtin_expect (_dl_debug_bindings
, 0))
608 _dl_debug_message (1, "binding file ",
609 (reference_name
&& reference_name
[0]
611 : (_dl_argv
[0] ?: "<main program>")),
612 " to ", current_value
.m
->l_name
[0]
613 ? current_value
.m
->l_name
: _dl_argv
[0],
614 ": ", protected ? "protected" : "normal",
615 " symbol `", undef_name
, "' [", version
->name
,
618 if (__builtin_expect (protected == 0, 1))
620 *ref
= current_value
.s
;
621 return LOOKUP_VALUE (current_value
.m
);
625 /* It is very tricky. We need to figure out what value to
626 return for the protected symbol */
627 struct sym_val protected_value
= { NULL
, NULL
};
629 if (i
>= (*scope
)->r_nlist
630 || !do_lookup_versioned (undef_name
, undef_map
, hash
, *ref
,
631 &protected_value
, *scope
, i
, version
,
634 if (do_lookup_versioned (undef_name
, undef_map
, hash
, *ref
,
635 &protected_value
, *scope
, 0, version
,
639 if (protected_value
.s
== NULL
|| protected_value
.m
== undef_map
)
641 *ref
= current_value
.s
;
642 return LOOKUP_VALUE (current_value
.m
);
645 return LOOKUP_VALUE (undef_map
);
650 /* Cache the location of MAP's hash table. */
654 _dl_setup_hash (struct link_map
*map
)
659 if (!map
->l_info
[DT_HASH
])
661 hash
= (void *)(map
->l_addr
+ map
->l_info
[DT_HASH
]->d_un
.d_ptr
);
663 map
->l_nbuckets
= *hash
++;
665 map
->l_buckets
= hash
;
666 hash
+= map
->l_nbuckets
;