]> 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 f577759a9d377797b9ed7ce74328fd4ba1ca4c6f..989b073e4f74d2dad53387b64aeaea9022ff5dad 100644 (file)
@@ -1,5 +1,5 @@
 /* Look up a symbol in the loaded objects.
-   Copyright (C) 1995-2016 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
@@ -14,7 +14,7 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
+   <https://www.gnu.org/licenses/>.  */
 
 #include <alloca.h>
 #include <libintl.h>
 #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>
 #include <atomic.h>
+#include <elf_machine_sym_no_match.h>
 
 #include <assert.h>
 
-/* Return nonzero if check_match should consider SYM to fail to match a
-   symbol reference for some machine-specific reason.  */
-#ifndef ELF_MACHINE_SYM_NO_MATCH
-# define ELF_MACHINE_SYM_NO_MATCH(sym) 0
-#endif
-
 #define VERSTAG(tag)   (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
 
-
 struct sym_val
   {
     const ElfW(Sym) *s;
@@ -47,23 +42,6 @@ struct sym_val
   };
 
 
-#define make_string(string, rest...) \
-  ({                                                                         \
-    const char *all[] = { string, ## rest };                                 \
-    size_t len, cnt;                                                         \
-    char *result, *cp;                                                       \
-                                                                             \
-    len = 1;                                                                 \
-    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)               \
-      len += strlen (all[cnt]);                                                      \
-                                                                             \
-    cp = result = alloca (len);                                                      \
-    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)               \
-      cp = __stpcpy (cp, all[cnt]);                                          \
-                                                                             \
-    result;                                                                  \
-  })
-
 /* Statistics function.  */
 #ifdef SHARED
 # define bump_num_relocations() ++GL(dl_num_relocations)
@@ -93,8 +71,9 @@ check_match (const char *const undef_name,
   unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
   assert (ELF_RTYPE_CLASS_PLT == 1);
   if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
+                        && sym->st_shndx != SHN_ABS
                         && stt != STT_TLS)
-                       || ELF_MACHINE_SYM_NO_MATCH (sym)
+                       || elf_machine_sym_no_match (sym)
                        || (type_class & (sym->st_shndx == SHN_UNDEF))))
     return NULL;
 
@@ -203,14 +182,37 @@ enter_unique_sym (struct unique_sym *table, size_t size,
   table[idx].map = map;
 }
 
+/* Mark MAP as NODELETE according to the lookup mode in FLAGS.  During
+   initial relocation, NODELETE state is pending only.  */
+static void
+mark_nodelete (struct link_map *map, int flags)
+{
+  if (flags & DL_LOOKUP_FOR_RELOCATE)
+    map->l_nodelete_pending = true;
+  else
+    map->l_nodelete_active = true;
+}
+
+/* Return true if MAP is marked as NODELETE according to the lookup
+   mode in FLAGS> */
+static bool
+is_nodelete (struct link_map *map, int flags)
+{
+  /* Non-pending NODELETE always counts.  Pending NODELETE only counts
+     during initial relocation processing.  */
+  return map->l_nodelete_active
+    || ((flags & DL_LOOKUP_FOR_RELOCATE) && map->l_nodelete_pending);
+}
+
 /* Utility function for do_lookup_x. Lookup an STB_GNU_UNIQUE symbol
    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,
-                 const struct link_map *map, struct sym_val *result,
+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)
+                 const ElfW(Sym) *ref, const struct link_map *undef_map,
+                 int flags)
 {
   /* We have to determine whether we already found a symbol with this
      name before.  If not then we have to add it to the search table.
@@ -238,7 +240,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
                     copy from the copy addressed through the
                     relocation.  */
                  result->s = sym;
-                 result->m = (struct link_map *) map;
+                 result->m = map;
                }
              else
                {
@@ -284,7 +286,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
          tab->size = newsize;
          size = newsize;
          entries = tab->entries = newentries;
-         tab->free = free;
+         tab->free = __rtld_free;
        }
     }
   else
@@ -294,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);
@@ -315,7 +304,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
 
       tab->entries = entries;
       tab->size = size;
-      tab->free = free;
+      tab->free = __rtld_free;
     }
 
   if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
@@ -326,16 +315,19 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
       enter_unique_sym (entries, size,
                         new_hash, strtab + sym->st_name, sym, map);
 
