about summary refs log tree commit diff
path: root/elf/dl-close.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-close.c')
-rw-r--r--elf/dl-close.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 5f829223cc..c98a21d57d 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -43,11 +43,15 @@ void
 internal_function
 _dl_close (void *_map)
 {
+  struct reldep_list
+  {
+    struct link_map **rellist;
+    unsigned int nrellist;
+    struct reldep_list *next;
+  } *reldeps = NULL;
   struct link_map **list;
-  struct link_map **rellist;
   struct link_map *map = _map;
   unsigned int nsearchlist;
-  unsigned int nrellist;
   unsigned int i;
   unsigned int *new_opencount;
 
@@ -119,9 +123,6 @@ _dl_close (void *_map)
       }
   assert (new_opencount[0] == 0);
 
-  rellist = map->l_reldeps;
-  nrellist = map->l_reldepsact;
-
   /* Call all termination functions at once.  */
   for (i = 0; i < nsearchlist; ++i)
     {
@@ -221,6 +222,20 @@ _dl_close (void *_map)
 	  if (imap->l_origin != NULL && imap->l_origin != (char *) -1)
 	    free ((char *) imap->l_origin);
 
+	  /* If the object has relocation dependencies save this
+             information for latter.  */
+	  if (__builtin_expect (imap->l_reldeps != NULL, 0))
+	    {
+	      struct reldep_list *newrel;
+
+	      newrel = (struct reldep_list *) alloca (sizeof (*reldeps));
+	      newrel->rellist = map->l_reldeps;
+	      newrel->nrellist = map->l_reldepsact;
+	      newrel->next = reldeps;
+
+	      reldeps = newrel;
+	    }
+
 	  /* This name always is allocated.  */
 	  free (imap->l_name);
 	  /* Remove the list with all the names of the shared object.  */
@@ -255,12 +270,14 @@ _dl_close (void *_map)
 
   /* Now we can perhaps also remove the modules for which we had
      dependencies because of symbol lookup.  */
-  if (__builtin_expect (rellist != NULL, 0))
+  while (__builtin_expect (reldeps != NULL, 0))
     {
-      while (nrellist-- > 0)
-	_dl_close (rellist[nrellist]);
+      while (reldeps->nrellist-- > 0)
+	_dl_close (reldeps->rellist[reldeps->nrellist]);
+
+      free (reldeps->rellist);
 
-      free (rellist);
+      reldeps = reldeps->next;
     }
 
   free (list);