This is the mail archive of the binutils@sourceware.cygnus.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]

Symbol visibility revised


This patch implements some of the symbol visibility aspects in the
static linker, which my previous patch assumed as the dynamic linker's
responsibility. It includes the patch Chip sent last month. The
immediate need for this patch is GCC's usage of .hidden as part of the
new C++ ABI, and the lack for .hidden support in dynamic linkers.

In particular, hidden and internal visibility are implemented using
the local symbols extension of the versioning feature. The linker
avoids assigning dynamic indices if possible, or clears them if the
already have been assigned, setting ELF_LINK_FORCED_LOCAL at the same
time. Provided that symbol versioning is already available for a
target, the hidden symbols mechanism should also work on that target.

It would be possible to implement protected visibility in the static
linker as well, however, that would require changes to the backends
(specifically, many places that check for ->symbolic || dynindx == -1
should also check for visibility). Since there is no immediate need
for supporting .protected, and since that will be most likely added to
dynamic linkers, anyway, this patch does not attempt to completely
perform .protected visibility.

As a result, .protected symbols can be overridden from another DSO
(i.e. they are visible, but not protected).  As a special case, PLT
entries for protected functions are eliminated, so protection works
for function calls already (based on the -Bsymbolic support in that
case).

I have tested this patch with a number of test cases for both
functions and data relocations, as well as with the current CVS GCC,
on i386-pc-linux-gnu.

If you have any questions, please let me know.

Regards,
Martin

Index: bfd/ChangeLog
===================================================================
RCS file: /cvs/src/src/bfd/ChangeLog,v
retrieving revision 1.411
diff -u -p -r1.411 ChangeLog
--- ChangeLog	2000/05/01 05:02:57	1.411
+++ ChangeLog	2000/05/01 16:41:54
@@ -1,3 +1,12 @@
+2000-05-01  Martin v. Löwis  <loewis@informatik.hu-berlin.de>
+
+	* elflink.h (elf_link_add_object_symbols): Reset dynindx for
+	hidden and internal symbols.
+	(elf_fix_symbol_flags): Clear NEEDS_PLT for symbols with
+	visibility.
+	* elflink.c (_bfd_elf_link_record_dynamic_symbol): Do not assign a
+	PLT or GOT entry to symbols with visibility.
+
 2000-05-01  Alan Modra  <alan@linuxcare.com.au>
 
 	* coff-sh.c (bfd_coff_small_swap_table): Fix Fri Apr 28 change.
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.10
diff -u -p -r1.10 elflink.c
--- elflink.c	2000/03/01 19:40:54	1.10
+++ elflink.c	2000/05/01 16:41:56
@@ -238,8 +238,8 @@ _bfd_elf_link_record_dynamic_symbol (inf
 	    }
 	  
 	  h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
-	  break;
-	  
+	  return true;
+
 	default:
 	  break;
 	}
Index: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.52
diff -u -p -r1.52 elflink.h
--- elflink.h	2000/04/27 00:31:16	1.52
+++ elflink.h	2000/05/01 16:42:05
@@ -891,6 +891,7 @@ elf_link_add_object_symbols (abfd, info)
   Elf_External_Sym *esym;
   Elf_External_Sym *esymend;
   struct elf_backend_data *bed;
+  boolean visibility_changed = false;
 
   bed = get_elf_backend_data (abfd);
   add_symbol_hook = bed->elf_add_symbol_hook;
@@ -1581,7 +1582,10 @@ elf_link_add_object_symbols (abfd, info)
 	      unsigned char symvis = ELF_ST_VISIBILITY (sym.st_other);
 	      
 	      if (symvis && (hvis > symvis || hvis == 0))
-		h->other = sym.st_other;
+		{
+		  visibility_changed = true;
+		  h->other = sym.st_other;
+		}
 	      
 	      /* If neither has visibility, use the st_other of the
 	         definition.  This is an arbitrary choice, since the
@@ -1852,6 +1856,18 @@ elf_link_add_object_symbols (abfd, info)
 		    goto error_return;
 		}
 	    }
+	  else if (dynsym && h->dynindx != -1 && visibility_changed)
+	    /* If the symbol already has a dynamic index, but
+	       visibility says it should not be visible, turn it into
+	       a local symbol.  */
+	    switch (ELF_ST_VISIBILITY (h->other))
+	      {
+	      case STV_INTERNAL:
+	      case STV_HIDDEN:  
+		h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+		(*bed->elf_backend_hide_symbol) (h);
+		break;
+	      }
 	}
     }
 
@@ -3339,10 +3355,12 @@ elf_fix_symbol_flags (h, eif)
   /* If -Bsymbolic was used (which means to bind references to global
      symbols to the definition within the shared object), and this
      symbol was defined in a regular object, then it actually doesn't
-     need a PLT entry.  */
+     need a PLT entry.  Likewise, if the symbol has any kind of
+     visibility (internal, hidden, or protected), it doesn't need a
+     PLT.  */
   if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
       && eif->info->shared
-      && eif->info->symbolic
+      && (eif->info->symbolic || ELF_ST_VISIBILITY (h->other))
       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
     {
       h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;

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