elf/dl-lookup.c: Move STB_GNU_UNIQUE handling to a function
authorWill Newton <will.newton@linaro.org>
Wed, 2 Apr 2014 15:04:12 +0000 (16:04 +0100)
committerWill Newton <will.newton@linaro.org>
Mon, 23 Jun 2014 13:13:30 +0000 (14:13 +0100)
Move handling of STB_GNU_UNIQUE symbols to a separate function
from do_lookup_x in order to make the code more readable.

The new function gets inlined with gcc 4.8 on ARM and the
do_lookup_x code becomes a few bytes smaller.

ChangeLog:

2014-06-23  Will Newton  <will.newton@linaro.org>

* elf/dl-lookup.c (do_lookup_unique): New function.
(do_lookup_x): Move STB_GNU_UNIQUE handling code
to a separate function.

ChangeLog
elf/dl-lookup.c

index 28f4771..4a2397e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-06-23  Will Newton  <will.newton@linaro.org>
+
+       * elf/dl-lookup.c (do_lookup_unique): New function.
+       (do_lookup_x): Move STB_GNU_UNIQUE handling code
+       to a separate function.
+
 2014-06-23  Andreas Schwab  <schwab@suse.de>
 
        [BZ #17079]
index be6f76f..896e1d2 100644 (file)
@@ -186,6 +186,162 @@ check_match (const char *const undef_name,
   return sym;
 }
 
+/* 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,
+                 int type_class, const ElfW(Sym) *sym, const char *strtab,
+                 const ElfW(Sym) *ref, const struct link_map *undef_map)
+{
+  /* 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.  If we already found a
+     definition we have to use it.  */
+  void enter (struct unique_sym *table, size_t size,
+             unsigned int hash, const char *name,
+             const ElfW(Sym) *sym, const struct link_map *map)
+  {
+    size_t idx = hash % size;
+    size_t hash2 = 1 + hash % (size - 2);
+    while (table[idx].name != NULL)
+      {
+       idx += hash2;
+       if (idx >= size)
+         idx -= size;
+      }
+
+    table[idx].hashval = hash;
+    table[idx].name = name;
+    table[idx].sym = sym;
+    table[idx].map = map;
+  }
+
+  struct unique_sym_table *tab
+    = &GL(dl_ns)[map->l_ns]._ns_unique_sym_table;
+
+  __rtld_lock_lock_recursive (tab->lock);
+
+  struct unique_sym *entries = tab->entries;
+  size_t size = tab->size;
+  if (entries != NULL)
+    {
+      size_t idx = new_hash % size;
+      size_t hash2 = 1 + new_hash % (size - 2);
+      while (1)
+       {
+         if (entries[idx].hashval == new_hash
+             && strcmp (entries[idx].name, undef_name) == 0)
+           {
+             if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
+               {
+                 /* We possibly have to initialize the central
+                    copy from the copy addressed through the
+                    relocation.  */
+                 result->s = sym;
+                 result->m = (struct link_map *) map;
+               }
+             else
+               {
+                 result->s = entries[idx].sym;
+                 result->m = (struct link_map *) entries[idx].map;
+               }
+             __rtld_lock_unlock_recursive (tab->lock);
+             return;
+           }
+
+         if (entries[idx].name == NULL)
+           break;
+
+         idx += hash2;
+         if (idx >= size)
+           idx -= size;
+       }
+
+      if (size * 3 <= tab->n_elements * 4)
+       {
+         /* Expand the table.  */
+#ifdef RTLD_CHECK_FOREIGN_CALL
+         /* This must not happen during runtime relocations.  */
+         assert (!RTLD_CHECK_FOREIGN_CALL);
+#endif
+         size_t newsize = _dl_higher_prime_number (size + 1);
+         struct unique_sym *newentries
+           = calloc (sizeof (struct unique_sym), newsize);
+         if (newentries == NULL)
+           {
+           nomem:
+             __rtld_lock_unlock_recursive (tab->lock);
+             _dl_fatal_printf ("out of memory\n");
+           }
+
+         for (idx = 0; idx < size; ++idx)
+           if (entries[idx].name != NULL)
+             enter (newentries, newsize, entries[idx].hashval,
+                    entries[idx].name, entries[idx].sym,
+                    entries[idx].map);
+
+         tab->free (entries);
+         tab->size = newsize;
+         size = newsize;
+         entries = tab->entries = newentries;
+         tab->free = free;
+       }
+    }
+  else
+    {
+#ifdef RTLD_CHECK_FOREIGN_CALL
+      /* This must not happen during runtime relocations.  */
+      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);
+      if (entries == NULL)
+       goto nomem;
+
+      tab->entries = entries;
+      tab->size = size;
+      tab->free = free;
+    }
+
+  if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
+    enter (entries, size, new_hash, strtab + sym->st_name, ref,
+          undef_map);
+  else
+    {
+      enter (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;
+    }
+  ++tab->n_elements;
+
+#ifdef SHARED
+ success:
+#endif
+  __rtld_lock_unlock_recursive (tab->lock);
+
+  result->s = sym;
+  result->m = (struct link_map *) map;
+}
 
 /* Inner part of the lookup functions.  We return a value > 0 if we
    found the symbol, the value 0 if nothing is found and < 0 if
@@ -323,157 +479,15 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
                }
              /* FALLTHROUGH */
            case STB_GLOBAL:
