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