This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

-Bdirect linking patch


Hi guys,

	So - I have an evily hackish prototype for glibc & binutils that gives
me a really nice speedup with relocation processing. It's inspired by
the Solaris -Bdirect feature of the same name, and is implemented in the
same way - by adding a section containing a 16bit word per .dynsym entry
with an index into the libraries DT_NEEDED table, built at library link
time.

	This then is replayed by the runtime linker removing the num_libs term
from the order of linking (for non-vague symbols) and thus giving a
substantial speedup with apps with large numbers of libraries &
relocations [ie. any large C++ app]. My tests yield these results for
runs of OpenOffice writer:

Times in ms to fully loaded:

Old glibc:       3968, 3978, 3983 Avg: 3980
Just new glibc:  4224, 4238, 4250 Avg: 4240 [260ms slower - hmm]
all -Bdirected:  2148, 2168, 2215 Avg: 2180 [1800ms faster - 45%]

Times in secs from instrumenting dlopen top/tail:

before: 2.693, 2.721, 2.714 Avg: 2.709
after:  0.675, 0.679, 0.682 Avg: 0.679 [75% faster]

	Punch line - it saves ~2 seconds from the OO.o warm start time, making
it nearly twice as fast.

	There are (at least) the following issues / questions.

        + How are new elf sections allocated ? and/or typically named
          I know DT_DIRECT / '.direct' are prolly beyond the pale
	  The Solaris linker uses a .SUNW_syminfo section.
	  cf. http://blogs.sun.com/roller/page/msw/20050614

        + LD_PRELOADs need handling for the direct dl-lookup.c
          case ? but that requires a search scope. Perhaps it'd
	  be possible to use the first N entries of the existing
	  searchlist (?)

        + Is there a better way to achieve what I do in dl-deps.c ?
	  the umpteen-string compares are clearly highly evil.
		+ How did I lose 260ms on OO.o startup with this
		  patch for the no .direct section case ?
		  [ could be a self-build glibc problem of course ]

        + In binutils - what is the best way to filter out the
          crucial 'Vague Linkage' symbols ? clearly we don't want to
          bind any of them - the current approach is clearly a gross
	  C++ specific, partial hack.
		+ should we propagate this information from target
		  libraries ? ie. libc can advertise 'foo_baa' as not
		  to be direct linked against ?
		+ should the compiler generate / markup the vague
		  linkage pieces to avoid yet-another link map type
		  thing ?

        + If we fail to find the symbol in the direct scope should we
          check the dependents of that library - to allow some limited
          re-factoring later; or just fallback to the global scope ?

        + Should we compress the .direct table more ? I can't envisage
          more than 12bits (4096) of DT_NEEDED libraries ever - prolly
          we should mask / save that space for future expansion
	  along with a few special values perhaps ?

	+ How useful is this generally ? - clearly OO.o is a 
	  pathalogical case; but how much is interposing used in a
	  typical Linux system ?

	Sorry to mail you directly Ulrich - but don't know where glibc /
development cogitation occurs.

	I append the binutils & glibc patches in-line.

---- glibc ----

diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.3-pristine/elf/dl-close.c glibc-2.3/elf/dl-close.c
--- glibc-2.3-pristine/elf/dl-close.c	2005-07-18 08:35:33.000000000 +0100
+++ glibc-2.3/elf/dl-close.c	2005-10-19 21:48:52.000000000 +0100
@@ -506,6 +506,9 @@
 	  /* Remove the searchlists.  */
 	  free (imap->l_initfini);
 
+	  /* Remove the dtneeded list */
+	  free (imap->l_dtneeded.r_list);
+
 	  /* Remove the scope array if we allocated it.  */
 	  if (imap->l_scope != imap->l_scope_mem)
 	    free (imap->l_scope);

diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.3-pristine/elf/dl-deps.c glibc-2.3/elf/dl-deps.c
--- glibc-2.3-pristine/elf/dl-deps.c	2005-04-06 07:57:05.000000000 +0100
+++ glibc-2.3/elf/dl-deps.c	2005-10-21 17:47:15.000000000 +0100
@@ -39,6 +39,9 @@
 #define FILTERTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
 		   + DT_EXTRATAGIDX (DT_FILTER))
 