-           success:
              /* Global definition.  Just what we need.  */
              result->s = sym;
              result->m = (struct link_map *) map;
              return 1;
 
            case STB_GNU_UNIQUE:;
-             /* 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.  If we already found a
-                definition we have to use it.  */
-             void enter (struct unique_sym *table, size_t size,
-                         unsigned int hash, const char *name,
-                         const ElfW(Sym) *sym, const struct link_map *map)
-             {
-               size_t idx = hash % size;
-               size_t hash2 = 1 + hash % (size - 2);
-               while (table[idx].name != NULL)
-                 {
-                   idx += hash2;
-                   if (idx >= size)
-                     idx -= size;
-                 }
-
-               table[idx].hashval = hash;
-               table[idx].name = name;
-               table[idx].sym = sym;
-               table[idx].map = map;
-             }
-
-             struct unique_sym_table *tab
-               = &GL(dl_ns)[map->l_ns]._ns_unique_sym_table;
-
-             __rtld_lock_lock_recursive (tab->lock);
-
-             struct unique_sym *entries = tab->entries;
-             size_t size = tab->size;
-             if (entries != NULL)
-               {
-                 size_t idx = new_hash % size;
-                 size_t hash2 = 1 + new_hash % (size - 2);
-                 while (1)
-                   {
-                     if (entries[idx].hashval == new_hash
-                         && strcmp (entries[idx].name, undef_name) == 0)
-                       {
-                         if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
-                           {
-                             /* We possibly have to initialize the central
-                                copy from the copy addressed through the
-                                relocation.  */
-                             result->s = sym;
-                             result->m = (struct link_map *) map;
-                           }
-                         else
-                           {
-                             result->s = entries[idx].sym;
-                             result->m = (struct link_map *) entries[idx].map;
-                           }
-                         __rtld_lock_unlock_recursive (tab->lock);
-                         return 1;
-                       }
-
-                     if (entries[idx].name == NULL)
-                       break;
-
-                     idx += hash2;
-                     if (idx >= size)
-                       idx -= size;
-                   }
-
-                 if (size * 3 <= tab->n_elements * 4)
-                   {
-                     /* Expand the table.  */
-#ifdef RTLD_CHECK_FOREIGN_CALL
-                     /* This must not happen during runtime relocations.  */
-                     assert (!RTLD_CHECK_FOREIGN_CALL);
-#endif
-                     size_t newsize = _dl_higher_prime_number (size + 1);
-                     struct unique_sym *newentries
-                       = calloc (sizeof (struct unique_sym), newsize);
-                     if (newentries == NULL)
-                       {
-                       nomem:
-                         __rtld_lock_unlock_recursive (tab->lock);
-                         _dl_fatal_printf ("out of memory\n");
-                       }
-
-                     for (idx = 0; idx < size; ++idx)
-                       if (entries[idx].name != NULL)
-                         enter (newentries, newsize, entries[idx].hashval,
-                                entries[idx].name, entries[idx].sym,
-                                entries[idx].map);
-
-                     tab->free (entries);
-                     tab->size = newsize;
-                     size = newsize;
-                     entries = tab->entries = newentries;
-                     tab->free = free;
-                   }
-               }
-             else
-               {
-#ifdef RTLD_CHECK_FOREIGN_CALL
-                 /* This must not happen during runtime relocations.  */
-                 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);
-                     __rtld_lock_unlock_recursive (tab->lock);
-                     goto success;
-                   }
-#endif
-
-#define INITIAL_NUNIQUE_SYM_TABLE 31
-                 size = INITIAL_NUNIQUE_SYM_TABLE;
-                 entries = calloc (sizeof (struct unique_sym), size);
-                 if (entries == NULL)
-                   goto nomem;
-
-                 tab->entries = entries;
-                 tab->size = size;
-                 tab->free = free;
-               }
-
-             if ((type_class & ELF_RTYPE_CLASS_COPY) != 0)
-               enter (entries, size, new_hash, strtab + sym->st_name, ref,
-                      undef_map);
-             else
-               {
-                 enter (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;
-               }
-             ++tab->n_elements;
-
-             __rtld_lock_unlock_recursive (tab->lock);
-
-             goto success;
+             do_lookup_unique (undef_name, new_hash, map, result, type_class,
+                               sym, strtab, ref, undef_map);
+             return 1;
 
            default:
              /* Local symbols are ignored.  */