public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PATCH: Add STB_SECONDARY support
@ 2012-06-30 21:19 H.J. Lu
  2012-07-02  6:24 ` Alan Modra
  0 siblings, 1 reply; 13+ messages in thread
From: H.J. Lu @ 2012-06-30 21:19 UTC (permalink / raw)
  To: binutils; +Cc: GNU C Library

Hi,

This patch adds STB_SECONDARY support.  I am enclosing the STB_SECONDARY 
proposal posted on the gABI group. This patch is backward compatible
with existing ld.so.  STB_SECONDARY symbols are generated only with
"ld -shared -z secondary" switch.  OK to install?

I will post a separate patch for glibc.

Thanks.


H.J.
----
We want to provide a relocatable object which can take advantage of all
versions of a supported OS.  For a function, foo, in the C library, we
can use it only if it is available on all versions of the C library or
we provide our own implementation of foo.  With our own foo, the one in
the C library will never be used.  Here is a proposal to add STB_SECONDARY
to gABI to support the secondary definition so that a software vendor
can provide an alternative implementation in case it isn't available
in the C library.

STB_SECONDARY
 
      Secondary symbols are similar to weak symbols, but their definitions
      have lower precedence than global and weak symbols.  The difference
      between secondary symbols and weak symbols are

	1. The link editor ignores the secondary definition if there is
	a global, weak or common definition with the same name.  Multiple
	secondary definitions with the same name will not cause an error.
	The first appearance of the secondary definition should be honored
	and the rest are ignored.
	2. The link editor must search archive library and extract
	archive members to resolve defined and undefined secondary symbol.
	3.  When the link editor searches a shared object, it must honor
	the global or weak definition in the shared object and ignore the
	secondary one with the same name.
	4. The link editor may treat the secondary definition in the
	shared object as a global definition.

      The purpose of this symbol binding is to provide the primary
      definition as a global, weak or common symbol in an archive library
      or a shared object while keeping a secondary definition in a
      relocatable object.  If there is no primary definition, the
      secondary definition will be used.

      When secondary definitions become part of an executable or shared
      object, the link editor may convert them to global or local
      definitions.

      At run-time, when resolving a symbol, after seeing a secondary
      definition, the dynamic linker must keep searching until a
      global or weak definition is found.  If a global or weak
      definition is found, it will be used to satisfy the symbol lookup.
      Otherwise, the secondary definition will be used.

      If the dlopen loads a global or weak definition after the program
      has already resolved references to a secondary definition, those
      references remain bound to the secondary definition.  Any
      references resolved after the dlopen, for which the dlopened
      module is included in the module search list, would be resolved
      to the global or weak definition.

STB_SECONDARY is defined as:

#define STB_SECONDARY	3	/* Secondary symbol */

NOTE:
      The behavior of secondary symbols in areas not specified by this
      proposal is implementation defined.

bfd/

2012-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* elflink.c (_bfd_elf_merge_symbol): Allow overriding secondary
	symbols.
	(elf_link_add_object_symbols): Treat secondary symbols as weak
	symbols.  Allow overriding secondary symbols.
	(elf_link_add_archive_symbols): Keep searching if a definition
	is secondary. 
	(elf_link_output_extsym): Generate STB_SECONDARY symbols if
	needed.  Treat undefined secondary symbols as weak symbols.
	* linker.c (_bfd_generic_link_add_one_symbol): Treat secondary
	symbol as weak symbol.  Mark secondary symbol.

2012-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* archive.c (_bfd_compute_and_write_armap): Treat BSF_SECONDARY
	symbol as global.
	* elf32-mips.c (mips_elf_sym_is_global): Likewise.
	* elfn32-mips.c (mips_elf_sym_is_global): Likewise.
	* elf.c (sym_is_global): Likewise.
	(swap_out_syms): Handle SECONDARY symbol.
	* elf64-ia64-vms.c (elf64_vms_link_add_object_symbols): Likewise.
	* elfcode.h (elf_slurp_symbol_table): Likewise.
	* elflink.c (elf_link_add_object_symbols): Likewise.

	* syms.c (BSF_SECONDARY): New.
	(bfd_print_symbol_vandf): Handle SECONDARY symbol.
	(bfd_decode_symclass): Likewise.

	* bfd-in2.h: Regenerated.

binutils/

2012-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* nm.c (filter_symbols): Treat BSF_SECONDARY symbol as global.

	* readelf.c (get_symbol_binding): Handle STB_SECONDARY.

gas/

2012-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* symbols.c (S_IS_SECONDARY): New.
	(S_SET_SECONDARY): Likewise.
	(S_FORCE_RELOC): Handle BSF_SECONDARY like BSF_WEAK.
	(S_SET_EXTERNAL): Likewise.
	(S_CLEAR_EXTERNAL): Likewise.
	(S_CLEAR_WEAKREFD): Likewise.
	(S_SET_WEAK): Also clear BSF_SECONDARY.

	* symbols.h (S_IS_SECONDARY): New.
	(S_SET_SECONDARY): Likewise.

	* config/obj-elf.c (obj_elf_secondary): New.
	(elf_pseudo_table): Add "secondary".
	(elf_frob_symbol): Handle secondary symbol for .symver.  Remove
	the unused secondary symbol.  Check secondary symbols.

	* doc/as.texinfo: Document .secondary directive.

gas/testsuite/

2012-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* gas/elf/common3.d: New file.
	* gas/elf/common3.l: Likewise.
	* gas/elf/common3.s: Likewise.
	* gas/elf/common4.d: Likewise.
	* gas/elf/common4.l: Likewise.
	* gas/elf/common4.s: Likewise.

	* gas/elf/elf.exp: Run common3 and common4.

	* gas/elf/type.s: Add .secondary tests.
	* gas/elf/type.e: Updated.

include/

2012-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* bfdlink.h (bfd_link_hash_entry): Add secondary.
	(bfd_link_info): Add emit_secondary.

include/elf/

2012-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* common.h (STB_SECONDARY): New.

ld/

2012-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* ld.texinfo: Document "-z secondary".

	* emultempl/elf32.em (gld${EMULATION_NAME}_handle_option): Set
	to link_info.emit_secondary to TRUE for "-z secondary".
	(gld${EMULATION_NAME}_list_options): Add "-z secondary".

ld/testsuite/

2012-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* ld-elf/library1.c: New file.
	* ld-elf/library1.out: Likewise.
	* ld-elf/library2.c: Likewise.
	* ld-elf/library2.out: Likewise.
	* ld-elf/library3.out: Likewise.
	* ld-elf/library4.out: Likewise.
	* ld-elf/secondary-main.c: Likewise.
	* ld-elf/secondary.c: Likewise.
	* ld-elf/secondary.exp: Likewise.
	* ld-elf/secondary1.out: Likewise.

diff --git a/bfd/archive.c b/bfd/archive.c
index 0620452..f7f4134 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -2316,6 +2316,7 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
 
 		  if (((flags & (BSF_GLOBAL
 				 | BSF_WEAK
+				 | BSF_SECONDARY
 				 | BSF_INDIRECT
 				 | BSF_GNU_UNIQUE)) != 0
 		       || bfd_is_com_section (sec))
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 11f3e49..aef27f4 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -5371,6 +5371,10 @@ typedef struct bfd_symbol
      with this name and type in use.  BSF_OBJECT must also be set.  */
 #define BSF_GNU_UNIQUE         (1 << 23)
 
+  /* A secondary global symbol, overridable without warnings by
+     a regular or weak global symbol of the same name.  */
+#define BSF_SECONDARY          (1 << 24)
+
   flagword flags;
 
   /* A pointer to the section to which this symbol is
diff --git a/bfd/elf.c b/bfd/elf.c
index 1a53548..ecbf727 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -3251,7 +3251,10 @@ sym_is_global (bfd *abfd, asymbol *sym)
   if (bed->elf_backend_sym_is_global)
     return (*bed->elf_backend_sym_is_global) (abfd, sym);
 
-  return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0
+  return ((sym->flags & (BSF_GLOBAL
+			 | BSF_WEAK
+			 | BSF_SECONDARY
+			 | BSF_GNU_UNIQUE)) != 0
 	  || bfd_is_und_section (bfd_get_section (sym))
 	  || bfd_is_com_section (bfd_get_section (sym)));
 }
@@ -6837,8 +6840,9 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
 #endif
 	    sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
 	}
+      /* Output undefined secondary symbols as weak.  */
       else if (bfd_is_und_section (syms[idx]->section))
-	sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
+	sym.st_info = ELF_ST_INFO (((flags & (BSF_WEAK | BSF_SECONDARY))
 				    ? STB_WEAK
 				    : STB_GLOBAL),
 				   type);
@@ -6852,6 +6856,8 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
 	    bind = STB_LOCAL;
 	  else if (flags & BSF_GNU_UNIQUE)
 	    bind = STB_GNU_UNIQUE;
+	  else if (flags & BSF_SECONDARY)
+	    bind = STB_SECONDARY;
 	  else if (flags & BSF_WEAK)
 	    bind = STB_WEAK;
 	  else if (flags & BSF_GLOBAL)
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index 61e8b45..ab4ffdc 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -2133,7 +2133,10 @@ mips_elf_sym_is_global (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym)
   if (SGI_COMPAT (abfd))
     return (sym->flags & BSF_SECTION_SYM) == 0;
   else
-    return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0
+    return ((sym->flags & (BSF_GLOBAL
+			   | BSF_WEAK
+			   | BSF_SECONDARY
+			   | BSF_GNU_UNIQUE)) != 0
 	    || bfd_is_und_section (bfd_get_section (sym))
 	    || bfd_is_com_section (bfd_get_section (sym)));
 }
diff --git a/bfd/elf64-ia64-vms.c b/bfd/elf64-ia64-vms.c
index ef78374..f37903e 100644
--- a/bfd/elf64-ia64-vms.c
+++ b/bfd/elf64-ia64-vms.c
@@ -4921,6 +4921,10 @@ error_free_dyn:
 	  flags = BSF_WEAK;
 	  break;
 
+	case STB_SECONDARY:
+	  flags = BSF_SECONDARY;
+	  break;
+
 	case STB_GNU_UNIQUE:
 	  flags = BSF_GNU_UNIQUE;
 	  break;
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index cc55c86..dd3896d 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1292,6 +1292,9 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
 	    case STB_WEAK:
 	      sym->symbol.flags |= BSF_WEAK;
 	      break;
+	    case STB_SECONDARY:
+	      sym->symbol.flags |= BSF_SECONDARY;
+	      break;
 	    case STB_GNU_UNIQUE:
 	      sym->symbol.flags |= BSF_GNU_UNIQUE;
 	      break;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index d9e1abe..d6f8d9d 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -924,7 +924,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   int bind;
   bfd *oldbfd;
   bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
-  bfd_boolean newweak, oldweak, newfunc, oldfunc;
+  bfd_boolean newweak, oldweak, newfunc, oldfunc, weakbind, oldsecondary;
   const struct elf_backend_data *bed;
 
   *skip = FALSE;
@@ -1007,8 +1007,13 @@ _bfd_elf_merge_symbol (bfd *abfd,
       break;
     }
 
+  oldsecondary = h->root.secondary != 0;
+
+  /* Treat secondary symbols as weak symbols.  */
+  weakbind = bind == STB_WEAK || bind == STB_SECONDARY;
+
   /* Differentiate strong and weak symbols.  */
-  newweak = bind == STB_WEAK;
+  newweak = weakbind;
   oldweak = (h->root.type == bfd_link_hash_defweak
 	     || h->root.type == bfd_link_hash_undefweak);
 
@@ -1146,10 +1151,10 @@ _bfd_elf_merge_symbol (bfd *abfd,
 	     if it is weak. Otherwise, we clear it.  */
 	  if (!h->ref_dynamic)
 	    {
-	      if (bind == STB_WEAK)
+	      if (weakbind)
 		h->dynamic_weak = 1;
 	    }
-	  else if (bind != STB_WEAK)
+	  else if (!weakbind)
 	    h->dynamic_weak = 0;
 	}
     }
@@ -1385,10 +1390,14 @@ _bfd_elf_merge_symbol (bfd *abfd,
      represent variables; this can cause confusion in principle, but
      any such confusion would seem to indicate an erroneous program or
      shared library.  We also permit a common symbol in a regular
-     object to override a weak symbol in a shared object.  */
+     object to override a weak symbol in a shared object.
+     
+     We let a definition in a dynamic object override the old secondary
+     symbol.  */
 
   if (newdyn
       && newdef
+      && !oldsecondary
       && (olddef
 	  || (h->root.type == bfd_link_hash_common
 	      && (newweak || newfunc))))
@@ -1427,8 +1436,9 @@ _bfd_elf_merge_symbol (bfd *abfd,
       *size_change_ok = TRUE;
     }
 
-  /* Skip weak definitions of symbols that are already defined.  */
-  if (newdef && olddef && newweak)
+  /* Skip weak definitions of symbols that are already defined unless
+     the old definition is secondary.  */
+  if (newdef && olddef && newweak && !oldsecondary)
     {
       /* Don't skip new non-IR weak syms.  */
       if (!(oldbfd != NULL
@@ -1456,18 +1466,20 @@ _bfd_elf_merge_symbol (bfd *abfd,
      always take precedence over symbols from dynamic objects, even if
      they are defined after the dynamic object in the link.
 
+     The new non-secondary definition overrides the old secondary
+     definition.
+
      As above, we again permit a common symbol in a regular object to
      override a definition in a shared object if the shared object
      symbol is a function or is weak.  */
 
   flip = NULL;
-  if (!newdyn
+  if (((!newdyn && olddyn && h->def_dynamic) || oldsecondary)
+      && bind != STB_SECONDARY
       && (newdef
 	  || (bfd_is_com_section (sec)
 	      && (oldweak || oldfunc)))
-      && olddyn
-      && olddef
-      && h->def_dynamic)
+      && olddef)
     {
       /* Change the hash table entry to undefined, and let
 	 _bfd_generic_link_add_one_symbol do the right thing with the
@@ -3847,6 +3859,7 @@ error_free_dyn:
       unsigned int old_alignment;
       bfd *old_bfd;
       bfd * undef_bfd = NULL;
+      unsigned int secondary;
 
       override = FALSE;
 
@@ -3875,6 +3888,10 @@ error_free_dyn:
 	  flags = BSF_WEAK;
 	  break;
 
+	case STB_SECONDARY:
+	  flags = BSF_SECONDARY;
+	  break;
+
 	case STB_GNU_UNIQUE:
 	  flags = BSF_GNU_UNIQUE;
 	  break;
@@ -4162,7 +4179,12 @@ error_free_dyn:
 	      && vernum > 1
 	      && definition)
 	    h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1];
+
+	  /* Remember if the old definition is secondary.  */
+	  secondary = h->root.secondary;
 	}
+      else
+	secondary = 0;
 
       if (! (_bfd_generic_link_add_one_symbol
 	     (info, abfd, name, flags, sec, value, NULL, FALSE, bed->collect,
@@ -4346,10 +4368,14 @@ error_free_dyn:
 	      if (! definition)
 		{
 		  h->ref_regular = 1;
-		  if (bind != STB_WEAK)
+		  /* Treat secondary symbols as weak symbols.  */
+		  if (bind != STB_WEAK && bind != STB_SECONDARY)
 		    h->ref_regular_nonweak = 1;
 		}
-	      else
+	      /* Mark it defined in a regular object if it is a
+		 non-secondary definition or it hasn't been defined
+		 in a dynamic object.  */
+	      else if (!h->def_dynamic || bind != STB_SECONDARY)
 		{
 		  h->def_regular = 1;
 		  if (h->def_dynamic)
@@ -4371,6 +4397,10 @@ error_free_dyn:
 		{
 		  h->def_dynamic = 1;
 		  h->dynamic_def = 1;
+		  /* Dynamic definition overrides regular secondary
+		     definition.  */
+		  if (secondary)
+		    h->def_regular = 0;
 		}
 	      if (h->def_regular
 		  || h->ref_regular
@@ -5064,7 +5094,9 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
 	      if (! elf_link_is_defined_archive_symbol (abfd, symdef))
 		continue;
 	    }
-	  else if (h->root.type != bfd_link_hash_undefined)
+	  /* Keep searching if a definition is secondary.  */
+	  else if (h->root.type != bfd_link_hash_undefined
+		   && !h->root.secondary)
 	    {
 	      if (h->root.type != bfd_link_hash_undefweak)
 		defined[i] = TRUE;
@@ -8742,7 +8774,21 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
     sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type);
   else if (h->root.type == bfd_link_hash_undefweak
 	   || h->root.type == bfd_link_hash_defweak)
-    sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
+    {
+      /* Generate defined secondary symbols for "ld -shared -z secondary"
+	 and "ld -r".  For undefined secondary symbols, we convert them
+	 to weak symbols.  We also convert defined secondary symbols in
+	 executables to weak symbols since their bindings in executables
+	 are final and can't be changed.  */
+      if ((flinfo->info->relocatable
+	   || (!flinfo->info->executable
+	       && flinfo->info->emit_secondary))
+	  && h->root.type == bfd_link_hash_defweak
+	  && h->root.secondary)
+	  sym.st_info = ELF_ST_INFO (STB_SECONDARY, h->type);
+	else
+	  sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
+    }
   else
     sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
   sym.st_target_internal = h->target_internal;
@@ -8873,7 +8919,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
   if (sym.st_shndx == SHN_UNDEF
       && h->ref_regular
       && (ELF_ST_BIND (sym.st_info) == STB_GLOBAL
-	  || ELF_ST_BIND (sym.st_info) == STB_WEAK))
+	  || ELF_ST_BIND (sym.st_info) == STB_WEAK
+	  || ELF_ST_BIND (sym.st_info) == STB_SECONDARY))
     {
       int bindtype;
       unsigned int type = ELF_ST_TYPE (sym.st_info);
@@ -8899,10 +8946,12 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
     sym.st_size = 0;
 
   /* If a non-weak symbol with non-default visibility is not defined
-     locally, it is a fatal error.  */
+     locally, it is a fatal error.  Treat secondary symbols as weak
+     symbols.  */
   if (!flinfo->info->relocatable
       && ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT
       && ELF_ST_BIND (sym.st_info) != STB_WEAK
+      && ELF_ST_BIND (sym.st_info) != STB_SECONDARY
       && h->root.type == bfd_link_hash_undefined
       && !h->def_regular)
     {
diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c
index 6728371..91870c5 100644
--- a/bfd/elfn32-mips.c
+++ b/bfd/elfn32-mips.c
@@ -3153,7 +3153,10 @@ mips_elf_sym_is_global (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym)
   if (SGI_COMPAT (abfd))
     return (sym->flags & BSF_SECTION_SYM) == 0;
   else
-    return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0
+    return ((sym->flags & (BSF_GLOBAL
+			   | BSF_WEAK
+			   | BSF_SECONDARY
+			   | BSF_GNU_UNIQUE)) != 0
 	    || bfd_is_und_section (bfd_get_section (sym))
 	    || bfd_is_com_section (bfd_get_section (sym)));
 }
diff --git a/bfd/linker.c b/bfd/linker.c
index 3caec96..182cfdf 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -1577,6 +1577,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
   enum link_row row;
   struct bfd_link_hash_entry *h;
   bfd_boolean cycle;
+  unsigned int secondary;
 
   BFD_ASSERT (section != NULL);
 
@@ -1626,15 +1627,53 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
 	return FALSE;
     }
 
+  /* Since secondary symbols have lower precedence than weak symbols,
+     we treat them as weak symbols here.  */
+  secondary = (flags & BSF_SECONDARY) != 0;
+  if (secondary)
+    switch (row)
+      {
+      default:
+	break;
+
+      case UNDEF_ROW:
+	row = UNDEFW_ROW;
+	break;
+
+      case DEF_ROW:
+	row = DEFW_ROW;
+	break;
+      }
+
   if (hashp != NULL)
     *hashp = h;
 
   do
     {
       enum link_action action;
+      enum bfd_link_hash_type type;
+      
+      type = h->type;
+      /* Convert a secondary symbol to a weak symbol.  Backend is
+	 responsible to let a weak symbol override a secondary
+	 symbol. */
+      if (h->secondary)
+	switch (type)
+	  {
+	  default:
+	    break;
+
+	  case bfd_link_hash_undefined:
+	    type = bfd_link_hash_undefweak;
+	    break;
+
+	  case bfd_link_hash_defined:
+	    type = bfd_link_hash_defweak;
+	    break;
+	  }
 
       cycle = FALSE;
-      action = link_action[(int) row][(int) h->type];
+      action = link_action[(int) row][(int) type];
       switch (action)
 	{
 	case FAIL:
@@ -1679,6 +1718,9 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
 	    h->u.def.section = section;
 	    h->u.def.value = value;
 
+	    /* Mark if this is a secondary symbol.  */
+	    h->secondary = secondary;
+
 	    /* If we have been asked to, we act like collect2 and
 	       identify all functions that might be global
 	       constructors and destructors and pass them up in a
diff --git a/bfd/syms.c b/bfd/syms.c
index bf5a488..69ced86 100644
--- a/bfd/syms.c
+++ b/bfd/syms.c
@@ -308,6 +308,10 @@ CODE_FRAGMENT
 .     with this name and type in use.  BSF_OBJECT must also be set.  *}
 .#define BSF_GNU_UNIQUE		(1 << 23)
 .
+.  {* A secondary global symbol, overridable without warnings by
+.     a regular or weak global symbol of the same name.  *}
+.#define BSF_SECONDARY		(1 << 24)
+.
 .  flagword flags;
 .
 .  {* A pointer to the section to which this symbol is
@@ -491,6 +495,7 @@ bfd_print_symbol_vandf (bfd *abfd, void *arg, asymbol *symbol)
 	   ((type & BSF_LOCAL)
 	    ? (type & BSF_GLOBAL) ? '!' : 'l'
 	    : (type & BSF_GLOBAL) ? 'g'
+	    : (type & BSF_SECONDARY) ? 's'
 	    : (type & BSF_GNU_UNIQUE) ? 'u' : ' '),
 	   (type & BSF_WEAK) ? 'w' : ' ',
 	   (type & BSF_CONSTRUCTOR) ? 'C' : ' ',
@@ -694,6 +699,15 @@ bfd_decode_symclass (asymbol *symbol)
     }
   if (symbol->flags & BSF_GNU_UNIQUE)
     return 'u';
+  if (symbol->flags & BSF_SECONDARY)
+    {
+      /* If secondary, determine if it's specifically an object
+	 or non-object weak.  */
+      if (symbol->flags & BSF_OBJECT)
+	return 'Y';
+      else
+	return 'S';
+    }
   if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
     return '?';
 
diff --git a/binutils/nm.c b/binutils/nm.c
index ad38e27..31e1508 100644
--- a/binutils/nm.c
+++ b/binutils/nm.c
@@ -438,6 +438,7 @@ filter_symbols (bfd *abfd, bfd_boolean is_dynamic, void *minisyms,
 	/* PR binutls/12753: Unique symbols are global too.  */
 	keep = ((sym->flags & (BSF_GLOBAL
 			       | BSF_WEAK
+			       | BSF_SECONDARY
 			       | BSF_GNU_UNIQUE)) != 0
 		|| bfd_is_und_section (sym->section)
 		|| bfd_is_com_section (sym->section));
diff --git a/binutils/readelf.c b/binutils/readelf.c
index b1bacfd..9329344 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -8702,6 +8702,7 @@ get_symbol_binding (unsigned int binding)
     case STB_LOCAL:	return "LOCAL";
     case STB_GLOBAL:	return "GLOBAL";
     case STB_WEAK:	return "WEAK";
+    case STB_SECONDARY:	return "SECOND";
     default:
       if (binding >= STB_LOPROC && binding <= STB_HIPROC)
 	snprintf (buff, sizeof (buff), _("<processor specific>: %d"),
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index d7c7665..fc702cb 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -66,6 +66,7 @@ static void obj_elf_line (int);
 static void obj_elf_size (int);
 static void obj_elf_type (int);
 static void obj_elf_ident (int);
+static void obj_elf_secondary (int);
 static void obj_elf_weak (int);
 static void obj_elf_local (int);
 static void obj_elf_visibility (int);
@@ -94,6 +95,7 @@ static const pseudo_typeS elf_pseudo_table[] =
   {"type", obj_elf_type, 0},
   {"version", obj_elf_version, 0},
   {"weak", obj_elf_weak, 0},
+  {"secondary", obj_elf_secondary, 0},
 
   /* These define symbol visibility.  */
   {"internal", obj_elf_visibility, STV_INTERNAL},
@@ -437,6 +439,29 @@ obj_elf_local (int ignore ATTRIBUTE_UNUSED)
 }
 
 static void
+obj_elf_secondary (int ignore ATTRIBUTE_UNUSED)
+{
+  int c;
+  symbolS *symbolP;
+
+  do
+    {
+      symbolP = get_sym_from_input_line_and_check ();
+      c = *input_line_pointer;
+      S_SET_SECONDARY (symbolP);
+      if (c == ',')
+	{
+	  input_line_pointer++;
+	  SKIP_WHITESPACE ();
+	  if (*input_line_pointer == '\n')
+	    c = '\n';
+	}
+    }
+  while (c == ',');
+  demand_empty_rest_of_line ();
+}
+
+static void
 obj_elf_weak (int ignore ATTRIBUTE_UNUSED)
 {
   int c;
@@ -1988,18 +2013,24 @@ elf_frob_symbol (symbolS *symp, int *puntp)
 	      if (S_IS_WEAK (symp))
 		S_SET_WEAK (symp2);
 
+	      if (S_IS_SECONDARY (symp))
+		S_SET_SECONDARY (symp2);
+
 	      if (S_IS_EXTERNAL (symp))
 		S_SET_EXTERNAL (symp2);
 	    }
 	}
     }
 
-  /* Double check weak symbols.  */
-  if (S_IS_WEAK (symp))
+  /* Double check weak and secondary symbols.  */
+  if (S_IS_COMMON (symp))
     {
-      if (S_IS_COMMON (symp))
+      if (S_IS_WEAK (symp))
 	as_bad (_("symbol `%s' can not be both weak and common"),
 		S_GET_NAME (symp));
