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: Force a hidden symbol global


On Thu, Mar 03, 2005 at 05:37:20PM -0800, H. J. Lu wrote:
> On Fri, Mar 04, 2005 at 08:24:44AM +1030, Alan Modra wrote:
> > On Thu, Mar 03, 2005 at 08:55:10AM -0800, H. J. Lu wrote:
> > > On Thu, Mar 03, 2005 at 07:55:04AM -0800, H. J. Lu wrote:
> > > > On Thu, Mar 03, 2005 at 11:19:13PM +1030, Alan Modra wrote:
> > > > > On Wed, Mar 02, 2005 at 08:14:59PM -0800, H. J. Lu wrote:
> > > > > > Protected visibility has almost everything, but requires
> > > > > > special handling at run-time.
> > > > > > 
> > > > > > I was wondering if we could allow version script to overwrite
> > > > > > hidden symbols. That is if a symbol is global in version script, we
> > > > > > export it even if it is marked hidden. It may improve run-time
> > > > > > performance.
> > > > > 
> > > > > How is this going to be different from using protected symbols?
> > > > 
> > > > No run-time special handling accociated with protected symbols, which
> > > > may take extra lookup.
> > > 
> > > Also compiler/linker can't optimize protected function pointers.
> > 
> > Which means that if you export hidden function symbols from shared
> > libraries by means of a version script, you will break function pointer
> > comparisons.
> 
> Yes. If you don't do any function pointer comparisons on exported
> functions in DSO, you should be OK.
> 

This patch will allow forcing a hidden symbol as global. It can be
used for performance and languange specific features.


H.J.
----
2005-04-21  H.J. Lu  <hongjiu.lu@intel.com>

	* elf-bfd.h (elf_link_hash_entry): Add forced_global.

	* elflink.c (bfd_elf_link_record_dynamic_symbol): Don't check
	symbol visibilty when we force a forced local symbol to global.
	(_bfd_elf_link_renumber_dynsyms): Move forced local symbols
	just before global ones.
	(_bfd_elf_link_assign_sym_version): Set the forced_global field
	if a forced local symbol is marked as global explicitly.
	(elf_link_output_extsym): Handle forced_global.

--- bfd/elf-bfd.h.global	2005-04-04 10:35:34.000000000 -0700
+++ bfd/elf-bfd.h	2005-04-21 10:00:36.000000000 -0700
@@ -155,6 +155,8 @@ struct elf_link_hash_entry
   unsigned int hidden : 1;
   /* Symbol was forced to local scope due to a version script file.  */
   unsigned int forced_local : 1;
+  /* Symbol was forced to global scope due to a version script file.  */
+  unsigned int forced_global : 1;
   /* Symbol was marked during garbage collection.  */
   unsigned int mark : 1;
   /* Symbol is referenced by a non-GOT/non-PLT relocation.  This is
--- bfd/elflink.c.global	2005-04-19 10:42:57.000000000 -0700
+++ bfd/elflink.c	2005-04-21 13:55:00.000000000 -0700
@@ -377,22 +377,24 @@ bfd_elf_link_record_dynamic_symbol (stru
       /* XXX: The ABI draft says the linker must turn hidden and
 	 internal symbols into STB_LOCAL symbols when producing the
 	 DSO. However, if ld.so honors st_other in the dynamic table,
-	 this would not be necessary.  */
-      switch (ELF_ST_VISIBILITY (h->other))
-	{
-	case STV_INTERNAL:
-	case STV_HIDDEN:
-	  if (h->root.type != bfd_link_hash_undefined
-	      && h->root.type != bfd_link_hash_undefweak)
-	    {
-	      h->forced_local = 1;
-	      if (!elf_hash_table (info)->is_relocatable_executable)
-		return TRUE;
-	    }
+	 this would not be necessary.  Don't check symbol visibilty
+	 when we force a forced local symbol to global.  */
+      if (!h->forced_global)
+	switch (ELF_ST_VISIBILITY (h->other))
+	  {
+	  case STV_INTERNAL:
+	  case STV_HIDDEN:
+	    if (h->root.type != bfd_link_hash_undefined
+		&& h->root.type != bfd_link_hash_undefweak)
+	      {
+		h->forced_local = 1;
+		if (!elf_hash_table (info)->is_relocatable_executable)
+		  return TRUE;
+	      }
 
-	default:
-	  break;
-	}
+	  default:
+	    break;
+	  }
 
       h->dynindx = elf_hash_table (info)->dynsymcount;
       ++elf_hash_table (info)->dynsymcount;
