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]

[RFC/proto-PATCH] Enable basic ELF version script support on PE targets?


    Hi gang,


  The current behaviour of LD is to accept and parse ELF version scripts
everywhere, ignoring their presence on non-ELF platforms.

  The attached (prototype, as no NEWS or docs or tests) patch demonstrates how
trivially easy it would be to support using ELF version scripts on PE targets
in order to filter the list of symbols during auto-export-everything mode.

  It makes no attempt at doing any actual versioning; it solely controls which
symbols get exported.  It also currently only filters out; the distinction is
subtle in auto-export mode, but for example you wouldn't be able to use it to
add back one of the symbols that gets autofiltered from the list of exports.

  Would this support be useful?  I'm bootstrapping GCC with it right now,
having already proved to my satisfaction that it DTRT during a libgcj DLL build.

  Note that I haven't made the behaviour subject to a command-line option, and
I would really very much rather not, for several reasons, the prime one being
that supplying a command-line option just to cancel the effects of another one
that the user wishes they hadn't passed in the first place seems nuts!  I also
expect that it should silently DTRT almost everywhere that currently is
passing ELF version scripts to non-ELF-targeted links in any case, but maybe
that's my lack of imagination.  In any case, I felt I ought to point out that
this would be a significant change to the default behaviour so that interested
parties can give it due consideration.

  If the other PE targets don't like the idea, I could always make it
Cygwin-only, but I think it'll be useful to everyone, so I haven't done that
in this draft.  Opinions please?  (If I don't hear back I'll assume nobody is
that bothered and go ahead with a formal submission).

    cheers,
      DaveK

? ld/autom4te.cache
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.476
diff -p -u -r1.476 bfd-in2.h
--- bfd/bfd-in2.h	27 Apr 2009 14:27:34 -0000	1.476
+++ bfd/bfd-in2.h	30 Apr 2009 04:34:15 -0000
@@ -5584,6 +5584,10 @@ bfd_boolean bfd_generic_define_common_sy
 #define bfd_define_common_symbol(output_bfd, info, h) \
        BFD_SEND (output_bfd, _bfd_define_common_symbol, (output_bfd, info, h))
 
+struct bfd_elf_version_tree * bfd_find_version_for_sym
+   (struct bfd_elf_version_tree *verdefs,
+    const char *sym_name, bfd_boolean *hide);
+
 /* Extracted from simple.c.  */
 bfd_byte *bfd_simple_get_relocated_section_contents
    (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.334
diff -p -u -r1.334 elflink.c
--- bfd/elflink.c	8 Apr 2009 16:04:48 -0000	1.334
+++ bfd/elflink.c	30 Apr 2009 04:34:18 -0000
@@ -1798,80 +1798,6 @@ nondefault:
   return TRUE;
 }
 
-static struct bfd_elf_version_tree *
-find_version_for_sym (struct bfd_elf_version_tree *verdefs,
-		      const char *sym_name,
-		      bfd_boolean *hide)
-{
-  struct bfd_elf_version_tree *t;
-  struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver;
-
-  local_ver = NULL;
-  global_ver = NULL;
-  exist_ver = NULL;
-  for (t = verdefs; t != NULL; t = t->next)
-    {
-      if (t->globals.list != NULL)
-	{
-	  struct bfd_elf_version_expr *d = NULL;
-
-	  while ((d = (*t->match) (&t->globals, d, sym_name)) != NULL)
-	    {
-	      global_ver = t;
-	      if (d->symver)
-		exist_ver = t;
-	      d->script = 1;
-	      /* If the match is a wildcard pattern, keep looking for
-		 a more explicit, perhaps even local, match.  */
-	      if (d->literal)
-		break;
-	    }
-
-	  if (d != NULL)
-	    break;
-	}
-
-      if (t->locals.list != NULL)
-	{
-	  struct bfd_elf_version_expr *d = NULL;
-
-	  while ((d = (*t->match) (&t->locals, d, sym_name)) != NULL)
-	    {
-	      local_ver = t;
-	      /* If the match is a wildcard pattern, keep looking for
-		 a more explicit, perhaps even global, match.  */
-	      if (d->literal)
-		{
-		  /* An exact match overrides a global wildcard.  */
-		  global_ver = NULL;
-		  break;
-		}
-	    }
-
-	  if (d != NULL)
-	    break;
-	}
-    }
-
-  if (global_ver != NULL)
-    {
-      /* If we already have a versioned symbol that matches the
-	 node for this symbol, then we don't want to create a
-	 duplicate from the unversioned symbol.  Instead hide the
-	 unversioned symbol.  */
-      *hide = exist_ver == global_ver;
-      return global_ver;
-    }
-
-  if (local_ver != NULL)
-    {
-      *hide = TRUE;
-      return local_ver;
-    }
-
-  return NULL;
-}
-
 /* This routine is used to export all defined symbols into the dynamic
    symbol table.  It is called via elf_link_hash_traverse.  */
 
