This patch omits the DT_SUSE_DIRECT define and hence depends
================================================================================
--- binutils-2.17.50.0.4/bfd/elf-bfd.h
+++ binutils-2.17.50.0.4/bfd/elf-bfd.h
@@ -172,6 +172,14 @@
      matters.  */
   unsigned int pointer_equality_needed : 1;
 
+  /* FIXME: these 2 bits consume another 4 bytes.  */
+  /* Symbol is concrete, ie. non-vague if we can detect that, from the
+     .direct section.  */
+  unsigned int concrete_ref : 1;
+  /* Symbol is certainly vague (if we can detect that), from the
+     .direct section.  */
+  unsigned int vague_ref : 1;
+
   /* String table index in .dynstr if this is a dynamic symbol.  */
   unsigned long dynstr_index;
 
@@ -403,6 +411,9 @@
   asection *tls_sec;
   bfd_size_type tls_size;
 
+  /* Direct linkage output section.  */
+  asection *direct_sec;
+
   /* A linked list of BFD's loaded in the link.  */
   struct elf_link_loaded_list *loaded;
 
@@ -1323,6 +1334,7 @@
      name actually used, which will be the DT_SONAME entry if there is
      one.  */
   const char *dt_name;
+  int         dt_needed_idx;
 
   /* Records the result of `get_program_header_size'.  */
   bfd_size_type program_header_size;
@@ -1426,6 +1438,7 @@
 #define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got.offsets)
 #define elf_local_got_ents(bfd) (elf_tdata(bfd) -> local_got.ents)
 #define elf_dt_name(bfd)	(elf_tdata(bfd) -> dt_name)
+#define elf_dt_needed_idx(bfd)	(elf_tdata(bfd) -> dt_needed_idx)
 #define elf_dyn_lib_class(bfd)	(elf_tdata(bfd) -> dyn_lib_class)
 #define elf_bad_symtab(bfd)	(elf_tdata(bfd) -> bad_symtab)
 #define elf_flags_init(bfd)	(elf_tdata(bfd) -> flags_init)
--- binutils-2.17.50.0.4/bfd/elf.c
+++ binutils-2.17.50.0.4/bfd/elf.c
@@ -1256,6 +1256,7 @@
 	    case DT_RELCOUNT: name = "RELCOUNT"; break;
 	    case DT_FLAGS_1: name = "FLAGS_1"; break;
 	    case DT_VERSYM: name = "VERSYM"; break;
+	    case DT_SUSE_DIRECT: name = "SUSE_DIRECT"; break;
 	    case DT_VERDEF: name = "VERDEF"; break;
 	    case DT_VERDEFNUM: name = "VERDEFNUM"; break;
 	    case DT_VERNEED: name = "VERNEED"; break;
@@ -1612,6 +1613,7 @@
   table->runpath = NULL;
   table->tls_sec = NULL;
   table->tls_size = 0;
+  table->direct_sec = NULL;
   table->loaded = NULL;
   table->is_relocatable_executable = FALSE;
 
--- binutils-2.17.50.0.4/bfd/elflink.c
+++ binutils-2.17.50.0.4/bfd/elflink.c
@@ -195,6 +195,16 @@
       elf_hash_table (info)->eh_info.hdr_sec = s;
     }
 
+  if (info->direct && !info->executable)
+    {
+      s = bfd_make_section (abfd, ".suse.direct");
+      if (s == NULL
+	  || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+	  || ! bfd_set_section_alignment (abfd, s, 2))
+	return FALSE;
+      elf_hash_table (info)->direct_sec = s;
+    }
+
   /* Create sections to hold version informations.  These are removed
      if they are not needed.  */
   s = bfd_make_section_with_flags (abfd, ".gnu.version_d",
@@ -2959,6 +2969,7 @@
 
       if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex))
 	return -1;
+      elf_dt_needed_idx (abfd) = ++(info->dt_needed_index);
     }
   else
     /* We were just checking for existence of the tag.  */
@@ -3166,10 +3177,15 @@
   long old_dynsymcount = 0;
   size_t tabsize = 0;
   size_t hashsize = 0;