+      else if (S_IS_SECONDARY (symp))
+	as_bad (_("symbol `%s' can not be both secondary and common"),
+		S_GET_NAME (symp));
     }
 
 #ifdef TC_MIPS
@@ -2214,7 +2245,7 @@ elf_frob_file_before_adjust (void)
 	    /* If there was .weak foo, but foo was neither defined nor
 	       used anywhere, remove it.  */
 
-	    else if (S_IS_WEAK (symp)
+	    else if ((S_IS_WEAK (symp) || S_IS_SECONDARY (symp))
 		     && symbol_used_p (symp) == 0
 		     && symbol_used_in_reloc_p (symp) == 0)
 	      symbol_remove (symp, &symbol_rootP, &symbol_lastP);
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index 5b5d268..d587857 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -4071,6 +4071,7 @@ Some machine configurations provide additional directives.
 * Print::			@code{.print @var{string}}
 @ifset ELF
 * Protected::                   @code{.protected @var{names}}
+* Secondary::                   @code{.secondary @var{names}}
 @end ifset
 
 * Psize::                       @code{.psize @var{lines}, @var{columns}}
@@ -5753,6 +5754,14 @@ their binding: local, global or weak).  The directive sets the visibility to
 components that defines them must be resolved to the definition in that
 component, even if a definition in another component would normally preempt
 this.
