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