+  asection *direct_sec;
+  unsigned char *direct_data;
 
   htab = elf_hash_table (info);
   bed = get_elf_backend_data (abfd);
 
+  direct_sec = NULL;
+  direct_data = NULL;
+
   if ((abfd->flags & DYNAMIC) == 0)
     dynamic = FALSE;
   else
@@ -3189,6 +3205,16 @@
 	    bfd_set_error (bfd_error_wrong_format);
 	  goto error_return;
 	}
+      if (info->direct)
+	direct_sec = bfd_get_section_by_name (abfd, ".suse.direct");
+      if (direct_sec != NULL)
+	{
+	  direct_data = bfd_alloc (abfd, direct_sec->size);
+	  if (direct_data == NULL
+	      || ! bfd_get_section_contents (abfd, direct_sec,
+					     direct_data, 0, direct_sec->size))
+	    goto error_return;
+	}
     }
 
   /* As a GNU extension, any input sections which are named
@@ -3907,6 +3933,22 @@
 	      && vernum > 1
 	      && definition)
 	    h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1];
+
+	  if (direct_sec != NULL)
+	    {
+	      unsigned long d_idx = isym - isymbuf;
+	      unsigned long direct_entry;
+	      d_idx += extsymoff;
+	      d_idx *= 2;
+	      BFD_ASSERT (d_idx <= bfd_get_section_size (direct_sec));
+	      direct_entry = bfd_get_16 (abfd, direct_data + d_idx);
+	      if ((direct_entry & DT_SUSE_DIRECT_VAGUE) != 0)
+		h->vague_ref = 1;
+	      if (!h->vague_ref
+		  && ((direct_entry & DT_SUSE_DIRECT_MASK)
+		      != DT_SUSE_DIRECT_UNKNOWN))
+		h->concrete_ref = 1;
+	    }
 	}
 
       if (! (_bfd_generic_link_add_one_symbol
@@ -4597,6 +4639,8 @@
   if (isymbuf != NULL)
     free (isymbuf);
  error_return:
+  if (direct_data != NULL)
+    free (direct_data);
   return FALSE;
 }
 
@@ -5963,6 +6007,24 @@
 	    return FALSE;
 	}
 
+      /* Create the direct bindings section - 1 entry per dynsym.  */
+      s = bfd_get_section_by_name (dynobj, ".suse.direct");
+      if (s != NULL)
+        {
+  	  if (dynsymcount == 0)
+            s->flags |= SEC_EXCLUDE;
+	  else
+	    {
+	      s->size = dynsymcount * sizeof (Elf_External_Direct);
+	      s->contents = bfd_zalloc (output_bfd, s->size);
+	      if (s->contents == NULL)
+	        return FALSE;
+	      memset (s->contents, 0xff, s->size);
+	      if (!_bfd_elf_add_dynamic_entry (info, DT_SUSE_DIRECT, 0))
+	        return FALSE;
+	    }
+	}
+
       /* Set the size of the .dynsym and .hash sections.  We counted
 	 the number of dynamic symbols in elf_link_add_object_symbols.
 	 We will build the contents of .dynsym and .hash when we build
@@ -6229,6 +6291,8 @@
   asection *hash_sec;
   /* symbol version section (.gnu.version).  */
   asection *symver_sec;
+  /* .direct linkage section.  */
+  asection *direct_sec;
   /* Buffer large enough to hold contents of any section.  */
   bfd_byte *contents;
   /* Buffer large enough to hold external relocs of any section.  */
@@ -7123,6 +7187,43 @@
 	  eversym += h->dynindx;
 	  _bfd_elf_swap_versym_out (finfo->output_bfd, &iversym, eversym);
 	}
