summary refs log tree commit diff
path: root/elf/dl-fini.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2005-03-19 07:22:23 +0000
committerUlrich Drepper <drepper@redhat.com>2005-03-19 07:22:23 +0000
commitc3381f3eb21b3660c8854e9bada5e7bd201a40af (patch)
treef6611e40528d1538584411b0cdc94855c0e09b38 /elf/dl-fini.c
parentbb4bb82b13533eee4dfe09e21a23a150d0d3ee8a (diff)
downloadglibc-c3381f3eb21b3660c8854e9bada5e7bd201a40af.tar.gz
glibc-c3381f3eb21b3660c8854e9bada5e7bd201a40af.tar.xz
glibc-c3381f3eb21b3660c8854e9bada5e7bd201a40af.zip
* elf/dl-fini.c (_dl_fini): Split sorting of the maps in separate
	function _dl_sort_fini.
	(_dl_sort_fini): New function.
	* sysdeps/generic/ldsodefs.h: Declare _dl_sort_fini.
	* elf/dl-close.c (_dl_close): Call _dl_sort_fini before running
	destructors to call them in the right order.
Diffstat (limited to 'elf/dl-fini.c')
-rw-r--r--elf/dl-fini.c177
1 files changed, 103 insertions, 74 deletions
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index a01b998ef0..3cd7e7bbff 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -29,6 +29,94 @@ typedef void (*fini_t) (void);
 
 void
 internal_function
+_dl_sort_fini (struct link_map *l, struct link_map **maps, size_t nmaps,
+	       char *used, Lmid_t ns)
+{
+  if (ns == LM_ID_BASE)
+    /* The main executable always comes first.  */
+    l = l->l_next;
+
+  for (; l != NULL; l = l->l_next)
+    /* Do not handle ld.so in secondary namespaces and object which
+       are not removed.  */
+    if (l == l->l_real && l->l_idx != -1)
+      {
+	/* Find the place in the 'maps' array.  */
+	unsigned int j;
+	for (j = ns == LM_ID_BASE ? 1 : 0; maps[j] != l; ++j)
+	  assert (j < nmaps);
+
+	/* Find all object for which the current one is a dependency
+	   and move the found object (if necessary) in front.  */
+	for (unsigned int k = j + 1; k < nmaps; ++k)
+	  {
+	    struct link_map **runp = maps[k]->l_initfini;
+	    if (runp != NULL)
+	      {
+		while (*runp != NULL)
+		  if (*runp == l)
+		    {
+		      struct link_map *here = maps[k];
+
+		      /* Move it now.  */
+		      memmove (&maps[j] + 1,
+			       &maps[j], (k - j) * sizeof (struct link_map *));
+		      maps[j] = here;
+
+		      if (used != NULL)
+			{
+			  char here_used = used[k];
+
+			  memmove (&used[j] + 1,
+				   &used[j], (k - j) * sizeof (char));
+			  used[j] = here_used;
+			}
+
+		      ++j;
+
+		      break;
+		    }
+		  else
+		    ++runp;
+	      }
+
+	    if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
+	      {
+		unsigned int m = maps[k]->l_reldepsact;
+		struct link_map **relmaps = maps[k]->l_reldeps;
+
+		while (m-- > 0)
+		  {
+		    if (relmaps[m] == l)
+		      {
+			struct link_map *here = maps[k];
+
+			/* Move it now.  */
+			memmove (&maps[j] + 1,
+				 &maps[j],
+				 (k - j) * sizeof (struct link_map *));
+			maps[j] = here;
+
+			if (used != NULL)
+			  {
+			    char here_used = used[k];
+
+			    memmove (&used[j] + 1,
+				     &used[j], (k - j) * sizeof (char));
+			    used[j] = here_used;
+			  }
+
+			break;
+		      }
+		  }
+	      }
+	  }
+      }
+}
+
+
+void
+internal_function
 _dl_fini (void)
 {
   /* Lots of fun ahead.  We have to call the destructors for all still
@@ -52,25 +140,25 @@ _dl_fini (void)
   int do_audit = 0;
  again:
 #endif
-  for (Lmid_t cnt = DL_NNS - 1; cnt >= 0; --cnt)
+  for (Lmid_t ns = DL_NNS - 1; ns >= 0; --ns)
     {
       /* Protect against concurrent loads and unloads.  */
       __rtld_lock_lock_recursive (GL(dl_load_lock));
 
       unsigned int nmaps = 0;
-      unsigned int nloaded = GL(dl_ns)[cnt]._ns_nloaded;
+      unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
       /* No need to do anything for empty namespaces or those used for
 	 auditing DSOs.  */
       if (nloaded == 0
 #ifdef SHARED
-	  || GL(dl_ns)[cnt]._ns_loaded->l_auditing != do_audit
+	  || GL(dl_ns)[ns]._ns_loaded->l_auditing != do_audit
 #endif
 	  )
 	goto out;
 
       /* XXX Could it be (in static binaries) that there is no object
 	 loaded?  */
-      assert (cnt != LM_ID_BASE || nloaded > 0);
+      assert (ns != LM_ID_BASE || nloaded > 0);
 
       /* Now we can allocate an array to hold all the pointers and copy
 	 the pointers in.  */
@@ -89,87 +177,28 @@ _dl_fini (void)
 
       unsigned int i;
       struct link_map *l;
-      assert (nloaded != 0 || GL(dl_ns)[cnt]._ns_loaded == NULL);
-      for (l = GL(dl_ns)[cnt]._ns_loaded, i = 0; l != NULL; l = l->l_next)
+      assert (nloaded != 0 || GL(dl_ns)[ns]._ns_loaded == NULL);
+      for (l = GL(dl_ns)[ns]._ns_loaded, i = 0; l != NULL; l = l->l_next)
 	/* Do not handle ld.so in secondary namespaces.  */
 	if (l == l->l_real)
 	  {
 	    assert (i < nloaded);
 
-	    maps[i++] = l;
+	    maps[i] = l;
+	    l->l_idx = i;
+	    ++i;
 
 	    /* Bump l_direct_opencount of all objects so that they are
 	       not dlclose()ed from underneath us.  */
 	    ++l->l_direct_opencount;
 	  }
-      assert (cnt != LM_ID_BASE || i == nloaded);
-      assert (cnt == LM_ID_BASE || i == nloaded || i == nloaded - 1);
+      assert (ns != LM_ID_BASE || i == nloaded);
+      assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1);
       nmaps = i;
 
       if (nmaps != 0)
