(_dl_lookup_symbol): Likewise.
[kopensolaris-gnu/glibc.git] / elf / dl-lookup.c
1 /* Look up a symbol in the loaded objects.
2    Copyright (C) 1995,96,97,98,99,2000  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 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.
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    Library General Public License for more details.
14
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.  */
19
20 #include <alloca.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <ldsodefs.h>
25 #include "dl-hash.h"
26 #include <dl-machine.h>
27 #include <bits/libc-lock.h>
28
29 #include <assert.h>
30
31 #define VERSTAG(tag)    (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (tag))
32
33 /* We need this string more than once.  */
34 static const char undefined_msg[] = "undefined symbol: ";
35
36
37 struct sym_val
38   {
39     const ElfW(Sym) *s;
40     struct link_map *m;
41   };
42
43
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)                \
56       cp = __stpcpy (cp, all[cnt]);                                           \
57                                                                               \
58     result;                                                                   \
59   })
60
61 /* Statistics function.  */
62 unsigned long int _dl_num_relocations;
63
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
73
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"
79
80 #define VERSIONED       1
81 #include "do-lookup.h"
82
83
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 int 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
105   if (__builtin_expect (i == act, 1))
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 (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
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 (__builtin_expect (act < undef_map->l_reldepsmax, 1))
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
183 /* Search loaded objects' symbol tables for a definition of the symbol
184    UNDEF_NAME.  */
185
186 lookup_t
187 internal_function
188 _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
189                    const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
190                    int reloc_type)
191 {
192   const char *reference_name = undef_map ? undef_map->l_name : NULL;
193   const unsigned long int hash = _dl_elf_hash (undef_name);
194   struct sym_val current_value = { NULL, NULL };
195   struct r_scope_elem **scope;
196
197   ++_dl_num_relocations;
198
199   /* Search the relevant loaded objects for a definition.  */
200   for (scope = symbol_scope; *scope; ++scope)
201     if (do_lookup (undef_name, undef_map, hash, *ref, &current_value,
202                    *scope, 0, NULL, reloc_type))
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 (__builtin_expect (current_value.m->l_global, 0)
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       }
221
222   if (__builtin_expect (current_value.s == NULL, 0))
223     {
224       if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
225         /* We could find no value for a strong reference.  */
226         _dl_signal_cerror (0, (reference_name && reference_name[0]
227                                ? reference_name
228                                : (_dl_argv[0] ?: "<main program>")),
229                            make_string (undefined_msg, undef_name));
230       *ref = NULL;
231       return 0;
232     }
233
234   if (__builtin_expect (_dl_debug_bindings, 0))
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]
240                        ? current_value.m->l_name : _dl_argv[0],
241                        ": symbol `", undef_name, "'\n", NULL);
242
243   *ref = current_value.s;
244   return LOOKUP_VALUE (current_value.m);
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 lookup_t
254 internal_function
255 _dl_lookup_symbol_skip (const char *undef_name,
256                         struct link_map *undef_map, const ElfW(Sym) **ref,
257                         struct r_scope_elem *symbol_scope[],
258                         struct link_map *skip_map)
259 {
260   const char *reference_name = undef_map ? undef_map->l_name : NULL;
261   const unsigned long int hash = _dl_elf_hash (undef_name);
262   struct sym_val current_value = { NULL, NULL };
263   struct r_scope_elem **scope;
264   size_t i;
265
266   ++_dl_num_relocations;
267
268   /* Search the relevant loaded objects for a definition.  */
269   scope = symbol_scope;
270   for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
271     assert (i < (*scope)->r_nduplist);
272
273   if (i < (*scope)->r_nlist
274       && do_lookup (undef_name, undef_map, hash, *ref, &current_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
293     while (*++scope)
294       if (do_lookup (undef_name, undef_map, hash, *ref, &current_value,
295                      *scope, 0, skip_map, 0))
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 (__builtin_expect (current_value.m->l_global, 0)
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         }
314
315   if (__builtin_expect (current_value.s == NULL, 0))
316     {
317       *ref = NULL;
318       return 0;
319     }
320
321   if (__builtin_expect (_dl_debug_bindings, 0))
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]
327                        ? current_value.m->l_name : _dl_argv[0],
328                        ": symbol `", undef_name, "' (skip)\n", NULL);
329
330   *ref = current_value.s;
331   return LOOKUP_VALUE (current_value.m);
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 lookup_t
341 internal_function
342 _dl_lookup_versioned_symbol (const char *undef_name,
343                              struct link_map *undef_map, const ElfW(Sym) **ref,
344                              struct r_scope_elem *symbol_scope[],
345                              const struct r_found_version *version,
346                              int reloc_type)
347 {
348   const char *reference_name = undef_map ? undef_map->l_name : NULL;
349   const unsigned long int hash = _dl_elf_hash (undef_name);
350   struct sym_val current_value = { NULL, NULL };
351   struct r_scope_elem **scope;
352
353   ++_dl_num_relocations;
354
355   /* Search the relevant loaded objects for a definition.  */
356   for (scope = symbol_scope; *scope; ++scope)
357     {
358       int res = do_lookup_versioned (undef_name, undef_map, hash, *ref,
359                                      &current_value, *scope, 0, version, NULL,
360                                      reloc_type);
361       if (res > 0)
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 (__builtin_expect (current_value.m->l_global, 0)
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         }
381
382       if (__builtin_expect (res, 0) < 0)
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         }
399     }
400
401   if (__builtin_expect (current_value.s == NULL, 0))
402     {
403       if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
404         /* We could find no value for a strong reference.  */
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));
410       *ref = NULL;
411       return 0;
412     }
413
414   if (__builtin_expect (_dl_debug_bindings, 0))
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]
420                        ? current_value.m->l_name : _dl_argv[0],
421                        ": symbol `", undef_name, "' [", version->name,
422                        "]\n", NULL);
423
424   *ref = current_value.s;
425   return LOOKUP_VALUE (current_value.m);
426 }
427
428
429 /* Similar to _dl_lookup_symbol_skip but takes an additional argument
430    with the version we are looking for.  */
431 lookup_t
432 internal_function
433 _dl_lookup_versioned_symbol_skip (const char *undef_name,
434                                   struct link_map *undef_map,
435                                   const ElfW(Sym) **ref,
436                                   struct r_scope_elem *symbol_scope[],
437                                   const struct r_found_version *version,
438                                   struct link_map *skip_map)
439 {
440   const char *reference_name = undef_map ? undef_map->l_name : NULL;
441   const unsigned long int hash = _dl_elf_hash (undef_name);
442   struct sym_val current_value = { NULL, NULL };
443   struct r_scope_elem **scope;
444   size_t i;
445
446   ++_dl_num_relocations;
447
448   /* Search the relevant loaded objects for a definition.  */
449   scope = symbol_scope;
450   for (i = 0; (*scope)->r_duplist[i] != skip_map; ++i)
451     assert (i < (*scope)->r_nduplist);
452
453   if (i < (*scope)->r_nlist
454       && do_lookup_versioned (undef_name, undef_map, hash, *ref,
455                               &current_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 (__builtin_expect (current_value.m->l_global, 0)
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
474     while (*++scope)
475       if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
476                                &current_value, *scope, 0, version, skip_map,
477                                0))
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         }
496
497   if (__builtin_expect (current_value.s == NULL, 0))
498     {
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);
506           _dl_signal_cerror (0, (reference_name && reference_name[0]
507                                  ? reference_name
508                                  : (_dl_argv[0] ?: "<main program>")), buf);
509         }
510       *ref = NULL;
511       return 0;
512     }
513
514   if (__builtin_expect (_dl_debug_bindings, 0))
515     _dl_debug_message (1, "binding file ",
516                        (reference_name && reference_name[0]
517                         ? reference_name
518                         : (_dl_argv[0] ?: "<main program>")),
519                        " to ",
520                        current_value.m->l_name[0]
521                        ? current_value.m->l_name : _dl_argv[0],
522                        ": symbol `", undef_name, "' [", version->name,
523                        "] (skip)\n", NULL);
524
525   *ref = current_value.s;
526   return LOOKUP_VALUE (current_value.m);
527 }
528
529
530 /* Cache the location of MAP's hash table.  */
531
532 void
533 internal_function
534 _dl_setup_hash (struct link_map *map)
535 {
536   Elf_Symndx *hash;
537   Elf_Symndx nchain;
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
543   map->l_nbuckets = *hash++;
544   nchain = *hash++;
545   map->l_buckets = hash;
546   hash += map->l_nbuckets;
547   map->l_chain = hash;
548 }