+
+@node Secondary
+@section @code{.secondary @var{names}}
+
+@cindex @code{secondary} directive
+This directive sets the secondary attribute on the comma separated list
+of symbol @code{names}.  If the symbols do not already exist, they will
+be created.
 @end ifset
 
 @node Psize
diff --git a/gas/symbols.c b/gas/symbols.c
index 1f325c4..79ea5bc 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -2035,6 +2035,14 @@ S_IS_WEAK (symbolS *s)
 }
 
 int
+S_IS_SECONDARY (symbolS *s)
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    return 0;
+  return (s->bsym->flags & BSF_SECONDARY) != 0;
+}
+
+int
 S_IS_WEAKREFR (symbolS *s)
 {
   if (LOCAL_SYMBOL_CHECK (s))
@@ -2081,7 +2089,7 @@ S_FORCE_RELOC (symbolS *s, int strict)
     return ((struct local_symbol *) s)->lsy_section == undefined_section;
 
   return ((strict
-	   && ((s->bsym->flags & BSF_WEAK) != 0
+	   && ((s->bsym->flags & (BSF_WEAK | BSF_SECONDARY)) != 0
 	       || (EXTERN_FORCE_RELOC
 		   && (s->bsym->flags & BSF_GLOBAL) != 0)))
 	  || (s->bsym->flags & BSF_GNU_INDIRECT_FUNCTION) != 0
@@ -2217,9 +2225,9 @@ S_SET_EXTERNAL (symbolS *s)
 {
   if (LOCAL_SYMBOL_CHECK (s))
     s = local_symbol_convert ((struct local_symbol *) s);
-  if ((s->bsym->flags & BSF_WEAK) != 0)
+  if ((s->bsym->flags & (BSF_WEAK | BSF_SECONDARY)) != 0)
     {
-      /* Let .weak override .global.  */
+      /* Let .weak/.secondary override .global.  */
       return;
     }
   if (s->bsym->flags & BSF_SECTION_SYM)
@@ -2242,7 +2250,7 @@ S_SET_EXTERNAL (symbolS *s)
     }
 #endif
   s->bsym->flags |= BSF_GLOBAL;
-  s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK);
+  s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK | BSF_SECONDARY);
 
 #ifdef TE_PE
   if (! an_external_name && S_GET_NAME(s)[0] != '.')
@@ -2255,13 +2263,13 @@ S_CLEAR_EXTERNAL (symbolS *s)
 {
   if (LOCAL_SYMBOL_CHECK (s))
     return;
-  if ((s->bsym->flags & BSF_WEAK) != 0)
+  if ((s->bsym->flags & (BSF_WEAK | BSF_SECONDARY)) != 0)
     {
-      /* Let .weak override.  */
+      /* Let .weak/.secondary override.  */
       return;
     }
   s->bsym->flags |= BSF_LOCAL;
-  s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
+  s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK | BSF_SECONDARY);
 }
 
 void