@@ -1898,7 +1824,7 @@ _bfd_elf_export_symbol (struct elf_link_
       bfd_boolean hide;
 
       if (eif->verdefs == NULL
-	  || (find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
+	  || (bfd_find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
 	      && !hide))
 	{
 	  if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
@@ -2160,7 +2086,7 @@ _bfd_elf_link_assign_sym_version (struct
     {
       bfd_boolean hide;
 
-      h->verinfo.vertree = find_version_for_sym (sinfo->verdefs,
+      h->verinfo.vertree = bfd_find_version_for_sym (sinfo->verdefs,
 						 h->root.root.string, &hide);
       if (h->verinfo.vertree != NULL && hide)
 	(*bed->elf_backend_hide_symbol) (info, h, TRUE);
Index: bfd/linker.c
===================================================================
RCS file: /cvs/src/src/bfd/linker.c,v
retrieving revision 1.68
diff -p -u -r1.68 linker.c
--- bfd/linker.c	16 Apr 2009 23:06:59 -0000	1.68
+++ bfd/linker.c	30 Apr 2009 04:34:18 -0000
@@ -3245,3 +3245,95 @@ bfd_generic_define_common_symbol (bfd *o
   section->flags &= ~SEC_IS_COMMON;
   return TRUE;
 }
+
+/*
+FUNCTION
+	bfd_find_version_for_sym 
+
+SYNOPSIS
+	struct bfd_elf_version_tree * bfd_find_version_for_sym
+	  (struct bfd_elf_version_tree *verdefs,
+	   const char *sym_name, bfd_boolean *hide);
+
+DESCRIPTION
+	Search an elf version script tree for version numbering
+	info and export / don't-export status for a given symbol.
+	Return non-NULL on success and NULL on failure; also sets
+	the output @samp{hide} boolean parameter.
+
+*/
+
+struct bfd_elf_version_tree *
+bfd_find_version_for_sym (struct bfd_elf_version_tree *verdefs,
+		      const char *sym_name,
+		      bfd_boolean *hide)
+{
+  struct bfd_elf_version_tree *t;
+  struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver;
+
+  local_ver = NULL;
+  global_ver = NULL;
+  exist_ver = NULL;
+  for (t = verdefs; t != NULL; t = t->next)
+    {
+      if (t->globals.list != NULL)
+	{
+	  struct bfd_elf_version_expr *d = NULL;
+
+	  while ((d = (*t->match) (&t->globals, d, sym_name)) != NULL)
+	    {
+	      global_ver = t;
+	      if (d->symver)
+		exist_ver = t;
+	      d->script = 1;
+	      /* If the match is a wildcard pattern, keep looking for
+		 a more explicit, perhaps even local, match.  */
+	      if (d->literal)
+		break;
+	    }
+
+	  if (d != NULL)
+	    break;
+	}
+
+      if (t->locals.list != NULL)
+	{
+	  struct bfd_elf_version_expr *d = NULL;
+
+	  while ((d = (*t->match) (&t->locals, d, sym_name)) != NULL)
+	    {
+	      local_ver = t;
+	      /* If the match is a wildcard pattern, keep looking for
+		 a more explicit, perhaps even global, match.  */
+	      if (d->literal)
+		{
+		  /* An exact match overrides a global wildcard.  */
+		  global_ver = NULL;
+		  break;
+		}
+	    }
+
+	  if (d != NULL)
+	    break;
+	}
+    }
+
+  if (global_ver != NULL)
+    {
+      /* If we already have a versioned symbol that matches the
+	 node for this symbol, then we don't want to create a
+	 duplicate from the unversioned symbol.  Instead hide the
+	 unversioned symbol.  */
+      *hide = exist_ver == global_ver;
+      return global_ver;
+    }
+
+  if (local_ver != NULL)
+    {
+      *hide = TRUE;
+      return local_ver;
+    }
+
+  return NULL;
+}
+
Index: ld/pe-dll.c
===================================================================
RCS file: /cvs/src/src/ld/pe-dll.c,v
retrieving revision 1.117
diff -p -u -r1.117 pe-dll.c
--- ld/pe-dll.c	18 Feb 2009 18:23:07 -0000	1.117
+++ ld/pe-dll.c	30 Apr 2009 04:34:20 -0000
@@ -670,9 +670,18 @@ process_def_file (bfd *abfd ATTRIBUTE_UN
 	      /* We should export symbols which are either global or not
 		 anything at all.  (.bss data is the latter)
 		 We should not export undefined symbols.  */
-	      if (symbols[j]->section != &bfd_und_section
-		  && ((symbols[j]->flags & BSF_GLOBAL)
-		      || (symbols[j]->flags == 0)))
+	      bfd_boolean would_export = symbols[j]->section != &bfd_und_section
+		      && ((symbols[j]->flags & BSF_GLOBAL)
+			  || (symbols[j]->flags == 0));
+	      if (lang_elf_version_info && would_export)
+		{
+		  bfd_boolean hide = 0;
+		  char ofs = pe_details->underscored && symbols[j]->name[0] == '_';
+		  (void) bfd_find_version_for_sym (lang_elf_version_info,
+				symbols[j]->name + ofs, &hide);
+		  would_export = !hide;
+		}
+	      if (would_export)
 		{
 		  const char *sn = symbols[j]->name;
 

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