+
+      if (finfo->direct_sec != NULL)
+	{
+	  int dt_index = DT_SUSE_DIRECT_UNKNOWN;
+	  bfd_vma offset = 2 * h->dynindx;
+	  BFD_ASSERT (offset <= finfo->direct_sec->size);
+
+	  if ((h->root.type == bfd_link_hash_defined
+	       || h->root.type == bfd_link_hash_defweak)
+	      && h->root.u.def.section != NULL
+	      && h->root.u.def.section->owner != NULL)
+	    {
+	      asection *sec = h->root.u.def.section;
+
+	      dt_index = elf_dt_needed_idx (sec->owner);
+
+	      if ((sec->owner->flags & DYNAMIC) == 0)
+		{
+		  if (sec->name == NULL
+		      || strncmp (sec->name, ".gnu.linkonce",
+				  strlen (".gnu.linkonce")) == 0)
+		    dt_index |= DT_SUSE_DIRECT_VAGUE;
+		  /* app -> library data references get turned into copy
+		     relocs, so objects can migrate unpredictably into the
+		     application itself.  */
+		  else if (h->type == STT_OBJECT)
+		    dt_index |= DT_SUSE_DIRECT_VAGUE;
+		}
+	      else if (h->vague_ref)
+		dt_index |= DT_SUSE_DIRECT_VAGUE;
+	      else if (!h->concrete_ref)
+		dt_index = DT_SUSE_DIRECT_UNKNOWN;
+	    }
+	  bfd_put_16 (finfo->output_bfd,
+		      dt_index,
+		      finfo->direct_sec->contents + offset);
+	}
     }
 
   /* If we're stripping it, then it was just a dynamic symbol, and
@@ -8273,12 +8374,14 @@
 
   if (! dynamic)
     {
+      finfo.direct_sec = NULL;
       finfo.dynsym_sec = NULL;
       finfo.hash_sec = NULL;
       finfo.symver_sec = NULL;
     }
   else
     {
+      finfo.direct_sec = bfd_get_section_by_name (dynobj, ".suse.direct");
       finfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym");
       finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash");
       BFD_ASSERT (finfo.dynsym_sec != NULL);
@@ -9067,6 +9170,9 @@
 	    case DT_VERNEED:
 	      name = ".gnu.version_r";
 	      goto get_vma;
+	    case DT_SUSE_DIRECT:
+	      name = ".suse.direct";
+	      goto get_vma;
 	    case DT_VERSYM:
 	      name = ".gnu.version";
 	    get_vma:
--- binutils-2.17.50.0.4/binutils/readelf.c
+++ binutils-2.17.50.0.4/binutils/readelf.c
@@ -147,6 +147,7 @@
 static int do_dynamic;
 static int do_syms;
 static int do_reloc;
+static int do_direct;
 static int do_sections;
 static int do_section_groups;
 static int do_section_details;
@@ -1514,6 +1515,7 @@
     case DT_SYMINFO:	return "SYMINFO"; /* aka ADDRRNGHI */
 
     case DT_VERSYM:	return "VERSYM";
+    case DT_SUSE_DIRECT: return "SUSE_DIRECT";
 
     case DT_TLSDESC_GOT: return "TLSDESC_GOT";
     case DT_TLSDESC_PLT: return "TLSDESC_PLT";
@@ -2682,6 +2684,7 @@
   {"symbols",	       no_argument, 0, 's'},
   {"syms",	       no_argument, 0, 's'},
   {"relocs",	       no_argument, 0, 'r'},
+  {"direct",	       no_argument, 0, 'y'},
   {"notes",	       no_argument, 0, 'n'},
   {"dynamic",	       no_argument, 0, 'd'},
   {"arch-specific",    no_argument, 0, 'A'},
@@ -2719,6 +2722,7 @@
       --symbols          An alias for --syms\n\
   -n --notes             Display the core notes (if present)\n\
   -r --relocs            Display the relocations (if present)\n\
+  -y --direct            Display direct linkage table (if present)\n\
   -u --unwind            Display the unwind info (if present)\n\
   -d --dynamic           Display the dynamic section (if present)\n\
   -V --version-info      Display the version sections (if present)\n\
