]>
Commit | Line | Data |
---|---|---|
d66e34cd | 1 | /* Look up a symbol in the loaded objects. |
a42195db | 2 | Copyright (C) 1995,96,97,98,99,2000 Free Software Foundation, Inc. |
afd4eb37 | 3 | This file is part of the GNU C Library. |
d66e34cd | 4 | |
afd4eb37 UD |
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. | |
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 | |
13 | Library General Public License for more details. | |
d66e34cd | 14 | |
afd4eb37 UD |
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. */ | |
d66e34cd | 19 | |
f671aeab | 20 | #include <alloca.h> |
cf197e41 | 21 | #include <stdlib.h> |
8d6468d0 | 22 | #include <string.h> |
3db52d94 | 23 | #include <unistd.h> |
a42195db | 24 | #include <ldsodefs.h> |
bc9f6000 UD |
25 | #include "dl-hash.h" |
26 | #include <dl-machine.h> | |
cf197e41 | 27 | #include <bits/libc-lock.h> |
c84142e8 | 28 | |
a853022c UD |
29 | #include <assert.h> |
30 | ||
c84142e8 | 31 | #define VERSTAG(tag) (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (tag)) |
266180eb | 32 | |
714a562f UD |
33 | /* We need this string more than once. */ |
34 | static const char undefined_msg[] = "undefined symbol: "; | |
35 | ||
36 | ||
84384f5b UD |
37 | struct sym_val |
38 | { | |
84384f5b | 39 | const ElfW(Sym) *s; |
0c367d92 | 40 | struct link_map *m; |
84384f5b UD |
41 | }; |
42 | ||
43 | ||
1fb05e3d UD |
44 | #define make_string(string, rest...) \ |
45 | ({ \ | |
46 | const char *all[] = { string, ## rest }; \ | |
47 | size_t len, cnt; \ | |
48 | char *result, *cp; \ | |
49 | \ | |
50 | len = 1; \ | |
51 | for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \ | |
52 | len += strlen (all[cnt]); \ | |
53 | \ | |
54 | cp = result = alloca (len); \ | |
55 | for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \ | |
da832465 | 56 | cp = __stpcpy (cp, all[cnt]); \ |
1fb05e3d UD |
57 | \ |
58 | result; \ | |
59 | }) | |
60 | ||
8352b484 UD |
61 | /* Statistics function. */ |
62 | unsigned long int _dl_num_relocations; | |
63 | ||
cf197e41 UD |
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. | |
67 | ||
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) | |
72 | ||
1fb05e3d | 73 | |
a0e3f6f4 UD |
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. */ | |
77 | #define VERSIONED 0 | |
78 | #include "do-lookup.h" | |
84384f5b | 79 | |
a0e3f6f4 UD |
80 | #define VERSIONED 1 |
81 | #include "do-lookup.h" | |
84384f5b | 82 | |
84384f5b | 83 | |
cf197e41 UD |
84 | /* Add extra dependency on MAP to UNDEF_MAP. */ |
85 | static int | |
86 | add_dependency (struct link_map *undef_map, struct link_map *map) | |
87 | { | |
88 | struct link_map **list; | |
89 | unsigned act; | |
90 | unsigned int i; | |
91 | int result = 0; | |
92 | ||
93 | /* Make sure nobody can unload the object while we are at it. */ | |
94 | __libc_lock_lock (_dl_load_lock); | |
95 | ||
96 | /* Determine whether UNDEF_MAP already has a reference to MAP. First | |
97 | look in the normal dependencies. */ | |
98 | list = undef_map->l_searchlist.r_list; | |
99 | act = undef_map->l_searchlist.r_nlist; | |
100 | ||
101 | for (i = 0; i < act; ++i) | |
102 | if (list[i] == map) | |
103 | break; | |
104 | ||
e3265f5b | 105 | if (__builtin_expect (i == act, 1)) |
cf197e41 UD |
106 | { |
107 | /* No normal dependency. See whether we already had to add it | |
108 | to the special list of dynamic dependencies. */ | |
109 | list = undef_map->l_reldeps; | |
110 | act = undef_map->l_reldepsact; | |
111 | ||
112 | for (i = 0; i < act; ++i) | |
113 | if (list[i] == map) | |
114 | break; | |
115 | ||
116 | if (i == act) | |
117 | { | |
118 | /* The object is not yet in the dependency list. Before we add | |
119 | it make sure just one more time the object we are about to | |
120 | reference is still available. There is a brief period in | |
121 | which the object could have been removed since we found the | |
122 | definition. */ | |
123 | struct link_map *runp = _dl_loaded; | |
124 | ||
125 | while (runp != NULL && runp != map) | |
126 | runp = runp->l_next; | |
127 | ||
128 | if (runp != NULL) | |
129 | { | |
130 | /* The object is still available. Add the reference now. */ | |
131 | if (act >= undef_map->l_reldepsmax) | |
132 | { | |
133 | /* Allocate more memory for the dependency list. Since | |
134 | this can never happen during the startup phase we can | |
135 | use `realloc'. */ | |
136 | void *newp; | |
137 | ||
138 | undef_map->l_reldepsmax += 5; | |
139 | newp = realloc (undef_map->l_reldeps, | |
140 | undef_map->l_reldepsmax); | |
141 | ||
142 | if (__builtin_expect (newp != NULL, 1)) | |
143 | undef_map->l_reldeps = (struct link_map **) newp; | |
144 | else | |
145 | /* Correct the addition. */ | |
146 | undef_map->l_reldepsmax -= 5; | |
147 | } | |
148 | ||
149 | /* If we didn't manage to allocate memory for the list this | |
150 | is no fatal mistake. We simply increment the use counter | |
151 | of the referenced object and don't record the dependencies. | |
152 | This means this increment can never be reverted and the | |
153 | object will never be unloaded. This is semantically the | |
154 | correct behaviour. */ | |
155 | if (act < undef_map->l_reldepsmax) | |
156 | undef_map->l_reldeps[undef_map->l_reldepsact++] = map; | |
157 | ||
158 | /* And increment the counter in the referenced object. */ | |
159 | ++map->l_opencount; | |
160 | ||
161 | /* Display information if we are debugging. */ | |
162 | if (__builtin_expect (_dl_debug_files, 0)) | |
163 | _dl_debug_message (1, "\nfile=", | |
164 | map->l_name[0] ? map->l_name : _dl_argv[0], | |
165 | "; needed by ", | |
166 | undef_map->l_name[0] | |
167 | ? undef_map->l_name : _dl_argv[0], | |
168 | " (relocation dependency)\n\n", NULL); | |
169 | } | |
170 | else | |
171 | /* Whoa, that was bad luck. We have to search again. */ | |
172 | result = -1; | |
173 | } | |
174 | } | |
175 | ||
176 | /* Release the lock. */ | |
177 | __libc_lock_unlock (_dl_load_lock); | |
178 | ||
179 | return result; | |
180 | } | |
181 | ||
182 | ||
6c03c2cf | 183 | /* Search loaded objects' symbol tables for a definition of the symbol |
bc9f6000 | 184 | UNDEF_NAME. */ |
d66e34cd | 185 | |
266180eb | 186 | ElfW(Addr) |
d0fc4041 | 187 | internal_function |
06535ae9 UD |
188 | _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map, |
189 | const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[], | |
bc9f6000 | 190 | int reloc_type) |
d66e34cd | 191 | { |
06535ae9 | 192 | const char *reference_name = undef_map ? undef_map->l_name : NULL; |
266180eb | 193 | const unsigned long int hash = _dl_elf_hash (undef_name); |
0c367d92 | 194 | struct sym_val current_value = { NULL, NULL }; |
be935610 | 195 | struct r_scope_elem **scope; |
d66e34cd | 196 | |
48f6496e UD |
197 | ++_dl_num_relocations; |
198 | ||
d66e34cd | 199 | /* Search the relevant loaded objects for a definition. */ |
ba79d61b | 200 | for (scope = symbol_scope; *scope; ++scope) |
06535ae9 UD |
201 | if (do_lookup (undef_name, undef_map, hash, *ref, ¤t_value, |
202 | *scope, 0, NULL, reloc_type)) | |
cf197e41 UD |
203 | { |
204 | /* We have to check whether this would bind UNDEF_MAP to an object | |
205 | in the global scope which was dynamically loaded. In this case | |
206 | we have to prevent the latter from being unloaded unless the | |
207 | UNDEF_MAP object is also unloaded. */ | |
208 | if (current_value.m->l_global | |
209 | && (__builtin_expect (current_value.m->l_type, lt_library) | |
210 | == lt_loaded) | |
211 | && undef_map != current_value.m | |
212 | /* Add UNDEF_MAP to the dependencies. */ | |
213 | && add_dependency (undef_map, current_value.m) < 0) | |
214 | /* Something went wrong. Perhaps the object we tried to reference | |
215 | was just removed. Try finding another definition. */ | |
216 | return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope, | |
217 | reloc_type); | |
218 | ||
219 | break; | |
220 | } | |
ba79d61b | 221 | |
0c367d92 UD |
222 | if (current_value.s == NULL) |
223 | { | |
224 | if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) | |
225 | /* We could find no value for a strong reference. */ | |
7730a3b9 | 226 | _dl_signal_cerror (0, (reference_name && reference_name[0] |
3f933dc2 UD |
227 | ? reference_name |
228 | : (_dl_argv[0] ?: "<main program>")), | |
229 | make_string (undefined_msg, undef_name)); | |
0c367d92 UD |
230 | *ref = NULL; |
231 | return 0; | |
232 | } | |
233 | ||
cf197e41 | 234 | if (__builtin_expect (_dl_debug_bindings, 0)) |
bc526b60 UD |
235 | _dl_debug_message (1, "binding file ", |
236 | (reference_name && reference_name[0] | |
237 | ? reference_name | |
238 | : (_dl_argv[0] ?: "<main program>")), | |
239 | " to ", current_value.m->l_name[0] | |
0c367d92 UD |
240 | ? current_value.m->l_name : _dl_argv[0], |
241 | ": symbol `", undef_name, "'\n", NULL); | |
d66e34cd | 242 | |
84384f5b | 243 | *ref = current_value.s; |
0c367d92 | 244 | return current_value.m->l_addr; |
84384f5b UD |
245 | } |
246 | ||
247 | ||
248 | /* This function is nearly the same as `_dl_lookup_symbol' but it | |
249 | skips in the first list all objects until SKIP_MAP is found. I.e., | |
250 | it only considers objects which were loaded after the described | |
251 | object. If there are more search lists the object described by | |
252 | SKIP_MAP is only skipped. */ | |
253 | ElfW(Addr) | |
d0fc4041 | 254 | internal_function |
06535ae9 UD |
255 | _dl_lookup_symbol_skip (const char *undef_name, |
256 | struct link_map *undef_map, const ElfW(Sym) **ref, | |
be935610 | 257 | struct r_scope_elem *symbol_scope[], |
bc9f6000 | 258 | struct link_map *skip_map) |
84384f5b | 259 | { |
06535ae9 | 260 | const char *reference_name = undef_map ? undef_map->l_name : NULL; |
84384f5b | 261 | const unsigned long int hash = _dl_elf_hash (undef_name); |
0c367d92 | 262 | struct sym_val current_value = { NULL, NULL }; |
be935610 | 263 | struct r_scope_elem **scope; |
84384f5b UD |
264 | size_t i; |
265 | ||
48f6496e UD |
266 | ++_dl_num_relocations; |
267 | ||
84384f5b UD |
268 | /* Search the relevant loaded objects for a definition. */ |
269 | scope = symbol_scope; | |
be935610 UD |
270 | for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i) |
271 | assert (i < (*scope)->r_nduplist); | |
84384f5b | 272 | |
cf197e41 UD |
273 | if (i < (*scope)->r_nlist |
274 | && do_lookup (undef_name, undef_map, hash, *ref, ¤t_value, | |
275 | *scope, i, skip_map, 0)) | |
276 | { | |
277 | /* We have to check whether this would bind UNDEF_MAP to an object | |
278 | in the global scope which was dynamically loaded. In this case | |
279 | we have to prevent the latter from being unloaded unless the | |
280 | UNDEF_MAP object is also unloaded. */ | |
281 | if (current_value.m->l_global | |
282 | && (__builtin_expect (current_value.m->l_type, lt_library) | |
283 | == lt_loaded) | |
284 | && undef_map != current_value.m | |
285 | /* Add UNDEF_MAP to the dependencies. */ | |
286 | && add_dependency (undef_map, current_value.m) < 0) | |
287 | /* Something went wrong. Perhaps the object we tried to reference | |
288 | was just removed. Try finding another definition. */ | |
289 | return _dl_lookup_symbol_skip (undef_name, undef_map, ref, | |
290 | symbol_scope, skip_map); | |
291 | } | |
292 | else | |
c84142e8 | 293 | while (*++scope) |
06535ae9 UD |
294 | if (do_lookup (undef_name, undef_map, hash, *ref, ¤t_value, |
295 | *scope, 0, skip_map, 0)) | |
cf197e41 UD |
296 | { |
297 | /* We have to check whether this would bind UNDEF_MAP to an object | |
298 | in the global scope which was dynamically loaded. In this case | |
299 | we have to prevent the latter from being unloaded unless the | |
300 | UNDEF_MAP object is also unloaded. */ | |
301 | if (current_value.m->l_global | |
302 | && (__builtin_expect (current_value.m->l_type, lt_library) | |
303 | == lt_loaded) | |
304 | && undef_map != current_value.m | |
305 | /* Add UNDEF_MAP to the dependencies. */ | |
306 | && add_dependency (undef_map, current_value.m) < 0) | |
307 | /* Something went wrong. Perhaps the object we tried to reference | |
308 | was just removed. Try finding another definition. */ | |
309 | return _dl_lookup_symbol_skip (undef_name, undef_map, ref, | |
310 | symbol_scope, skip_map); | |
311 | ||
312 | break; | |
313 | } | |
c84142e8 | 314 | |
0c367d92 UD |
315 | if (current_value.s == NULL) |
316 | { | |
317 | *ref = NULL; | |
318 | return 0; | |
319 | } | |
320 | ||
cf197e41 | 321 | if (__builtin_expect (_dl_debug_bindings, 0)) |
bc526b60 UD |
322 | _dl_debug_message (1, "binding file ", |
323 | (reference_name && reference_name[0] | |
324 | ? reference_name | |
325 | : (_dl_argv[0] ?: "<main program>")), | |
326 | " to ", current_value.m->l_name[0] | |
0c367d92 | 327 | ? current_value.m->l_name : _dl_argv[0], |
bc526b60 | 328 | ": symbol `", undef_name, "' (skip)\n", NULL); |
0c367d92 | 329 | |
c84142e8 | 330 | *ref = current_value.s; |
0c367d92 | 331 | return current_value.m->l_addr; |
c84142e8 UD |
332 | } |
333 | ||
334 | ||
335 | /* This function works like _dl_lookup_symbol but it takes an | |
336 | additional arguement with the version number of the requested | |
337 | symbol. | |
338 | ||
339 | XXX We'll see whether we need this separate function. */ | |
340 | ElfW(Addr) | |
d0fc4041 | 341 | internal_function |
06535ae9 UD |
342 | _dl_lookup_versioned_symbol (const char *undef_name, |
343 | struct link_map *undef_map, const ElfW(Sym) **ref, | |
be935610 | 344 | struct r_scope_elem *symbol_scope[], |
bc9f6000 UD |
345 | const struct r_found_version *version, |
346 | int reloc_type) | |
c84142e8 | 347 | { |
06535ae9 | 348 | const char *reference_name = undef_map ? undef_map->l_name : NULL; |
c84142e8 | 349 | const unsigned long int hash = _dl_elf_hash (undef_name); |
0c367d92 | 350 | struct sym_val current_value = { NULL, NULL }; |
be935610 | 351 | struct r_scope_elem **scope; |
c84142e8 | 352 | |
48f6496e UD |
353 | ++_dl_num_relocations; |
354 | ||
c84142e8 UD |
355 | /* Search the relevant loaded objects for a definition. */ |
356 | for (scope = symbol_scope; *scope; ++scope) | |
1fb05e3d | 357 | { |
06535ae9 UD |
358 | int res = do_lookup_versioned (undef_name, undef_map, hash, *ref, |
359 | ¤t_value, *scope, 0, version, NULL, | |
a0e3f6f4 | 360 | reloc_type); |
1fb05e3d | 361 | if (res > 0) |
cf197e41 UD |
362 | { |
363 | /* We have to check whether this would bind UNDEF_MAP to an object | |
364 | in the global scope which was dynamically loaded. In this case | |
365 | we have to prevent the latter from being unloaded unless the | |
366 | UNDEF_MAP object is also unloaded. */ | |
367 | if (current_value.m->l_global | |
368 | && (__builtin_expect (current_value.m->l_type, lt_library) | |
369 | == lt_loaded) | |
370 | && undef_map != current_value.m | |
371 | /* Add UNDEF_MAP to the dependencies. */ | |
372 | && add_dependency (undef_map, current_value.m) < 0) | |
373 | /* Something went wrong. Perhaps the object we tried to reference | |
374 | was just removed. Try finding another definition. */ | |
375 | return _dl_lookup_versioned_symbol (undef_name, undef_map, ref, | |
376 | symbol_scope, version, | |
377 | reloc_type); | |
378 | ||
379 | break; | |
380 | } | |
1fb05e3d UD |
381 | |
382 | if (res < 0) | |
3f933dc2 UD |
383 | { |
384 | /* Oh, oh. The file named in the relocation entry does not | |
385 | contain the needed symbol. */ | |
386 | _dl_signal_cerror (0, (reference_name && reference_name[0] | |
387 | ? reference_name | |
388 | : (_dl_argv[0] ?: "<main program>")), | |
389 | make_string ("symbol ", undef_name, ", version ", | |
390 | version->name, | |
391 | " not defined in file ", | |
392 | version->filename, | |
393 | " with link time reference", | |
394 | res == -2 | |
395 | ? " (no version symbols)" : "")); | |
396 | *ref = NULL; | |
397 | return 0; | |
398 | } | |
1fb05e3d | 399 | } |
c84142e8 | 400 | |
0c367d92 UD |
401 | if (current_value.s == NULL) |
402 | { | |
403 | if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) | |
404 | /* We could find no value for a strong reference. */ | |
3f933dc2 UD |
405 | _dl_signal_cerror (0, (reference_name && reference_name[0] |
406 | ? reference_name | |
407 | : (_dl_argv[0] ?: "<main program>")), | |
408 | make_string (undefined_msg, undef_name, | |
409 | ", version ", version->name ?: NULL)); | |
0c367d92 UD |
410 | *ref = NULL; |
411 | return 0; | |
412 | } | |
413 | ||
cf197e41 | 414 | if (__builtin_expect (_dl_debug_bindings, 0)) |
bc526b60 UD |
415 | _dl_debug_message (1, "binding file ", |
416 | (reference_name && reference_name[0] | |
417 | ? reference_name | |
418 | : (_dl_argv[0] ?: "<main program>")), | |
419 | " to ", current_value.m->l_name[0] | |
0c367d92 | 420 | ? current_value.m->l_name : _dl_argv[0], |
db0b91a9 UD |
421 | ": symbol `", undef_name, "' [", version->name, |
422 | "]\n", NULL); | |
c84142e8 UD |
423 | |
424 | *ref = current_value.s; | |
0c367d92 | 425 | return current_value.m->l_addr; |
c84142e8 UD |
426 | } |
427 | ||
428 | ||
429 | /* Similar to _dl_lookup_symbol_skip but takes an additional argument | |
430 | with the version we are looking for. */ | |
431 | ElfW(Addr) | |
d0fc4041 | 432 | internal_function |
c84142e8 | 433 | _dl_lookup_versioned_symbol_skip (const char *undef_name, |
06535ae9 | 434 | struct link_map *undef_map, |
c84142e8 | 435 | const ElfW(Sym) **ref, |
be935610 | 436 | struct r_scope_elem *symbol_scope[], |
1fb05e3d | 437 | const struct r_found_version *version, |
bc9f6000 | 438 | struct link_map *skip_map) |
c84142e8 | 439 | { |
06535ae9 | 440 | const char *reference_name = undef_map ? undef_map->l_name : NULL; |
c84142e8 | 441 | const unsigned long int hash = _dl_elf_hash (undef_name); |
0c367d92 | 442 | struct sym_val current_value = { NULL, NULL }; |
be935610 | 443 | struct r_scope_elem **scope; |
c84142e8 UD |
444 | size_t i; |
445 | ||
48f6496e UD |
446 | ++_dl_num_relocations; |
447 | ||
c84142e8 UD |
448 | /* Search the relevant loaded objects for a definition. */ |
449 | scope = symbol_scope; | |
be935610 UD |
450 | for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i) |
451 | assert (i < (*scope)->r_nduplist); | |
c84142e8 | 452 | |
cf197e41 UD |
453 | if (i < (*scope)->r_nlist |
454 | && do_lookup_versioned (undef_name, undef_map, hash, *ref, | |
455 | ¤t_value, *scope, i, version, skip_map, 0)) | |
456 | { | |
457 | /* We have to check whether this would bind UNDEF_MAP to an object | |
458 | in the global scope which was dynamically loaded. In this case | |
459 | we have to prevent the latter from being unloaded unless the | |
460 | UNDEF_MAP object is also unloaded. */ | |
461 | if (current_value.m->l_global | |
462 | && (__builtin_expect (current_value.m->l_type, lt_library) | |
463 | == lt_loaded) | |
464 | && undef_map != current_value.m | |
465 | /* Add UNDEF_MAP to the dependencies. */ | |
466 | && add_dependency (undef_map, current_value.m) < 0) | |
467 | /* Something went wrong. Perhaps the object we tried to reference | |
468 | was just removed. Try finding another definition. */ | |
469 | return _dl_lookup_versioned_symbol_skip (undef_name, undef_map, ref, | |
470 | symbol_scope, version, | |
471 | skip_map); | |
472 | } | |
473 | else | |
84384f5b | 474 | while (*++scope) |
06535ae9 UD |
475 | if (do_lookup_versioned (undef_name, undef_map, hash, *ref, |
476 | ¤t_value, *scope, 0, version, skip_map, | |
477 | 0)) | |
cf197e41 UD |
478 | { |
479 | /* We have to check whether this would bind UNDEF_MAP to an object | |
480 | in the global scope which was dynamically loaded. In this case | |
481 | we have to prevent the latter from being unloaded unless the | |
482 | UNDEF_MAP object is also unloaded. */ | |
483 | if (current_value.m->l_global | |
484 | && (__builtin_expect (current_value.m->l_type, lt_library) | |
485 | == lt_loaded) | |
486 | && undef_map != current_value.m | |
487 | /* Add UNDEF_MAP to the dependencies. */ | |
488 | && add_dependency (undef_map, current_value.m) < 0) | |
489 | /* Something went wrong. Perhaps the object we tried to reference | |
490 | was just removed. Try finding another definition. */ | |
491 | return _dl_lookup_versioned_symbol_skip (undef_name, undef_map, | |
492 | ref, symbol_scope, | |
493 | version, skip_map); | |
494 | break; | |
495 | } | |
84384f5b | 496 | |
0c367d92 | 497 | if (current_value.s == NULL) |
1f205a47 | 498 | { |
0c367d92 UD |
499 | if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) |
500 | { | |
501 | /* We could find no value for a strong reference. */ | |
502 | const size_t len = strlen (undef_name); | |
503 | char buf[sizeof undefined_msg + len]; | |
504 | __mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1), | |
505 | undef_name, len + 1); | |
3f933dc2 UD |
506 | _dl_signal_cerror (0, (reference_name && reference_name[0] |
507 | ? reference_name | |
508 | : (_dl_argv[0] ?: "<main program>")), buf); | |
0c367d92 UD |
509 | } |
510 | *ref = NULL; | |
511 | return 0; | |
1f205a47 UD |
512 | } |
513 | ||
cf197e41 | 514 | if (__builtin_expect (_dl_debug_bindings, 0)) |
bc526b60 UD |
515 | _dl_debug_message (1, "binding file ", |
516 | (reference_name && reference_name[0] | |
517 | ? reference_name | |
518 | : (_dl_argv[0] ?: "<main program>")), | |
519 | " to ", | |
0c367d92 UD |
520 | current_value.m->l_name[0] |
521 | ? current_value.m->l_name : _dl_argv[0], | |
db0b91a9 | 522 | ": symbol `", undef_name, "' [", version->name, |
bc526b60 | 523 | "] (skip)\n", NULL); |
0c367d92 | 524 | |
84384f5b | 525 | *ref = current_value.s; |
0c367d92 | 526 | return current_value.m->l_addr; |
d66e34cd RM |
527 | } |
528 | ||
529 | ||
530 | /* Cache the location of MAP's hash table. */ | |
531 | ||
532 | void | |
d0fc4041 | 533 | internal_function |
d66e34cd RM |
534 | _dl_setup_hash (struct link_map *map) |
535 | { | |
a1eca9f3 UD |
536 | Elf_Symndx *hash; |
537 | Elf_Symndx nchain; | |
f41c8091 UD |
538 | |
539 | if (!map->l_info[DT_HASH]) | |
540 | return; | |
541 | hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr); | |
542 | ||
d66e34cd RM |
543 | map->l_nbuckets = *hash++; |
544 | nchain = *hash++; | |
545 | map->l_buckets = hash; | |
546 | hash += map->l_nbuckets; | |
547 | map->l_chain = hash; | |
548 | } |