Back to index

glibc  2.9
dl-lookup.c
Go to the documentation of this file.
00001 /* Look up a symbol in the loaded objects.
00002    Copyright (C) 1995-2005, 2006, 2007 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <alloca.h>
00021 #include <libintl.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <unistd.h>
00025 #include <ldsodefs.h>
00026 #include <dl-hash.h>
00027 #include <dl-machine.h>
00028 #include <sysdep-cancel.h>
00029 #include <bits/libc-lock.h>
00030 #include <tls.h>
00031 
00032 #include <assert.h>
00033 
00034 #define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
00035 
00036 /* We need this string more than once.  */
00037 static const char undefined_msg[] = "undefined symbol: ";
00038 
00039 
00040 struct sym_val
00041   {
00042     const ElfW(Sym) *s;
00043     struct link_map *m;
00044   };
00045 
00046 
00047 #define make_string(string, rest...) \
00048   ({                                                                 \
00049     const char *all[] = { string, ## rest };                                \
00050     size_t len, cnt;                                                 \
00051     char *result, *cp;                                                      \
00052                                                                      \
00053     len = 1;                                                         \
00054     for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)              \
00055       len += strlen (all[cnt]);                                             \
00056                                                                      \
00057     cp = result = alloca (len);                                             \
00058     for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)              \
00059       cp = __stpcpy (cp, all[cnt]);                                         \
00060                                                                      \
00061     result;                                                          \
00062   })
00063 
00064 /* Statistics function.  */
00065 #ifdef SHARED
00066 # define bump_num_relocations() ++GL(dl_num_relocations)
00067 #else
00068 # define bump_num_relocations() ((void) 0)
00069 #endif
00070 
00071 
00072 /* The actual lookup code.  */
00073 #include "do-lookup.h"
00074 
00075 
00076 static uint_fast32_t
00077 dl_new_hash (const char *s)
00078 {
00079   uint_fast32_t h = 5381;
00080   for (unsigned char c = *s; c != '\0'; c = *++s)
00081     h = h * 33 + c;
00082   return h & 0xffffffff;
00083 }
00084 
00085 
00086 /* Add extra dependency on MAP to UNDEF_MAP.  */
00087 static int
00088 internal_function
00089 add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
00090 {
00091   struct link_map *runp;
00092   unsigned int i;
00093   int result = 0;
00094 
00095   /* Avoid self-references and references to objects which cannot be
00096      unloaded anyway.  */
00097   if (undef_map == map)
00098     return 0;
00099 
00100   /* Avoid references to objects which cannot be unloaded anyway.  */
00101   assert (map->l_type == lt_loaded);
00102   if ((map->l_flags_1 & DF_1_NODELETE) != 0)
00103     return 0;
00104 
00105   struct link_map_reldeps *l_reldeps
00106     = atomic_forced_read (undef_map->l_reldeps);
00107 
00108   /* Make sure l_reldeps is read before l_initfini.  */
00109   atomic_read_barrier ();
00110 
00111   /* Determine whether UNDEF_MAP already has a reference to MAP.  First
00112      look in the normal dependencies.  */
00113   struct link_map **l_initfini = atomic_forced_read (undef_map->l_initfini);
00114   if (l_initfini != NULL)
00115     {
00116       for (i = 0; l_initfini[i] != NULL; ++i)
00117        if (l_initfini[i] == map)
00118          return 0;
00119     }
00120 
00121   /* No normal dependency.  See whether we already had to add it
00122      to the special list of dynamic dependencies.  */
00123   unsigned int l_reldepsact = 0;
00124   if (l_reldeps != NULL)
00125     {
00126       struct link_map **list = &l_reldeps->list[0];
00127       l_reldepsact = l_reldeps->act;
00128       for (i = 0; i < l_reldepsact; ++i)
00129        if (list[i] == map)
00130          return 0;
00131     }
00132 
00133   /* Save serial number of the target MAP.  */
00134   unsigned long long serial = map->l_serial;
00135 
00136   /* Make sure nobody can unload the object while we are at it.  */
00137   if (__builtin_expect (flags & DL_LOOKUP_GSCOPE_LOCK, 0))
00138     {
00139       /* We can't just call __rtld_lock_lock_recursive (GL(dl_load_lock))
00140         here, that can result in ABBA deadlock.  */
00141       THREAD_GSCOPE_RESET_FLAG ();
00142       __rtld_lock_lock_recursive (GL(dl_load_lock));
00143       /* While MAP value won't change, after THREAD_GSCOPE_RESET_FLAG ()
00144         it can e.g. point to unallocated memory.  So avoid the optimizer
00145         treating the above read from MAP->l_serial as ensurance it
00146         can safely dereference it.  */
00147       map = atomic_forced_read (map);
00148 
00149       /* From this point on it is unsafe to dereference MAP, until it
00150         has been found in one of the lists.  */
00151 
00152       /* Redo the l_initfini check in case undef_map's l_initfini
00153         changed in the mean time.  */
00154       if (undef_map->l_initfini != l_initfini
00155          && undef_map->l_initfini != NULL)
00156        {
00157          l_initfini = undef_map->l_initfini;
00158          for (i = 0; l_initfini[i] != NULL; ++i)
00159            if (l_initfini[i] == map)
00160              goto out_check;
00161        }
00162 
00163       /* Redo the l_reldeps check if undef_map's l_reldeps changed in
00164         the mean time.  */
00165       if (undef_map->l_reldeps != NULL)
00166        {
00167          if (undef_map->l_reldeps != l_reldeps)
00168            {
00169              struct link_map **list = &undef_map->l_reldeps->list[0];
00170              l_reldepsact = undef_map->l_reldeps->act;
00171              for (i = 0; i < l_reldepsact; ++i)
00172               if (list[i] == map)
00173                 goto out_check;
00174            }
00175          else if (undef_map->l_reldeps->act > l_reldepsact)
00176            {
00177              struct link_map **list
00178               = &undef_map->l_reldeps->list[0];
00179              i = l_reldepsact;
00180              l_reldepsact = undef_map->l_reldeps->act;
00181              for (; i < l_reldepsact; ++i)
00182               if (list[i] == map)
00183                 goto out_check;
00184            }
00185        }
00186     }
00187   else
00188     __rtld_lock_lock_recursive (GL(dl_load_lock));
00189 
00190   /* The object is not yet in the dependency list.  Before we add
00191      it make sure just one more time the object we are about to
00192      reference is still available.  There is a brief period in
00193      which the object could have been removed since we found the
00194      definition.  */
00195   runp = GL(dl_ns)[undef_map->l_ns]._ns_loaded;
00196   while (runp != NULL && runp != map)
00197     runp = runp->l_next;
00198 
00199   if (runp != NULL)
00200     {
00201       /* The object is still available.  */
00202 
00203       /* MAP could have been dlclosed, freed and then some other dlopened
00204         library could have the same link_map pointer.  */
00205       if (map->l_serial != serial)
00206        goto out_check;
00207 
00208       /* Redo the NODELETE check, as when dl_load_lock wasn't held
00209         yet this could have changed.  */
00210       if ((map->l_flags_1 & DF_1_NODELETE) != 0)
00211        goto out;
00212 
00213       /* If the object with the undefined reference cannot be removed ever
00214         just make sure the same is true for the object which contains the
00215         definition.  */
00216       if (undef_map->l_type != lt_loaded
00217          || (undef_map->l_flags_1 & DF_1_NODELETE) != 0)
00218        {
00219          map->l_flags_1 |= DF_1_NODELETE;
00220          goto out;
00221        }
00222 
00223       /* Add the reference now.  */
00224       if (__builtin_expect (l_reldepsact >= undef_map->l_reldepsmax, 0))
00225        {
00226          /* Allocate more memory for the dependency list.  Since this
00227             can never happen during the startup phase we can use
00228             `realloc'.  */
00229          struct link_map_reldeps *newp;
00230          unsigned int max
00231            = undef_map->l_reldepsmax ? undef_map->l_reldepsmax * 2 : 10;
00232 
00233          newp = malloc (sizeof (*newp) + max * sizeof (struct link_map *));
00234          if (newp == NULL)
00235            {
00236              /* If we didn't manage to allocate memory for the list this is
00237                no fatal problem.  We simply make sure the referenced object
00238                cannot be unloaded.  This is semantically the correct
00239                behavior.  */
00240              map->l_flags_1 |= DF_1_NODELETE;
00241              goto out;
00242            }
00243          else
00244            {
00245              if (l_reldepsact)
00246               memcpy (&newp->list[0], &undef_map->l_reldeps->list[0],
00247                      l_reldepsact * sizeof (struct link_map *));
00248              newp->list[l_reldepsact] = map;
00249              newp->act = l_reldepsact + 1;
00250              atomic_write_barrier ();
00251              void *old = undef_map->l_reldeps;
00252              undef_map->l_reldeps = newp;
00253              undef_map->l_reldepsmax = max;
00254              if (old)
00255               _dl_scope_free (old);
00256            }
00257        }
00258       else
00259        {
00260          undef_map->l_reldeps->list[l_reldepsact] = map;
00261          atomic_write_barrier ();
00262          undef_map->l_reldeps->act = l_reldepsact + 1;
00263        }
00264 
00265       /* Display information if we are debugging.  */
00266       if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
00267        _dl_debug_printf ("\
00268 \nfile=%s [%lu];  needed by %s [%lu] (relocation dependency)\n\n",
00269                        map->l_name[0] ? map->l_name : rtld_progname,
00270                        map->l_ns,
00271                        undef_map->l_name[0]
00272                        ? undef_map->l_name : rtld_progname,
00273                        undef_map->l_ns);
00274     }
00275   else
00276     /* Whoa, that was bad luck.  We have to search again.  */
00277     result = -1;
00278 
00279  out:
00280   /* Release the lock.  */
00281   __rtld_lock_unlock_recursive (GL(dl_load_lock));
00282 
00283   if (__builtin_expect (flags & DL_LOOKUP_GSCOPE_LOCK, 0))
00284     THREAD_GSCOPE_SET_FLAG ();
00285 
00286   return result;
00287 
00288  out_check:
00289   if (map->l_serial != serial)
00290     result = -1;
00291   goto out;
00292 }
00293 
00294 static void
00295 internal_function
00296 _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
00297                   const ElfW(Sym) **ref, struct sym_val *value,
00298                   const struct r_found_version *version, int type_class,
00299                   int protected);
00300 
00301 
00302 /* Search loaded objects' symbol tables for a definition of the symbol
00303    UNDEF_NAME, perhaps with a requested version for the symbol.
00304 
00305    We must never have calls to the audit functions inside this function
00306    or in any function which gets called.  If this would happen the audit
00307    code might create a thread which can throw off all the scope locking.  */
00308 lookup_t
00309 internal_function
00310 _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
00311                    const ElfW(Sym) **ref,
00312                    struct r_scope_elem *symbol_scope[],
00313                    const struct r_found_version *version,
00314                    int type_class, int flags, struct link_map *skip_map)
00315 {
00316   const uint_fast32_t new_hash = dl_new_hash (undef_name);
00317   unsigned long int old_hash = 0xffffffff;
00318   struct sym_val current_value = { NULL, NULL };
00319   struct r_scope_elem **scope = symbol_scope;
00320 
00321   bump_num_relocations ();
00322 
00323   /* No other flag than DL_LOOKUP_ADD_DEPENDENCY or DL_LOOKUP_GSCOPE_LOCK
00324      is allowed if we look up a versioned symbol.  */
00325   assert (version == NULL
00326          || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK))
00327             == 0);
00328 
00329   size_t i = 0;
00330   if (__builtin_expect (skip_map != NULL, 0))
00331     /* Search the relevant loaded objects for a definition.  */
00332     while ((*scope)->r_list[i] != skip_map)
00333       ++i;
00334 
00335   /* Search the relevant loaded objects for a definition.  */
00336   for (size_t start = i; *scope != NULL; start = 0, ++scope)
00337     {
00338       int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref,
00339                           &current_value, *scope, start, version, flags,
00340                           skip_map, type_class);
00341       if (res > 0)
00342        break;
00343 
00344       if (__builtin_expect (res, 0) < 0 && skip_map == NULL)
00345        {
00346          /* Oh, oh.  The file named in the relocation entry does not
00347             contain the needed symbol.  This code is never reached
00348             for unversioned lookups.  */
00349          assert (version != NULL);
00350          const char *reference_name = undef_map ? undef_map->l_name : NULL;
00351 
00352          /* XXX We cannot translate the message.  */
00353          _dl_signal_cerror (0, (reference_name[0]
00354                              ? reference_name
00355                              : (rtld_progname ?: "<main program>")),
00356                           N_("relocation error"),
00357                           make_string ("symbol ", undef_name, ", version ",
00358                                      version->name,
00359                                      " not defined in file ",
00360                                      version->filename,
00361                                      " with link time reference",
00362                                      res == -2
00363                                      ? " (no version symbols)" : ""));
00364          *ref = NULL;
00365          return 0;
00366        }
00367     }
00368 
00369   if (__builtin_expect (current_value.s == NULL, 0))
00370     {
00371       if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
00372          && skip_map == NULL)
00373        {
00374          /* We could find no value for a strong reference.  */
00375          const char *reference_name = undef_map ? undef_map->l_name : "";
00376          const char *versionstr = version ? ", version " : "";
00377          const char *versionname = (version && version->name
00378                                  ? version->name : "");
00379 
00380          /* XXX We cannot translate the message.  */
00381          _dl_signal_cerror (0, (reference_name[0]
00382                              ? reference_name
00383                              : (rtld_progname ?: "<main program>")),
00384                           N_("symbol lookup error"),
00385                           make_string (undefined_msg, undef_name,
00386                                      versionstr, versionname));
00387        }
00388       *ref = NULL;
00389       return 0;
00390     }
00391 
00392   int protected = (*ref
00393                  && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED);
00394   if (__builtin_expect (protected != 0, 0))
00395     {
00396       /* It is very tricky.  We need to figure out what value to
00397          return for the protected symbol.  */
00398       if (type_class == ELF_RTYPE_CLASS_PLT)
00399        {
00400          if (current_value.s != NULL && current_value.m != undef_map)
00401            {
00402              current_value.s = *ref;
00403              current_value.m = undef_map;
00404            }
00405        }
00406       else
00407        {
00408          struct sym_val protected_value = { NULL, NULL };
00409 
00410          for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
00411            if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
00412                           &protected_value, *scope, i, version, flags,
00413                           skip_map, ELF_RTYPE_CLASS_PLT) != 0)
00414              break;
00415 
00416          if (protected_value.s != NULL && protected_value.m != undef_map)
00417            {
00418              current_value.s = *ref;
00419              current_value.m = undef_map;
00420            }
00421        }
00422     }
00423 
00424   /* We have to check whether this would bind UNDEF_MAP to an object
00425      in the global scope which was dynamically loaded.  In this case
00426      we have to prevent the latter from being unloaded unless the
00427      UNDEF_MAP object is also unloaded.  */
00428   if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
00429       /* Don't do this for explicit lookups as opposed to implicit
00430         runtime lookups.  */
00431       && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
00432       /* Add UNDEF_MAP to the dependencies.  */
00433       && add_dependency (undef_map, current_value.m, flags) < 0)
00434       /* Something went wrong.  Perhaps the object we tried to reference
00435         was just removed.  Try finding another definition.  */
00436       return _dl_lookup_symbol_x (undef_name, undef_map, ref,
00437                               (flags & DL_LOOKUP_GSCOPE_LOCK)
00438                               ? undef_map->l_scope : symbol_scope,
00439                               version, type_class, flags, skip_map);
00440 
00441   /* The object is used.  */
00442   current_value.m->l_used = 1;
00443 
00444   if (__builtin_expect (GLRO(dl_debug_mask)
00445                      & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
00446     _dl_debug_bindings (undef_name, undef_map, ref,
00447                      &current_value, version, type_class, protected);
00448 
00449   *ref = current_value.s;
00450   return LOOKUP_VALUE (current_value.m);
00451 }
00452 
00453 
00454 /* Cache the location of MAP's hash table.  */
00455 
00456 void
00457 internal_function
00458 _dl_setup_hash (struct link_map *map)
00459 {
00460   Elf_Symndx *hash;
00461   Elf_Symndx nchain;
00462 
00463   if (__builtin_expect (map->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
00464                                 + DT_THISPROCNUM + DT_VERSIONTAGNUM
00465                                 + DT_EXTRANUM + DT_VALNUM] != NULL, 1))
00466     {
00467       Elf32_Word *hash32
00468        = (void *) D_PTR (map, l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
00469                                   + DT_THISPROCNUM + DT_VERSIONTAGNUM
00470                                   + DT_EXTRANUM + DT_VALNUM]);
00471       map->l_nbuckets = *hash32++;
00472       Elf32_Word symbias = *hash32++;
00473       Elf32_Word bitmask_nwords = *hash32++;
00474       /* Must be a power of two.  */
00475       assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0);
00476       map->l_gnu_bitmask_idxbits = bitmask_nwords - 1;
00477       map->l_gnu_shift = *hash32++;
00478 
00479       map->l_gnu_bitmask = (ElfW(Addr) *) hash32;
00480       hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords;
00481 
00482       map->l_gnu_buckets = hash32;
00483       hash32 += map->l_nbuckets;
00484       map->l_gnu_chain_zero = hash32 - symbias;
00485       return;
00486     }
00487 
00488   if (!map->l_info[DT_HASH])
00489     return;
00490   hash = (void *) D_PTR (map, l_info[DT_HASH]);
00491 
00492   map->l_nbuckets = *hash++;
00493   nchain = *hash++;
00494   map->l_buckets = hash;
00495   hash += map->l_nbuckets;
00496   map->l_chain = hash;
00497 }
00498 
00499 
00500 static void
00501 internal_function
00502 _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
00503                   const ElfW(Sym) **ref, struct sym_val *value,
00504                   const struct r_found_version *version, int type_class,
00505                   int protected)
00506 {
00507   const char *reference_name = undef_map->l_name;
00508 
00509   if (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS)
00510     {
00511       _dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol `%s'",
00512                      (reference_name[0]
00513                       ? reference_name
00514                       : (rtld_progname ?: "<main program>")),
00515                      undef_map->l_ns,
00516                      value->m->l_name[0] ? value->m->l_name : rtld_progname,
00517                      value->m->l_ns,
00518                      protected ? "protected" : "normal", undef_name);
00519       if (version)
00520        _dl_debug_printf_c (" [%s]\n", version->name);
00521       else
00522        _dl_debug_printf_c ("\n");
00523     }
00524 #ifdef SHARED
00525   if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
00526     {
00527       int conflict = 0;
00528       struct sym_val val = { NULL, NULL };
00529 
00530       if ((GLRO(dl_trace_prelink_map) == NULL
00531           || GLRO(dl_trace_prelink_map) == GL(dl_ns)[LM_ID_BASE]._ns_loaded)
00532          && undef_map != GL(dl_ns)[LM_ID_BASE]._ns_loaded)
00533        {
00534          const uint_fast32_t new_hash = dl_new_hash (undef_name);
00535          unsigned long int old_hash = 0xffffffff;
00536 
00537          do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val,
00538                      undef_map->l_local_scope[0], 0, version, 0, NULL,
00539                      type_class);
00540 
00541          if (val.s != value->s || val.m != value->m)
00542            conflict = 1;
00543        }
00544 
00545       if (value->s
00546          && (__builtin_expect (ELFW(ST_TYPE) (value->s->st_info)
00547                             == STT_TLS, 0)))
00548        type_class = 4;
00549 
00550       if (conflict
00551          || GLRO(dl_trace_prelink_map) == undef_map
00552          || GLRO(dl_trace_prelink_map) == NULL
00553          || type_class == 4)
00554        {
00555          _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
00556                     conflict ? "conflict" : "lookup",
00557                     (int) sizeof (ElfW(Addr)) * 2,
00558                     (size_t) undef_map->l_map_start,
00559                     (int) sizeof (ElfW(Addr)) * 2,
00560                     (size_t) (((ElfW(Addr)) *ref) - undef_map->l_map_start),
00561                     (int) sizeof (ElfW(Addr)) * 2,
00562                     (size_t) (value->s ? value->m->l_map_start : 0),
00563                     (int) sizeof (ElfW(Addr)) * 2,
00564                     (size_t) (value->s ? value->s->st_value : 0));
00565 
00566          if (conflict)
00567            _dl_printf ("x 0x%0*Zx 0x%0*Zx ",
00568                      (int) sizeof (ElfW(Addr)) * 2,
00569                      (size_t) (val.s ? val.m->l_map_start : 0),
00570                      (int) sizeof (ElfW(Addr)) * 2,
00571                      (size_t) (val.s ? val.s->st_value : 0));
00572 
00573          _dl_printf ("/%x %s\n", type_class, undef_name);
00574        }
00575     }
00576 #endif
00577 }