@@ -702,9 +704,9 @@ _bfd_elf_link_omit_section_dynsym (bfd *
 }
 
 /* Assign dynsym indices.  In a shared library we generate a section
-   symbol for each output section, which come first.  Next come symbols
-   which have been forced to local binding.  Then all of the back-end
-   allocated local dynamic syms, followed by the rest of the global
+   symbol for each output section, which come first.  Next come all of
+   the back-end allocated local dynamic syms.  Then symbols which have
+   been forced to local binding, followed by the rest of the global
    symbols.  */
 
 static unsigned long
@@ -726,10 +728,6 @@ _bfd_elf_link_renumber_dynsyms (bfd *out
     }
   *section_sym_count = dynsymcount;
 
-  elf_link_hash_traverse (elf_hash_table (info),
-			  elf_link_renumber_local_hash_table_dynsyms,
-			  &dynsymcount);
-
   if (elf_hash_table (info)->dynlocal)
     {
       struct elf_link_local_dynamic_entry *p;
@@ -738,6 +736,10 @@ _bfd_elf_link_renumber_dynsyms (bfd *out
     }
 
   elf_link_hash_traverse (elf_hash_table (info),
+			  elf_link_renumber_local_hash_table_dynsyms,
+			  &dynsymcount);
+
+  elf_link_hash_traverse (elf_hash_table (info),
 			  elf_link_renumber_hash_table_dynsyms,
 			  &dynsymcount);
 
@@ -1694,6 +1696,7 @@ _bfd_elf_link_assign_sym_version (struct
   struct elf_info_failed eif;
   char *p;
   bfd_size_type amt;
+  bfd_boolean forced_global;
 
   sinfo = data;
   info = sinfo->info;
@@ -1716,6 +1719,10 @@ _bfd_elf_link_assign_sym_version (struct
   if (!h->def_regular)
     return TRUE;
 
+  /* Check if a forced local symbol is marked as global explicitly in
+     version script.  */
+  forced_global = FALSE;
+
   bed = get_elf_backend_data (sinfo->output_bfd);
   p = strchr (h->root.root.string, ELF_VER_CHR);
   if (p != NULL && h->verinfo.vertree == NULL)
@@ -1778,6 +1785,8 @@ _bfd_elf_link_assign_sym_version (struct
 		      && ! info->export_dynamic)
 		    (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 		}
+	      else if (d)
+		forced_global = TRUE;
 
 	      free (alc);
 	      break;
@@ -1868,6 +1877,7 @@ _bfd_elf_link_assign_sym_version (struct
 		    h->verinfo.vertree = t;
 		    local_ver = NULL;
 		    d->script = 1;
+		    forced_global = TRUE;
 		    break;
 		  }
 	      if (d != NULL)
@@ -1904,11 +1914,20 @@ _bfd_elf_link_assign_sym_version (struct
 	      && info->shared
 	      && ! info->export_dynamic)
 	    {
+	      forced_global = FALSE;
 	      (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 	    }
 	}
     }
 
+  if (h->forced_local && forced_global)
+    {
+      h->forced_global = 1;
+
+      if (! bfd_elf_link_record_dynamic_symbol (info, h))
+	return FALSE;
+    }
+
   return TRUE;
 }
 
@@ -6316,12 +6335,12 @@ elf_link_output_extsym (struct elf_link_
   /* Decide whether to output this symbol in this pass.  */
   if (eoinfo->localsyms)
     {
-      if (!h->forced_local)
+      if (!h->forced_local || h->forced_global)
 	return TRUE;
     }
   else
     {
-      if (h->forced_local)
+      if (h->forced_local && !h->forced_global)
 	return TRUE;
     }
 
@@ -6351,6 +6370,7 @@ elf_link_output_extsym (struct elf_link_
   if (! finfo->info->relocatable
       && (! finfo->info->shared)
       && h->forced_local
+      && !h->forced_global
       && h->ref_dynamic
       && !h->dynamic_def
       && !h->dynamic_weak
@@ -6404,7 +6424,14 @@ elf_link_output_extsym (struct elf_link_
   sym.st_value = 0;
   sym.st_size = h->size;
   sym.st_other = h->other;
-  if (h->forced_local)
+  if (h->forced_global)
+    {
+      /* A forced global symbol has the default visibility.  */
+      sym.st_other
+	= STV_DEFAULT | (h->other & ~ ELF_ST_VISIBILITY (-1));
+      sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
+    }
+  else if (h->forced_local)
     sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
   else if (h->root.type == bfd_link_hash_undefweak
 	   || h->root.type == bfd_link_hash_defweak)


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