]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-lookup.c
[BZ #2510, BZ #2830, BZ #3137, BZ #3313, BZ #3426, BZ #3465, BZ #3480, BZ #3483,...
[thirdparty/glibc.git] / elf / dl-lookup.c
CommitLineData
d66e34cd 1/* Look up a symbol in the loaded objects.
11bf311e 2 Copyright (C) 1995-2005, 2006 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>
8f480b4b 26#include <dl-hash.h>
bc9f6000 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
bdf4a4f1 71/* The actual lookup code. */
a0e3f6f4 72#include "do-lookup.h"
84384f5b 73
84384f5b 74
871b9158
UD
75static uint_fast32_t
76dl_new_hash (const char *s)
77{
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;
82}
83
84
cf197e41
UD
85/* Add extra dependency on MAP to UNDEF_MAP. */
86static int
80d9c5f0 87internal_function
cf197e41
UD
88add_dependency (struct link_map *undef_map, struct link_map *map)
89{
90 struct link_map **list;
c4bb124a 91 struct link_map *runp;
c0282c06 92 unsigned int act;
cf197e41
UD
93 unsigned int i;
94 int result = 0;
95
aff4519d
UD
96 /* Avoid self-references and references to objects which cannot be
97 unloaded anyway. */
c4bb124a
UD
98 if (undef_map == map)
99 return 0;
100
aff4519d
UD
101 /* Make sure nobody can unload the object while we are at it. */
102 __rtld_lock_lock_recursive (GL(dl_load_lock));
103
aff4519d
UD
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;
108
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)
114 {
a752d0cc 115 map->l_flags_1 |= DF_1_NODELETE;
aff4519d
UD
116 goto out;
117 }
cf197e41
UD
118
119 /* Determine whether UNDEF_MAP already has a reference to MAP. First
120 look in the normal dependencies. */
f7e39466 121 if (undef_map->l_initfini != NULL)
cf197e41 122 {
c4bb124a 123 list = undef_map->l_initfini;
cf197e41 124
c4bb124a 125 for (i = 0; list[i] != NULL; ++i)
cf197e41 126 if (list[i] == map)
c4bb124a
UD
127 goto out;
128 }
129
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;
cf197e41 134
c4bb124a
UD
135 for (i = 0; i < act; ++i)
136 if (list[i] == map)
137 goto out;
138
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. */
c0f62c56 144 runp = GL(dl_ns)[undef_map->l_ns]._ns_loaded;
c4bb124a
UD
145 while (runp != NULL && runp != map)
146 runp = runp->l_next;
147
148 if (runp != NULL)
149 {
150 /* The object is still available. Add the reference now. */
151 if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
cf197e41 152 {
c4bb124a
UD
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;
157
158 undef_map->l_reldepsmax += 5;
159 newp = realloc (undef_map->l_reldeps,
160 undef_map->l_reldepsmax
161 * sizeof (struct link_map *));
162
163 if (__builtin_expect (newp != NULL, 1))
164 undef_map->l_reldeps = (struct link_map **) newp;
cf197e41 165 else
c4bb124a
UD
166 /* Correct the addition. */
167 undef_map->l_reldepsmax -= 5;
cf197e41 168 }
c4bb124a
UD
169
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
0b5045fe 175 behavior. */
c4bb124a
UD
176 if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
177 undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
178
c4bb124a 179 /* Display information if we are debugging. */
afdca0f2 180 if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
154d10bd 181 _dl_debug_printf ("\
c0f62c56 182\nfile=%s [%lu]; needed by %s [%lu] (relocation dependency)\n\n",
154d10bd 183 map->l_name[0] ? map->l_name : rtld_progname,
c0f62c56 184 map->l_ns,
154d10bd 185 undef_map->l_name[0]
c0f62c56
UD
186 ? undef_map->l_name : rtld_progname,
187 undef_map->l_ns);
cf197e41 188 }
c4bb124a
UD
189 else
190 /* Whoa, that was bad luck. We have to search again. */
191 result = -1;
cf197e41 192
c4bb124a 193 out:
cf197e41 194 /* Release the lock. */
d3c9f895 195 __rtld_lock_unlock_recursive (GL(dl_load_lock));
cf197e41
UD
196
197 return result;
198}
199
32e6df36
UD
200static void
201internal_function
202_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
c0a777e8 203 const ElfW(Sym) **ref, struct sym_val *value,
7969407a
UD
204 const struct r_found_version *version, int type_class,
205 int protected);
647eb037 206
84384f5b 207
bdf4a4f1 208/* Search loaded objects' symbol tables for a definition of the symbol
609cf614
UD
209 UNDEF_NAME, perhaps with a requested version for the symbol.
210
211 We must never have calls to the audit functions inside this function
212 or in any function which gets called. If this would happen the audit
213 code might create a thread which can throw off all the scope locking. */
c0282c06 214lookup_t
d0fc4041 215internal_function
bdf4a4f1
UD
216_dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
217 const ElfW(Sym) **ref,
218 struct r_scope_elem *symbol_scope[],
219 const struct r_found_version *version,
220 int type_class, int flags, struct link_map *skip_map)
84384f5b 221{
871b9158
UD
222 const uint_fast32_t new_hash = dl_new_hash (undef_name);
223 unsigned long int old_hash = 0xffffffff;
0c367d92 224 struct sym_val current_value = { NULL, NULL };
bdf4a4f1 225 struct r_scope_elem **scope = symbol_scope;
84384f5b 226
be4b5a95 227 bump_num_relocations ();
48f6496e 228
bdf4a4f1
UD
229 /* No other flag than DL_LOOKUP_ADD_DEPENDENCY is allowed if we look
230 up a versioned symbol. */
11bf311e 231 assert (version == NULL || flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY);
c84142e8 232
bdf4a4f1
UD
233 size_t i = 0;
234 if (__builtin_expect (skip_map != NULL, 0))
11bf311e
UD
235 {
236 /* Search the relevant loaded objects for a definition. */
237 while ((*scope)->r_list[i] != skip_map)
238 ++i;
239
240 assert (i < (*scope)->r_nlist);
241 }
32e6df36 242
c84142e8 243 /* Search the relevant loaded objects for a definition. */
bdf4a4f1 244 for (size_t start = i; *scope != NULL; start = 0, ++scope)
1fb05e3d 245 {
871b9158
UD
246 int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref,
247 &current_value, *scope, start, version, flags,
248 skip_map, type_class);
1fb05e3d 249 if (res > 0)
78575a84 250 break;
1fb05e3d 251
bdf4a4f1 252 if (__builtin_expect (res, 0) < 0 && skip_map == NULL)
3f933dc2
UD
253 {
254 /* Oh, oh. The file named in the relocation entry does not
bdf4a4f1
UD
255 contain the needed symbol. This code is never reached
256 for unversioned lookups. */
257 assert (version != NULL);
c90b5d28
UD
258 const char *reference_name = undef_map ? undef_map->l_name : NULL;
259
8e17ea58 260 /* XXX We cannot translate the message. */
32e6df36 261 _dl_signal_cerror (0, (reference_name[0]
3f933dc2 262 ? reference_name
e6caf4e1 263 : (rtld_progname ?: "<main program>")),
407fe3bb 264 N_("relocation error"),
3f933dc2
UD
265 make_string ("symbol ", undef_name, ", version ",
266 version->name,
267 " not defined in file ",
268 version->filename,
269 " with link time reference",
270 res == -2
271 ? " (no version symbols)" : ""));
272 *ref = NULL;
273 return 0;
274 }
1fb05e3d 275 }
c84142e8 276
466a0ec9 277 if (__builtin_expect (current_value.s == NULL, 0))
0c367d92 278 {
bdf4a4f1
UD
279 if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
280 && skip_map == NULL)
c90b5d28
UD
281 {
282 /* We could find no value for a strong reference. */
9363dbb8 283 const char *reference_name = undef_map ? undef_map->l_name : "";
bdf4a4f1
UD
284 const char *versionstr = version ? ", version " : "";
285 const char *versionname = (version && version->name
286 ? version->name : "");
c90b5d28
UD
287
288 /* XXX We cannot translate the message. */
32e6df36 289 _dl_signal_cerror (0, (reference_name[0]
c90b5d28 290 ? reference_name
24a07b1f
UD
291 : (rtld_progname ?: "<main program>")),
292 N_("symbol lookup error"),
c90b5d28 293 make_string (undefined_msg, undef_name,
bdf4a4f1 294 versionstr, versionname));
c90b5d28 295 }
0c367d92
UD
296 *ref = NULL;
297 return 0;
298 }
299
bdf4a4f1
UD
300 int protected = (*ref
301 && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED);
32e6df36 302 if (__builtin_expect (protected != 0, 0))
6aa29abe 303 {
78575a84
UD
304 /* It is very tricky. We need to figure out what value to
305 return for the protected symbol. */
697119d6 306 if (type_class == ELF_RTYPE_CLASS_PLT)
6aa29abe 307 {
697119d6
UD
308 if (current_value.s != NULL && current_value.m != undef_map)
309 {
310 current_value.s = *ref;
311 current_value.m = undef_map;
312 }
313 }
314 else
315 {
316 struct sym_val protected_value = { NULL, NULL };
317
9363dbb8 318 for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
871b9158
UD
319 if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
320 &protected_value, *scope, i, version, flags,
321 skip_map, ELF_RTYPE_CLASS_PLT) != 0)
697119d6
UD
322 break;
323
9363dbb8 324 if (protected_value.s != NULL && protected_value.m != undef_map)
697119d6
UD
325 {
326 current_value.s = *ref;
327 current_value.m = undef_map;
328 }
6aa29abe 329 }
6aa29abe 330 }
32e6df36 331
78575a84
UD
332 /* We have to check whether this would bind UNDEF_MAP to an object
333 in the global scope which was dynamically loaded. In this case
334 we have to prevent the latter from being unloaded unless the
335 UNDEF_MAP object is also unloaded. */
336 if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
337 /* Don't do this for explicit lookups as opposed to implicit
338 runtime lookups. */
bdf4a4f1 339 && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
78575a84
UD
340 /* Add UNDEF_MAP to the dependencies. */
341 && add_dependency (undef_map, current_value.m) < 0)
342 /* Something went wrong. Perhaps the object we tried to reference
343 was just removed. Try finding another definition. */
11bf311e
UD
344 return _dl_lookup_symbol_x (undef_name, undef_map, ref,
345 symbol_scope, version, type_class,
346 flags, skip_map);
78575a84 347
7a11603d
UD
348 /* The object is used. */
349 current_value.m->l_used = 1;
350
afdca0f2 351 if (__builtin_expect (GLRO(dl_debug_mask)
32e6df36 352 & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
c0a777e8 353 _dl_debug_bindings (undef_name, undef_map, ref,
32e6df36
UD
354 &current_value, version, type_class, protected);
355
356 *ref = current_value.s;
357 return LOOKUP_VALUE (current_value.m);
c84142e8
UD
358}
359
360
d66e34cd
RM
361/* Cache the location of MAP's hash table. */
362
363void
d0fc4041 364internal_function
d66e34cd
RM
365_dl_setup_hash (struct link_map *map)
366{
a1eca9f3
UD
367 Elf_Symndx *hash;
368 Elf_Symndx nchain;
f41c8091 369
871b9158
UD
370 if (__builtin_expect (map->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
371 + DT_THISPROCNUM + DT_VERSIONTAGNUM
372 + DT_EXTRANUM + DT_VALNUM] != NULL, 1))
373 {
374 Elf32_Word *hash32
375 = (void *) D_PTR (map, l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
376 + DT_THISPROCNUM + DT_VERSIONTAGNUM
377 + DT_EXTRANUM + DT_VALNUM]);
378 map->l_nbuckets = *hash32++;
379 Elf32_Word symbias = *hash32++;
380 Elf32_Word bitmask_nwords = *hash32++;
381 /* Must be a power of two. */
382 assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0);
383 map->l_gnu_bitmask_idxbits = bitmask_nwords - 1;
384 map->l_gnu_shift = *hash32++;
385
386 map->l_gnu_bitmask = (ElfW(Addr) *) hash32;
387 hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords;
388
389 map->l_gnu_buckets = hash32;
390 hash32 += map->l_nbuckets;
391 map->l_gnu_chain_zero = hash32 - symbias;
392 return;
393 }
394
f41c8091
UD
395 if (!map->l_info[DT_HASH])
396 return;
9a88a2d7 397 hash = (void *) D_PTR (map, l_info[DT_HASH]);
f41c8091 398
d66e34cd
RM
399 map->l_nbuckets = *hash++;
400 nchain = *hash++;
401 map->l_buckets = hash;
402 hash += map->l_nbuckets;
403 map->l_chain = hash;
404}
80d9c5f0 405
f9f2a150 406
32e6df36
UD
407static void
408internal_function
409_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
c0a777e8 410 const ElfW(Sym) **ref, struct sym_val *value,
f9f2a150
UD
411 const struct r_found_version *version, int type_class,
412 int protected)
32e6df36
UD
413{
414 const char *reference_name = undef_map->l_name;
415
afdca0f2 416 if (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS)
32e6df36 417 {
21e2d3a4 418 _dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol `%s'",
154d10bd
UD
419 (reference_name[0]
420 ? reference_name
421 : (rtld_progname ?: "<main program>")),
21e2d3a4 422 undef_map->l_ns,
154d10bd 423 value->m->l_name[0] ? value->m->l_name : rtld_progname,
21e2d3a4 424 value->m->l_ns,
154d10bd 425 protected ? "protected" : "normal", undef_name);
32e6df36
UD
426 if (version)
427 _dl_debug_printf_c (" [%s]\n", version->name);
428 else
429 _dl_debug_printf_c ("\n");
430 }
431#ifdef SHARED
afdca0f2 432 if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
32e6df36
UD
433 {
434 int conflict = 0;
435 struct sym_val val = { NULL, NULL };
436
afdca0f2 437 if ((GLRO(dl_trace_prelink_map) == NULL
c0f62c56
UD
438 || GLRO(dl_trace_prelink_map) == GL(dl_ns)[LM_ID_BASE]._ns_loaded)
439 && undef_map != GL(dl_ns)[LM_ID_BASE]._ns_loaded)
32e6df36 440 {
871b9158
UD
441 const uint_fast32_t new_hash = dl_new_hash (undef_name);
442 unsigned long int old_hash = 0xffffffff;
32e6df36 443
871b9158 444 do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val,
bdf4a4f1
UD
445 undef_map->l_local_scope[0], 0, version, 0, NULL,
446 type_class);
32e6df36
UD
447
448 if (val.s != value->s || val.m != value->m)
449 conflict = 1;
450 }
451
1d0ad773
RM
452 if (value->s
453 && (__builtin_expect (ELFW(ST_TYPE) (value->s->st_info)
454 == STT_TLS, 0)))
455 type_class = 4;
1d0ad773 456
32e6df36 457 if (conflict
afdca0f2
UD
458 || GLRO(dl_trace_prelink_map) == undef_map
459 || GLRO(dl_trace_prelink_map) == NULL
1d0ad773 460 || type_class == 4)
32e6df36
UD
461 {
462 _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
463 conflict ? "conflict" : "lookup",
32e6df36 464 (int) sizeof (ElfW(Addr)) * 2,
d347a4ab 465 (size_t) undef_map->l_map_start,
32e6df36 466 (int) sizeof (ElfW(Addr)) * 2,
d347a4ab 467 (size_t) (((ElfW(Addr)) *ref) - undef_map->l_map_start),
32e6df36 468 (int) sizeof (ElfW(Addr)) * 2,
d347a4ab
UD
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));
32e6df36
UD
472
473 if (conflict)
474 _dl_printf ("x 0x%0*Zx 0x%0*Zx ",
475 (int) sizeof (ElfW(Addr)) * 2,
d347a4ab 476 (size_t) (val.s ? val.m->l_map_start : 0),
32e6df36 477 (int) sizeof (ElfW(Addr)) * 2,
d347a4ab 478 (size_t) (val.s ? val.s->st_value : 0));
32e6df36
UD
479
480 _dl_printf ("/%x %s\n", type_class, undef_name);
481 }
482 }
483#endif
484}