Update.
authorUlrich Drepper <drepper@redhat.com>
Fri, 7 Sep 2001 07:57:11 +0000 (07:57 +0000)
committerUlrich Drepper <drepper@redhat.com>
Fri, 7 Sep 2001 07:57:11 +0000 (07:57 +0000)
2001-09-07  Ulrich Drepper  <drepper@redhat.com>

* include/link.h (struct link_map): Add l_scope_mem and l_scope_max
elements.  Change l_scope to be a pointer only.
* elf/dl-object.c (_dl_new_ojbect): Initialize l_scope and l_scope_max.
* elf/dl-open.c (dl_open_worker): If dependency wasn't just opened
here add searchlist of newly open file to the dependency's scope.
* elf/dl-close.c (_dl_close): If dependency is used otherwise remove
only searchlist from its scope.  Free own scope array if necessary.
* elf/Makefile (tests): Add dblload and dblunload now.

ChangeLog
elf/Makefile
elf/dl-close.c
elf/dl-object.c
elf/dl-open.c

index 5793c0a..21653dc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2001-09-07  Ulrich Drepper  <drepper@redhat.com>
+
+       * include/link.h (struct link_map): Add l_scope_mem and l_scope_max
+       elements.  Change l_scope to be a pointer only.
+       * elf/dl-object.c (_dl_new_ojbect): Initialize l_scope and l_scope_max.
+       * elf/dl-open.c (dl_open_worker): If dependency wasn't just opened
+       here add searchlist of newly open file to the dependency's scope.
+       * elf/dl-close.c (_dl_close): If dependency is used otherwise remove
+       only searchlist from its scope.  Free own scope array if necessary.
+       * elf/Makefile (tests): Add dblload and dblunload now.
+
 2001-09-06  Andreas Jaeger  <aj@suse.de>
 
        * sysdeps/ieee754/ldbl-128/e_lgammal_r.c: New file, contributed
index 0831662..160d901 100644 (file)
@@ -106,7 +106,7 @@ tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
        reldep reldep2 reldep3 reldep4 $(tests-nodelete-$(have-z-nodelete)) \
        $(tests-nodlopen-$(have-z-nodlopen)) neededtest neededtest2 \
        neededtest3 neededtest4 unload2 lateglobal initfirst global \
-       restest2 next #dblload dblunload
+       restest2 next dblload dblunload
 test-srcs = tst-pathopt
 tests-vis-yes = vismain
 tests-nodelete-yes = nodelete
index e83865f..dfc204d 100644 (file)
@@ -146,6 +146,25 @@ _dl_close (void *_map)
              (imap, (void *) imap->l_addr
                     + imap->l_info[DT_FINI]->d_un.d_ptr)) ();
        }
+      else if (new_opencount[i] != 0 && imap->l_type == lt_loaded)
+       {
+         /* The object is still used.  But the object we are unloading
+            right now is responsible for loading it and therefore we
+            have the search list of the current object in its scope.
+            Remove it.  */
+         struct r_scope_elem **runp = imap->l_scope;
+
+         while (*runp != NULL)
+           if (*runp == &map->l_searchlist)
+             {
+               /* Copy all later elements.  */
+               while ((runp[0] = runp[1]) != NULL)
+                 ++runp;
+               break;
+             }
+         else
+           ++runp;
+       }
 
       /* Store the new l_opencount value.  */
       imap->l_opencount = new_opencount[i];
@@ -241,6 +260,10 @@ _dl_close (void *_map)
          if (imap != map)
              free (imap->l_initfini);
 
+         /* Remove the scope array if we allocated it.  */
+         if (imap->l_scope != imap->l_scope_mem)
+           free (imap->l_scope);
+
          if (imap->l_phdr_allocated)
            free ((void *) imap->l_phdr);
 
index 07e428e..9c32c08 100644 (file)
@@ -50,6 +50,12 @@ _dl_new_object (char *realname, const char *libname, int type,
   new->l_loader = loader;
   /* new->l_global = 0;        We use calloc therefore not necessary.  */
 
+  /* Use the 'l_scope_mem' array by default for the the 'l_scope'
+     information.  If we need more entries we will allocate a large
+     array dynamically.  */
+  new->l_scope = new->l_scope_mem;
+  new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
+
   /* Counter for the scopes we have to handle.  */
   idx = 0;
 
index ec88c79..f79c317 100644 (file)
@@ -295,9 +295,55 @@ dl_open_worker (void *a)
       l = l->l_prev;
     }
 
-  /* Increment the open count for all dependencies.  */
+  /* Increment the open count for all dependencies.  If the file is
+     not loaded as a dependency here add the search list of the newly
+     loaded object to the scope.  */
   for (i = 0; i < new->l_searchlist.r_nlist; ++i)
-    ++new->l_searchlist.r_list[i]->l_opencount;
+    if (++new->l_searchlist.r_list[i]->l_opencount > 1
+       && new->l_searchlist.r_list[i]->l_type == lt_loaded)
+      {
+       struct link_map *imap = new->l_searchlist.r_list[i];
+       struct r_scope_elem **runp = imap->l_scope;
+       size_t cnt = 0;
+
+       while (*runp != NULL)
+         {
+           ++cnt;
+           ++runp;
+         }
+
+       if (__builtin_expect (cnt + 1 < imap->l_scope_max, 0))
+         {
+           /* The 'r_scope' array is too small.  Allocate a new one
+              dynamically.  */
+           struct r_scope_elem **newp;
+           size_t new_size = imap->l_scope_max * 2;
+
+           if (imap->l_scope == imap->l_scope_mem)
+             {
+               newp = (struct r_scope_elem **)
+                 malloc (new_size * sizeof (struct r_scope_elem *));
+               if (newp == NULL)
+                 _dl_signal_error (ENOMEM, "dlopen", NULL,
+                                   N_("cannot create scope list"));
+               imap->l_scope = memcpy (newp, imap->l_scope,
+                                       cnt * imap->l_scope_max);
+             }
+           else
+             {
+               newp = (struct r_scope_elem **)
+                 realloc (imap->l_scope,
+                          new_size * sizeof (struct r_scope_elem *));
+               if (newp == NULL)
+                 _dl_signal_error (ENOMEM, "dlopen", NULL,
+                                   N_("cannot create scope list"));
+               imap->l_scope = newp;
+             }
+
+           imap->l_scope[cnt++] = &new->l_searchlist;
+           imap->l_scope[cnt] = NULL;
+         }
+      }
 
   /* Run the initializer functions of new objects.  */
   _dl_init (new, __libc_argc, __libc_argv, __environ);