+#ifndef VERSYMIDX
+# define VERSYMIDX(sym)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
+#endif
 
 /* When loading auxiliary objects we must ignore errors.  It's ok if
    an object is missing.  */
@@ -139,6 +142,65 @@
     __result; })
 
 
+static void
+setup_direct (struct link_map *map, struct r_scope_elem *scope)
+{
+  if (map->l_info[VERSYMIDX(DT_DIRECT)] && map->l_info[DT_NEEDED])
+    {
+      const ElfW(Dyn) *d;
+      unsigned int i;
+      const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+
+      if (GLRO(dl_debug_mask) & DL_DEBUG_DIRECT)
+	 _dl_debug_printf ("** direct linkage section in '%s' **\n",
+			map->l_name ? map->l_name : "<null>");
+
+      map->l_dtneeded.r_nlist = 1;
+      for (d = map->l_ld; d->d_tag != DT_NULL; ++d)
+        {
+	  if (__builtin_expect (d->d_tag, DT_NEEDED) == DT_NEEDED)
+	    map->l_dtneeded.r_nlist++;
+	}
+
+      map->l_dtneeded.r_list = (struct link_map **)
+	malloc (map->l_dtneeded.r_nlist * sizeof (struct link_map *));
+
+      map->l_dtneeded.r_list[0] = map;
+      for (i = 1, d = map->l_ld; d->d_tag != DT_NULL; ++d)
+        {
+	  const char *name;
+	  unsigned int j;
+
+	  if (d->d_tag != DT_NEEDED)
+	    continue;
+
+	  name = expand_dst (map, strtab + d->d_un.d_val, 0);
+          if (GLRO(dl_debug_mask) & DL_DEBUG_DIRECT)
+	      _dl_debug_printf (" direct index %u object '%s'\n", i, name);
+	  for (j = 0; j < scope->r_nlist; j++)
+	    {
+	      if (scope->r_list[j] &&
+		  _dl_name_match_p (name, scope->r_list[j]))
+	        {
+	          map->l_dtneeded.r_list[i] = scope->r_list[j];
+		  break;
+		}
+	    }
+          if (!map->l_dtneeded.r_list[i])
+	    _dl_debug_printf (" impossible error - can't find '%s'\n", name);
+	  i++;
+	}
+    }
+  else
+    {
+      if (GLRO(dl_debug_mask) & DL_DEBUG_DIRECT)
+        _dl_debug_printf ("no direct linkage section in '%s'\n",
+			  map->l_name ? map->l_name : "<null>");
+      map->l_dtneeded.r_nlist = 0;
+      map->l_dtneeded.r_list = NULL;
+    }
+}
+
 void
 internal_function
 _dl_map_object_deps (struct link_map *map,
@@ -555,6 +617,10 @@
 	}
     }
 
+  /* Setup direct linkage dtneeded table */
+  for (i = 0; i < nlist; ++i)
+    setup_direct (map->l_searchlist.r_list[i], &map->l_searchlist);
+
   /* Maybe we can remove some relocation dependencies now.  */
   assert (map->l_searchlist.r_list[0] == map);
   for (i = 0; i < map->l_reldepsact; ++i)


diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.3-pristine/elf/dl-lookup.c glibc-2.3/elf/dl-lookup.c
--- glibc-2.3-pristine/elf/dl-lookup.c	2005-04-06 07:57:05.000000000 +0100
+++ glibc-2.3/elf/dl-lookup.c	2005-10-19 22:23:15.000000000 +0100
@@ -32,6 +32,10 @@
 
 #define VERSTAG(tag)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
 
+#ifndef VERSYMIDX
+# define VERSYMIDX(sym)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
+#endif
+
 /* We need this string more than once.  */
 static const char undefined_msg[] = "undefined symbol: ";
 
@@ -209,6 +213,7 @@
   const unsigned long int hash = _dl_elf_hash (undef_name);
   struct sym_val current_value = { NULL, NULL };
   struct r_scope_elem **scope = symbol_scope;
