This is the mail archive of the binutils@sources.redhat.com 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]

[patch] Default symbol versions.


The ARM EABI requires that a default symbol version based on the soname is 
created and used for unversioned symbols. The attached patch implements this.

Tested on i686-linux and cross to arm-none-symbianelf, and build 
--enable-targets=all
Ok?

Paul

2004-10-14  Paul Brook  <paul@codesourcery.com>

bfd/
 * elflink.c (elf_finalize_dynstr): Skip shared aux structure.
 (bfd_elf_size_dynamic_sections): Create default version definition.
 (elf_link_output_extsym): Adjust for default symbol version.
include/
 * bfdlink.h (struct bfd_link_info): Add create_default_symver.
ld/
 * ld.texinfo: Document --default-symver.
 * ldmain.c (main): Set link_info.create_default_symver.
 * lexsup.c (enum option_values): Add OPTION_DEFAULT_SYMVER.
 (ld_options): Add default-symver.
 (parse_args): Handle OPTION_DEFAULT_SYMVER.
ld/testsuite/
 * ld-elfvers/vers.exp (build_binary): Add ldargs parameter.
 (build_vers_lib_pic_flags): New function.
 Add vers29 test.
 * ld-elfvers/vers29.c: New file.
 * ld-elfvers/vers29.dsym: New file.
 * ld-elfvers/vers29.ver: New file.
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.110
diff -u -p -r1.110 elflink.c
--- bfd/elflink.c	12 Oct 2004 02:27:53 -0000	1.110
+++ bfd/elflink.c	14 Oct 2004 15:35:39 -0000
@@ -2891,6 +2891,8 @@ elf_finalize_dynstr (bfd *output_bfd, st
 	  _bfd_elf_swap_verdef_in (output_bfd, (Elf_External_Verdef *) p,
 				   &def);
 	  p += sizeof (Elf_External_Verdef);
+	  if (def.vd_aux != sizeof (Elf_External_Verdef))
+	    continue;
 	  for (i = 0; i < def.vd_cnt; ++i)
 	    {
 	      _bfd_elf_swap_verdaux_in (output_bfd,
@@ -5077,7 +5079,7 @@ bfd_elf_size_dynamic_sections (bfd *outp
       if (verdefs != NULL && verdefs->vernum == 0)
 	verdefs = verdefs->next;
 
-      if (verdefs == NULL)
+      if (verdefs == NULL && !info->create_default_symver)
 	_bfd_strip_section_from_output (info, s);
       else
 	{
@@ -5087,6 +5089,9 @@ bfd_elf_size_dynamic_sections (bfd *outp
 	  bfd_byte *p;
 	  Elf_Internal_Verdef def;
 	  Elf_Internal_Verdaux defaux;
+	  struct bfd_link_hash_entry *bh;
+	  struct elf_link_hash_entry *h;
+	  const char *name;
 
 	  cdefs = 0;
 	  size = 0;
@@ -5096,6 +5101,13 @@ bfd_elf_size_dynamic_sections (bfd *outp
 	  size += sizeof (Elf_External_Verdaux);
 	  ++cdefs;
 
+	  /* Make space for the default version.  */
+	  if (info->create_default_symver)
+	    {
+	      size += sizeof (Elf_External_Verdef);
+	      ++cdefs;
+	    }
+
 	  for (t = verdefs; t != NULL; t = t->next)
 	    {
 	      struct bfd_elf_version_deps *n;
@@ -5121,9 +5133,17 @@ bfd_elf_size_dynamic_sections (bfd *outp
 	  def.vd_flags = VER_FLG_BASE;
 	  def.vd_ndx = 1;
 	  def.vd_cnt = 1;
-	  def.vd_aux = sizeof (Elf_External_Verdef);
-	  def.vd_next = (sizeof (Elf_External_Verdef)
-			 + sizeof (Elf_External_Verdaux));
+	  if (info->create_default_symver)
+	    {
+	      def.vd_aux = 2 * sizeof (Elf_External_Verdef);
+	      def.vd_next = sizeof (Elf_External_Verdef);
+	    }
+	  else
+	    {
+	      def.vd_aux = sizeof (Elf_External_Verdef);
+	      def.vd_next = (sizeof (Elf_External_Verdef)
+			     + sizeof (Elf_External_Verdaux));
+	    }
 
 	  if (soname_indx != (bfd_size_type) -1)
 	    {
@@ -5131,10 +5151,10 @@ bfd_elf_size_dynamic_sections (bfd *outp
 				      soname_indx);
 	      def.vd_hash = bfd_elf_hash (soname);
 	      defaux.vda_name = soname_indx;
+	      name = soname;
 	    }
 	  else
 	    {
-	      const char *name;
 	      bfd_size_type indx;
 
 	      name = basename (output_bfd->filename);
@@ -5150,6 +5170,38 @@ bfd_elf_size_dynamic_sections (bfd *outp
 	  _bfd_elf_swap_verdef_out (output_bfd, &def,
 				    (Elf_External_Verdef *) p);
 	  p += sizeof (Elf_External_Verdef);
+	  if (info->create_default_symver)
+	    {
+	      /* Add a symbol representing this version.  */
+	      bh = NULL;
+	      if (! (_bfd_generic_link_add_one_symbol
+		     (info, dynobj, name, BSF_GLOBAL, bfd_abs_section_ptr,
+		      0, NULL, FALSE,
+		      get_elf_backend_data (dynobj)->collect, &bh)))
+		return FALSE;
+	      h = (struct elf_link_hash_entry *) bh;
+	      h->non_elf = 0;
+	      h->def_regular = 1;
+	      h->type = STT_OBJECT;
+	      h->verinfo.vertree = NULL;
+
+	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
+		return FALSE;
+
+	      /* Create a duplicate of the base version with the same
+		 aux block, but different flags.  */
+	      def.vd_flags = 0;
+	      def.vd_ndx = 2;
+	      def.vd_aux = sizeof (Elf_External_Verdef);
+	      if (verdefs)
+		def.vd_next = (sizeof (Elf_External_Verdef)
+			       + sizeof (Elf_External_Verdaux));
+	      else
+		def.vd_next = 0;
+	      _bfd_elf_swap_verdef_out (output_bfd, &def,
+					(Elf_External_Verdef *) p);
+	      p += sizeof (Elf_External_Verdef);
+	    }
 	  _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
 				     (Elf_External_Verdaux *) p);
 	  p += sizeof (Elf_External_Verdaux);
@@ -5158,8 +5210,6 @@ bfd_elf_size_dynamic_sections (bfd *outp
 	    {
 	      unsigned int cdeps;
 	      struct bfd_elf_version_deps *n;
-	      struct elf_link_hash_entry *h;
-	      struct bfd_link_hash_entry *bh;
 
 	      cdeps = 0;
 	      for (n = t->deps; n != NULL; n = n->next)
@@ -5187,7 +5237,7 @@ bfd_elf_size_dynamic_sections (bfd *outp
 		  && t->locals.list == NULL
 		  && ! t->used)
 		def.vd_flags |= VER_FLG_WEAK;
-	      def.vd_ndx = t->vernum + 1;
+	      def.vd_ndx = t->vernum + (info->create_default_symver ? 2 : 1);
 	      def.vd_cnt = cdeps + 1;
 	      def.vd_hash = bfd_elf_hash (t->name);
 	      def.vd_aux = sizeof (Elf_External_Verdef);
@@ -5384,7 +5434,8 @@ bfd_elf_size_dynamic_sections (bfd *outp
       s = bfd_get_section_by_name (dynobj, ".gnu.version");
       BFD_ASSERT (s != NULL);
       if (dynsymcount == 0
-	  || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL))
+	  || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL
+	      && !info->create_default_symver))
 	{
 	  _bfd_strip_section_from_output (info, s);
 	  /* The DYNSYMCOUNT might have changed if we were going to
@@ -6322,6 +6373,8 @@ elf_link_output_extsym (struct elf_link_
 		iversym.vs_vers = 1;
 	      else
 		iversym.vs_vers = h->verinfo.vertree->vernum + 1;
+	      if (finfo->info->create_default_symver)
+		iversym.vs_vers++;
 	    }
 
 	  if (h->hidden)
Index: include/bfdlink.h
===================================================================
RCS file: /cvs/src/src/include/bfdlink.h,v
retrieving revision 1.47
diff -u -p -r1.47 bfdlink.h
--- include/bfdlink.h	7 Oct 2004 14:45:23 -0000	1.47
+++ include/bfdlink.h	14 Oct 2004 15:35:44 -0000
@@ -262,6 +262,9 @@ struct bfd_link_info
   /* TRUE if ok to have version with no definition.  */
   unsigned int allow_undefined_version: 1;
 
+  /* TRUE id a fedault symbol version should be created and used.  */
+  unsigned int create_default_symver: 1;
+
   /* TRUE if symbols should be retained in memory, FALSE if they
      should be freed and reread.  */
   unsigned int keep_memory: 1;
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.126
diff -u -p -r1.126 ld.texinfo
--- ld/ld.texinfo	8 Oct 2004 00:22:13 -0000	1.126
+++ ld/ld.texinfo	14 Oct 2004 15:35:47 -0000
@@ -1223,6 +1223,11 @@ Normally when a symbol has an undefined 
 it. This option disallows symbols with undefined version and a fatal error
 will be issued instead.
 
+@kindex --default-symver
+@item --default-symver
+Create and use a default symbol version (the soname) for unversioned
+symbols.
+
 @kindex --no-warn-mismatch
 @item --no-warn-mismatch
 Normally @command{ld} will give an error if you try to link together input
Index: ld/ldmain.c
===================================================================
RCS file: /cvs/src/src/ld/ldmain.c,v
retrieving revision 1.86
diff -u -p -r1.86 ldmain.c
--- ld/ldmain.c	7 Oct 2004 14:45:22 -0000	1.86
+++ ld/ldmain.c	14 Oct 2004 15:35:48 -0000
@@ -306,6 +306,7 @@ main (int argc, char **argv)
   link_info.unresolved_syms_in_shared_libs = RM_NOT_YET_SET;
   link_info.allow_multiple_definition = FALSE;
   link_info.allow_undefined_version = TRUE;
+  link_info.create_default_symver = FALSE;
   link_info.keep_memory = TRUE;
   link_info.notice_all = FALSE;
   link_info.nocopyreloc = FALSE;
Index: ld/lexsup.c
===================================================================
RCS file: /cvs/src/src/ld/lexsup.c,v
retrieving revision 1.78
diff -u -p -r1.78 lexsup.c
--- ld/lexsup.c	7 Oct 2004 14:45:22 -0000	1.78
+++ ld/lexsup.c	14 Oct 2004 15:35:49 -0000
@@ -134,6 +134,7 @@ enum option_values
   OPTION_NO_ALLOW_SHLIB_UNDEFINED,
   OPTION_ALLOW_MULTIPLE_DEFINITION,
   OPTION_NO_UNDEFINED_VERSION,
+  OPTION_DEFAULT_SYMVER,
   OPTION_DISCARD_NONE,
   OPTION_SPARE_DYNAMIC_TAGS,
   OPTION_NO_DEFINE_COMMON,
@@ -393,6 +394,8 @@ static const struct ld_option ld_options
     '\0', NULL, N_("Allow multiple definitions"), TWO_DASHES },
   { {"no-undefined-version", no_argument, NULL, OPTION_NO_UNDEFINED_VERSION},
     '\0', NULL, N_("Disallow undefined version"), TWO_DASHES },
+  { {"default-symver", no_argument, NULL, OPTION_DEFAULT_SYMVER},
+    '\0', NULL, N_("Create default symbol version"), TWO_DASHES },
   { {"no-warn-mismatch", no_argument, NULL, OPTION_NO_WARN_MISMATCH},
     '\0', NULL, N_("Don't warn about mismatched input files"), TWO_DASHES},
   { {"no-whole-archive", no_argument, NULL, OPTION_NO_WHOLE_ARCHIVE},
@@ -902,6 +905,9 @@ parse_args (unsigned argc, char **argv)
 	case OPTION_NO_UNDEFINED_VERSION:
 	  link_info.allow_undefined_version = FALSE;
 	  break;
+	case OPTION_DEFAULT_SYMVER:
+	  link_info.create_default_symver = TRUE;
+	  break;
 	case OPTION_NO_WARN_MISMATCH:
 	  command_line.warn_mismatch = FALSE;
 	  break;
Index: ld/testsuite/ld-elfvers/vers.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-elfvers/vers.exp,v
retrieving revision 1.33
diff -u -p -r1.33 vers.exp
--- ld/testsuite/ld-elfvers/vers.exp	24 Jun 2004 15:07:43 -0000	1.33
+++ ld/testsuite/ld-elfvers/vers.exp	14 Oct 2004 15:35:49 -0000
@@ -498,7 +498,7 @@ proc objdump_versionstuff { objdump obje
     }
 }
 
-proc build_binary { shared pic test source libname other mapfile verexp versymexp symexp } {
+proc build_binary { shared pic test source libname other mapfile verexp versymexp symexp ldargs } {
     global ld
     global srcdir
     global subdir
@@ -534,7 +534,7 @@ proc build_binary { shared pic test sour
 	set script_arg "$script $srcdir/$subdir/$mapfile"
     }
 
-    if {![ld_simple_link $ld $tmpdir/$libname.so "$shared $tmpdir/$libname.o $other_lib $script_arg"]}     {
+    if {![ld_simple_link $ld $tmpdir/$libname.so "$shared $tmpdir/$libname.o $other_lib $script_arg $ldargs"]}     {
 	fail "$test"
 	return
     }
@@ -566,18 +566,24 @@ proc build_binary { shared pic test sour
 }
 
 proc build_executable { test source libname other mapfile verexp versymexp symexp } {
-  build_binary "" "" $test $source $libname $other $mapfile $verexp $versymexp $symexp 
+  build_binary "" "" $test $source $libname $other $mapfile $verexp $versymexp $symexp ""
 }
 
 proc build_vers_lib_no_pic { test source libname other mapfile verexp versymexp symexp } {
   global shared
-  build_binary $shared "" $test $source $libname $other $mapfile $verexp $versymexp $symexp 
+  build_binary $shared "" $test $source $libname $other $mapfile $verexp $versymexp $symexp ""
 }
 
 proc build_vers_lib_pic { test source libname other mapfile verexp versymexp symexp } {
   global picflag
   global shared
-  build_binary $shared $picflag $test $source $libname $other $mapfile $verexp $versymexp $symexp 
+  build_binary $shared $picflag $test $source $libname $other $mapfile $verexp $versymexp $symexp ""
+}
+
+proc build_vers_lib_pic_flags { test source libname other mapfile verexp versymexp symexp ldargs } {
+  global picflag
+  global shared
+  build_binary $shared $picflag $test $source $libname $other $mapfile $verexp $versymexp $symexp $ldargs
 }
 
 proc test_ldfail { test flag source execname other mapfile whyfail } {
@@ -944,3 +950,4 @@ build_executable "vers27d5" vers27d3.c v
 build_vers_lib_pic "vers28a" vers28a.c vers28a "" "" vers28a.ver vers28a.dsym ""
 build_vers_lib_pic "vers28b" vers28b.c vers28b "" vers28b.map vers28b.ver vers28b.dsym ""
 build_vers_lib_pic "vers28c" vers28c.c vers28c "vers28b.so vers28a.so" "" vers28c.ver vers28c.dsym ""
+build_vers_lib_pic_flags "vers29" vers29.c vers29 "" "" vers29.ver vers29.dsym "" "--default-symver"
Index: ld/testsuite/ld-elfvers/vers29.c
===================================================================
RCS file: ld/testsuite/ld-elfvers/vers29.c
diff -N ld/testsuite/ld-elfvers/vers29.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-elfvers/vers29.c	14 Oct 2004 15:35:49 -0000
@@ -0,0 +1,5 @@
+/* Test for default versioning. */
+void show()
+{
+}
+
Index: ld/testsuite/ld-elfvers/vers29.dsym
===================================================================
RCS file: ld/testsuite/ld-elfvers/vers29.dsym
diff -N ld/testsuite/ld-elfvers/vers29.dsym
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-elfvers/vers29.dsym	14 Oct 2004 15:35:49 -0000
@@ -0,0 +1 @@
+[0-9a-f]*[ 	]+g[ 	]+DF[ 	]+.text[	]+[0-9a-f]*[ 	]+vers29.so[ 	]+(0x[0-9a-f]*|)[ 	]*show
Index: ld/testsuite/ld-elfvers/vers29.ver
===================================================================
RCS file: ld/testsuite/ld-elfvers/vers29.ver
diff -N ld/testsuite/ld-elfvers/vers29.ver
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-elfvers/vers29.ver	14 Oct 2004 15:35:49 -0000
@@ -0,0 +1,3 @@
+Version definitions:
+1 0x01 0x0965d95f vers29.so
+2 0x00 0x0965d95f vers29.so

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