]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - elf/dl-lookup.c
Replace {u}int_fast{16|32} with {u}int32_t
[thirdparty/glibc.git] / elf / dl-lookup.c
index 807f3ea9b67489b3116535b7c433c774a72e4c29..989b073e4f74d2dad53387b64aeaea9022ff5dad 100644 (file)
@@ -1,5 +1,5 @@
 /* Look up a symbol in the loaded objects.
-   Copyright (C) 1995-2020 Free Software Foundation, Inc.
+   Copyright (C) 1995-2022 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -24,6 +24,7 @@
 #include <ldsodefs.h>
 #include <dl-hash.h>
 #include <dl-machine.h>
+#include <dl-protected.h>
 #include <sysdep-cancel.h>
 #include <libc-lock.h>
 #include <tls.h>
@@ -207,7 +208,7 @@ is_nodelete (struct link_map *map, int flags)
    in the unique symbol table, creating a new entry if necessary.
    Return the matching symbol in RESULT.  */
 static void
-do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
+do_lookup_unique (const char *undef_name, unsigned int new_hash,
                  struct link_map *map, struct sym_val *result,
                  int type_class, const ElfW(Sym) *sym, const char *strtab,
                  const ElfW(Sym) *ref, const struct link_map *undef_map,
@@ -295,19 +296,6 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
       assert (!RTLD_CHECK_FOREIGN_CALL);
 #endif
 
-#ifdef SHARED
-      /* If tab->entries is NULL, but tab->size is not, it means
-        this is the second, conflict finding, lookup for
-        LD_TRACE_PRELINKING in _dl_debug_bindings.  Don't
-        allocate anything and don't enter anything into the
-        hash table.  */
-      if (__glibc_unlikely (tab->size))
-       {
-         assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK);
-         goto success;
-       }
-#endif
-
 #define INITIAL_NUNIQUE_SYM_TABLE 31
       size = INITIAL_NUNIQUE_SYM_TABLE;
       entries = calloc (sizeof (struct unique_sym), size);
@@ -340,9 +328,6 @@ marking %s [%lu] as NODELETE due to unique symbol\n",
     }
   ++tab->n_elements;
 
-#ifdef SHARED
- success:
-#endif
   __rtld_lock_unlock_recursive (tab->lock);
 
   result->s = sym;
@@ -354,7 +339,7 @@ marking %s [%lu] as NODELETE due to unique symbol\n",
    something bad happened.  */
 static int
 __attribute_noinline__
-do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
+do_lookup_x (const char *undef_name, unsigned int new_hash,
             unsigned long int *old_hash, const ElfW(Sym) *ref,
             struct sym_val *result, struct r_scope_elem *scope, size_t i,
             const struct r_found_version *const version, int flags,
@@ -527,6 +512,10 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
          if (__glibc_unlikely (dl_symbol_visibility_binds_local_p (sym)))
            goto skip;
 
+         if (ELFW(ST_VISIBILITY) (sym->st_other) == STV_PROTECTED)
+           _dl_check_protected_symbol (undef_name, undef_map, ref, map,
+                                       type_class);
+
          switch (ELFW(ST_BIND) (sym->st_info))
            {
            case STB_WEAK:
@@ -569,13 +558,13 @@ skip:
 }
 
 
-static uint_fast32_t
+static uint32_t
 dl_new_hash (const char *s)
 {
-  uint_fast32_t h = 5381;
+  uint32_t h = 5381;
   for (unsigned char c = *s; c != '\0'; c = *++s)
     h = h * 33 + c;
-  return h & 0xffffffff;
+  return h;
 }
 
 
@@ -813,12 +802,6 @@ marking %s [%lu] as NODELETE due to memory allocation failure\n",
   goto out;
 }
 