@@ -2273,7 +2281,16 @@ S_SET_WEAK (symbolS *s)
   obj_set_weak_hook (s);
 #endif
   s->bsym->flags |= BSF_WEAK;
-  s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL);
+  s->bsym->flags &= ~(BSF_GLOBAL | BSF_SECONDARY | BSF_LOCAL);
+}
+
+void
+S_SET_SECONDARY (symbolS *s)
+{
+  if (LOCAL_SYMBOL_CHECK (s))
+    s = local_symbol_convert ((struct local_symbol *) s);
+  s->bsym->flags |= BSF_SECONDARY;
+  s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK | BSF_LOCAL);
 }
 
 void
@@ -2330,6 +2347,12 @@ S_CLEAR_WEAKREFD (symbolS *s)
 	  s->bsym->flags &= ~BSF_WEAK;
 	  s->bsym->flags |= BSF_LOCAL;
 	}
+      /* The same applies to secondary symbol.  */
+      else if (s->bsym->flags & BSF_SECONDARY)
+	{
+	  s->bsym->flags &= ~BSF_SECONDARY;
+	  s->bsym->flags |= BSF_LOCAL;
+	}
     }
 }
 
diff --git a/gas/symbols.h b/gas/symbols.h
index a3a31f7..6ec3266 100644
--- a/gas/symbols.h
+++ b/gas/symbols.h
@@ -92,6 +92,7 @@ extern void S_SET_VALUE (symbolS *, valueT);
 extern int S_IS_FUNCTION (symbolS *);
 extern int S_IS_EXTERNAL (symbolS *);
 extern int S_IS_WEAK (symbolS *);
+extern int S_IS_SECONDARY (symbolS *);
 extern int S_IS_WEAKREFR (symbolS *);
 extern int S_IS_WEAKREFD (symbolS *);
 extern int S_IS_COMMON (symbolS *);
@@ -110,6 +111,7 @@ extern void S_SET_EXTERNAL (symbolS *);
 extern void S_SET_NAME (symbolS *, const char *);
 extern void S_CLEAR_EXTERNAL (symbolS *);
 extern void S_SET_WEAK (symbolS *);
+extern void S_SET_SECONDARY (symbolS *);
 extern void S_SET_WEAKREFR (symbolS *);
 extern void S_CLEAR_WEAKREFR (symbolS *);
 extern void S_SET_WEAKREFD (symbolS *);
