summary refs log tree commit diff
path: root/elf/dl-lookup.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-lookup.c')
-rw-r--r--elf/dl-lookup.c142
1 files changed, 70 insertions, 72 deletions
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 2faa9fb99c..26c839caa7 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -79,92 +79,94 @@ internal_function
 add_dependency (struct link_map *undef_map, struct link_map *map)
 {
   struct link_map **list;
+  struct link_map *runp;
   unsigned int act;
   unsigned int i;
   int result = 0;
 
+  /* Avoid self-references.  */
+  if (undef_map == map)
+    return 0;
+
   /* Make sure nobody can unload the object while we are at it.  */
   __libc_lock_lock_recursive (_dl_load_lock);
 
   /* Determine whether UNDEF_MAP already has a reference to MAP.  First
      look in the normal dependencies.  */
-  list = undef_map->l_initfini;
-
-  for (i = 0; list[i] != NULL; ++i)
-    if (list[i] == map)
-      break;
-
-  if (__builtin_expect (list[i] == NULL, 1))
+  if (undef_map->l_searchlist.r_list != NULL)
     {
-      /* No normal dependency.  See whether we already had to add it
-	 to the special list of dynamic dependencies.  */
-      list = undef_map->l_reldeps;
-      act = undef_map->l_reldepsact;
+      list = undef_map->l_initfini;
 
-      for (i = 0; i < act; ++i)
+      for (i = 0; list[i] != NULL; ++i)
 	if (list[i] == map)
-	  break;
+	  goto out;
+    }
+
+  /* No normal dependency.  See whether we already had to add it
+     to the special list of dynamic dependencies.  */
+  list = undef_map->l_reldeps;
+  act = undef_map->l_reldepsact;
 
-      if (i == act)
+  for (i = 0; i < act; ++i)
+    if (list[i] == map)
+      goto out;
+
+  /* The object is not yet in the dependency list.  Before we add
+     it make sure just one more time the object we are about to
+     reference is still available.  There is a brief period in
+     which the object could have been removed since we found the
+     definition.  */
+  runp = _dl_loaded;
+  while (runp != NULL && runp != map)
+    runp = runp->l_next;
+
+  if (runp != NULL)
+    {
+      /* The object is still available.  Add the reference now.  */
+      if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
 	{
-	  /* The object is not yet in the dependency list.  Before we add
-	     it make sure just one more time the object we are about to
-	     reference is still available.  There is a brief period in
-	     which the object could have been removed since we found the
-	     definition.  */
-	  struct link_map *runp = _dl_loaded;
-
-	  while (runp != NULL && runp != map)
-	    runp = runp->l_next;
-
-	  if (runp != NULL)
-	    {
-	      /* The object is still available.  Add the reference now.  */
-	      if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
-		{
-		  /* Allocate more memory for the dependency list.  Since
-		     this can never happen during the startup phase we can
-		     use `realloc'.  */
-		  void *newp;
-
-		  undef_map->l_reldepsmax += 5;
-		  newp = realloc (undef_map->l_reldeps,
-				  undef_map->l_reldepsmax
-				  * sizeof(struct link_map *));
-
-		  if (__builtin_expect (newp != NULL, 1))
-		    undef_map->l_reldeps = (struct link_map **) newp;
-		  else
-		    /* Correct the addition.  */
-		    undef_map->l_reldepsmax -= 5;
-		}
-
-	      /* If we didn't manage to allocate memory for the list this
-		 is no fatal mistake.  We simply increment the use counter
-		 of the referenced object and don't record the dependencies.
-		 This means this increment can never be reverted and the
-		 object will never be unloaded.  This is semantically the
-		 correct behaviour.  */
-	      if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
-		undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
-
-	      /* And increment the counter in the referenced object.  */
-	      ++map->l_opencount;
-
-	      /* Display information if we are debugging.  */
-	      if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
-		_dl_debug_printf ("\
-\nfile=%s;  needed by %s (relocation dependency)\n\n",
-				  map->l_name[0] ? map->l_name : _dl_argv[0],
-				  undef_map->l_name[0]
-				  ? undef_map->l_name : _dl_argv[0]);
-	    }
+	  /* Allocate more memory for the dependency list.  Since this
+	     can never happen during the startup phase we can use
+	     `realloc'.  */
+	  void *newp;
+
+	  undef_map->l_reldepsmax += 5;
+	  newp = realloc (undef_map->l_reldeps,
+			  undef_map->l_reldepsmax
+			  * sizeof (struct link_map *));
+
+	  if (__builtin_expect (newp != NULL, 1))
+	    undef_map->l_reldeps = (struct link_map **) newp;
 	  else
-	    /* Whoa, that was bad luck.  We have to search again.  */
-	    result = -1;
+	    /* Correct the addition.  */
+	    undef_map->l_reldepsmax -= 5;
 	}
+
+      /* If we didn't manage to allocate memory for the list this is
+	 no fatal mistake.  We simply increment the use counter of the
+	 referenced object and don't record the dependencies.  This
+	 means this increment can never be reverted and the object
+	 will never be unloaded.  This is semantically the correct
+	 behaviour.  */
+      if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
+	undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
+
+      /* And increment the counter in the referenced object.  */
+      ++map->l_opencount;
+
+      /* Display information if we are debugging.  */
+      if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
+	_dl_debug_printf ("\
+\nfile=%s;  needed by %s (relocation dependency)\n\n",
+			  map->l_name[0] ? map->l_name : _dl_argv[0],
+			  undef_map->l_name[0]
+			  ? undef_map->l_name : _dl_argv[0]);
     }
+  else
+    /* Whoa, that was bad luck.  We have to search again.  */
+    result = -1;
 
+ out:
   /* Release the lock.  */
   __libc_lock_unlock_recursive (_dl_load_lock);
 
@@ -212,8 +214,6 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
 	   we have to prevent the latter from being unloaded unless the
 	   UNDEF_MAP object is also unloaded.  */
 	if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
-	    && current_value.m->l_global
-	    && undef_map != current_value.m
 	    /* Don't do this for explicit lookups as opposed to implicit
 	       runtime lookups.  */
 	    && ! explicit
@@ -395,8 +395,6 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 	     we have to prevent the latter from being unloaded unless the
 	     UNDEF_MAP object is also unloaded.  */
 	  if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
-	      && current_value.m->l_global
-	      && undef_map != current_value.m
 	      /* Don't do this for explicit lookups as opposed to implicit
 		 runtime lookups.  */
 	      && ! explicit