about summary refs log tree commit diff
path: root/elf/dl-fini.c
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@suse.de>2017-11-07 15:24:19 +0100
committerAndreas Schwab <schwab@suse.de>2017-11-27 11:37:19 +0100
commitc2c299fd24e87b83c63191ff979d41a86b37d714 (patch)
tree47b1dcdd9bd9348b5a15f93b376a8e7d275a324b /elf/dl-fini.c
parentde61465c04d36dadce2f4e7f78ebbe50bae6a21e (diff)
downloadglibc-c2c299fd24e87b83c63191ff979d41a86b37d714.tar.gz
glibc-c2c299fd24e87b83c63191ff979d41a86b37d714.tar.xz
glibc-c2c299fd24e87b83c63191ff979d41a86b37d714.zip
Consolidate link map sorting
Combine the four places where link maps are sorted into a single function.
This also moves the logic to skip the first map (representing the main
binary) to the callers.
Diffstat (limited to 'elf/dl-fini.c')
-rw-r--r--elf/dl-fini.c105
1 files changed, 5 insertions, 100 deletions
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index 71c06fc68b..8421c4fab8 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -26,104 +26,6 @@ typedef void (*fini_t) (void);
 
 
 void
-_dl_sort_fini (struct link_map **maps, size_t nmaps, char *used, Lmid_t ns)
-{
-  /* A list of one element need not be sorted.  */
-  if (nmaps == 1)
-    return;
-
-  /* We can skip looking for the binary itself which is at the front
-     of the search list for the main namespace.  */
-  unsigned int i = ns == LM_ID_BASE;
-  uint16_t seen[nmaps];
-  memset (seen, 0, nmaps * sizeof (seen[0]));
-  while (1)
-    {
-      /* Keep track of which object we looked at this round.  */
-      ++seen[i];
-      struct link_map *thisp = maps[i];
-
-      /* Do not handle ld.so in secondary namespaces and object which
-	 are not removed.  */
-      if (thisp != thisp->l_real || thisp->l_idx == -1)
-	goto skip;
-
-      /* Find the last object in the list for which the current one is
-	 a dependency and move the current object behind the object
-	 with the dependency.  */
-      unsigned int k = nmaps - 1;
-      while (k > i)
-	{
-	  struct link_map **runp = maps[k]->l_initfini;
-	  if (runp != NULL)
-	    /* Look through the dependencies of the object.  */
-	    while (*runp != NULL)
-	      if (__glibc_unlikely (*runp++ == thisp))
-		{
-		move:
-		  /* Move the current object to the back past the last
-		     object with it as the dependency.  */
-		  memmove (&maps[i], &maps[i + 1],
-			   (k - i) * sizeof (maps[0]));
-		  maps[k] = thisp;
-
-		  if (used != NULL)
-		    {
-		      char here_used = used[i];
-		      memmove (&used[i], &used[i + 1],
-			       (k - i) * sizeof (used[0]));
-		      used[k] = here_used;
-		    }
-
-		  if (seen[i + 1] > nmaps - i)
-		    {
-		      ++i;
-		      goto next_clear;
-		    }
-
-		  uint16_t this_seen = seen[i];
-		  memmove (&seen[i], &seen[i + 1], (k - i) * sizeof (seen[0]));
-		  seen[k] = this_seen;
-
-		  goto next;
-		}
-
-	  if (__glibc_unlikely (maps[k]->l_reldeps != NULL))
-	    {
-	      unsigned int m = maps[k]->l_reldeps->act;
-	      struct link_map **relmaps = &maps[k]->l_reldeps->list[0];
-
-	      /* Look through the relocation dependencies of the object.  */
-	      while (m-- > 0)
-		if (__glibc_unlikely (relmaps[m] == thisp))
-		  {
-		    /* If a cycle exists with a link time dependency,
-		       preserve the latter.  */
-		    struct link_map **runp = thisp->l_initfini;
-		    if (runp != NULL)
-		      while (*runp != NULL)
-			if (__glibc_unlikely (*runp++ == maps[k]))
-			  goto ignore;
-		    goto move;
-		  }
-	    ignore:;
-	    }
-
-	  --k;
-	}
-
-    skip:
-      if (++i == nmaps)
-	break;
-    next_clear:
-      memset (&seen[i], 0, (nmaps - i) * sizeof (seen[0]));
-
-    next:;
-    }
-}
-
-
-void
 _dl_fini (void)
 {
   /* Lots of fun ahead.  We have to call the destructors for all still
@@ -186,8 +88,11 @@ _dl_fini (void)
 	  assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1);
 	  unsigned int nmaps = i;
 
-	  /* Now we have to do the sorting.  */
-	  _dl_sort_fini (maps, nmaps, NULL, ns);
+	  /* Now we have to do the sorting.  We can skip looking for the
+	     binary itself which is at the front of the search list for
+	     the main namespace.  */
+	  _dl_sort_maps (maps + (ns == LM_ID_BASE), nmaps - (ns == LM_ID_BASE),
+			 NULL, true);
 
 	  /* We do not rely on the linked list of loaded object anymore
 	     from this point on.  We have our own list here (maps).  The