-      if (map->l_type == lt_loaded)
-       /* Make sure we don't unload this object by
-          setting the appropriate flag.  */
-       ((struct link_map *) map)->l_flags_1 |= DF_1_NODELETE;
+      if (map->l_type == lt_loaded && !is_nodelete (map, flags))
+       {
+         /* Make sure we don't unload this object by
+            setting the appropriate flag.  */
+         if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS))
+           _dl_debug_printf ("\
+marking %s [%lu] as NODELETE due to unique symbol\n",
+                             map->l_name, map->l_ns);
+         mark_nodelete (map, flags);
+       }
     }
   ++tab->n_elements;
 
-#ifdef SHARED
- success:
-#endif
   __rtld_lock_unlock_recursive (tab->lock);
 
   result->s = sym;
@@ -347,7 +339,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
    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,
@@ -419,7 +411,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
                  do
                    if (((*hasharr ^ new_hash) >> 1) == 0)
                      {
-                       symidx = hasharr - map->l_gnu_chain_zero;
+                       symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr);
                        sym = check_match (undef_name, ref, version, flags,
                                           type_class, &symtab[symidx], symidx,
                                           strtab, map, &versioned_sym,
@@ -516,6 +508,14 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
 #endif
            }
 
+         /* Hidden and internal symbols are local, ignore them.  */
+         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:
@@ -537,8 +537,9 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
              return 1;
 
            case STB_GNU_UNIQUE:;
-             do_lookup_unique (undef_name, new_hash, map, result, type_class,
-                               sym, strtab, ref, undef_map);
+             do_lookup_unique (undef_name, new_hash, (struct link_map *) map,
+                               result, type_class, sym, strtab, ref,
+                               undef_map, flags);
              return 1;
 
            default:
@@ -548,11 +549,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
        }
 
 skip:
-      /* If this current map is the one mentioned in the verneed entry
-        and we have not found a weak entry, it is a bug.  */
-      if (symidx == STN_UNDEF && version != NULL && version->filename != NULL
-         && __glibc_unlikely (_dl_name_match_p (version->filename, map)))
-       return -1;
+      ;
     }
   while (++i < n);
 
@@ -561,19 +558,18 @@ 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;
 }
 
 
 /* Add extra dependency on MAP to UNDEF_MAP.  */
 static int
-internal_function
 add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
 {
   struct link_map *runp;
@@ -585,9 +581,13 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
   if (undef_map == map)
     return 0;
 
-  /* Avoid references to objects which cannot be unloaded anyway.  */
+  /* Avoid references to objects which cannot be unloaded anyway.  We
+     do not need to record dependencies if this object goes away
+     during dlopen failure, either.  IFUNC resolvers with relocation
+     dependencies may pick an dependency which can be dlclose'd, but
+     such IFUNC resolvers are undefined anyway.  */
   assert (map->l_type == lt_loaded);
-  if ((map->l_flags_1 & DF_1_NODELETE) != 0)
+  if (is_nodelete (map, flags))
     return 0;
 
   struct link_map_reldeps *l_reldeps
@@ -695,16 +695,28 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
 
       /* Redo the NODELETE check, as when dl_load_lock wasn't held
         yet this could have changed.  */
-      if ((map->l_flags_1 & DF_1_NODELETE) != 0)
+      if (is_nodelete (map, flags))
        goto out;
 
       /* If the object with the undefined reference cannot be removed ever
         just make sure the same is true for the object which contains the
         definition.  */
-      if (undef_map->l_type != lt_loaded
-         || (undef_map->l_flags_1 & DF_1_NODELETE) != 0)
+      if (undef_map->l_type != lt_loaded || is_nodelete (map, flags))
        {
-         map->l_flags_1 |= DF_1_NODELETE;
+         if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
+             && !is_nodelete (map, flags))
+           {
+             if (undef_map->l_name[0] == '\0')
+               _dl_debug_printf ("\
+marking %s [%lu] as NODELETE due to reference to main program\n",
+                                 map->l_name, map->l_ns);
+             else
+               _dl_debug_printf ("\
+marking %s [%lu] as NODELETE due to reference to %s [%lu]\n",
+                                 map->l_name, map->l_ns,
+                                 undef_map->l_name, undef_map->l_ns);
+           }
+         mark_nodelete (map, flags);
          goto out;
        }
 
@@ -729,7 +741,15 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
                 no fatal problem.  We simply make sure the referenced object
                 cannot be unloaded.  This is semantically the correct
                 behavior.  */