+  size_t i = 0;
 
   bump_num_relocations ();
 
@@ -216,7 +221,74 @@
      up a versioned symbol.  */
   assert (version == NULL || flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY);
 
-  size_t i = 0;
+  if (undef_map && undef_map->l_dtneeded.r_nlist && *ref)
+    {
+      unsigned int idx, noffset;
+      const ElfW(Sym) *symtab;
+      ElfW(Addr) direct;
+
+      /* We need a dynsym index ... */
+      symtab = (const void *) D_PTR (undef_map, l_info[DT_SYMTAB]);
+      direct = D_PTR (undef_map, l_info[VERSYMIDX(DT_DIRECT)]);
+
+      idx = *ref - symtab;
+      if (GLRO(dl_debug_mask) & DL_DEBUG_DIRECT)
+        _dl_debug_printf ("dynamic symbol index %u from '%s' for %s base direct 0x%x start 0x%x\n", idx,
+			  undef_map->l_name ? undef_map->l_name : "<noname>",
+			  undef_name ? undef_name : "<undef>",
+			  (int) direct, (int) undef_map->l_map_start);
+      direct += idx * 2;
+      if (direct >= undef_map->l_map_end || direct <= undef_map->l_map_start)
+        _dl_debug_printf ("broken: off end of map 0x%x\n", (int) direct);
+      else
+        {
+          noffset = *(uint16_t *)direct;
+	  if (GLRO(dl_debug_mask) & DL_DEBUG_DIRECT)
+	    _dl_debug_printf ("dynamic symbol offset %u from %u\n", noffset, (int) direct);
+	  if (noffset < undef_map->l_dtneeded.r_nlist)
+	    {
+	      int res;
+	      struct r_scope_elem direct_elem;
+
+	      /* FIXME - requires LD_PRELOAD support ... */
+	      direct_elem.r_list = undef_map->l_dtneeded.r_list + noffset;
+	      direct_elem.r_nlist = 1;
+
+	      if (direct_elem.r_list[0] == skip_map)
+	        goto normal_lookup; /* FIXME - correct ? */
+
+	      res = do_lookup_x (undef_name, hash, *ref, &current_value, &direct_elem,
+				 0, version, flags, skip_map, type_class);
+	      if (res > 0)
+	        {
+	          if (GLRO(dl_debug_mask) & DL_DEBUG_DIRECT)
+		    _dl_debug_printf ("direct lookup ...\n");
+	          goto match;
+		}
+	      else
+		_dl_debug_printf ("Error in lookup %u - missing (?) - fallback "
+				  "to deps & then global ? ...\n", res);
+	    }
+	  else if (noffset == 0xffff)
+	    { 
+	      _dl_debug_printf ("unknown/undefined symbol '%s'\n",
+				undef_name ? undef_name : "<undef>");
+	    }
+	  else if (noffset == 0xfffe)
+	    { 
+              if (GLRO(dl_debug_mask) & DL_DEBUG_DIRECT)
+	        _dl_debug_printf ("vague symbol\n");
+	    }
+	  else
+	    {
+	      _dl_debug_printf ("Error: foo symbol '%s' 0 < %u < %u\n",
+				undef_name ? undef_name : "<undef>",
+				noffset, undef_map->l_dtneeded.r_nlist);
+	    }
+	}
+    }
+ normal_lookup:
+
   if (__builtin_expect (skip_map != NULL, 0))
     {
       /* Search the relevant loaded objects for a definition.  */
@@ -258,7 +330,7 @@
 	  return 0;
 	}
     }
-
+ match:
   if (__builtin_expect (current_value.s == NULL, 0))
     {
       if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)

diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.3-pristine/elf/dynamic-link.h glibc-2.3/elf/dynamic-link.h
--- glibc-2.3-pristine/elf/dynamic-link.h	2005-10-18 15:29:20.000000000 +0100
+++ glibc-2.3/elf/dynamic-link.h	2005-10-19 21:01:06.000000000 +0100
@@ -94,6 +94,7 @@
       ADJUST_DYN_INFO (DT_PLTGOT);
       ADJUST_DYN_INFO (DT_STRTAB);
       ADJUST_DYN_INFO (DT_SYMTAB);