@@ -2808,7 +2812,7 @@
     usage ();
 
   while ((c = getopt_long
-	  (argc, argv, "ersuahnldSDAINtgw::x:i:vVWH", options, NULL)) != EOF)
+	  (argc, argv, "erysuahnldSDAINtgw::x:i:vVWH", options, NULL)) != EOF)
     {
       char *cp;
       int section;
@@ -2825,6 +2829,7 @@
 	case 'a':
 	  do_syms++;
 	  do_reloc++;
+	  do_direct++;
 	  do_unwind++;
 	  do_dynamic++;
 	  do_header++;
@@ -2858,6 +2863,9 @@
 	case 'r':
 	  do_reloc++;
 	  break;
+	case 'y':
+	  do_direct++;
+	  break;
 	case 'u':
 	  do_unwind++;
 	  break;
@@ -3067,7 +3075,7 @@
   if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections
       && !do_segments && !do_header && !do_dump && !do_version
       && !do_histogram && !do_debugging && !do_arch && !do_notes
-      && !do_section_groups)
+      && !do_section_groups && !do_direct)
     usage ();
   else if (argc < 3)
     {
@@ -4722,6 +4730,131 @@
   return 1;
 }
 
+static void
+print_dt_needed_name (int idx)
+{
+  const char *name = NULL;
+  Elf_Internal_Dyn *entry;
+
+  idx &= DT_SUSE_DIRECT_MASK;
+ 
+  switch (idx)
+    {
+    case 0:
+      name = _("<self>");
+      break;
+    case DT_SUSE_DIRECT_UNKNOWN:
+      name = _("<unknown>");
+      break;
+    default:
+      idx--;
+
+      for (entry = dynamic_section;
+	   entry < dynamic_section + dynamic_nent && idx > 0;
+	   entry++)
+	if (entry->d_tag == DT_NEEDED)
+	  idx--;
+  
+      if (idx == 0)
+        {
+          if (VALID_DYNAMIC_NAME (entry->d_un.d_val))
+	    name = GET_DYNAMIC_NAME (entry->d_un.d_val);
+	  else
+	    name = NULL;
+	}
+      break;
+    }
+
+  if (!name)
+    name = _("<out-of-range>");
+  if (do_wide)
+    printf ("%s", name);
+  else
+    printf ("%-25s", name);
+}
+
+static int
+process_direct (FILE *file)
+{
+  unsigned int i;
+  unsigned int si;
+  char *strtab;
+  unsigned char *directtab;
+  Elf_Internal_Sym *symtab = NULL;
+  Elf_Internal_Sym *psym;
+  Elf_Internal_Shdr *direct = NULL;
+  Elf_Internal_Shdr *dynsym = NULL;
+  Elf_Internal_Shdr *section;
+
+  if (!do_direct)
+    return 1;
+  if (!dynamic_symbols || !dynamic_section || !dynamic_strings)
+    return 1;
+
+  for (i = 0, section = section_headers;
+       i < elf_header.e_shnum;
+       i++, section++)
+    {
+      if (section->sh_type == SHT_DYNSYM)
+	dynsym = section;
+      if (!strcmp (SECTION_NAME (section), ".suse.direct"))
+	direct = section;
+    }
+  if (!dynsym || !direct)
+    return 1;
+  
+  symtab = GET_ELF_SYMBOLS (file, dynsym);
+  if (!symtab)
+    return 1;
+
+  directtab = get_data (NULL, file, direct->sh_offset,
+			direct->sh_size, 1, _("direct linkage table"));
+  if (!symtab)
+    {
+      free (symtab);
+      return 1;
+    }
+
+  if (dynsym->sh_link == elf_header.e_shstrndx)
+    strtab = string_table;
+  else
+    {
+      Elf_Internal_Shdr *string_sec;
+
+      string_sec = SECTION_HEADER (dynsym->sh_link);
+
+      strtab = get_data (NULL, file, string_sec->sh_offset,
+			 string_sec->sh_size, 1, _("string table"));
+    }
+
+  assert (strtab != NULL);
+
+  printf (_("\nDirect relocations for image:\n"));
+  printf (_("   Num:  Index     Vague   Binding                    Symbol\n"));
+  for (si = 0, psym = symtab;
+       si < dynsym->sh_size / dynsym->sh_entsize;
+       si++, psym++)
+    {
+      unsigned int field;
+      printf ("%6d: ", si);
+      field = byte_get (directtab + (si * 2), 2);
+      printf ("[0x%.4x]   ", field);
+      printf ("%s", (field & DT_SUSE_DIRECT_VAGUE) ? "Vague" : "     ");
+      printf ("  ");
+      print_dt_needed_name (field);
+      printf ("  ");
+      print_symbol (25, strtab + psym->st_name);
+      printf ("\n");
+    }
+
+  free (symtab);
+  if (strtab != string_table)
+    free (strtab);
+
+  return 1;
+}
+
+
 /* Process the unwind section.  */
 
 #include "unwind-ia64.h"