-             map->l_flags_1 |= DF_1_NODELETE;
+             if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)
+                 && !is_nodelete (map, flags))
+               _dl_debug_printf ("\
+marking %s [%lu] as NODELETE due to memory allocation failure\n",
+                                 map->l_name, map->l_ns);
+             /* In case of non-lazy binding, we could actually report
+                the memory allocation error, but for now, we use the
+                conservative approximation as well.  */
+             mark_nodelete (map, flags);
              goto out;
            }
          else
@@ -782,13 +802,6 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
   goto out;
 }
 
-static void
-internal_function
-_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.
@@ -797,25 +810,22 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
    or in any function which gets called.  If this would happen the audit
    code might create a thread which can throw off all the scope locking.  */
 lookup_t
-internal_function
 _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
                     const ElfW(Sym) **ref,
                     struct r_scope_elem *symbol_scope[],
                     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;
 
   bump_num_relocations ();
 
-  /* No other flag than DL_LOOKUP_ADD_DEPENDENCY or DL_LOOKUP_GSCOPE_LOCK
-     is allowed if we look up a versioned symbol.  */
-  assert (version == NULL
-         || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK))
-            == 0);
+  /* DL_LOOKUP_RETURN_NEWEST does not make sense for versioned
+     lookups.  */
+  assert (version == NULL || !(flags & DL_LOOKUP_RETURN_NEWEST));
 
   size_t i = 0;
   if (__glibc_unlikely (skip_map != NULL))
@@ -825,40 +835,14 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
 
   /* Search the relevant loaded objects for a definition.  */
   for (size_t start = i; *scope != NULL; start = 0, ++scope)
-    {
-      int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref,
-                            &current_value, *scope, start, version, flags,
-                            skip_map, type_class, undef_map);
-      if (res > 0)
-       break;
-
-      if (__glibc_unlikely (res < 0) && skip_map == NULL)
-       {
-         /* Oh, oh.  The file named in the relocation entry does not
-            contain the needed symbol.  This code is never reached
-            for unversioned lookups.  */
-         assert (version != NULL);
-         const char *reference_name = undef_map ? undef_map->l_name : "";
-
-         /* XXX We cannot translate the message.  */
-         _dl_signal_cerror (0, DSO_FILENAME (reference_name),
-                            N_("relocation error"),
-                            make_string ("symbol ", undef_name, ", version ",
-                                         version->name,
-                                         " not defined in file ",
-                                         version->filename,
-                                         " with link time reference",
-                                         res == -2
-                                         ? " (no version symbols)" : ""));
-         *ref = NULL;
-         return 0;
-       }
-    }
+    if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
+                    &current_value, *scope, start, version, flags,
+                    skip_map, type_class, undef_map) != 0)
+      break;
 
   if (__glibc_unlikely (current_value.s == NULL))
     {
       if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
-         && skip_map == NULL
          && !(GLRO(dl_debug_mask) & DL_DEBUG_UNUSED))
        {
          /* We could find no value for a strong reference.  */
@@ -866,12 +850,14 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
          const char *versionstr = version ? ", version " : "";
          const char *versionname = (version && version->name
                                     ? version->name : "");
-
+         struct dl_exception exception;
          /* XXX We cannot translate the message.  */
-         _dl_signal_cerror (0, DSO_FILENAME (reference_name),
-                            N_("symbol lookup error"),
-                            make_string ("undefined symbol: ", undef_name,
-                                         versionstr, versionname));
+         _dl_exception_create_format
+           (&exception, DSO_FILENAME (reference_name),
+            "undefined symbol: %s%s%s",
+            undef_name, versionstr, versionname);
+         _dl_signal_cexception (0, &exception, N_("symbol lookup error"));
+         _dl_exception_free (&exception);
        }
       *ref = NULL;
       return 0;
@@ -935,192 +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
-internal_function
-_dl_setup_hash (struct link_map *map)
-{
-  Elf_Symndx *hash;
-
-  if (__glibc_likely (map->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
-                                   + DT_THISPROCNUM + DT_VERSIONTAGNUM
-                                   + DT_EXTRANUM + DT_VALNUM] != NULL))
-    {
-      Elf32_Word *hash32
-       = (void *) D_PTR (map, l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM
-                                     + DT_THISPROCNUM + DT_VERSIONTAGNUM
-                                     + DT_EXTRANUM + DT_VALNUM]);
-      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;
-      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
-internal_function
-_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
-}