This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc 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]

Protected symbol lookup


I really hate "it is very tricky" comments.  I wonder how many people
have looked at this comment and managed to figure out why protected
symbol lookup is "tricky", and what this code in dl-lookup.c is doing?
Unless you have a very good understanding of how ELF linkers and ld.so
work together, I suspect most people would waste hours trying.  So I
set about writing a proper comment.

I also noticed that the code is doing unnecessary lookups.  Consider
the case where ld.so is resolving a relocation for a function pointer
(ie. type_class isn't ELF_RTYPE_CLASS_PLT) in a shared library.  If
the main executable doesn't define one of those non-zero value
SHN_UNDEF PLT symbols (*), then the main executable doesn't take the
address of the function and thus the shared library can simply use the
real function address.  Yet current code runs around the
protected_value do_lookup_x loop for this case.

Regression tested i686-linux and powerpc64-linux.

*) Requires a linker that implements Jakub's pointer_equality_needed
optimisation.

2008-02-22  Alan Modra  <amodra@bigpond.net.au>

	* elf/dl-lookup.c (_dl_lookup_symbol_x): Optimise protected
	symbol lookup.  Comment.

Index: elf/dl-lookup.c
===================================================================
RCS file: /cvs/glibc/libc/elf/dl-lookup.c,v
retrieving revision 1.131
diff -u -p -r1.131 dl-lookup.c
--- elf/dl-lookup.c	29 Sep 2007 06:57:50 -0000	1.131
+++ elf/dl-lookup.c	21 Feb 2008 23:55:56 -0000
@@ -389,30 +389,46 @@ _dl_lookup_symbol_x (const char *undef_n
       return 0;
     }
 
+  /* Protected symbols resolve locally except in one particular case
+     when resolving a symbol for a function pointer relocation.  If we
+     found a PLT entry symbol (SHN_UNDEF with non-zero value) match in
+     the executable *and* the executable is using the function in this
+     component, then we want to use the executable PLT entry symbol
+     for such relocations.  This ensures that the main executable and
+     the shared library defining a protected function use the same
+     address for the function.  */
   int protected = (*ref
 		   && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED);
-  if (__builtin_expect (protected != 0, 0))
+  if (__builtin_expect (protected != 0
+			&& current_value.s != NULL
+			&& current_value.m != undef_map, 0))
     {
-      /* It is very tricky.  We need to figure out what value to
-         return for the protected symbol.  */
-      if (type_class == ELF_RTYPE_CLASS_PLT)
+      if (current_value.s->st_shndx != SHN_UNDEF)
 	{
-	  if (current_value.s != NULL && current_value.m != undef_map)
-	    {
-	      current_value.s = *ref;
-	      current_value.m = undef_map;
-	    }
+	  /* We found a match somewhere other than the current
+	     component, and the match is not one of those PLT entry
+	     symbols.  Throw away the match and resolve locally.  */
+	  current_value.s = *ref;
+	  current_value.m = undef_map;
 	}
       else
 	{
 	  struct sym_val protected_value = { NULL, NULL };
 
+	  /* We found a match somewhere other than the current
+	     component, and the match is a PLT entry symbol.
+	     "Somewhere other" must in fact be the main executable,
+	     because that is the only place we find these symbols.
+	     Find out how the main executable resolves this symbol
+	     when relocating the PLT.  */
 	  for (scope = symbol_scope; *scope != NULL; i = 0, ++scope)
 	    if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
 			     &protected_value, *scope, i, version, flags,
 			     skip_map, ELF_RTYPE_CLASS_PLT) != 0)
 	      break;
 
+	  /* If the main executable PLT doesn't use this component's
+	     symbol, then resolve locally.  */
 	  if (protected_value.s != NULL && protected_value.m != undef_map)
 	    {
 	      current_value.s = *ref;

-- 
Alan Modra
Australia Development Lab, IBM


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