about summary refs log tree commit diff
path: root/elf/dl-open.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2001-09-07 07:57:11 +0000
committerUlrich Drepper <drepper@redhat.com>2001-09-07 07:57:11 +0000
commit5a21d307c518c911f81848b6c0056fcc39e3ddcd (patch)
tree9b2c8e176909392cb03b76cf2eb5d29e61c55d40 /elf/dl-open.c
parentb98e518f5627b95c79bf75d178ae41527c333886 (diff)
downloadglibc-5a21d307c518c911f81848b6c0056fcc39e3ddcd.tar.gz
glibc-5a21d307c518c911f81848b6c0056fcc39e3ddcd.tar.xz
glibc-5a21d307c518c911f81848b6c0056fcc39e3ddcd.zip
Update.
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.
Diffstat (limited to 'elf/dl-open.c')
-rw-r--r--elf/dl-open.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/elf/dl-open.c b/elf/dl-open.c
index ec88c79a27..f79c317da8 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -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);