a2cf7d
commit 0a8ce6a0966283b17f373f430929bcadef1ae205
a2cf7d
Author: David Kilroy <David.Kilroy@arm.com>
a2cf7d
Date:   Wed Feb 12 14:31:17 2020 -0300
a2cf7d
a2cf7d
    elf: avoid stack allocation in dl_open_worker
a2cf7d
    
a2cf7d
    As the sort was removed, there's no need to keep a separate map of
a2cf7d
    links. Instead, when relocating objects iterate over l_initfini
a2cf7d
    directly.
a2cf7d
    
a2cf7d
    This allows us to remove the loop copying l_initfini elements into
a2cf7d
    map. We still need a loop to identify the first and last elements that
a2cf7d
    need relocation.
a2cf7d
    
a2cf7d
    Tested by running the testsuite on x86_64.
a2cf7d
a2cf7d
diff --git a/elf/dl-open.c b/elf/dl-open.c
a2cf7d
index 980a28c836ca9a7a..46a4c1e5a3f8d2dd 100644
a2cf7d
--- a/elf/dl-open.c
a2cf7d
+++ b/elf/dl-open.c
a2cf7d
@@ -618,25 +618,18 @@ dl_open_worker (void *a)
a2cf7d
      This allows IFUNC relocations to work and it also means copy
a2cf7d
      relocation of dependencies are if necessary overwritten.
a2cf7d
      __dl_map_object_deps has already sorted l_initfini for us.  */
a2cf7d
-  unsigned int nmaps = 0;
a2cf7d
+  unsigned int first = UINT_MAX;
a2cf7d
+  unsigned int last = 0;
a2cf7d
   unsigned int j = 0;
a2cf7d
   struct link_map *l = new->l_initfini[0];
a2cf7d
   do
a2cf7d
     {
a2cf7d
       if (! l->l_real->l_relocated)
a2cf7d
-	++nmaps;
a2cf7d
-      l = new->l_initfini[++j];
a2cf7d
-    }
a2cf7d
-  while (l != NULL);
a2cf7d
-  /* Stack allocation is limited by the number of loaded objects.  */
a2cf7d
-  struct link_map *maps[nmaps];
a2cf7d
-  nmaps = 0;
a2cf7d
-  j = 0;
a2cf7d
-  l = new->l_initfini[0];
a2cf7d
-  do
a2cf7d
-    {
a2cf7d
-      if (! l->l_real->l_relocated)
a2cf7d
-	maps[nmaps++] = l;
a2cf7d
+	{
a2cf7d
+	  if (first == UINT_MAX)
a2cf7d
+	    first = j;
a2cf7d
+	  last = j + 1;
a2cf7d
+	}
a2cf7d
       l = new->l_initfini[++j];
a2cf7d
     }
a2cf7d
   while (l != NULL);
a2cf7d
@@ -651,9 +644,12 @@ dl_open_worker (void *a)
a2cf7d
      them.  However, such relocation dependencies in IFUNC resolvers
a2cf7d
      are undefined anyway, so this is not a problem.  */
a2cf7d
 
a2cf7d
-  for (unsigned int i = nmaps; i-- > 0; )
a2cf7d
+  for (unsigned int i = last; i-- > first; )
a2cf7d
     {
a2cf7d
-      l = maps[i];
a2cf7d
+      l = new->l_initfini[i];
a2cf7d
+
a2cf7d
+      if (l->l_real->l_relocated)
a2cf7d
+	continue;
a2cf7d
 
a2cf7d
       if (! relocation_in_progress)
a2cf7d
 	{