-	{
-	  /* Now we have to do the sorting.  */
-	  l = GL(dl_ns)[cnt]._ns_loaded;
-	  if (cnt == LM_ID_BASE)
-	    /* The main executable always comes first.  */
-	    l = l->l_next;
-	  for (; l != NULL; l = l->l_next)
-	    /* Do not handle ld.so in secondary namespaces.  */
-	    if (l == l->l_real)
-	      {
-		/* Find the place in the 'maps' array.  */
-		unsigned int j;
-		for (j = cnt == LM_ID_BASE ? 1 : 0; maps[j] != l; ++j)
-		  assert (j < nmaps);
-
-		/* Find all object for which the current one is a dependency
-		   and move the found object (if necessary) in front.  */
-		for (unsigned int k = j + 1; k < nmaps; ++k)
-		  {
-		    struct link_map **runp = maps[k]->l_initfini;
-		    if (runp != NULL)
-		      {
-			while (*runp != NULL)
-			  if (*runp == l)
-			    {
-			      struct link_map *here = maps[k];
-
-			      /* Move it now.  */
-			      memmove (&maps[j] + 1,
-				       &maps[j],
-				       (k - j) * sizeof (struct link_map *));
-			      maps[j++] = here;
-
-			      break;
-			    }
-			  else
-			    ++runp;
-		      }
-
-		    if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
-		      {
-			unsigned int m = maps[k]->l_reldepsact;
-			struct link_map **relmaps = maps[k]->l_reldeps;
-
-			while (m-- > 0)
-			  {
-			    if (relmaps[m] == l)
-			      {
-				struct link_map *here = maps[k];
-
-				/* Move it now.  */
-				memmove (&maps[j] + 1,
-					 &maps[j],
-					 (k - j) * sizeof (struct link_map *));
-				maps[j] = here;
-
-				break;
-			      }
-			  }
-		      }
-		  }
-	      }
-	}
+	/* Now we have to do the sorting.  */
+	_dl_sort_fini (GL(dl_ns)[ns]._ns_loaded, maps, nmaps, NULL, ns);
 
       /* We do not rely on the linked list of loaded object anymore from
 	 this point on.  We have our own list here (maps).  The various
@@ -200,7 +229,7 @@ _dl_fini (void)
 					& DL_DEBUG_IMPCALLS, 0))
 		    _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
 				      l->l_name[0] ? l->l_name : rtld_progname,
-				      cnt);
+				      ns);
 
 		  /* First see whether an array is given.  */
 		  if (l->l_info[DT_FINI_ARRAY] != NULL)
@@ -247,7 +276,6 @@ _dl_fini (void)
       do_audit = 1;
       goto again;
     }
-#endif
 
   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS, 0))
     _dl_debug_printf ("\nruntime linker statistics:\n"
@@ -255,4 +283,5 @@ _dl_fini (void)
 		      "final number of relocations from cache: %lu\n",
 		      GL(dl_num_relocations),
 		      GL(dl_num_cache_relocations));
+#endif
 }