PATCH: Further optimize protected symbol

H. J. Lu hjl@lucon.org
Thu Mar 27 19:03:00 GMT 2003


This patch adds some comments on protected symbol handling and optimizes
protected symbol a bit more. As I said yesterday, we still don't handle
protected symbol right when copy relocation is involved.


H.J.
-------------- next part --------------
2003-03-27  H.J. Lu <hjl@gnu.org>

	* elf/dl-lookup.c (_dl_lookup_symbol): Stop the search of the
	current value is defined. Continue the search for the real
	definition instead of starting from scratch if it is undefined.
	(_dl_lookup_symbol_skip): Likewise.
	(_dl_lookup_versioned_symbol): Likewise.
	(_dl_lookup_versioned_symbol_skip): Likewise.

--- elf/dl-lookup.c.protected	2003-03-26 08:22:01.000000000 -0800
+++ elf/dl-lookup.c	2003-03-27 11:01:51.000000000 -0800
@@ -271,9 +271,24 @@ _dl_lookup_symbol (const char *undef_nam
   protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
   if (__builtin_expect (protected != 0, 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)
+      /* When we get here, there are 3 possibilities:
+
+	 1. current_value has a real definition.
+	 2. current_value has a definition from a copy relocation.
+	 3. current_value doesn't have any definition, which may be the
+	    case for an ELF_RTYPE_CLASS_PLT relocation.
+
+	 For the protected symbol, we need to make sure that the
+	 definition from undef_map is used.
+
+	 If it is defined and not from a copy relocation, we make sure
+	 the definition from undef_map is used.
+
+	 FIXME: We can't tell if a definition is from a copy relocation
+		or not.  */
+      if (type_class == ELF_RTYPE_CLASS_PLT
+	  || (current_value.s
+	      && current_value.s->st_shndx != SHN_UNDEF))
 	{
 	  if (current_value.s != NULL && current_value.m != undef_map)
 	    {
@@ -285,7 +300,14 @@ _dl_lookup_symbol (const char *undef_nam
 	{
 	  struct sym_val protected_value = { NULL, NULL };
 
-	  for (scope = symbol_scope; *scope; ++scope)
+	  /* Now, current_value is either undefined or from a copy
+	     relocation. We continue the search for the real
+	     definition, using ELF_RTYPE_CLASS_PLT to skip undefined
+	     symbols.
+
+	     FIXME: How do we skip a definition from a copy
+		    relocation?  */
+	  for (; *scope; ++scope)
 	    if (_dl_do_lookup (undef_name, hash, *ref,
 			       &protected_value, *scope, 0, flags,
 			       NULL, ELF_RTYPE_CLASS_PLT))
@@ -368,24 +390,53 @@ _dl_lookup_symbol_skip (const char *unde
 
   if (__builtin_expect (protected != 0, 0))
     {
-      /* It is very tricky.  We need to figure out what value to
-         return for the protected symbol.  */
-      struct sym_val protected_value = { NULL, NULL };
-
-      if (i >= (*scope)->r_nlist
-	  || !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
-			     i, DL_LOOKUP_RETURN_NEWEST, skip_map,
-			     ELF_RTYPE_CLASS_PLT))
-	while (*++scope)
-	  if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
-			     0, DL_LOOKUP_RETURN_NEWEST, skip_map,
-			     ELF_RTYPE_CLASS_PLT))
-	    break;
+      /* When we get here, there are 3 possibilities:
 
-      if (protected_value.s != NULL && protected_value.m != undef_map)
+	 1. current_value has a real definition.
+	 2. current_value has a definition from a copy relocation.
+	 3. current_value doesn't have any definition, which may be the
+	    case for an ELF_RTYPE_CLASS_PLT relocation.
+
+	 For the protected symbol, we need to make sure that the
+	 definition from undef_map is used.
+
+	 If it is defined and not from a copy relocation, we make sure
+	 the definition from undef_map is used.
+
+	 FIXME: We can't tell if a definition is from a copy relocation
+		or not.  */
+      if (current_value.s && current_value.s->st_shndx != SHN_UNDEF)
 	{
-	  current_value.s = *ref;
-	  current_value.m = undef_map;
+	  if (current_value.s != NULL && current_value.m != undef_map)
+	    {
+	      current_value.s = *ref;
+	      current_value.m = undef_map;
+	    }
+	}
+      else
+	{
+	  struct sym_val protected_value = { NULL, NULL };
+
+	  /* Now, current_value is either undefined or from a copy
+	     relocation. We continue the search for the real
+	     definition, using ELF_RTYPE_CLASS_PLT to skip undefined
+	     symbols.
+
+	     FIXME: How do we skip a definition from a copy
+		    relocation?  */
+	  while (*++scope)
+	    if (_dl_do_lookup (undef_name, hash, *ref,
+			       &protected_value, *scope, 0,
+			       DL_LOOKUP_RETURN_NEWEST,
+			       skip_map, ELF_RTYPE_CLASS_PLT))
+	      break;
+
+	  if (protected_value.s != NULL
+	      && protected_value.m != undef_map)
+	    {
+	      current_value.s = *ref;
+	      current_value.m = undef_map;
+	    }
 	}
     }
 
@@ -476,9 +527,24 @@ _dl_lookup_versioned_symbol (const char 
 
   if (__builtin_expect (protected != 0, 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)
+      /* When we get here, there are 3 possibilities:
+
+	 1. current_value has a real definition.
+	 2. current_value has a definition from a copy relocation.
+	 3. current_value doesn't have any definition, which may be the
+	    case for an ELF_RTYPE_CLASS_PLT relocation.
+
+	 For the protected symbol, we need to make sure that the
+	 definition from undef_map is used.
+
+	 If it is defined and not from a copy relocation, we make sure
+	 the definition from undef_map is used.
+
+	 FIXME: We can't tell if a definition is from a copy relocation
+		or not.  */
+      if (type_class == ELF_RTYPE_CLASS_PLT
+	  || (current_value.s
+	      && current_value.s->st_shndx != SHN_UNDEF))
 	{
 	  if (current_value.s != NULL && current_value.m != undef_map)
 	    {
@@ -490,7 +556,14 @@ _dl_lookup_versioned_symbol (const char 
 	{
 	  struct sym_val protected_value = { NULL, NULL };
 
-	  for (scope = symbol_scope; *scope; ++scope)
+	  /* Now, current_value is either undefined or from a copy
+	     relocation. We continue the search for the real
+	     definition, using ELF_RTYPE_CLASS_PLT to skip undefined
+	     symbols.
+
+	     FIXME: How do we skip a definition from a copy
+		    relocation?  */
+	  for (; *scope; ++scope)
 	    if (_dl_do_lookup_versioned (undef_name, hash, *ref,
 					 &protected_value,
 					 *scope, 0, version, NULL,
@@ -588,24 +661,53 @@ _dl_lookup_versioned_symbol_skip (const 
 
   if (__builtin_expect (protected != 0, 0))
     {
-      /* It is very tricky.  We need to figure out what value to
-         return for the protected symbol.  */
-      struct sym_val protected_value = { NULL, NULL };
-
-      if (i >= (*scope)->r_nlist
-	  || !_dl_do_lookup_versioned (undef_name, hash, *ref,
-				       &protected_value, *scope, i, version,
-				       skip_map, ELF_RTYPE_CLASS_PLT))
-	while (*++scope)
-	  if (_dl_do_lookup_versioned (undef_name, hash, *ref,
-				       &protected_value, *scope, 0, version,
-				       skip_map, ELF_RTYPE_CLASS_PLT))
-	    break;
+      /* When we get here, there are 3 possibilities:
 
-      if (protected_value.s != NULL && protected_value.m != undef_map)
+	 1. current_value has a real definition.
+	 2. current_value has a definition from a copy relocation.
+	 3. current_value doesn't have any definition, which may be the
+	    case for an ELF_RTYPE_CLASS_PLT relocation.
+
+	 For the protected symbol, we need to make sure that the
+	 definition from undef_map is used.
+
+	 If it is defined and not from a copy relocation, we make sure
+	 the definition from undef_map is used.
+
+	 FIXME: We can't tell if a definition is from a copy relocation
+		or not.  */
+      if (current_value.s && current_value.s->st_shndx != SHN_UNDEF)
 	{
-	  current_value.s = *ref;
-	  current_value.m = undef_map;
+	  if (current_value.s != NULL && current_value.m != undef_map)
+	    {
+	      current_value.s = *ref;
+	      current_value.m = undef_map;
+	    }
+	}
+      else
+	{
+	  struct sym_val protected_value = { NULL, NULL };
+
+	  /* Now, current_value is either undefined or from a copy
+	     relocation. We continue the search for the real
+	     definition, using ELF_RTYPE_CLASS_PLT to skip undefined
+	     symbols.
+
+	     FIXME: How do we skip a definition from a copy
+		    relocation?  */
+	  while (*++scope)
+	    if (_dl_do_lookup_versioned (undef_name, hash, *ref,
+					 &protected_value, *scope, 0,
+					 version, skip_map,
+					 ELF_RTYPE_CLASS_PLT))
+	      break;
+
+	  if (protected_value.s != NULL
+	      && protected_value.m != undef_map)
+	    {
+	      current_value.s = *ref;
+	      current_value.m = undef_map;
+	    }
 	}
     }
 


More information about the Libc-alpha mailing list