-static void
-_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
-                   const ElfW(Sym) **ref, struct sym_val *value,
-                   const struct r_found_version *version, int type_class,
-                   int protected);
-
 
 /* Search loaded objects' symbol tables for a definition of the symbol
    UNDEF_NAME, perhaps with a requested version for the symbol.
@@ -833,7 +816,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
                     const struct r_found_version *version,
                     int type_class, int flags, struct link_map *skip_map)
 {
-  const uint_fast32_t new_hash = dl_new_hash (undef_name);
+  const unsigned int new_hash = dl_new_hash (undef_name);
   unsigned long int old_hash = 0xffffffff;
   struct sym_val current_value = { NULL, NULL };
   struct r_scope_elem **scope = symbol_scope;
@@ -938,190 +921,6 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
   if (__glibc_unlikely (current_value.m->l_used == 0))
     current_value.m->l_used = 1;
 
-  if (__glibc_unlikely (GLRO(dl_debug_mask)
-                       & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK)))
-    _dl_debug_bindings (undef_name, undef_map, ref,
-                       &current_value, version, type_class, protected);
-
   *ref = current_value.s;
   return LOOKUP_VALUE (current_value.m);
 }
-
-
-/* Cache the location of MAP's hash table.  */
-
-void
-_dl_setup_hash (struct link_map *map)
-{
-  Elf_Symndx *hash;
-
-  if (__glibc_likely (map->l_info[ELF_MACHINE_GNU_HASH_ADDRIDX] != NULL))
-    {
-      Elf32_Word *hash32
-       = (void *) D_PTR (map, l_info[ELF_MACHINE_GNU_HASH_ADDRIDX]);
-      map->l_nbuckets = *hash32++;
-      Elf32_Word symbias = *hash32++;
-      Elf32_Word bitmask_nwords = *hash32++;
-      /* Must be a power of two.  */
-      assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0);
-      map->l_gnu_bitmask_idxbits = bitmask_nwords - 1;
-      map->l_gnu_shift = *hash32++;
-
-      map->l_gnu_bitmask = (ElfW(Addr) *) hash32;
-      hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords;
-
-      map->l_gnu_buckets = hash32;
-      hash32 += map->l_nbuckets;
-      map->l_gnu_chain_zero = hash32 - symbias;
-
-      /* Initialize MIPS xhash translation table.  */
-      ELF_MACHINE_XHASH_SETUP (hash32, symbias, map);
-
-      return;
-    }
-
-  if (!map->l_info[DT_HASH])
-    return;
-  hash = (void *) D_PTR (map, l_info[DT_HASH]);
-
-  map->l_nbuckets = *hash++;
-  /* Skip nchain.  */
-  hash++;
-  map->l_buckets = hash;
-  hash += map->l_nbuckets;
-  map->l_chain = hash;
-}
-
-
-static void
-_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
-                   const ElfW(Sym) **ref, struct sym_val *value,
-                   const struct r_found_version *version, int type_class,
-                   int protected)
-{
-  const char *reference_name = undef_map->l_name;
-
-  if (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS)
-    {
-      _dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol `%s'",
-                       DSO_FILENAME (reference_name),
-                       undef_map->l_ns,
-                       DSO_FILENAME (value->m->l_name),
-                       value->m->l_ns,
-                       protected ? "protected" : "normal", undef_name);
-      if (version)
-       _dl_debug_printf_c (" [%s]\n", version->name);
-      else
-       _dl_debug_printf_c ("\n");
-    }
-#ifdef SHARED
-  if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
-    {
-/* ELF_RTYPE_CLASS_XXX must match RTYPE_CLASS_XXX used by prelink with
-   LD_TRACE_PRELINKING.  */
-#define RTYPE_CLASS_VALID      8
-#define RTYPE_CLASS_PLT                (8|1)
-#define RTYPE_CLASS_COPY       (8|2)
-#define RTYPE_CLASS_TLS                (8|4)
-#if ELF_RTYPE_CLASS_PLT != 0 && ELF_RTYPE_CLASS_PLT != 1
-# error ELF_RTYPE_CLASS_PLT must be 0 or 1!
-#endif
-#if ELF_RTYPE_CLASS_COPY != 0 && ELF_RTYPE_CLASS_COPY != 2
-# error ELF_RTYPE_CLASS_COPY must be 0 or 2!
-#endif
-      int conflict = 0;
-      struct sym_val val = { NULL, NULL };
-
-      if ((GLRO(dl_trace_prelink_map) == NULL
-          || GLRO(dl_trace_prelink_map) == GL(dl_ns)[LM_ID_BASE]._ns_loaded)
-         && undef_map != GL(dl_ns)[LM_ID_BASE]._ns_loaded)
-       {
-         const uint_fast32_t new_hash = dl_new_hash (undef_name);
-         unsigned long int old_hash = 0xffffffff;
-         struct unique_sym *saved_entries
-           = GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries;
-
-         GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = NULL;
-         do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val,
-                      undef_map->l_local_scope[0], 0, version, 0, NULL,
-                      type_class, undef_map);
-         if (val.s != value->s || val.m != value->m)
-           conflict = 1;
-         else if (__glibc_unlikely (undef_map->l_symbolic_in_local_scope)
-                  && val.s
-                  && __glibc_unlikely (ELFW(ST_BIND) (val.s->st_info)
-                                       == STB_GNU_UNIQUE))
-           {
-             /* If it is STB_GNU_UNIQUE and undef_map's l_local_scope
-                contains any DT_SYMBOLIC libraries, unfortunately there
-                can be conflicts even if the above is equal.  As symbol
-                resolution goes from the last library to the first and
-                if a STB_GNU_UNIQUE symbol is found in some late DT_SYMBOLIC
-                library, it would be the one that is looked up.  */
-             struct sym_val val2 = { NULL, NULL };
-             size_t n;
-             struct r_scope_elem *scope = undef_map->l_local_scope[0];
-
-             for (n = 0; n < scope->r_nlist; n++)
-               if (scope->r_list[n] == val.m)
-                 break;
-
-             for (n++; n < scope->r_nlist; n++)
-               if (scope->r_list[n]->l_info[DT_SYMBOLIC] != NULL
-                   && do_lookup_x (undef_name, new_hash, &old_hash, *ref,
-                                   &val2,
-                                   &scope->r_list[n]->l_symbolic_searchlist,
-                                   0, version, 0, NULL, type_class,
-                                   undef_map) > 0)
-                 {
-                   conflict = 1;
-                   val = val2;
-                   break;
-                 }
-           }
-         GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = saved_entries;
-       }
-
-      if (value->s)
-       {
-         /* Keep only ELF_RTYPE_CLASS_PLT and ELF_RTYPE_CLASS_COPY
-            bits since since prelink only uses them.  */
-         type_class &= ELF_RTYPE_CLASS_PLT | ELF_RTYPE_CLASS_COPY;
-         if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
-                               == STT_TLS))
-           /* Clear the RTYPE_CLASS_VALID bit in RTYPE_CLASS_TLS.  */
-           type_class = RTYPE_CLASS_TLS & ~RTYPE_CLASS_VALID;
-         else if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
-                                    == STT_GNU_IFUNC))
-           /* Set the RTYPE_CLASS_VALID bit.  */
-           type_class |= RTYPE_CLASS_VALID;
-       }
-
-      if (conflict
-         || GLRO(dl_trace_prelink_map) == undef_map
-         || GLRO(dl_trace_prelink_map) == NULL
-         || type_class >= 4)
-       {
-         _dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
-                     conflict ? "conflict" : "lookup",
-                     (int) sizeof (ElfW(Addr)) * 2,
-                     (size_t) undef_map->l_map_start,
-                     (int) sizeof (ElfW(Addr)) * 2,
-                     (size_t) (((ElfW(Addr)) *ref) - undef_map->l_map_start),
-                     (int) sizeof (ElfW(Addr)) * 2,
-                     (size_t) (value->s ? value->m->l_map_start : 0),
-                     (int) sizeof (ElfW(Addr)) * 2,
-                     (size_t) (value->s ? value->s->st_value : 0));
-
-         if (conflict)
-           _dl_printf ("x 0x%0*Zx 0x%0*Zx ",
-                       (int) sizeof (ElfW(Addr)) * 2,
-                       (size_t) (val.s ? val.m->l_map_start : 0),
-                       (int) sizeof (ElfW(Addr)) * 2,
-                       (size_t) (val.s ? val.s->st_value : 0));
-
-         _dl_printf ("/%x %s\n", type_class, undef_name);
-       }
-    }
-#endif
-}