@@ -9236,6 +9369,8 @@
 
   process_relocs (file);
 
+  process_direct (file);
+
   process_unwind (file);
 
   process_symbol_table (file);
--- binutils-2.17.50.0.4/include/bfdlink.h
+++ binutils-2.17.50.0.4/include/bfdlink.h
@@ -246,6 +246,9 @@
   /* TRUE if BFD should pre-bind symbols in a shared object.  */
   unsigned int symbolic: 1;
 
+  /* TRUE if BFD should bind symbols directly to resolved at link time.  */
+  unsigned int direct: 1;
+
   /* TRUE if BFD should export all symbols in the dynamic symbol table
      of an executable, rather than only those used.  */
   unsigned int export_dynamic: 1;
@@ -441,6 +444,9 @@
 
   /* List of symbols should be dynamic.  */
   struct bfd_elf_dynamic_list *dynamic;
+
+  /* current max dtinfo section number.  */
+  int dt_needed_index;
 };
 
 /* This structures holds a set of callback functions.  These are
--- binutils-2.17.50.0.4/include/elf/common.h
+++ binutils-2.17.50.0.4/include/elf/common.h
@@ -651,6 +651,11 @@
 #define DF_BIND_NOW	(1 << 3)
 #define DF_STATIC_TLS	(1 << 4)
 
+/* Constants for the DT_DIRECT entries.  */
+#define DT_SUSE_DIRECT_VAGUE   (1<<15)
+#define DT_SUSE_DIRECT_MASK     0xfff
+#define DT_SUSE_DIRECT_UNKNOWN  DT_SUSE_DIRECT_MASK
+
 /* These constants are used for the version number of a Elf32_Verdef
    structure.  */
 
--- binutils-2.17.50.0.4/include/elf/external.h
+++ binutils-2.17.50.0.4/include/elf/external.h
@@ -213,6 +213,10 @@
   unsigned char		vd_next[4];
 } Elf_External_Verdef;
 
+typedef struct {
+  unsigned char		dir_libidx[2];
+} Elf_External_Direct;
+
 /* This structure appears in a SHT_GNU_verdef section.  */
 
 typedef struct {
--- binutils-2.17.50.0.4/ld/lexsup.c
+++ binutils-2.17.50.0.4/ld/lexsup.c
@@ -71,6 +71,7 @@
   OPTION_CREF,
   OPTION_DEFSYM,
   OPTION_DEMANGLE,
+  OPTION_DIRECT,
   OPTION_DYNAMIC_LINKER,
   OPTION_SYSROOT,
   OPTION_EB,
@@ -346,6 +347,8 @@
     '\0', NULL, NULL, ONE_DASH },
   { {"Bsymbolic", no_argument, NULL, OPTION_SYMBOLIC},
     '\0', NULL, N_("Bind global references locally"), ONE_DASH },
+  { {"Bdirect", no_argument, NULL, OPTION_DIRECT},
+    '\0', NULL, N_("Direct-linkage the the shared libraries"), ONE_DASH },
   { {"check-sections", no_argument, NULL, OPTION_CHECK_SECTIONS},
     '\0', NULL, N_("Check section addresses for overlaps (default)"),
     TWO_DASHES },
@@ -761,6 +764,9 @@
 	      cplus_demangle_set_style (style);
 	    }
 	  break;
+	case OPTION_DIRECT:
+	  link_info.direct = TRUE;
+	  break;
 	case 'I':		/* Used on Solaris.  */
 	case OPTION_DYNAMIC_LINKER:
 	  command_line.interpreter = optarg;
