--- binutils-2.17.50.0.3/bfd/elf.c
+++ binutils-2.17.50.0.3/bfd/elf.c
@@ -1256,6 +1256,7 @@
 	    case DT_AUXILIARY: name = "AUXILIARY"; stringp = TRUE; break;
 	    case DT_USED: name = "USED"; break;
 	    case DT_FILTER: name = "FILTER"; stringp = TRUE; break;
+	    case DT_SUSE_HASHVALS: name = "SUSE_HASHVALS"; break;
 	    case DT_GNU_HASH: name = "GNU_HASH"; break;
 	    }
 
--- binutils-2.17.50.0.3/bfd/elflink.c
+++ binutils-2.17.50.0.3/bfd/elflink.c
@@ -175,6 +175,15 @@
 
   flags = bed->dynamic_sec_flags;
 
+  if (info->hashvals)
+    {
+      s = bfd_make_section (abfd, ".suse.hashvals");
+      if (s == NULL
+	  || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+	  || ! bfd_set_section_alignment (abfd, s, 2))
+	return FALSE;
+    }
+
   /* A dynamically linked executable has a .interp section, but a
      shared library does not.  */
   if (info->executable)
@@ -6143,6 +6152,24 @@
 
       elf_hash_table (info)->bucketcount = 0;
 
+      /* Create the direct bindings section - 1 entry per dynsym.  */
+      s = bfd_get_section_by_name (dynobj, ".suse.hashvals");
+      if (s != NULL)
+        {
+  	  if (dynsymcount == 0)
+	    s->flags |= SEC_EXCLUDE;
+	  else
+	    {
+	      s->size = dynsymcount * bed->s->sizeof_hash_entry;
+	      s->contents = bfd_zalloc (output_bfd, s->size);
+	      if (s->contents == NULL)
+	        return FALSE;
+	      memset (s->contents, 0xfe, s->size);
+	      if (!_bfd_elf_add_dynamic_entry (info, DT_SUSE_HASHVALS, 0))
+	        return FALSE;
+	    }
+	}
+
       /* Compute the size of the hashing table.  As a side effect this
 	 computes the hash values for all the names we export.  */
       if (info->emit_hash)
@@ -6417,6 +6444,8 @@
   /* Array large enough to hold a section pointer for each local
      symbol of any input BFD.  */
   asection **sections;
+  /* .suse.hashvals section.  */
+  asection *hashvals_sec;
   /* Buffer to hold swapped out symbols.  */
   bfd_byte *symbuf;
   /* And one for symbol section indices.  */
@@ -7302,6 +7331,18 @@
 		    + (bucketcount + 2 + h->dynindx) * hash_entry_size));
 	}
 
+      if (finfo->hashvals_sec != NULL)
+	{
+	  size_t hash_entry_size
+	    = elf_section_data (finfo->hashvals_sec)->this_hdr.sh_entsize;
+	  bfd_vma offset = hash_entry_size * h->dynindx;
+
+	  BFD_ASSERT (offset <= finfo->hashvals_sec->size);
+	  bfd_put (8 * hash_entry_size, finfo->output_bfd,
+		   h->u.elf_hash_value,
+		   finfo->hashvals_sec->contents + offset);
+	}
+
       if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL)
 	{
 	  Elf_Internal_Versym iversym;
@@ -8520,6 +8561,7 @@
       finfo.dynsym_sec = NULL;
       finfo.hash_sec = NULL;
       finfo.symver_sec = NULL;
+      finfo.hashvals_sec = NULL;
     }
   else
     {
@@ -8529,6 +8571,7 @@
       BFD_ASSERT (finfo.dynsym_sec != NULL);
       finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version");
       /* Note that it is OK if symver_sec is NULL.  */
+      finfo.hashvals_sec = bfd_get_section_by_name (dynobj, ".suse.hashvals");
     }
 
   finfo.contents = NULL;
@@ -9289,6 +9332,9 @@
 	    case DT_GNU_HASH:
 	      name = ".gnu.hash";
 	      goto get_vma;
+	    case DT_SUSE_HASHVALS:
+	      name = ".suse.hashvals";
+	      goto get_vma;
 	    case DT_STRTAB:
 	      name = ".dynstr";
 	      goto get_vma;
--- binutils-2.17.50.0.3/include/bfdlink.h
+++ binutils-2.17.50.0.3/include/bfdlink.h
@@ -264,6 +264,10 @@
      need much more time and therefore must be explicitly selected.  */
   unsigned int optimize: 1;
 
+  /* TRUE if we want to produced a section containing pre-computed
+     hash values. This consumes more space.  */
+  unsigned int hashvals: 1;
+
   /* TRUE if ok to have multiple definition.  */
   unsigned int allow_multiple_definition: 1;
 
--- binutils-2.17.50.0.3/include/elf/common.h
+++ binutils-2.17.50.0.3/include/elf/common.h
@@ -613,6 +613,12 @@
 #define DT_FILTER	0x7fffffff
 
 
+/* Selected at random.  */
+#define DT_SUSE_LO 0x6cbdd030
+#define DT_SUSE_HASHVALS DT_SUSE_LO
+#define DT_SUSE_DIRECT DT_SUSE_LO + 1
+#define DT_SUSE_HI 0x6cbdd040
+
 /* Values used in DT_FEATURE .dynamic entry.  */
 #define DTF_1_PARINIT	0x00000001
 /* From
--- binutils-2.17.50.0.3/ld/lexsup.c
+++ binutils-2.17.50.0.3/ld/lexsup.c
@@ -79,6 +79,7 @@
   OPTION_EL,
   OPTION_EMBEDDED_RELOCS,
   OPTION_EXPORT_DYNAMIC,
+  OPTION_HASHVALS,
   OPTION_HELP,
   OPTION_IGNORE,
   OPTION_MAP,
@@ -342,6 +343,8 @@
     '\0', NULL, NULL, ONE_DASH },
   { {"static", no_argument, NULL, OPTION_NON_SHARED},
     '\0', NULL, NULL, ONE_DASH },
+  { {"hashvals", no_argument, NULL, OPTION_HASHVALS},
+    '\0', NULL, N_("Store pre-computed elf hash codes"), ONE_DASH },
   { {"Bsymbolic", no_argument, NULL, OPTION_SYMBOLIC},
     '\0', NULL, N_("Bind global references locally"), ONE_DASH },
   { {"Bdirect", no_argument, NULL, OPTION_DIRECT},
@@ -1117,6 +1120,9 @@
 	case OPTION_SYMBOLIC:
 	  link_info.symbolic = TRUE;
 	  break;
+	case OPTION_HASHVALS:
+	  link_info.hashvals = TRUE;
+	  break;
 	case 't':
 	  trace_files = TRUE;
 	  break;