+      ADJUST_DYN_INFO (VERSYMIDX(DT_DIRECT));
 # if ! ELF_MACHINE_NO_RELA
       ADJUST_DYN_INFO (DT_RELA);
 # endif


diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.3-pristine/elf/elf.h glibc-2.3/elf/elf.h
--- glibc-2.3-pristine/elf/elf.h	2004-11-15 09:35:22.000000000 +0000
+++ glibc-2.3/elf/elf.h	2005-10-18 15:58:28.000000000 +0100
@@ -714,6 +714,7 @@
 /* The versioning entry types.  The next are defined as part of the
    GNU extension.  */
 #define DT_VERSYM	0x6ffffff0
+#define DT_DIRECT	0x6ffffff1 /* FIXME - how are these allocated ? */
 
 #define DT_RELACOUNT	0x6ffffff9
 #define DT_RELCOUNT	0x6ffffffa

diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.3-pristine/elf/rtld.c glibc-2.3/elf/rtld.c
--- glibc-2.3-pristine/elf/rtld.c	2005-10-18 15:29:20.000000000 +0100
+++ glibc-2.3/elf/rtld.c	2005-10-19 21:59:08.000000000 +0100
@@ -2056,11 +2056,13 @@
 	DL_DEBUG_SYMBOLS | DL_DEBUG_IMPCALLS },
       { LEN_AND_STR ("bindings"), "display information about symbol binding",
 	DL_DEBUG_BINDINGS | DL_DEBUG_IMPCALLS },
+      { LEN_AND_STR ("direct"), "display information about direct binding",
+	DL_DEBUG_DIRECT | DL_DEBUG_IMPCALLS },
       { LEN_AND_STR ("versions"), "display version dependencies",
 	DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
       { LEN_AND_STR ("all"), "all previous options combined",
 	DL_DEBUG_LIBS | DL_DEBUG_RELOC | DL_DEBUG_FILES | DL_DEBUG_SYMBOLS
-	| DL_DEBUG_BINDINGS | DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
+	| DL_DEBUG_BINDINGS | DL_DEBUG_DIRECT | DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
       { LEN_AND_STR ("statistics"), "display relocation statistics",
 	DL_DEBUG_STATISTICS },
       { LEN_AND_STR ("unused"), "determined unused DSOs",
Only in glibc-2.3/elf: rtld.c~
diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.3-pristine/include/link.h glibc-2.3/include/link.h
--- glibc-2.3-pristine/include/link.h	2005-10-18 15:29:20.000000000 +0100
+++ glibc-2.3/include/link.h	2005-10-19 21:13:12.000000000 +0100
@@ -299,6 +299,10 @@
        done.  */
     ElfW(Addr) l_relro_addr;
     size_t l_relro_size;
+
+    /* Array of DT_NEEDED dependencies in order for use in
+       direct linkage - l_dtneeded[0] entry is self  */
+    struct r_scope_elem l_dtneeded;
   };
 
 struct dl_phdr_info


diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' glibc-2.3-pristine/sysdeps/generic/ldsodefs.h glibc-2.3/sysdeps/generic/ldsodefs.h
--- glibc-2.3-pristine/sysdeps/generic/ldsodefs.h	2005-10-18 15:29:20.000000000 +0100
+++ glibc-2.3/sysdeps/generic/ldsodefs.h	2005-10-19 21:58:12.000000000 +0100
@@ -388,6 +388,7 @@
 /* These two are used only internally.  */
 #define DL_DEBUG_HELP       (1 << 9)
 #define DL_DEBUG_PRELINK    (1 << 10)
+#define DL_DEBUG_DIRECT     (1 << 11)
 
   /* Cached value of `getpagesize ()'.  */
   EXTERN size_t _dl_pagesize;



---- binutils ----


diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16/bfd/elf-bfd.h binutils.current/bfd/elf-bfd.h
--- binutils-2.16/bfd/elf-bfd.h	2005-03-03 20:52:31.000000000 +0000
+++ binutils.current/bfd/elf-bfd.h	2005-10-17 11:47:08.000000000 +0100
@@ -396,6 +396,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;
 
@@ -1238,6 +1241,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;
@@ -1338,6 +1342,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)
Only in binutils.current/bfd: elf-bfd.h~
diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16/bfd/elf.c binutils.current/bfd/elf.c
--- binutils-2.16/bfd/elf.c	2005-03-06 02:02:15.000000000 +0000
+++ binutils.current/bfd/elf.c	2005-10-19 20:25:03.000000000 +0100
@@ -1145,6 +1145,7 @@
 	    case DT_RELCOUNT: name = "RELCOUNT"; break;
 	    case DT_FLAGS_1: name = "FLAGS_1"; break;
 	    case DT_VERSYM: name = "VERSYM"; break;
+	    case DT_DIRECT: name = "DIRECT"; break;
 	    case DT_VERDEF: name = "VERDEF"; break;
 	    case DT_VERDEFNUM: name = "VERDEFNUM"; break;
 	    case DT_VERNEED: name = "VERNEED"; break;
@@ -1495,6 +1496,7 @@
   table->runpath = NULL;
   table->tls_sec = NULL;
   table->tls_size = 0;
+  table->direct_sec = NULL;
   table->loaded = NULL;
   table->is_relocatable_executable = FALSE;
 
Only in binutils.current/bfd: elf.c~
diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16/bfd/elflink.c binutils.current/bfd/elflink.c
--- binutils-2.16/bfd/elflink.c	2005-04-29 14:40:22.000000000 +0100
+++ binutils.current/bfd/elflink.c	2005-10-20 17:15:26.000000000 +0100
@@ -172,6 +172,16 @@
       elf_hash_table (info)->eh_info.hdr_sec = s;
     }
 
