aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--elf/Makefile2
-rw-r--r--elf/dl-close.c23
-rw-r--r--elf/dl-object.c6
-rw-r--r--elf/dl-open.c50
5 files changed, 89 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 5793c0a2d8..21653dc4d9 100644
--- 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
diff --git a/elf/Makefile b/elf/Makefile
index 0831662715..160d901526 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -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
diff --git a/elf/dl-close.c b/elf/dl-close.c
index e83865f0a1..dfc204d478 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -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);
diff --git a/elf/dl-object.c b/elf/dl-object.c
index 07e428e8e6..9c32c08ff2 100644
--- a/elf/dl-object.c
+++ b/elf/dl-object.c
@@ -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;
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);