diff --git a/gas/testsuite/gas/elf/common3.d b/gas/testsuite/gas/elf/common3.d
new file mode 100644
index 0000000..e73f6c5
--- /dev/null
+++ b/gas/testsuite/gas/elf/common3.d
@@ -0,0 +1,2 @@
+#name: secondary and common directives
+#error-output: common3.l
diff --git a/gas/testsuite/gas/elf/common3.l b/gas/testsuite/gas/elf/common3.l
new file mode 100644
index 0000000..58d5142
--- /dev/null
+++ b/gas/testsuite/gas/elf/common3.l
@@ -0,0 +1,2 @@
+[^:]*: Assembler messages:
+[^:]*: Error: symbol `foobar' can not be both secondary and common
diff --git a/gas/testsuite/gas/elf/common3.s b/gas/testsuite/gas/elf/common3.s
new file mode 100644
index 0000000..df8b7ed
--- /dev/null
+++ b/gas/testsuite/gas/elf/common3.s
@@ -0,0 +1,2 @@
+	.secondary foobar
+	.comm foobar,30
diff --git a/gas/testsuite/gas/elf/common4.d b/gas/testsuite/gas/elf/common4.d
new file mode 100644
index 0000000..aca59c0
--- /dev/null
+++ b/gas/testsuite/gas/elf/common4.d
@@ -0,0 +1,2 @@
+#name: common and secondary directives
+#error-output: common4.l
diff --git a/gas/testsuite/gas/elf/common4.l b/gas/testsuite/gas/elf/common4.l
new file mode 100644
index 0000000..58d5142
--- /dev/null
+++ b/gas/testsuite/gas/elf/common4.l
@@ -0,0 +1,2 @@
+[^:]*: Assembler messages:
+[^:]*: Error: symbol `foobar' can not be both secondary and common
diff --git a/gas/testsuite/gas/elf/common4.s b/gas/testsuite/gas/elf/common4.s
new file mode 100644
index 0000000..37bd0ce
--- /dev/null
+++ b/gas/testsuite/gas/elf/common4.s
@@ -0,0 +1,2 @@
+	.comm foobar,30
+	.secondary foobar
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 7897788..7c5095b 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -188,6 +188,8 @@ if { [is_elf_format] } then {
     
     run_dump_test "common1"
     run_dump_test "common2"
+    run_dump_test "common3"
+    run_dump_test "common4"
 
 load_lib gas-dg.exp
 dg-init
diff --git a/gas/testsuite/gas/elf/type.e b/gas/testsuite/gas/elf/type.e
index fbc9aac..2968fd0 100644
--- a/gas/testsuite/gas/elf/type.e
+++ b/gas/testsuite/gas/elf/type.e
@@ -3,5 +3,7 @@
  +.: 0+0 +1 +OBJECT +LOCAL +DEFAULT +. object
  +.: 0+1 +1 +TLS +LOCAL +DEFAULT +. tls_object
  +..: 0+2 +1 +NOTYPE +LOCAL +DEFAULT +. notype
+ +.: 0+2 +1 +FUNC +SECOND +DEFAULT +. secondary_function
  +..: 0+3 +1 +OBJECT +UNIQUE +DEFAULT +. unique_global
+ +..: 0+4 +1 +OBJECT +SECOND +DEFAULT +. secondary_object
  +..: 0+1 +1 +(COMMON|OBJECT) +GLOBAL +DEFAULT +COM common
diff --git a/gas/testsuite/gas/elf/type.s b/gas/testsuite/gas/elf/type.s
index d0a1afd..bd7df2c 100644
--- a/gas/testsuite/gas/elf/type.s
+++ b/gas/testsuite/gas/elf/type.s
@@ -10,6 +10,12 @@ function:
 indirect_function:
 	.byte	0x0
 	
+        .size   secondary_function,1
+	.secondary secondary_function
+        .type   secondary_function,%function
+secondary_function:
+	.byte	0x0
+	
         .data
 	
         .type   object,%object
@@ -32,6 +38,11 @@ unique_global:
 	.byte	0x0
 	.size	unique_global,1
 
+        .type   secondary_object,%object
+	.secondary secondary_object
+secondary_object:
+	.byte	0x0
+        .size   secondary_object,1
+
 	.comm	common, 1
 	.type   common,STT_COMMON
-	
\ No newline at end of file
diff --git a/include/bfdlink.h b/include/bfdlink.h
index d900b47..2a116c9 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -95,6 +95,9 @@ struct bfd_link_hash_entry
 
   unsigned int non_ir_ref : 1;
 
+  /* Set if it is a secondary symbol.  */
+  unsigned int secondary : 1;
+
   /* A union of information depending upon the type.  */
   union
     {
@@ -346,6 +349,9 @@ struct bfd_link_info
   /* TRUE if .gnu.hash section should be created.  */
   unsigned int emit_gnu_hash: 1;
 
+  /* TRUE if secondary symbols should be generated.  */
+  unsigned int emit_secondary: 1;
+
   /* If TRUE reduce memory overheads, at the expense of speed. This will
      cause map file generation to use an O(N^2) algorithm and disable
      caching ELF symbol buffer.  */
diff --git a/include/elf/common.h b/include/elf/common.h
index 58e489a..2a4452b 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -649,6 +649,7 @@
 #define STB_LOCAL	0		/* Symbol not visible outside obj */
 #define STB_GLOBAL	1		/* Symbol visible outside obj */
 #define STB_WEAK	2		/* Like globals, lower precedence */
+#define STB_SECONDARY	3		/* Like weaks, lower precedence */
 #define STB_LOOS	10		/* OS-specific semantics */
 #define STB_GNU_UNIQUE	10		/* Symbol is unique in namespace */
 #define STB_HIOS	12		/* OS-specific semantics */
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 2b7a352..18f0010 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -2334,6 +2334,8 @@ fragment <<EOF
 	link_info.error_textrel = FALSE;
       else if (strcmp (optarg, "textoff") == 0)
 	link_info.error_textrel = FALSE;
+      else if (strcmp (optarg, "secondary") == 0)
+	link_info.emit_secondary = TRUE;
 EOF
 fi
 
@@ -2456,6 +2458,8 @@ fragment <<EOF
                                 processing at runtime\n"));
   fprintf (file, _("\
   -z relro                    Create RELRO program header\n"));
+  fprintf (file, _("\
+  -z secondary                Emit secondary symbols\n"));
 EOF
 fi
 
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 6c74ff5..22fccd5 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1087,6 +1087,12 @@ Marks the object may contain $ORIGIN.
 @item relro
 Create an ELF @code{PT_GNU_RELRO} segment header in the object.
 
+@item secondary
+By default, the linker converts secondary symbols to weak symbols.  This
+option disables secondary symbol conversion and emits secondary symbols
+when generating a shared library.  The resulting shared library requires
+secondary symbol support in the dynamic linker.
+
 @item max-page-size=@var{value}
 Set the emulation maximum page size to @var{value}.
 
diff --git a/ld/testsuite/ld-elf/library1.c b/ld/testsuite/ld-elf/library1.c
new file mode 100644
index 0000000..28e255d
--- /dev/null
+++ b/ld/testsuite/ld-elf/library1.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+void
+bar (void)
+{
+#ifdef SHARED
+  printf ("library bar (SHARED)\n");
+#else
+  printf ("library bar\n");
+#endif
+}
diff --git a/ld/testsuite/ld-elf/library1.out b/ld/testsuite/ld-elf/library1.out
new file mode 100644
index 0000000..2050e74
--- /dev/null
+++ b/ld/testsuite/ld-elf/library1.out
@@ -0,0 +1 @@
+library bar
diff --git a/ld/testsuite/ld-elf/library2.c b/ld/testsuite/ld-elf/library2.c
new file mode 100644
index 0000000..271ebd6
--- /dev/null
+++ b/ld/testsuite/ld-elf/library2.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+void
+__attribute__((weak))
+bar (void)
+{
+#ifdef SHARED
+  printf ("weak library bar (SHARED)\n");
+#else
+  printf ("weak library bar\n");
+#endif
+}
diff --git a/ld/testsuite/ld-elf/library2.out b/ld/testsuite/ld-elf/library2.out
new file mode 100644
index 0000000..ddd3d10
--- /dev/null
+++ b/ld/testsuite/ld-elf/library2.out
@@ -0,0 +1 @@
+weak library bar
diff --git a/ld/testsuite/ld-elf/library3.out b/ld/testsuite/ld-elf/library3.out
new file mode 100644
index 0000000..881856e
--- /dev/null
+++ b/ld/testsuite/ld-elf/library3.out
@@ -0,0 +1 @@
+library bar (SHARED)
diff --git a/ld/testsuite/ld-elf/library4.out b/ld/testsuite/ld-elf/library4.out
new file mode 100644
index 0000000..1ff1840
--- /dev/null
+++ b/ld/testsuite/ld-elf/library4.out
@@ -0,0 +1 @@
+weak library bar (SHARED)
diff --git a/ld/testsuite/ld-elf/secondary-main.c b/ld/testsuite/ld-elf/secondary-main.c
new file mode 100644
index 0000000..8d509ad
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary-main.c
@@ -0,0 +1,8 @@
+extern void bar (void);
+
+int
+main (void)
+{
+  bar ();
+  return 0;
+}
diff --git a/ld/testsuite/ld-elf/secondary.c b/ld/testsuite/ld-elf/secondary.c
new file mode 100644
index 0000000..6d64ed7
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+asm (".secondary bar");
+
+void
+bar (void)
+{
+  printf ("secondary bar\n");
+}
diff --git a/ld/testsuite/ld-elf/secondary.exp b/ld/testsuite/ld-elf/secondary.exp
new file mode 100644
index 0000000..434b99e
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary.exp
@@ -0,0 +1,94 @@
+# Expect script for ELF secondary symbol tests.
+#   Copyright 2012
+#   Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# Exclude non-ELF targets.
+
+# The following tests require running the executable generated by ld,
+# or enough of a build environment to create a fully linked executable.
+# This is not commonly available when testing a cross-built linker.
+if ![isnative] {
+    return
+}
+
+if ![is_elf_format] {
+    return
+}
+
+# Check to see if the C compiler works
+if { [which $CC] == 0 } {
+    return
+}
+
+set build_tests {
+  {"Build secondary.so"
+   "-shared" "-fPIC"
+   {secondary.c} {} "secondary.so"}
+  {"Build library1.so"
+   "-shared" "-fPIC -DSHARED"
+   {library1.c} {} "library1.so"}
+  {"Build library2.so"
+   "-shared" "-fPIC -DSHARED"
+   {library2.c} {} "library2.so"}
+  {"Build library1.a"
+   "" ""
+   {library1.c} {} "library1.a"}
+  {"Build library2.a"
+   "" ""
+   {library2.c} {} "library2.a"}
+}
+
+run_cc_link_tests $build_tests
+
+set run_tests {
+    {"Run secondary-main with secondary.o"
+     "tmpdir/secondary.o" ""
+     {secondary-main.c} "secondary1" "secondary1.out"}
+    {"Run secondary-main with secondary.so"
+     "tmpdir/secondary.so" ""
+     {secondary-main.c} "secondary2" "secondary1.out"}
+    {"Run secondary-main with secondary.o library1.o"
+     "tmpdir/secondary.o tmpdir/secondary.o tmpdir/library1.o" ""
+     {secondary-main.c} "secondary3" "library1.out"}
+    {"Run secondary-main with library1.o secondary.o"
+     "tmpdir/library1.o tmpdir/secondary.o tmpdir/secondary.o" ""
+     {secondary-main.c} "secondary4" "library1.out"}
+    {"Run secondary-main with secondary.o library2.o"
+     "tmpdir/secondary.o tmpdir/library2.o" ""
+     {secondary-main.c} "secondary5" "library2.out"}
+    {"Run secondary-main with library2.o secondary.o"
+     "tmpdir/library2.o tmpdir/secondary.o" ""
+     {secondary-main.c} "secondary6" "library2.out"}
+    {"Run secondary-main with secondary.o library1.so"
+     "tmpdir/secondary.o tmpdir/library1.so" ""
+     {secondary-main.c} "secondary7" "library3.out"}
+    {"Run secondary-main with library1.so secondary.o"
+     "tmpdir/library1.so tmpdir/secondary.o" ""
+     {secondary-main.c} "secondary8" "library3.out"}
+    {"Run secondary-main with secondary.o library2.so"
+     "tmpdir/secondary.o tmpdir/library2.so" ""
+     {secondary-main.c} "secondary9" "library4.out"}
+    {"Run secondary-main with library2.so secondary.o"
+     "tmpdir/library2.so tmpdir/secondary.o" ""
+     {secondary-main.c} "secondary10" "library4.out"}
+}
+
+run_ld_link_exec_tests [] $run_tests
diff --git a/ld/testsuite/ld-elf/secondary1.out b/ld/testsuite/ld-elf/secondary1.out
new file mode 100644
index 0000000..8d9378f
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary1.out
@@ -0,0 +1 @@
+secondary bar

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-06-30 21:19 PATCH: Add STB_SECONDARY support H.J. Lu
@ 2012-07-02  6:24 ` Alan Modra
  2012-07-02 13:31   ` H.J. Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2012-07-02  6:24 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, GNU C Library

On Sat, Jun 30, 2012 at 02:18:41PM -0700, H.J. Lu wrote:
> This patch adds STB_SECONDARY support.  I am enclosing the STB_SECONDARY 
> proposal posted on the gABI group. This patch is backward compatible
> with existing ld.so.  STB_SECONDARY symbols are generated only with
> "ld -shared -z secondary" switch.  OK to install?

I think there are a few problems with this proposal.  One is that weak
symbol behaviour is not well defined by the gABI.  In fact the spec
says

"The behavior of weak symbols in areas not specified by this document
is implementation defined. Weak symbols are intended primarily for use
in system software. Applications using weak symbols are unreliable
since changes in the runtime environment might cause the execution to
fail."

Left unspecified is the behaviour of weak symbols in dynamic objects
at runtime.  So I think your specification is standing on shaky ground
when saying anything about runtime behaviour of secondary symbols.
You really ought to first specify runtime behaviour of weak symbols
(and trying to do that will likely result in a conflict).

After reading some of the history of your proposal on
https://groups.google.com/forum/?fromgroups#!forum/generic-abi I see
that you originally only wanted secondary symbols for relocatable
objects, but were pushed to specify them more widely by other well-
meaning but perhaps inexperienced people.  (I'm not intending any
insult in that comment, I simply don't know the experience or
otherwise of people who responded.)  I also have not seen positive
comments from anyone I know is experienced in GNU toolchain work.
Maybe that is simply because I haven't looked far enough, but right
now I can't see any compelling reason to accept this proposal.  You
need to convince me or another global binutils maintainer that
STB_SECONDARY is a good idea.

If the reason for your proposal still only remains a way of providing
lower precedence symbols at link time, why can you not get the
behaviour you want just with weak symbols?  For example, place all
your lower precedence weak symbol functions/data in an archive library
that is linked last?  That might not be convenient.  I'm just asking
whether it would be possible.  (*)  If it is possible then no
extension to the gABI is necessary.


*) Convenience might be improved by implementing a linker switch that
says "link this object file as if it were inside an archive library
placed last on the linker command line".

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-07-02  6:24 ` Alan Modra
@ 2012-07-02 13:31   ` H.J. Lu
  2012-07-03  8:26     ` Alan Modra
  0 siblings, 1 reply; 13+ messages in thread
From: H.J. Lu @ 2012-07-02 13:31 UTC (permalink / raw)
  To: binutils, GNU C Library

On Sun, Jul 1, 2012 at 11:24 PM, Alan Modra <amodra@gmail.com> wrote:
> On Sat, Jun 30, 2012 at 02:18:41PM -0700, H.J. Lu wrote:
>> This patch adds STB_SECONDARY support.  I am enclosing the STB_SECONDARY
>> proposal posted on the gABI group. This patch is backward compatible
>> with existing ld.so.  STB_SECONDARY symbols are generated only with
>> "ld -shared -z secondary" switch.  OK to install?
>
> I think there are a few problems with this proposal.  One is that weak
> symbol behaviour is not well defined by the gABI.  In fact the spec
> says
>
> "The behavior of weak symbols in areas not specified by this document
> is implementation defined. Weak symbols are intended primarily for use
> in system software. Applications using weak symbols are unreliable
> since changes in the runtime environment might cause the execution to
> fail."
>
> Left unspecified is the behaviour of weak symbols in dynamic objects
> at runtime.  So I think your specification is standing on shaky ground
> when saying anything about runtime behaviour of secondary symbols.
> You really ought to first specify runtime behaviour of weak symbols
> (and trying to do that will likely result in a conflict).

I don't think we can change the weak specification
for the reason you stated above.

> After reading some of the history of your proposal on
> https://groups.google.com/forum/?fromgroups#!forum/generic-abi I see
> that you originally only wanted secondary symbols for relocatable
> objects, but were pushed to specify them more widely by other well-
> meaning but perhaps inexperienced people.  (I'm not intending any
> insult in that comment, I simply don't know the experience or
> otherwise of people who responded.)  I also have not seen positive
> comments from anyone I know is experienced in GNU toolchain work.
> Maybe that is simply because I haven't looked far enough, but right
> now I can't see any compelling reason to accept this proposal.  You
> need to convince me or another global binutils maintainer that
> STB_SECONDARY is a good idea.

It will be used to provide the backup implementation for a new
library function, which will only used if there is no a weak/global
implementation at link-time, so that a software package can use
the new library function to link against both the new and old versions
of  the library.  When linking against the old library, the backup
one will be used and when linking against the new library, the
one in the new library will be used.

As for the run-time behavior, secondary symbol s identical to weak
symbol when LD_DYNAMIC_WEAK is set in glibc:

http://sourceware.org/ml/libc-alpha/2012-06/msg00810.html

This provides the original run-time behavior of weak symbols
in glibc, which has the same backup effect at run-time.

BTW, here is my proposal as the GNU extension:

http://sourceware.org/ml/binutils/2012-04/msg00259.html

I was suggested to make it an extension to gABI.

> If the reason for your proposal still only remains a way of providing
> lower precedence symbols at link time, why can you not get the
> behaviour you want just with weak symbols?  For example, place all
> your lower precedence weak symbol functions/data in an archive library
> that is linked last?  That might not be convenient.  I'm just asking
> whether it would be possible.  (*)  If it is possible then no
> extension to the gABI is necessary.

The main usage is

1. ISV defines a secondary symbol in a library.
2. The library with a secondary symbol is used by programmers.

#1 and #2 are different people. ISV has no control over
the command line used by programmers.  We need
a reliable solution which is transparent to programmers,

>
> *) Convenience might be improved by implementing a linker switch that
> says "link this object file as if it were inside an archive library
> placed last on the linker command line".
>


-- 
H.J.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-07-02 13:31   ` H.J. Lu
@ 2012-07-03  8:26     ` Alan Modra
  2012-07-03 11:39       ` H.J. Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2012-07-03  8:26 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, GNU C Library

On Mon, Jul 02, 2012 at 06:31:34AM -0700, H.J. Lu wrote:
> The main usage is
> 
> 1. ISV defines a secondary symbol in a library.
> 2. The library with a secondary symbol is used by programmers.
> 
> #1 and #2 are different people. ISV has no control over
> the command line used by programmers.  We need
> a reliable solution which is transparent to programmers,

It sounds to me that the best solution would be to define a way of
marking an archive that instructs the linker to link it last
regardless of where it is placed on the command line, then just use
weak symbols.  This has the added benefit that your backup
implementations will be included on an object file granularity, which
is likely to be the simplest and most useful model.  Also, this should
work with PE and other object formats rather than being ELF only.

Options for marking the archive are
- A new magic string to replace "!<arch>\012", as we did for thin
  archives. 
- A special file name in the archive, similar to the way extended file
  names are recognized.
- A magic symbol in the armap.

I'm not sure which is best.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-07-03  8:26     ` Alan Modra
@ 2012-07-03 11:39       ` H.J. Lu
  2012-07-03 14:31         ` Alan Modra
  0 siblings, 1 reply; 13+ messages in thread
From: H.J. Lu @ 2012-07-03 11:39 UTC (permalink / raw)
  To: binutils, GNU C Library

On Tue, Jul 3, 2012 at 1:25 AM, Alan Modra <amodra@gmail.com> wrote:
> On Mon, Jul 02, 2012 at 06:31:34AM -0700, H.J. Lu wrote:
>> The main usage is
>>
>> 1. ISV defines a secondary symbol in a library.
>> 2. The library with a secondary symbol is used by programmers.
>>
>> #1 and #2 are different people. ISV has no control over
>> the command line used by programmers.  We need
>> a reliable solution which is transparent to programmers,
>
> It sounds to me that the best solution would be to define a way of
> marking an archive that instructs the linker to link it last
> regardless of where it is placed on the command line, then just use
> weak symbols.  This has the added benefit that your backup
> implementations will be included on an object file granularity, which
> is likely to be the simplest and most useful model.  Also, this should
> work with PE and other object formats rather than being ELF only.
>
> Options for marking the archive are
> - A new magic string to replace "!<arch>\012", as we did for thin
>   archives.
> - A special file name in the archive, similar to the way extended file
>   names are recognized.
> - A magic symbol in the armap.
>
> I'm not sure which is best.
>

This is not transparent to programmers.  Programmers shouldn't
need to make any changes to their build environment other than
installing a new binutils.

-- 
H.J.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-07-03 11:39       ` H.J. Lu
@ 2012-07-03 14:31         ` Alan Modra
  2012-07-03 16:26           ` H.J. Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2012-07-03 14:31 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, GNU C Library

On Tue, Jul 03, 2012 at 04:38:29AM -0700, H.J. Lu wrote:
> This is not transparent to programmers.  Programmers shouldn't
> need to make any changes to their build environment other than
> installing a new binutils.

What on earth are you talking about?

You gave me your main usage requirement involving a library provided
by an ISV.  I showed how your hypothetical ISV can provide a library
as a specially marked archive containing the backup functions/data,
and have your hypothetical user link this, without any change other
than installing a new linker.  No ELF ABI changes needed.  Sounds
pretty simple to me.  Easy for the ISV too.  In fact, you wouldn't
even need to use weak symbols in the archive.

Now if your ISV wants to provide a "normal" library as well as a
"backup" one, but for some reason wants this to be available to the
linker in a single -lisv option, then just use a linker script as we
do for libc.so.  Packaging problem solved.  Hmm, and that leads to
another idea.  Simply invent a linker script keyword that says to link
a file last, and then you don't even need specially marked archives.

User links with -lisv as he always has.  ISV provides libisv.so (or
libisv.a), a script containing
	INPUT ( -lisvnormal )
	INPUT_AT_END ( -lisvbackup )

Remember also that I don't have to convince you that your ABI
extension is unnecessary.  You have to convince us that it is needed.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-07-03 14:31         ` Alan Modra
@ 2012-07-03 16:26           ` H.J. Lu
  2012-07-03 23:45             ` Alan Modra
  0 siblings, 1 reply; 13+ messages in thread
From: H.J. Lu @ 2012-07-03 16:26 UTC (permalink / raw)
  To: binutils, GNU C Library

On Tue, Jul 3, 2012 at 7:31 AM, Alan Modra <amodra@gmail.com> wrote:
> On Tue, Jul 03, 2012 at 04:38:29AM -0700, H.J. Lu wrote:
>> This is not transparent to programmers.  Programmers shouldn't
>> need to make any changes to their build environment other than
>> installing a new binutils.
>
> What on earth are you talking about?
>
> You gave me your main usage requirement involving a library provided
> by an ISV.  I showed how your hypothetical ISV can provide a library
> as a specially marked archive containing the backup functions/data,
> and have your hypothetical user link this, without any change other
> than installing a new linker.  No ELF ABI changes needed.  Sounds
> pretty simple to me.  Easy for the ISV too.  In fact, you wouldn't
> even need to use weak symbols in the archive.
>
> Now if your ISV wants to provide a "normal" library as well as a
> "backup" one, but for some reason wants this to be available to the
> linker in a single -lisv option, then just use a linker script as we
> do for libc.so.  Packaging problem solved.  Hmm, and that leads to
> another idea.  Simply invent a linker script keyword that says to link
> a file last, and then you don't even need specially marked archives.
>
> User links with -lisv as he always has.  ISV provides libisv.so (or
> libisv.a), a script containing
>         INPUT ( -lisvnormal )
>         INPUT_AT_END ( -lisvbackup )
>
> Remember also that I don't have to convince you that your ABI
> extension is unnecessary.  You have to convince us that it is needed.
>

This scheme works for simple link-time backup.  It doesn't
work with backup symbol defined in DSO. You can't override
it at run-time.

Weak symbol spec is very limited and many behaviors are
implementation defined. Secondary symbol provides a better-defined
"weak" symbol, which is the same as dynamic weak symbol in
glibc.

-- 
H.J.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-07-03 16:26           ` H.J. Lu
@ 2012-07-03 23:45             ` Alan Modra
  2012-07-04  0:19               ` H.J. Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2012-07-03 23:45 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, GNU C Library

On Tue, Jul 03, 2012 at 09:26:11AM -0700, H.J. Lu wrote:
> This scheme works for simple link-time backup.

Right.  I thought that's what you wanted, because run-time backup can
be done easily right now.

>  It doesn't
> work with backup symbol defined in DSO. You can't override
> it at run-time.

If you want run-time backup, use a shared library for your backup.
The ELF spec has well defined search order rules for resolving
multiple global symbols in shared libraries.  I'm sure you know the
rules, and could devise a way of linking a backup library.

Needing to provide a backup implementation of some function isn't a
new thing.  How have we managed without secondary symbols in over 20
years since ELF was invented?

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-07-03 23:45             ` Alan Modra
@ 2012-07-04  0:19               ` H.J. Lu
  2012-07-04  0:39                 ` Alan Modra
  0 siblings, 1 reply; 13+ messages in thread
From: H.J. Lu @ 2012-07-04  0:19 UTC (permalink / raw)
  To: binutils, GNU C Library

On Tue, Jul 3, 2012 at 4:45 PM, Alan Modra <amodra@gmail.com> wrote:
> On Tue, Jul 03, 2012 at 09:26:11AM -0700, H.J. Lu wrote:
>> This scheme works for simple link-time backup.
>
> Right.  I thought that's what you wanted, because run-time backup can
> be done easily right now.
>
>>  It doesn't
>> work with backup symbol defined in DSO. You can't override
>> it at run-time.
>
> If you want run-time backup, use a shared library for your backup.
> The ELF spec has well defined search order rules for resolving
> multiple global symbols in shared libraries.  I'm sure you know the
> rules, and could devise a way of linking a backup library.
>
> Needing to provide a backup implementation of some function isn't a
> new thing.  How have we managed without secondary symbols in over 20
> years since ELF was invented?
>

Take binutils as an example, when you use --enable-shared, you
get

[hjl@gnu-6 local]$ readelf -d ./bin/ld

Dynamic section at offset 0xca530 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library:
[libbfd-2.22.52.20120703.so]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

libbfd-2.22.52.20120703.so is linked against libiberty.a.  When you build
binutils, libbfd will include a backup copy of standard functions
which don't exist
in libc.so at the time when you compile it.  Even after you upgrade your
libc.so with the latest and greatest standard functions, ld stiil uses
the backup one from libiberty since ld.so searches libbfd.so before
libc.so.6.  STB_SECONDARY solves this problem by making the
backup copy "dynamic weak".  The  the latest and greatest standard
functions in libc.so will be used instead of the backup copy in libbfd.so.

-- 
H.J.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-07-04  0:19               ` H.J. Lu
@ 2012-07-04  0:39                 ` Alan Modra
  2012-07-04 14:00                   ` H.J. Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2012-07-04  0:39 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, GNU C Library

On Tue, Jul 03, 2012 at 05:18:42PM -0700, H.J. Lu wrote:
>  0x0000000000000001 (NEEDED)             Shared library:
> [libbfd-2.22.52.20120703.so]
>  0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
>  0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
>  0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
> 
> libbfd-2.22.52.20120703.so is linked against libiberty.a.  When you build
> binutils, libbfd will include a backup copy of standard functions
> which don't exist
> in libc.so at the time when you compile it.  Even after you upgrade your
> libc.so with the latest and greatest standard functions, ld stiil uses
> the backup one from libiberty since ld.so searches libbfd.so before
> libc.so.6.

Like I said, I'm sure you could devise a way to put your backup
functions in another shared library that is searched after libc.so.6
That's dead easy.  Deeper nesting of shared libraries is a little more
difficult, due to breadth first library search, but still possible for
any given depth of libraries.  I imagine this case would be rare
anyway.

Who really is pushing for STB_SECONDARY?  Is it some hide-bound
company that uses a non-ELF toolchain and doesn't want to adapt any
process of theirs?

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-07-04  0:39                 ` Alan Modra
@ 2012-07-04 14:00                   ` H.J. Lu
  2012-07-10  7:05                     ` Alan Modra
  0 siblings, 1 reply; 13+ messages in thread
From: H.J. Lu @ 2012-07-04 14:00 UTC (permalink / raw)
  To: binutils, GNU C Library

On Tue, Jul 3, 2012 at 5:39 PM, Alan Modra <amodra@gmail.com> wrote:
> On Tue, Jul 03, 2012 at 05:18:42PM -0700, H.J. Lu wrote:
>>  0x0000000000000001 (NEEDED)             Shared library:
>> [libbfd-2.22.52.20120703.so]
>>  0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
>>  0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
>>  0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
>>
>> libbfd-2.22.52.20120703.so is linked against libiberty.a.  When you build
>> binutils, libbfd will include a backup copy of standard functions
>> which don't exist
>> in libc.so at the time when you compile it.  Even after you upgrade your
>> libc.so with the latest and greatest standard functions, ld stiil uses
>> the backup one from libiberty since ld.so searches libbfd.so before
>> libc.so.6.
>
> Like I said, I'm sure you could devise a way to put your backup
> functions in another shared library that is searched after libc.so.6
> That's dead easy.  Deeper nesting of shared libraries is a little more
> difficult, due to breadth first library search, but still possible for
> any given depth of libraries.  I imagine this case would be rare
> anyway.

Sure, we can do it on glibc with LD_DYNAMIC_WEAK.
But I haven't found another easy way to achieve the same
result

> Who really is pushing for STB_SECONDARY?  Is it some hide-bound
> company that uses a non-ELF toolchain and doesn't want to adapt any
> process of theirs?
>

STB_SECONDARY is my proposal and we have found
some nice usages.

-- 
H.J.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-07-04 14:00                   ` H.J. Lu
@ 2012-07-10  7:05                     ` Alan Modra
  2012-07-10  7:58                       ` H.J. Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2012-07-10  7:05 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, GNU C Library

On Wed, Jul 04, 2012 at 07:00:38AM -0700, H.J. Lu wrote:
> On Tue, Jul 3, 2012 at 5:39 PM, Alan Modra <amodra@gmail.com> wrote:
> > Like I said, I'm sure you could devise a way to put your backup
> > functions in another shared library that is searched after libc.so.6
> > That's dead easy.  Deeper nesting of shared libraries is a little more
> > difficult, due to breadth first library search, but still possible for
> > any given depth of libraries.  I imagine this case would be rare
> > anyway.
> 
> Sure, we can do it on glibc with LD_DYNAMIC_WEAK.
> But I haven't found another easy way to achieve the same
> result

You don't need LD_DYNAMIC_WEAK with the scheme I proposed.  The normal
ELF shared library symbol resolution works.  The only difficulty is in
ensuring a backup library is searched last.

> STB_SECONDARY is my proposal and we have found
> some nice usages.

Well, STB_SECONDARY allows you to put your backup functions anywhere.

Other than that I see no advantage.  In fact, I think there are a
whole lot of disadvantages to the whole tool-chain needing to know
about another symbol binding.  For instance, won't users need to
compile their code differently?  And if you're marking source with
attributes, what happens when users manage to make only part of a
compilation unit secondary?  How does this new binding play with C++?
We know from past experience that there is a whole world of pain with
mismatched libstdc++.so and inline functions.  I see STB_SECONDARY as
another way to get things wrong.  Sorry.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add STB_SECONDARY support
  2012-07-10  7:05                     ` Alan Modra
@ 2012-07-10  7:58                       ` H.J. Lu
  0 siblings, 0 replies; 13+ messages in thread
From: H.J. Lu @ 2012-07-10  7:58 UTC (permalink / raw)
  To: binutils, GNU C Library

On Tue, Jul 10, 2012 at 12:04 AM, Alan Modra <amodra@gmail.com> wrote:
> On Wed, Jul 04, 2012 at 07:00:38AM -0700, H.J. Lu wrote:
>> On Tue, Jul 3, 2012 at 5:39 PM, Alan Modra <amodra@gmail.com> wrote:
>> > Like I said, I'm sure you could devise a way to put your backup
>> > functions in another shared library that is searched after libc.so.6
>> > That's dead easy.  Deeper nesting of shared libraries is a little more
>> > difficult, due to breadth first library search, but still possible for
>> > any given depth of libraries.  I imagine this case would be rare
>> > anyway.
>>
>> Sure, we can do it on glibc with LD_DYNAMIC_WEAK.
>> But I haven't found another easy way to achieve the same
>> result
>
> You don't need LD_DYNAMIC_WEAK with the scheme I proposed.  The normal
> ELF shared library symbol resolution works.  The only difficulty is in
> ensuring a backup library is searched last.

Search order isn't easily controlled and glibc already supports
LD_DYNAMIC_WEAK.

>> STB_SECONDARY is my proposal and we have found
>> some nice usages.
>
> Well, STB_SECONDARY allows you to put your backup functions anywhere.
>
> Other than that I see no advantage.  In fact, I think there are a
> whole lot of disadvantages to the whole tool-chain needing to know
> about another symbol binding.  For instance, won't users need to
> compile their code differently?  And if you're marking source with
> attributes, what happens when users manage to make only part of a
> compilation unit secondary?  How does this new binding play with C++?
> We know from past experience that there is a whole world of pain with
> mismatched libstdc++.so and inline functions.  I see STB_SECONDARY as
> another way to get things wrong.  Sorry.
>

STB_SECONDARY should be mainly used by compiler writers and
library developers.  It should be transparent to end users.

As of partial secondary compilation, secondary is only applied to
definition.  You only need to apply secondary to backup definition.
You can provide backup C++ class definition, which should be applied
to the whole class.  The only difference is secondary will make it
dynamic weak.


-- 
H.J.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2012-07-10  7:58 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-30 21:19 PATCH: Add STB_SECONDARY support H.J. Lu
2012-07-02  6:24 ` Alan Modra
2012-07-02 13:31   ` H.J. Lu
2012-07-03  8:26     ` Alan Modra
2012-07-03 11:39       ` H.J. Lu
2012-07-03 14:31         ` Alan Modra
2012-07-03 16:26           ` H.J. Lu
2012-07-03 23:45             ` Alan Modra
2012-07-04  0:19               ` H.J. Lu
2012-07-04  0:39                 ` Alan Modra
2012-07-04 14:00                   ` H.J. Lu
2012-07-10  7:05                     ` Alan Modra
2012-07-10  7:58                       ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).