+  if ( info->direct && ! info->executable )
+    {
+      s = bfd_make_section (abfd, ".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 (abfd, ".gnu.version_d");
@@ -2193,7 +2203,9 @@
 
   return TRUE;
 }
+
 
+
 /* Fix up the flags for a symbol.  This handles various cases which
    can only be fixed after all the input files are seen.  This is
    currently called by both adjust_dynamic_symbol and
@@ -2848,6 +2860,9 @@
 
       if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex))
 	return -1;
+      elf_dt_needed_idx (abfd) = ++(info->dt_needed_index);
+/*      fprintf (stderr, "Set soname '%s' as index %d\n",
+	       soname, info->dt_needed_index); */
     }
   else
     /* We were just checking for existence of the tag.  */
@@ -5671,6 +5686,24 @@
 	    return FALSE;
 	}
 
+      /* Create the direct bindings section - 1 entry per dynsym */
+      s = bfd_get_section_by_name (dynobj, ".direct");
+      if (s)
+        {
+  	  if (dynsymcount == 0)
+	    _bfd_strip_section_from_output (info, s);
+	  else
+	    {
+	      s->size = dynsymcount * sizeof (Elf_External_Direct);
+	      s->contents = bfd_zalloc (output_bfd, s->size);
+	      if (s->contents == NULL)
+	        return FALSE;
+
+	      if (!_bfd_elf_add_dynamic_entry (info, DT_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
@@ -5749,6 +5782,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.  */
@@ -6603,6 +6638,40 @@
 	  eversym += h->dynindx;
 	  _bfd_elf_swap_versym_out (finfo->output_bfd, &iversym, eversym);
 	}
+
+      if (finfo->direct_sec)
+	{
+	  bfd_vma offset = 2 * h->dynindx;
+	  if (offset > finfo->direct_sec->size)
+	    fprintf (stderr, "Out of bounds direct section index %d\n",
+		     (int) offset);
+	  else
+	    {
+	      int dt_index = 0xffff;
+
+/*	      fprintf (stderr, "Symbol '%s' type %d\n",
+	               h->root.root.string, h->root.type); */
+
+	      if (finfo->info->direct_vague (finfo->info, h->root.root.string))
+                {
+/*		  fprintf (stderr, "Symbol is vague !\n"); */
+		  dt_index = 0xfffe;
+		}
+	      else if (h->root.type == bfd_link_hash_defined
+		  || h->root.type == bfd_link_hash_defweak)
+	        {
+		   asection *sec = h->root.u.def.section;
+		   if (sec && sec->owner)
+		     dt_index = elf_dt_needed_idx (sec->owner);
+/*		   fprintf (stderr, "Section %p, owner '%s' [%d] offset %d\n",
+		            sec, sec && sec->owner ? sec->owner->filename : "<noowner?>",
+			    dt_index, (int) offset); */
+		}
+	      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
@@ -7732,6 +7801,7 @@
       finfo.dynsym_sec = NULL;
       finfo.hash_sec = NULL;
       finfo.symver_sec = NULL;
+      finfo.direct_sec = NULL;
     }
   else
     {
@@ -7740,6 +7810,7 @@
       BFD_ASSERT (finfo.dynsym_sec != NULL && finfo.hash_sec != NULL);
       finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version");
       /* Note that it is OK if symver_sec is NULL.  */
+      finfo.direct_sec = bfd_get_section_by_name (dynobj, ".direct");
     }
 
   finfo.contents = NULL;
@@ -8492,6 +8563,9 @@
 	    case DT_VERNEED:
 	      name = ".gnu.version_r";
 	      goto get_vma;
+	    case DT_DIRECT:
+	      name = ".direct";
+	      goto get_vma;
 	    case DT_VERSYM:
 	      name = ".gnu.version";
 	    get_vma:

diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16/binutils/readelf.c binutils.current/binutils/readelf.c
--- binutils-2.16/binutils/readelf.c	2005-04-20 19:43:36.000000000 +0100
+++ binutils.current/binutils/readelf.c	2005-10-19 21:08:57.000000000 +0100
@@ -143,6 +143,7 @@
 int do_dynamic;
 int do_syms;
 int do_reloc;
+int do_direct;
 int do_sections;
 int do_section_groups;
 int do_segments;
@@ -1519,6 +1520,7 @@
     case DT_SYMINFO:	return "SYMINFO"; /* aka ADDRRNGHI */
 
     case DT_VERSYM:	return "VERSYM";
+    case DT_DIRECT:	return "DIRECT";
 
     case DT_RELACOUNT:	return "RELACOUNT";
     case DT_RELCOUNT:	return "RELCOUNT";
@@ -2590,6 +2592,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'},
@@ -2626,6 +2629,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\
@@ -2693,7 +2697,7 @@
     usage ();
 
   while ((c = getopt_long
-	  (argc, argv, "ersuahnldSDAIgw::x:i:vVWH", options, NULL)) != EOF)
+	  (argc, argv, "erysuahnldSDAIgw::x:i:vVWH", options, NULL)) != EOF)
     {
       char *cp;
       int section;
@@ -2710,6 +2714,7 @@
 	case 'a':
 	  do_syms++;
 	  do_reloc++;
+	  do_direct++;
 	  do_unwind++;
 	  do_dynamic++;
 	  do_header++;
@@ -2738,6 +2743,9 @@
 	case 'r':
 	  do_reloc++;
 	  break;
+	case 'y':
+	  do_direct++;
+	  break;
 	case 'u':
 	  do_unwind++;
 	  break;
@@ -2943,7 +2951,7 @@
 	}
     }
 
-  if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections
+  if (!do_dynamic && !do_syms && !do_reloc && !do_direct && !do_unwind && !do_sections
       && !do_segments && !do_header && !do_dump && !do_version
       && !do_histogram && !do_debugging && !do_arch && !do_notes
       && !do_section_groups)
@@ -4328,6 +4336,131 @@
   return 1;
 }
 
