Updated to fedora-glibc-20060905T0633
[glibc.git] / elf / dl-lookup.c
blob7cfcc620a7a7a693ca3f568c1232c55f67da477b
1 /* Look up a symbol in the loaded objects.
2 Copyright (C) 1995-2005, 2006 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 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.
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.
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. */
20 #include <alloca.h>
21 #include <libintl.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <ldsodefs.h>
26 #include <dl-hash.h>
27 #include <dl-machine.h>
28 #include <bits/libc-lock.h>
29 #include <tls.h>
31 #include <assert.h>
33 #define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
35 /* We need this string more than once. */
36 static const char undefined_msg[] = "undefined symbol: ";
39 struct sym_val
41 const ElfW(Sym) *s;
42 struct link_map *m;
46 #define make_string(string, rest...) \
47 ({ \
48 const char *all[] = { string, ## rest }; \
49 size_t len, cnt; \
50 char *result, *cp; \
52 len = 1; \
53 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
54 len += strlen (all[cnt]); \
56 cp = result = alloca (len); \
57 for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
58 cp = __stpcpy (cp, all[cnt]); \
60 result; \
63 /* Statistics function. */
64 #ifdef SHARED
65 # define bump_num_relocations() ++GL(dl_num_relocations)
66 #else
67 # define bump_num_relocations() ((void) 0)
68 #endif
71 /* The actual lookup code. */
72 #include "do-lookup.h"
75 static uint_fast32_t
76 dl_new_hash (const char *s)
78 uint_fast32_t h = 5381;
79 for (unsigned char c = *s; c != '\0'; c = *++s)
80 h = h * 33 + c;
81 return h & 0xffffffff;
85 /* Add extra dependency on MAP to UNDEF_MAP. */
86 static int
87 internal_function
88 add_dependency (struct link_map *undef_map, struct link_map *map)
90 struct link_map **list;
91 struct link_map *runp;
92 unsigned int act;
93 unsigned int i;
94 int result = 0;
96 /* Avoid self-references and references to objects which cannot be
97 unloaded anyway. */
98 if (undef_map == map)
99 return 0;
101 /* Make sure nobody can unload the object while we are at it. */
102 __rtld_lock_lock_recursive (GL(dl_load_lock));
104 /* Avoid references to objects which cannot be unloaded anyway. */
105 if (map->l_type != lt_loaded
106 || (map->l_flags_1 & DF_1_NODELETE) != 0)
107 goto out;
109 /* If the object with the undefined reference cannot be removed ever
110 just make sure the same is true for the object which contains the
111 definition. */
112 if (undef_map->l_type != lt_loaded
113 || (undef_map->l_flags_1 & DF_1_NODELETE) != 0)
115 map->l_flags_1 |= DF_1_NODELETE;
116 goto out;
119 /* Determine whether UNDEF_MAP already has a reference to MAP. First
120 look in the normal dependencies. */
121 if (undef_map->l_initfini != NULL)
123 list = undef_map->l_initfini;
125 for (i = 0; list[i] != NULL; ++i)
126 if (list[i] == map)
127 goto out;
130 /* No normal dependency. See whether we already had to add it
131 to the special list of dynamic dependencies. */
132 list = undef_map->l_reldeps;
133 act = undef_map->l_reldepsact;
135 for (i = 0; i < act; ++i)
136 if (list[i] == map)
137 goto out;
139 /* The object is not yet in the dependency list. Before we add
140 it make sure just one more time the object we are about to
141 reference is still available. There is a brief period in
142 which the object could have been removed since we found the
143 definition. */
144 runp = GL(dl_ns)[undef_map->l_ns]._ns_loaded;
145 while (runp != NULL && runp != map)
146 runp = runp->l_next;
148 if (runp != NULL)
150 /* The object is still available. Add the reference now. */
151 if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
153 /* Allocate more memory for the dependency list. Since this
154 can never happen during the startup phase we can use
155 `realloc'. */
156 void *newp;
158 undef_map->l_reldepsmax += 5;
159 newp = realloc (undef_map->l_reldeps,
160 undef_map->l_reldepsmax
161 * sizeof (struct link_map *));
163 if (__builtin_expect (newp != NULL, 1))
164 undef_map->l_reldeps = (struct link_map **) newp;
165 else
166 /* Correct the addition. */
167 undef_map->l_reldepsmax -= 5;
170 /* If we didn't manage to allocate memory for the list this is
171 no fatal mistake. We simply increment the use counter of the
172 referenced object and don't record the dependencies. This
173 means this increment can never be reverted and the object
174 will never be unloaded. This is semantically the correct
175 behavior. */
176 if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
177 undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
179 /* Display information if we are debugging. */
180 if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
181 _dl_debug_printf ("\
182 \nfile=%s [%lu]; needed by %s [%lu] (relocation dependency)\n\n",
183 map->l_name[0] ? map->l_name : rtld_progname,
184 map->l_ns,
185 undef_map->l_name[0]
186 ? undef_map->l_name : rtld_progname,
187 undef_map->l_ns);
189 else
190 /* Whoa, that was bad luck. We have to search again. */
191 result = -1;
193 out:
194 /* Release the lock. */
195 __rtld_lock_unlock_recursive (GL(dl_load_lock));
197 return result;
200 static void
201 internal_function
202 _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
203 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
204 struct sym_val *value,
205 const struct r_found_version *version, int type_class,
206 int protected);
209 /* Search loaded objects' symbol tables for a definition of the symbol
210 UNDEF_NAME, perhaps with a requested version for the symbol. */
211 lookup_t
212 internal_function
213 _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
214 const ElfW(Sym) **ref,
215 struct r_scope_elem *symbol_scope[],
216 const struct r_found_version *version,
217 int type_class, int flags, struct link_map *skip_map)
219 const uint_fast32_t new_hash = dl_new_hash (undef_name);
220 unsigned long int old_hash = 0xffffffff;
221 struct sym_val current_value = { NULL, NULL };
222 struct r_scope_elem **scope = symbol_scope;
224 bump_num_relocations ();
226 /* No other flag than DL_LOOKUP_ADD_DEPENDENCY is allowed if we look
227 up a versioned symbol. */
228 assert (version == NULL || flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY);
230 size_t i = 0;
231 if (__builtin_expect (skip_map != NULL, 0))
233 /* Search the relevant loaded objects for a definition. */
234 while ((*scope)->r_list[i] != skip_map)
235 ++i;
237 assert (i < (*scope)->r_nlist);
240 /* Search the relevant loaded objects for a definition. */
241 for (size_t start = i; *scope != NULL; start = 0, ++scope)
243 int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref,
244 &current_value, *scope, start, version, flags,
245 skip_map, type_class);
246 if (res > 0)
247 break;
249 if (__builtin_expect (res, 0) < 0 && skip_map == NULL)
251 /* Oh, oh. The file named in the relocation entry does not
252 contain the needed symbol. This code is never reached
253 for unversioned lookups. */
254 assert (version != NULL);
255 const char *reference_name = undef_map ? undef_map->l_name : NULL;
257 /* XXX We cannot translate the message. */
258 _dl_signal_cerror (0, (reference_name[0]
259 ? reference_name
260 : (rtld_progname ?: "<main program>")),
261 N_("relocation error"),
262 make_string ("symbol ", undef_name, ", version ",
263 version->name,
264 " not defined in file ",
265 version->filename,
266 " with link time reference",
267 res == -2
268 ? " (no version symbols)" : ""));
269 *ref = NULL;
270 return 0;
274 if (__builtin_expect (current_value.s == NULL, 0))
276 if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
277 && skip_map == NULL)
279 /* We could find no value for a strong reference. */
280 const char *reference_name = undef_map ? undef_map->l_name : "";
281 const char *versionstr = version ? ", version " : "";
282 const char *versionname = (version && version->name
283 ? version->name : "");
285 /* XXX We cannot translate the message. */
286 _dl_signal_cerror (0, (reference_name[0]
287 ? reference_name
288 : (rtld_progname ?: "<main program>")),
289 N_("symbol lookup error"),
290 make_string (undefined_msg, undef_name,
291 versionstr, versionname));
293 *ref = NULL;
294 return 0;
297 int protected = (*ref
298 && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED);
299 if (__builtin_expect (protected != 0, 0))
301 /* It is very tricky. We need to figure out what value to
302 return for the protected symbol. */
303 if (type_class == ELF_RTYPE_CLASS_PLT)
305 if (current_value.s != NULL && current_value.m != undef_map)
307 current_value.s = *ref;
308 current_value.m = undef_map;
311 else
313 struct sym_val protected_value = { NULL, NULL };
315 for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
316 if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
317 &protected_value, *scope, i, version, flags,
318 skip_map, ELF_RTYPE_CLASS_PLT) != 0)
319 break;
321 if (protected_value.s != NULL && protected_value.m != undef_map)
323 current_value.s = *ref;
324 current_value.m = undef_map;
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_type == lt_loaded, 0)
334 /* Don't do this for explicit lookups as opposed to implicit
335 runtime lookups. */
336 && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
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_x (undef_name, undef_map, ref,
342 symbol_scope, version, type_class,
343 flags, skip_map);
345 /* The object is used. */
346 current_value.m->l_used = 1;
348 if (__builtin_expect (GLRO(dl_debug_mask)
349 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
350 _dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
351 &current_value, version, type_class, protected);
353 *ref = current_value.s;
354 return LOOKUP_VALUE (current_value.m);
358 /* Cache the location of MAP's hash table. */
360 void
361 internal_function
362 _dl_setup_hash (struct link_map *map)
364 Elf_Symndx *hash;
365 Elf_Symndx nchain;
367 if (__builtin_expect (map->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
368 + DT_THISPROCNUM + DT_VERSIONTAGNUM
369 + DT_EXTRANUM + DT_VALNUM] != NULL, 1))
371 Elf32_Word *hash32
372 = (void *) D_PTR (map, l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
373 + DT_THISPROCNUM + DT_VERSIONTAGNUM
374 + DT_EXTRANUM + DT_VALNUM]);
375 map->l_nbuckets = *hash32++;
376 Elf32_Word symbias = *hash32++;
377 Elf32_Word bitmask_nwords = *hash32++;
378 /* Must be a power of two. */
379 assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0);
380 map->l_gnu_bitmask_idxbits = bitmask_nwords - 1;
381 map->l_gnu_shift = *hash32++;
383 map->l_gnu_bitmask = (ElfW(Addr) *) hash32;
384 hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords;
386 map->l_gnu_buckets = hash32;
387 hash32 += map->l_nbuckets;
388 map->l_gnu_chain_zero = hash32 - symbias;
389 return;
392 if (!map->l_info[DT_HASH])
393 return;
394 hash = (void *) D_PTR (map, l_info[DT_HASH]);
396 map->l_nbuckets = *hash++;
397 nchain = *hash++;
398 map->l_buckets = hash;
399 hash += map->l_nbuckets;
400 map->l_chain = hash;
404 static void
405 internal_function
406 _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
407 const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
408 struct sym_val *value,
409 const struct r_found_version *version, int type_class,
410 int protected)
412 const char *reference_name = undef_map->l_name;
414 if (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS)
416 _dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol `%s'",
417 (reference_name[0]
418 ? reference_name
419 : (rtld_progname ?: "<main program>")),
420 undef_map->l_ns,
421 value->m->l_name[0] ? value->m->l_name : rtld_progname,
422 value->m->l_ns,
423 protected ? "protected" : "normal", undef_name);
424 if (version)
425 _dl_debug_printf_c (" [%s]\n", version->name);
426 else
427 _dl_debug_printf_c ("\n");
429 #ifdef SHARED
430 if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
432 int conflict = 0;
433 struct sym_val val = { NULL, NULL };
435 if ((GLRO(dl_trace_prelink_map) == NULL
436 || GLRO(dl_trace_prelink_map) == GL(dl_ns)[LM_ID_BASE]._ns_loaded)
437 && undef_map != GL(dl_ns)[LM_ID_BASE]._ns_loaded)
439 const uint_fast32_t new_hash = dl_new_hash (undef_name);
440 unsigned long int old_hash = 0xffffffff;
442 do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val,
443 undef_map->l_local_scope[0], 0, version, 0, NULL,
444 type_class);
446 if (val.s != value->s || val.m != value->m)
447 conflict = 1;
450 # ifdef USE_TLS
451 if (value->s
452 && (__builtin_expect (ELFW(ST_TYPE) (value->s->st_info)
453 == STT_TLS, 0)))
454 type_class = 4;
455 # endif
457 if (conflict
458 || GLRO(dl_trace_prelink_map) == undef_map
459 || GLRO(dl_trace_prelink_map) == NULL
460 || type_class == 4)
462 _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
463 conflict ? "conflict" : "lookup",
464 (int) sizeof (ElfW(Addr)) * 2,
465 (size_t) undef_map->l_map_start,
466 (int) sizeof (ElfW(Addr)) * 2,
467 (size_t) (((ElfW(Addr)) *ref) - undef_map->l_map_start),
468 (int) sizeof (ElfW(Addr)) * 2,
469 (size_t) (value->s ? value->m->l_map_start : 0),
470 (int) sizeof (ElfW(Addr)) * 2,
471 (size_t) (value->s ? value->s->st_value : 0));
473 if (conflict)
474 _dl_printf ("x 0x%0*Zx 0x%0*Zx ",
475 (int) sizeof (ElfW(Addr)) * 2,
476 (size_t) (val.s ? val.m->l_map_start : 0),
477 (int) sizeof (ElfW(Addr)) * 2,
478 (size_t) (val.s ? val.s->st_value : 0));
480 _dl_printf ("/%x %s\n", type_class, undef_name);
483 #endif