+static void
+print_dt_needed_name (int idx)
+{
+  const char *name = NULL;
+  Elf_Internal_Dyn *entry;
+ 
+  switch (idx)
+    {
+    case 0:
+      name = _("<self>");
+      break;
+    case 0xffff:
+      name = _("<unknown>");
+      break;
+    case 0xfffe:
+      name = _("<vague>");
+      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), ".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, _("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, _("string table"));
+    }
+
+  assert (strtab != NULL);
+
+  printf (_("\nDirect relocations for image:\n"));
+  printf (_("   Num:  Index     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);
+       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"
@@ -11784,6 +11917,8 @@
 
   process_relocs (file);
 
+  process_direct (file);
+
   process_unwind (file);
 
   process_symbol_table (file);

diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16/include/bfdlink.h binutils.current/include/bfdlink.h
--- binutils-2.16/include/bfdlink.h	2005-03-03 11:58:00.000000000 +0000
+++ binutils.current/include/bfdlink.h	2005-10-19 20:39:19.000000000 +0100
@@ -244,6 +244,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;
@@ -416,6 +419,12 @@
 
   /* Start and end of RELRO region.  */
   bfd_vma relro_start, relro_end;
+
+  /* function to filter out symbols that must not be directly linked */
+  int (*direct_vague) (struct bfd_link_info *, const char *symbol);
+
+  /* current max dtinfo section number */
+  int dt_needed_index;
 };
 
 /* This structures holds a set of callback functions.  These are
Only in binutils.current/include: bfdlink.h~
diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16/include/elf/common.h binutils.current/include/elf/common.h
--- binutils-2.16/include/elf/common.h	2004-10-08 14:55:08.000000000 +0100
+++ binutils.current/include/elf/common.h	2005-10-15 11:31:38.000000000 +0100
@@ -586,6 +586,7 @@
 
 /* This tag is a GNU extension to the Solaris version scheme.  */
 #define DT_VERSYM	0x6ffffff0
+#define DT_DIRECT	0x6ffffff1 /* FIXME - how are these allocated ? */
 
 #define DT_LOPROC	0x70000000
 #define DT_HIPROC	0x7fffffff
Only in binutils.current/include/elf: common.h~
diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16/include/elf/external.h binutils.current/include/elf/external.h
--- binutils-2.16/include/elf/external.h	2005-03-03 11:58:05.000000000 +0000
+++ binutils.current/include/elf/external.h	2005-10-15 11:29:45.000000000 +0100
@@ -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 {
Only in binutils.current/include/elf: external.h~
Files binutils-2.16/ld/ld-new and binutils.current/ld/ld-new differ
diff -u -r -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16/ld/lexsup.c binutils.current/ld/lexsup.c
--- binutils-2.16/ld/lexsup.c	2005-03-03 11:52:00.000000000 +0000
+++ binutils.current/ld/lexsup.c	2005-10-20 14:57:01.000000000 +0100
@@ -70,6 +70,7 @@
   OPTION_CREF,
   OPTION_DEFSYM,
   OPTION_DEMANGLE,
+  OPTION_DIRECT,
   OPTION_DYNAMIC_LINKER,
   OPTION_SYSROOT,
   OPTION_EB,
@@ -341,6 +342,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 },
@@ -522,6 +525,25 @@
 
 #define OPTION_COUNT ARRAY_SIZE (ld_options)
 
+static int
+is_direct_vague (struct bfd_link_info *info, const char *symbol)
+{
+  int ret = 0;
+
+  /* C++ typeinfo foo */
+  if (symbol && getenv ("KILL_CPP_VAGUE"))
+    {
+      if (symbol[0] == '_' && symbol[1] == 'Z' && symbol[2] == 'T'
+	  && (symbol[3] == 'I' || symbol[3] == 'S'))
+        ret = 1;
+    }
+
+/* fprintf (stderr, "Is '%s' %c%c%c vague (%d)\n",
+   symbol, symbol[0], symbol[1], symbol[2], ret); */
+
+  return ret;
+}
+
 void
 parse_args (unsigned argc, char **argv)
 {
@@ -746,6 +768,10 @@
 	      cplus_demangle_set_style (style);
 	    }
 	  break;
+	case OPTION_DIRECT:
+	  link_info.direct = TRUE;
+	  link_info.direct_vague = is_direct_vague;
+	  break;
 	case 'I':		/* Used on Solaris.  */
 	case OPTION_DYNAMIC_LINKER:
 	  command_line.interpreter = optarg;


	Thanks,

		Michael.

-- 
 michael.meeks@novell.com  <><, Pseudo Engineer, itinerant idiot


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]