summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-03-20 18:56:01 +0000
committerJakub Jelinek <jakub@redhat.com>2005-03-20 18:56:01 +0000
commit67e218b53a309ba3bdb3d7bdc0b8e05bc0354b06 (patch)
tree689fb8bd472a15303915d7c2a7f9ef4c823f77d2
parent792542d56249281f383a5455f021ec619cd32671 (diff)
-rw-r--r--ChangeLog78
-rw-r--r--elf/Makefile32
-rw-r--r--elf/circleload1.c2
-rw-r--r--elf/dl-close.c360
-rw-r--r--elf/dl-deps.c2
-rw-r--r--elf/dl-fini.c183
-rw-r--r--elf/dl-load.c5
-rw-r--r--elf/dl-lookup.c21
-rw-r--r--elf/dl-open.c279
-rw-r--r--elf/do-lookup.h4
-rw-r--r--elf/loadtest.c8
-rw-r--r--elf/neededtest.c2
-rw-r--r--elf/neededtest2.c2
-rw-r--r--elf/neededtest3.c2
-rw-r--r--elf/neededtest4.c2
-rw-r--r--elf/order2.c46
-rw-r--r--elf/order2mod1.c8
-rw-r--r--elf/order2mod2.c18
-rw-r--r--elf/order2mod3.c14
-rw-r--r--elf/order2mod4.c16
-rw-r--r--elf/rtld.c141
-rw-r--r--elf/testobj2.c1
-rw-r--r--elf/unload.c4
-rw-r--r--elf/unload2.c4
-rw-r--r--elf/unload3mod4.c2
-rw-r--r--elf/unload4.c48
-rw-r--r--elf/unload4mod1.c10
-rw-r--r--elf/unload4mod2.c8
-rw-r--r--elf/unload4mod3.c16
-rw-r--r--elf/unload4mod4.c16
-rw-r--r--elf/unload5.c42
-rw-r--r--fedora/glibc.spec.in5
-rw-r--r--include/link.h6
-rw-r--r--sysdeps/generic/ldsodefs.h5
34 files changed, 838 insertions, 554 deletions
diff --git a/ChangeLog b/ChangeLog
index 448d370a9d..ba07a31ba6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,81 @@
+2005-03-20 Alfred M. Szmidt <ams@gnu.org>
+
+ * elf/dl-open.c (dl_open_worker): Fix typo.
+
+2005-03-19 Ulrich Drepper <drepper@redhat.com>
+
+ * elf/dl-lookup.c (add_dependency): Always search l_initfini if
+ the list exists.
+
+ * elf/Makefile: Add rules to build and run order2.
+ * elf/order2.c: New file.
+ * elf/order2mod1.c: New file.
+ * elf/order2mod2.c: New file.
+ * elf/order2mod3.c: New file.
+ * elf/order2mod4.c: New file.
+
+2005-03-19 Jakub Jelinek <jakub@redhat.com>
+
+ * elf/dl-open.c (dl_open_worker): Print exact l_direct_opencount value,
+ it has been incremented before.
+
+2005-03-18 Ulrich Drepper <drepper@redhat.com>
+
+ * elf/dl-fini.c (_dl_fini): Split sorting of the maps in separate
+ function _dl_sort_fini.
+ (_dl_sort_fini): New function.
+ * sysdeps/generic/ldsodefs.h: Declare _dl_sort_fini.
+ * elf/dl-close.c (_dl_close): Call _dl_sort_fini before running
+ destructors to call them in the right order.
+
+2005-03-18 Ulrich Drepper <drepper@redhat.com>
+
+ * include/link.h (struct link_map): Remove l_opencount. Add l_removed.
+ Change type of l_idx to int.
+ * elf/dl-close.c: Basically rewrite. Do not use l_opencount to
+ determine whether a DSO has to be unloaded. Instead compute this
+ in this function.
+ * elf/dl-deps.c: No need to manipulate l_opencount anymore.
+ * elf/dl-lookup.c: Likewise.
+ * elf/rtld.c: Likewise
+ * elf/dl-open.c: Likewise. Use l_init_called to determine whether
+ object was just loaded.
+ * elf/dl-fini.c: Bump l_direct_opencount instead of l_opencount.
+ * elf/dl-load.c (_dl_map_object_from_fd): Do not recognize DSO which
+ is about to be unloaded as a match.
+ (_dl_map_object): Likewise.
+ * elf/do-lookup.h (do_lookup_x): Do not look into DSO which is about
+ to be unloaded.
+ * elf/circleload1.c: Don't use l_opencount anymore.
+ * elf/neededtest.c: Likewise.
+ * elf/neededtest2.c: Likewise.
+ * elf/neededtest3.c: Likewise.
+ * elf/neededtest4.c: Likewise.
+ * elf/unload.c: Likewise.
+ * elf/unload2.c: Likewise.
+ * elf/loadtest.c: Likewise.
+
+ * elf/rtld.c: Preloading errors are now never fatal.
+
+2005-03-08 Jakub Jelinek <jakub@redhat.com>
+
+ * elf/Makefile: Add rules to build and run unload5 test.
+ * elf/unload5.c: New file.
+
+2005-03-08 Jakub Jelinek <jakub@redhat.com>
+
+ * elf/Makefile: Add rules to build and run unload4 test.
+ * elf/unload4.c: New file.
+ * elf/unload4mod1.c: New file.
+ * elf/unload4mod2.c: New file.
+ * elf/unload4mod3.c: New file.
+ * elf/unload4mod4.c: New file.
+
+2005-03-05 Roland McGrath <roland@redhat.com>
+
+ * elf/unload3mod4.c: Declare foo.
+ * elf/testobj2.c: Include <stdio.h>.
+
2005-03-01 H.J. Lu <hongjiu.lu@intel.com>
[BZ #776]
diff --git a/elf/Makefile b/elf/Makefile
index d00ad65748..04ff7f42a1 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -84,7 +84,9 @@ distribute := rtld-Rules \
tst-execstack-mod.c tst-dlmodcount.c \
check-textrel.c dl-sysdep.h test-dlopenrpathmod.c \
tst-deep1mod1.c tst-deep1mod2.c tst-deep1mod3.c \
- unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c
+ unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c \
+ unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \
+ order2mod1.c order2mod2.c order2mod3.c order2mod4.c
CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables
@@ -156,7 +158,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \
tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
- unload3 tst-global1
+ unload3 unload4 unload5 tst-global1 order2
# reldep9
test-srcs = tst-pathopt
tests-vis-yes = vismain
@@ -192,7 +194,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
$(modules-execstack-$(have-z-execstack)) \
tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \
tst-dlmopen1mod \
- unload3mod1 unload3mod2 unload3mod3 unload3mod4
+ unload3mod1 unload3mod2 unload3mod3 unload3mod4 \
+ unload4mod1 unload4mod2 unload4mod3 unload4mod4 \
+ order2mod1 order2mod2 order2mod3 order2mod4
ifeq (yes,$(have-initfini-array))
modules-names += tst-array2dep
endif
@@ -427,6 +431,8 @@ $(objpfx)reldep9mod3.so: $(objpfx)reldep9mod1.so $(objpfx)reldep9mod2.so
$(objpfx)unload3mod1.so: $(objpfx)unload3mod3.so
$(objpfx)unload3mod2.so: $(objpfx)unload3mod3.so
$(objpfx)unload3mod3.so: $(objpfx)unload3mod4.so
+$(objpfx)unload4mod1.so: $(objpfx)unload4mod2.so $(objpfx)unload4mod3.so
+$(objpfx)unload4mod2.so: $(objpfx)unload4mod4.so $(objpfx)unload4mod3.so
LDFLAGS-tst-tlsmod5.so = -nostdlib
LDFLAGS-tst-tlsmod6.so = -nostdlib
@@ -467,6 +473,7 @@ circlemod3a.so-no-z-defs = yes
reldep8mod2.so-no-z-defs = yes
reldep9mod1.so-no-z-defs = yes
unload3mod4.so-no-z-defs = yes
+unload4mod1.so-no-z-defs = yes
# filtmod1.so has a special rule
$(filter-out $(objpfx)filtmod1.so, $(test-modules)): $(objpfx)%.so: $(objpfx)%.os
@@ -687,6 +694,13 @@ $(objpfx)unload3: $(libdl)
$(objpfx)unload3.out: $(objpfx)unload3mod1.so $(objpfx)unload3mod2.so \
$(objpfx)unload3mod3.so $(objpfx)unload3mod4.so
+$(objpfx)unload4: $(libdl)
+$(objpfx)unload4.out: $(objpfx)unload4mod1.so $(objpfx)unload4mod3.so
+
+$(objpfx)unload5: $(libdl)
+$(objpfx)unload5.out: $(objpfx)unload3mod1.so $(objpfx)unload3mod2.so \
+ $(objpfx)unload3mod3.so $(objpfx)unload3mod4.so
+
ifdef libdl
$(objpfx)tst-tls9-static: $(common-objpfx)dlfcn/libdl.a
$(objpfx)tst-tls9-static.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so
@@ -793,3 +807,15 @@ $(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so
$(objpfx)tst-global1: $(libdl)
$(objpfx)tst-global1.out: $(objpfx)testobj6.so $(objpfx)testobj2.so
+
+$(objpfx)order2: $(libdl)
+$(objpfx)order2.out: $(objpfx)order2 $(objpfx)order2mod1.so \
+ $(objpfx)order2mod2.so
+ $(elf-objpfx)$(rtld-installed-name) \
+ --library-path $(rpath-link)$(patsubst %,:%,$(sysdep-library-path)) \
+ $(objpfx)order2 > $@
+ (echo "12345" | cmp $@ -) > /dev/null
+$(objpfx)order2mod1.so: $(objpfx)order2mod4.so
+$(objpfx)order2mod4.so: $(objpfx)order2mod3.so
+$(objpfx)order2mod2.so: $(objpfx)order2mod3.so
+order2mod2.so-no-z-defs = yes
diff --git a/elf/circleload1.c b/elf/circleload1.c
index 7ac101a799..1fb885cf50 100644
--- a/elf/circleload1.c
+++ b/elf/circleload1.c
@@ -27,7 +27,7 @@ check_loaded_objects (const char **loaded)
for (lm = _r_debug.r_map; lm; lm = lm->l_next)
{
if (lm->l_name && lm->l_name[0])
- printf(" %s, count = %d\n", lm->l_name, (int) lm->l_opencount);
+ printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
if (lm->l_type == lt_loaded && lm->l_name)
{
int match = 0;
diff --git a/elf/dl-close.c b/elf/dl-close.c
index f40d5b0d89..df4f5aed87 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -102,18 +102,9 @@ void
internal_function
_dl_close (void *_map)
{
- struct reldep_list
- {
- struct link_map **rellist;
- unsigned int nrellist;
- unsigned int nhandled;
- struct reldep_list *next;
- bool handled[0];
- } *reldeps = NULL;
- struct link_map **list;
struct link_map *map = _map;
unsigned int i;
- unsigned int *new_opencount;
+ Lmid_t ns = map->l_ns;
#ifdef USE_TLS
bool any_tls = false;
#endif
@@ -124,162 +115,134 @@ _dl_close (void *_map)
/* Nope. Do nothing. */
return;
- if (__builtin_expect (map->l_opencount, 1) == 0)
+ if (__builtin_expect (map->l_direct_opencount, 1) == 0)
GLRO(dl_signal_error) (0, map->l_name, NULL, N_("shared object not open"));
/* Acquire the lock. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
/* One less direct use. */
- assert (map->l_direct_opencount > 0);
--map->l_direct_opencount;
/* Decrement the reference count. */
- if (map->l_opencount > 1 || map->l_type != lt_loaded)
+ if (map->l_direct_opencount > 1 || map->l_type != lt_loaded)
{
/* There are still references to this object. Do nothing more. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
- GLRO(dl_debug_printf) ("\nclosing file=%s; opencount == %u\n",
- map->l_name, map->l_opencount);
-
- /* Decrement the object's reference counter, not the dependencies'. */
- --map->l_opencount;
-
- /* If the direct use counter reaches zero we have to decrement
- all the dependencies' usage counter. */
- if (map->l_direct_opencount == 0)
- for (i = 1; i < map->l_searchlist.r_nlist; ++i)
- --map->l_searchlist.r_list[i]->l_opencount;
+ GLRO(dl_debug_printf) ("\nclosing file=%s; direct_opencount == %u\n",
+ map->l_name, map->l_direct_opencount);
__rtld_lock_unlock_recursive (GL(dl_load_lock));
return;
}
- list = map->l_initfini;
+ const unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
+ char used[nloaded];
+ char done[nloaded];
+ struct link_map *maps[nloaded];
- /* Compute the new l_opencount values. */
- i = map->l_searchlist.r_nlist;
- if (__builtin_expect (i == 0, 0))
- /* This can happen if we handle relocation dependencies for an
- object which wasn't loaded directly. */
- for (i = 1; list[i] != NULL; ++i)
- ;
+ /* Run over the list and assign indeces to the link maps and enter
+ them into the MAPS array. */
+ int idx = 0;
+ for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
+ {
+ l->l_idx = idx;
+ maps[idx] = l;
+ ++idx;
+ }
+ assert (idx == nloaded);
- unsigned int nopencount = i;
- new_opencount = (unsigned int *) alloca (i * sizeof (unsigned int));
+ /* Prepare the bitmaps. */
+ memset (used, '\0', sizeof (used));
+ memset (done, '\0', sizeof (done));
- for (i = 0; list[i] != NULL; ++i)
+ /* Keep track of the lowest index link map we have covered already. */
+ int done_index = -1;
+ while (++done_index < nloaded)
{
- list[i]->l_idx = i;
- new_opencount[i] = list[i]->l_opencount;
- }
- --new_opencount[0];
- for (i = 1; list[i] != NULL; ++i)
- if ((list[i]->l_flags_1 & DF_1_NODELETE) == 0
- /* Decrement counter. */
- && (assert (new_opencount[i] > 0), --new_opencount[i] == 0))
- {
- void mark_removed (struct link_map *remmap)
- {
- /* Test whether this object was also loaded directly. */
- if (remmap->l_searchlist.r_list != NULL
- && remmap->l_direct_opencount > 0)
- {
- /* In this case we have to decrement all the dependencies of
- this object. They are all in MAP's dependency list. */
- unsigned int j;
- struct link_map **dep_list = remmap->l_searchlist.r_list;
-
- for (j = 1; j < remmap->l_searchlist.r_nlist; ++j)
- if (! (dep_list[j]->l_flags_1 & DF_1_NODELETE)
- || ! dep_list[j]->l_init_called)
+ struct link_map *l = maps[done_index];
+
+ if (done[done_index])
+ /* Already handled. */
+ continue;
+
+ /* Check whether this object is still used. */
+ if (l->l_type == lt_loaded
+ && l->l_direct_opencount == 0
+ && (l->l_flags_1 & DF_1_NODELETE) == 0
+ && !used[done_index])
+ continue;
+
+ /* We need this object and we handle it now. */
+ done[done_index] = 1;
+ used[done_index] = 1;
+ /* Signal the object is still needed. */
+ l->l_idx = -1;
+
+ /* Mark all dependencies as used. */
+ if (l->l_initfini != NULL)
+ {
+ struct link_map **lp = &l->l_initfini[1];
+ while (*lp != NULL)
+ {
+ if ((*lp)->l_idx != -1)
{
- assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist);
- assert (new_opencount[dep_list[j]->l_idx] > 0);
- if (--new_opencount[dep_list[j]->l_idx] == 0)
+ assert ((*lp)->l_idx >= 0 && (*lp)->l_idx < nloaded);
+
+ if (!used[(*lp)->l_idx])
{
- assert (dep_list[j]->l_type == lt_loaded);
- mark_removed (dep_list[j]);
+ used[(*lp)->l_idx] = 1;
+ if ((*lp)->l_idx - 1 < done_index)
+ done_index = (*lp)->l_idx - 1;
}
}
- }
- if (remmap->l_reldeps != NULL)
+ ++lp;
+ }
+ }
+ /* And the same for relocation dependencies. */
+ if (l->l_reldeps != NULL)
+ for (unsigned int j = 0; j < l->l_reldepsact; ++j)
+ {
+ struct link_map *jmap = l->l_reldeps[j];
+
+ if (jmap->l_idx != -1)
{
- unsigned int j;
- for (j = 0; j < remmap->l_reldepsact; ++j)
+ assert (jmap->l_idx >= 0 && jmap->l_idx < nloaded);
+
+ if (!used[jmap->l_idx])
{
- struct link_map *depmap = remmap->l_reldeps[j];
-
- /* Find out whether this object is in our list. */
- if (depmap->l_idx < nopencount
- && list[depmap->l_idx] == depmap)
- {
- /* Yes, it is. If is has a search list, make a
- recursive call to handle this. */
- if (depmap->l_searchlist.r_list != NULL)
- {
- assert (new_opencount[depmap->l_idx] > 0);
- if (--new_opencount[depmap->l_idx] == 0)
- {
- /* This one is now gone, too. */
- assert (depmap->l_type == lt_loaded);
- mark_removed (depmap);
- }
- }
- else
- {
- /* Otherwise we have to handle the dependency
- deallocation here. */
- unsigned int k;
- for (k = 0; depmap->l_initfini[k] != NULL; ++k)
- {
- struct link_map *rl = depmap->l_initfini[k];
-
- if (rl->l_idx < nopencount
- && list[rl->l_idx] == rl)
- {
- assert (new_opencount[rl->l_idx] > 0);
- if (--new_opencount[rl->l_idx] == 0)
- {
- /* Another module to remove. */
- assert (rl->l_type == lt_loaded);
- mark_removed (rl);
- }
- }
- else
- {
- assert (rl->l_opencount > 0);
- if (--rl->l_opencount == 0)
- mark_removed (rl);
- }
- }
- }
- }
+ used[jmap->l_idx] = 1;
+ if (jmap->l_idx - 1 < done_index)
+ done_index = jmap->l_idx - 1;
}
}
}
+ }
- mark_removed (list[i]);
- }
- assert (new_opencount[0] == 0);
+ /* Sort the entries. */
+ _dl_sort_fini (GL(dl_ns)[ns]._ns_loaded, maps, nloaded, used, ns);
- /* Call all termination functions at once. */
- for (i = 0; list[i] != NULL; ++i)
+ bool unload_any = false;
+ unsigned int first_loaded = ~0;
+ for (i = 0; i < nloaded; ++i)
{
- struct link_map *imap = list[i];
- if (new_opencount[i] == 0 && imap->l_type == lt_loaded
- && (imap->l_flags_1 & DF_1_NODELETE) == 0)
- {
- /* When debugging print a message first. */
- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
- GLRO(dl_debug_printf) ("\ncalling fini: %s [%lu]\n\n",
- imap->l_name, imap->l_ns);
+ struct link_map *imap = maps[i];
+
+ if (!used[i])
+ {
+ assert (imap->l_type == lt_loaded
+ && (imap->l_flags_1 & DF_1_NODELETE) == 0);
/* Call its termination function. Do not do it for
half-cooked objects. */
if (imap->l_init_called)
{
+ /* When debugging print a message first. */
+ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
+ GLRO(dl_debug_printf) ("\ncalling fini: %s [%lu]\n\n",
+ imap->l_name, ns);
+
if (imap->l_info[DT_FINI_ARRAY] != NULL)
{
ElfW(Addr) *array =
@@ -299,42 +262,60 @@ _dl_close (void *_map)
+ imap->l_info[DT_FINI]->d_un.d_ptr))) ();
}
- /* This object must not be used anymore. We must remove the
- reference from the scope. */
- unsigned int j;
- struct link_map **searchlist = map->l_searchlist.r_list;
- unsigned int nsearchlist = map->l_searchlist.r_nlist;
-
-#ifndef NDEBUG
- bool found = false;
-#endif
- for (j = 0; j < nsearchlist; ++j)
- if (imap == searchlist[j])
- {
- /* This is the object to remove. Copy all the
- following ones. */
- while (++j < nsearchlist)
- searchlist[j - 1] = searchlist[j];
-
- searchlist[j - 1] = NULL;
+ /* This object must not be used anymore. */
+ imap->l_removed = 1;
- --map->l_searchlist.r_nlist;
+ /* We indeed have an object to remove. */
+ unload_any = true;
-#ifndef NDEBUG
- found = true;
-#endif
- break;
- }
- assert (found);
+ /* Remember where the first dynamically loaded object is. */
+ if (i < first_loaded)
+ first_loaded = i;
}
+ /* Else used[i]. */
+ else if (imap->l_type == lt_loaded)
+ {
+ if (imap->l_searchlist.r_list == NULL
+ && imap->l_initfini != NULL)
+ {
+ /* The object is still used. But the object we are
+ unloading right now is responsible for loading it. If
+ the current object does not have it's own scope yet we
+ have to create one. This has to be done before running
+ the finalizers.
+
+ To do this count the number of dependencies. */
+ unsigned int cnt;
+ for (cnt = 1; imap->l_initfini[cnt] != NULL; ++cnt)
+ ;
+
+ /* We simply reuse the l_initfini list. */
+ imap->l_searchlist.r_list = &imap->l_initfini[cnt + 1];
+ imap->l_searchlist.r_nlist = cnt;
+
+ for (cnt = 0; imap->l_scope[cnt] != NULL; ++cnt)
+ if (imap->l_scope[cnt] == &map->l_searchlist)
+ {
+ imap->l_scope[cnt] = &imap->l_searchlist;
+ break;
+ }
+ }
- /* Store the new l_opencount value. */
- imap->l_opencount = new_opencount[i];
+ /* The loader is gone, so mark the object as not having one.
+ Note: l_idx == -1 -> object will be removed. */
+ if (imap->l_loader != NULL && imap->l_loader->l_idx != -1)
+ imap->l_loader = NULL;
- /* Just a sanity check. */
- assert (imap->l_type == lt_loaded || imap->l_opencount > 0);
+ /* Remember where the first dynamically loaded object is. */
+ if (i < first_loaded)
+ first_loaded = i;
+ }
}
+ /* If there are no objects to unload, do nothing further. */
+ if (!unload_any)
+ goto out;
+
/* Notify the debugger we are about to remove some loaded objects. */
_r_debug.r_state = RT_DELETE;
GLRO(dl_debug_state) ();
@@ -347,12 +328,12 @@ _dl_close (void *_map)
/* Check each element of the search list to see if all references to
it are gone. */
- for (i = 0; list[i] != NULL; ++i)
+ for (i = first_loaded; i < nloaded; ++i)
{
- struct link_map *imap = list[i];
- if (imap->l_opencount == 0 && imap->l_type == lt_loaded)
+ struct link_map *imap = maps[i];
+ if (!used[i])
{
- struct libname_list *lnp;
+ assert (imap->l_type == lt_loaded);
/* That was the last reference, and this was a dlopen-loaded
object. We can unmap it. */
@@ -482,39 +463,13 @@ _dl_close (void *_map)
if (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)
- + (imap->l_reldepsact
- * sizeof (bool)));
- newrel->rellist = imap->l_reldeps;
- newrel->nrellist = imap->l_reldepsact;
- newrel->next = reldeps;
-
- newrel->nhandled = imap->l_reldepsact;
- unsigned int j;
- for (j = 0; j < imap->l_reldepsact; ++j)
- {
- /* Find out whether this object is in our list. */
- if (imap->l_reldeps[j]->l_idx < nopencount
- && list[imap->l_reldeps[j]->l_idx] == imap->l_reldeps[j])
- /* Yes, it is. */
- newrel->handled[j] = true;
- else
- newrel->handled[j] = false;
- }
-
- reldeps = newrel;
- }
+ free (imap->l_reldeps);
/* This name always is allocated. */
free (imap->l_name);
/* Remove the list with all the names of the shared object. */
- lnp = imap->l_libname;
+
+ struct libname_list *lnp = imap->l_libname;
do
{
struct libname_list *this = lnp;
@@ -525,8 +480,7 @@ _dl_close (void *_map)
while (lnp != NULL);
/* Remove the searchlists. */
- if (imap != map)
- free (imap->l_initfini);
+ free (imap->l_initfini);
/* Remove the scope array if we allocated it. */
if (imap->l_scope != imap->l_scope_mem)
@@ -560,26 +514,8 @@ _dl_close (void *_map)
_r_debug.r_state = RT_CONSISTENT;
GLRO(dl_debug_state) ();
- /* Now we can perhaps also remove the modules for which we had
- dependencies because of symbol lookup. */
- while (__builtin_expect (reldeps != NULL, 0))
- {
- while (reldeps->nrellist-- > 0)
- /* Some of the relocation dependencies might be on the
- dependency list of the object we are closing right now.
- They were already handled. Do not close them again. */
- if (reldeps->nrellist < reldeps->nhandled
- && ! reldeps->handled[reldeps->nrellist])
- _dl_close (reldeps->rellist[reldeps->nrellist]);
-
- free (reldeps->rellist);
-
- reldeps = reldeps->next;
- }
-
- free (list);
-
/* Release the lock. */
+ out:
__rtld_lock_unlock_recursive (GL(dl_load_lock));
}
libc_hidden_def (_dl_close)
@@ -657,3 +593,7 @@ libc_freeres_fn (free_mem)
}
#endif
}
+
+#ifdef SHARED
+#include "dl-fini.c"
+#endif
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index a1c16d7310..acc8fc3a07 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -566,8 +566,6 @@ Filters not supported with LD_TRACE_PRELINKING"));
{
/* A direct or transitive dependency is also on the list
of relocation dependencies. Remove the latter. */
- --map->l_reldeps[i]->l_opencount;
-
for (j = i + 1; j < map->l_reldepsact; ++j)
map->l_reldeps[j - 1] = map->l_reldeps[j];
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index f43f4a00ed..0964396828 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -23,10 +23,97 @@
#include <ldsodefs.h>
+void
+internal_function
+_dl_sort_fini (struct link_map *l, struct link_map **maps, size_t nmaps,
+ char *used, Lmid_t ns)
+{
+ if (ns == LM_ID_BASE)
+ /* The main executable always comes first. */
+ l = l->l_next;
+
+ for (; l != NULL; l = l->l_next)
+ /* Do not handle ld.so in secondary namespaces and object which
+ are not removed. */
+ if (l == l->l_real && l->l_idx != -1)
+ {
+ /* Find the place in the 'maps' array. */
+ unsigned int j;
+ for (j = ns == LM_ID_BASE ? 1 : 0; maps[j] != l; ++j)
+ assert (j < nmaps);
+
+ /* Find all object for which the current one is a dependency
+ and move the found object (if necessary) in front. */
+ for (unsigned int k = j + 1; k < nmaps; ++k)
+ {
+ struct link_map **runp = maps[k]->l_initfini;
+ if (runp != NULL)
+ {
+ while (*runp != NULL)
+ if (*runp == l)
+ {
+ struct link_map *here = maps[k];
+
+ /* Move it now. */
+ memmove (&maps[j] + 1,
+ &maps[j], (k - j) * sizeof (struct link_map *));
+ maps[j] = here;
+
+ if (used != NULL)
+ {
+ char here_used = used[k];
+
+ memmove (&used[j] + 1,
+ &used[j], (k - j) * sizeof (char));
+ used[j] = here_used;
+ }
+
+ ++j;
+
+ break;
+ }
+ else
+ ++runp;
+ }
+
+ if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
+ {
+ unsigned int m = maps[k]->l_reldepsact;
+ struct link_map **relmaps = maps[k]->l_reldeps;
+
+ while (m-- > 0)
+ {
+ if (relmaps[m] == l)
+ {
+ struct link_map *here = maps[k];
+
+ /* Move it now. */
+ memmove (&maps[j] + 1,
+ &maps[j],
+ (k - j) * sizeof (struct link_map *));
+ maps[j] = here;
+
+ if (used != NULL)
+ {
+ char here_used = used[k];
+
+ memmove (&used[j] + 1,
+ &used[j], (k - j) * sizeof (char));
+ used[j] = here_used;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+#if !defined SHARED || defined IS_IN_rtld
/* Type of the constructor functions. */
typedef void (*fini_t) (void);
-
void
internal_function
_dl_fini (void)
@@ -48,16 +135,16 @@ _dl_fini (void)
/* We run the destructors of the main namespaces last. As for the
other namespaces, we pick run the destructors in them in reverse
order of the namespace ID. */
- for (Lmid_t cnt = DL_NNS - 1; cnt >= 0; --cnt)
+ for (Lmid_t ns = DL_NNS - 1; ns >= 0; --ns)
{
/* Protect against concurrent loads and unloads. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
- unsigned int nloaded = GL(dl_ns)[cnt]._ns_nloaded;
+ unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
/* XXX Could it be (in static binaries) that there is no object
loaded? */
- assert (cnt != LM_ID_BASE || nloaded > 0);
+ assert (ns != LM_ID_BASE || nloaded > 0);
/* Now we can allocate an array to hold all the pointers and copy
the pointers in. */
@@ -76,86 +163,27 @@ _dl_fini (void)
unsigned int i;
struct link_map *l;
- for (l = GL(dl_ns)[cnt]._ns_loaded, i = 0; l != NULL; l = l->l_next)
+ for (l = GL(dl_ns)[ns]._ns_loaded, i = 0; l != NULL; l = l->l_next)
/* Do not handle ld.so in secondary namespaces. */
if (l == l->l_real)
{
assert (i < nloaded);
- maps[i++] = l;
+ maps[i] = l;
+ l->l_idx = i;
+ ++i;
- /* Bump l_opencount of all objects so that they are not
- dlclose()ed from underneath us. */
- ++l->l_opencount;
+ /* Bump l_direct_opencount of all objects so that they are
+ not dlclose()ed from underneath us. */
+ ++l->l_direct_opencount;
}
- assert (cnt != LM_ID_BASE || i == nloaded);
- assert (cnt == LM_ID_BASE || i == nloaded || i == nloaded - 1);
+ assert (ns != LM_ID_BASE || i == nloaded);
+ assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1);
unsigned int nmaps = i;
if (nmaps != 0)
- {
- /* Now we have to do the sorting. */
- l = GL(dl_ns)[cnt]._ns_loaded;
- if (cnt == LM_ID_BASE)
- /* The main executable always comes first. */
- l = l->l_next;
- for (; l != NULL; l = l->l_next)
- /* Do not handle ld.so in secondary namespaces. */
- if (l == l->l_real)
- {
- /* Find the place in the 'maps' array. */
- unsigned int j;
- for (j = cnt == LM_ID_BASE ? 1 : 0; maps[j] != l; ++j)
- assert (j < nmaps);
-
- /* Find all object for which the current one is a dependency
- and move the found object (if necessary) in front. */
- for (unsigned int k = j + 1; k < nmaps; ++k)
- {
- struct link_map **runp = maps[k]->l_initfini;
- if (runp != NULL)
- {
- while (*runp != NULL)
- if (*runp == l)
- {
- struct link_map *here = maps[k];
-
- /* Move it now. */
- memmove (&maps[j] + 1,
- &maps[j],
- (k - j) * sizeof (struct link_map *));
- maps[j++] = here;
-
- break;
- }
- else
- ++runp;
- }
-
- if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
- {
- unsigned int m = maps[k]->l_reldepsact;
- struct link_map **relmaps = maps[k]->l_reldeps;
-
- while (m-- > 0)
- {
- if (relmaps[m] == l)
- {
- struct link_map *here = maps[k];
-
- /* Move it now. */
- memmove (&maps[j] + 1,
- &maps[j],
- (k - j) * sizeof (struct link_map *));
- maps[j] = here;
-
- break;
- }
- }
- }
- }
- }
- }
+ /* Now we have to do the sorting. */
+ _dl_sort_fini (GL(dl_ns)[ns]._ns_loaded, maps, nmaps, NULL, ns);
/* We do not rely on the linked list of loaded object anymore from
this point on. We have our own list here (maps). The various
@@ -191,7 +219,7 @@ _dl_fini (void)
0))
_dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
l->l_name[0] ? l->l_name : rtld_progname,
- cnt);
+ ns);
/* First see whether an array is given. */
if (l->l_info[DT_FINI_ARRAY] != NULL)
@@ -211,14 +239,17 @@ _dl_fini (void)
}
/* Correct the previous increment. */
- --l->l_opencount;
+ --l->l_direct_opencount;
}
}
+#ifdef SHARED
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS, 0))
_dl_debug_printf ("\nruntime linker statistics:\n"
" final number of relocations: %lu\n"
"final number of relocations from cache: %lu\n",
GL(dl_num_relocations),
GL(dl_num_cache_relocations));
+#endif
}
+#endif
diff --git a/elf/dl-load.c b/elf/dl-load.c
index ab1080e51f..0daceb2184 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -839,7 +839,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
/* Look again to see if the real name matched another already loaded. */
for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
- if (l->l_ino == st.st_ino && l->l_dev == st.st_dev)
+ if (l->l_removed == 0 && l->l_ino == st.st_ino && l->l_dev == st.st_dev)
{
/* The object is already loaded.
Just bump its reference count and return it. */
@@ -1824,7 +1824,8 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
/* If the requested name matches the soname of a loaded object,
use that object. Elide this check for names that have not
yet been opened. */
- if (__builtin_expect (l->l_faked, 0) != 0)
+ if (__builtin_expect (l->l_faked, 0) != 0
+ || __builtin_expect (l->l_removed, 0) != 0)
continue;
if (!_dl_name_match_p (name, l))
{
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index fdb076951d..cdf2ef8ea6 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -91,11 +91,6 @@ add_dependency (struct link_map *undef_map, struct link_map *map)
/* Make sure nobody can unload the object while we are at it. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
- /* Don't create cross-reference between modules which are
- dynamically loaded by the same dlopen() call. */
- if (undef_map->l_opencount == 0 && map->l_opencount == 0)
- goto out;
-
/* Avoid references to objects which cannot be unloaded anyway. */
if (map->l_type != lt_loaded
|| (map->l_flags_1 & DF_1_NODELETE) != 0)
@@ -107,14 +102,13 @@ add_dependency (struct link_map *undef_map, struct link_map *map)
if (undef_map->l_type != lt_loaded
|| (undef_map->l_flags_1 & DF_1_NODELETE) != 0)
{
- ++map->l_opencount;
map->l_flags_1 |= DF_1_NODELETE;
goto out;
}
/* Determine whether UNDEF_MAP already has a reference to MAP. First
look in the normal dependencies. */
- if (undef_map->l_searchlist.r_list != NULL)
+ if (undef_map->l_initfini != NULL)
{
list = undef_map->l_initfini;
@@ -172,19 +166,6 @@ add_dependency (struct link_map *undef_map, struct link_map *map)
if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
- if (map->l_searchlist.r_list != NULL)
- /* And increment the counter in the referenced object. */
- ++map->l_opencount;
- else
- /* We have to bump the counts for all dependencies since so far
- this object was only a normal or transitive dependency.
- Now it might be closed with _dl_close() directly. */
- for (list = map->l_initfini; *list != NULL; ++list)
- ++(*list)->l_opencount;
-
- /* As if it is opened through _dl_open. */
- ++map->l_direct_opencount;
-
/* Display information if we are debugging. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
_dl_debug_printf ("\
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 7e890ad7f7..8cc3ad0964 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -279,23 +279,14 @@ dl_open_worker (void *a)
{
/* Let the user know about the opencount. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
- GLRO(dl_debug_printf) ("opening file=%s [%lu]; opencount=%u\n\n",
- new->l_name, new->l_ns, new->l_opencount);
+ GLRO(dl_debug_printf) ("opening file=%s [%lu]; direct_opencount=%u\n\n",
+ new->l_name, new->l_ns, new->l_direct_opencount);
/* If the user requested the object to be in the global namespace
but it is not so far, add it now. */
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
(void) add_to_global (new);
- if (new->l_direct_opencount == 1)
- /* This is the only direct reference. Increment all the
- dependencies' reference counter. */
- for (i = 0; i < new->l_searchlist.r_nlist; ++i)
- ++new->l_searchlist.r_list[i]->l_opencount;
- else
- /* Increment just the reference counter of the object. */
- ++new->l_opencount;
-
return;
}
@@ -373,136 +364,136 @@ dl_open_worker (void *a)
any_tls = false;
#endif
- /* 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. */
+ /* If the file is not loaded now as a dependency, add the search
+ list of the newly loaded object to the scope. */
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
- if (++new->l_searchlist.r_list[i]->l_opencount > 1
- && new->l_real->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)
- {
- /* This can happen if imap was just loaded, but during
- relocation had l_opencount bumped because of relocation
- dependency. Avoid duplicates in l_scope. */
- if (__builtin_expect (*runp == &new->l_searchlist, 0))
- break;
-
- ++cnt;
- ++runp;
- }
-
- if (*runp != NULL)
- /* Avoid duplicates. */
- continue;
-
- 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)
- GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL,
- N_("cannot create scope list"));
- imap->l_scope = memcpy (newp, imap->l_scope,
- cnt * sizeof (imap->l_scope[0]));
- }
- else
- {
- newp = (struct r_scope_elem **)
- realloc (imap->l_scope,
- new_size * sizeof (struct r_scope_elem *));
- if (newp == NULL)
- GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL,
- N_("cannot create scope list"));
- imap->l_scope = newp;
- }
-
- imap->l_scope_max = new_size;
- }
-
- imap->l_scope[cnt++] = &new->l_searchlist;
- imap->l_scope[cnt] = NULL;
- }
+ {
+ struct link_map *imap = new->l_searchlist.r_list[i];
+
+ /* If the initializer has been called already, the object has
+ not been loaded here and now. */
+ if (imap->l_init_called && imap->l_type == lt_loaded)
+ {
+ struct r_scope_elem **runp = imap->l_scope;
+ size_t cnt = 0;
+
+ while (*runp != NULL)
+ {
+ ++cnt;
+ ++runp;
+ }
+
+ if (*runp != NULL)
+ /* Avoid duplicates. */
+ continue;
+
+ 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)
+ GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL,
+ N_("cannot create scope list"));
+ imap->l_scope = memcpy (newp, imap->l_scope,
+ cnt * sizeof (imap->l_scope[0]));
+ }
+ else
+ {
+ newp = (struct r_scope_elem **)
+ realloc (imap->l_scope,
+ new_size * sizeof (struct r_scope_elem *));
+ if (newp == NULL)
+ GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL,
+ N_("cannot create scope list"));
+ imap->l_scope = newp;
+ }
+
+ imap->l_scope_max = new_size;
+ }
+
+ imap->l_scope[cnt++] = &new->l_searchlist;
+ imap->l_scope[cnt] = NULL;
+ }
#if USE_TLS
- else if (new->l_searchlist.r_list[i]->l_opencount == 1
- /* Only if the module defines thread local data. */
- && __builtin_expect (new->l_searchlist.r_list[i]->l_tls_blocksize
- > 0, 0))
- {
- /* Now that we know the object is loaded successfully add
- modules containing TLS data to the dtv info table. We
- might have to increase its size. */
- struct dtv_slotinfo_list *listp;
- struct dtv_slotinfo_list *prevp;
- size_t idx = new->l_searchlist.r_list[i]->l_tls_modid;
-
- assert (new->l_searchlist.r_list[i]->l_type == lt_loaded);
-
- /* Find the place in the dtv slotinfo list. */
- listp = GL(dl_tls_dtv_slotinfo_list);
- prevp = NULL; /* Needed to shut up gcc. */
- do
- {
- /* Does it fit in the array of this list element? */
- if (idx < listp->len)
- break;
- idx -= listp->len;
- prevp = listp;
- listp = listp->next;
- }
- while (listp != NULL);
-
- if (listp == NULL)
- {
- /* When we come here it means we have to add a new element
- to the slotinfo list. And the new module must be in
- the first slot. */
- assert (idx == 0);
-
- listp = prevp->next = (struct dtv_slotinfo_list *)
- malloc (sizeof (struct dtv_slotinfo_list)
- + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
- if (listp == NULL)
- {
- /* We ran out of memory. We will simply fail this
- call but don't undo anything we did so far. The
- application will crash or be terminated anyway very
- soon. */
-
- /* We have to do this since some entries in the dtv
- slotinfo array might already point to this
- generation. */
- ++GL(dl_tls_generation);
-
- GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL, N_("\
-cannot create TLS data structures"));
- }
-
- listp->len = TLS_SLOTINFO_SURPLUS;
- listp->next = NULL;
- memset (listp->slotinfo, '\0',
- TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
- }
-
- /* Add the information into the slotinfo data structure. */
- listp->slotinfo[idx].map = new->l_searchlist.r_list[i];
- listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
-
- /* We have to bump the generation counter. */
- any_tls = true;
- }
+ /* Only add TLS memory if this object is loaded now and
+ therefore is not yet initialized. */
+ else if (! imap->l_init_called
+ /* Only if the module defines thread local data. */
+ && __builtin_expect (imap->l_tls_blocksize > 0, 0))
+ {
+ /* Now that we know the object is loaded successfully add
+ modules containing TLS data to the dtv info table. We
+ might have to increase its size. */
+ struct dtv_slotinfo_list *listp;
+ struct dtv_slotinfo_list *prevp;
+ size_t idx = imap->l_tls_modid;
+
+ assert (imap->l_type == lt_loaded);
+
+ /* Find the place in the dtv slotinfo list. */
+ listp = GL(dl_tls_dtv_slotinfo_list);
+ prevp = NULL; /* Needed to shut up gcc. */
+ do
+ {
+ /* Does it fit in the array of this list element? */
+ if (idx < listp->len)
+ break;
+ idx -= listp->len;
+ prevp = listp;
+ listp = listp->next;
+ }
+ while (listp != NULL);
+
+ if (listp == NULL)
+ {
+ /* When we come here it means we have to add a new element
+ to the slotinfo list. And the new module must be in
+ the first slot. */
+ assert (idx == 0);
+
+ listp = prevp->next = (struct dtv_slotinfo_list *)
+ malloc (sizeof (struct dtv_slotinfo_list)
+ + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
+ if (listp == NULL)
+ {
+ /* We ran out of memory. We will simply fail this
+ call but don't undo anything we did so far. The
+ application will crash or be terminated anyway very
+ soon. */
+
+ /* We have to do this since some entries in the dtv
+ slotinfo array might already point to this
+ generation. */
+ ++GL(dl_tls_generation);
+
+ GLRO(dl_signal_error) (ENOMEM, "dlopen", NULL, N_("\
+ cannot create TLS data structures"));
+ }
+ listp->len = TLS_SLOTINFO_SURPLUS;
+ listp->next = NULL;
+ memset (listp->slotinfo, '\0',
+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
+ }
+
+ /* Add the information into the slotinfo data structure. */
+ listp->slotinfo[idx].map = imap;
+ listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
+
+ /* We have to bump the generation counter. */
+ any_tls = true;
+ }
+#endif
+ }
+
+#if USE_TLS
/* Bump the generation number if necessary. */
if (any_tls)
if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
@@ -532,8 +523,8 @@ cannot create TLS data structures"));
/* Let the user know about the opencount. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
- GLRO(dl_debug_printf) ("opening file=%s [%lu]; opencount=%u\n\n",
- new->l_name, new->l_ns, new->l_opencount);
+ GLRO(dl_debug_printf) ("opening file=%s [%lu]; direct_opencount=%u\n\n",
+ new->l_name, new->l_ns, new->l_direct_opencount);
}
@@ -603,14 +594,6 @@ no more namespaces available for dlmopen()"));
state if relocation failed, for example. */
if (args.map)
{
- unsigned int i;
-
- /* Increment open counters for all objects since this
- sometimes has not happened yet. */
- if (args.map->l_searchlist.r_list[0]->l_opencount == 0)
- for (i = 0; i < args.map->l_searchlist.r_nlist; ++i)
- ++args.map->l_searchlist.r_list[i]->l_opencount;
-
#ifdef USE_TLS
/* Maybe some of the modules which were loaded uses TLS.
Since it will be removed in the following _dl_close call
diff --git a/elf/do-lookup.h b/elf/do-lookup.h
index e57d9df26d..88de3fe26f 100644
--- a/elf/do-lookup.h
+++ b/elf/do-lookup.h
@@ -52,6 +52,10 @@ do_lookup_x (const char *undef_name, unsigned long int hash,
if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
continue;
+ /* Do not look into objects which are going to be removed. */
+ if (map->l_removed)
+ continue;
+
/* Print some debugging info if wanted. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_SYMBOLS, 0))
_dl_debug_printf ("symbol=%s; lookup in file=%s\n",
diff --git a/elf/loadtest.c b/elf/loadtest.c
index 6b8f4bb7d0..ee106ea152 100644
--- a/elf/loadtest.c
+++ b/elf/loadtest.c
@@ -73,8 +73,8 @@ static const struct
#define OUT \
for (map = _r_debug.r_map; map != NULL; map = map->l_next) \
if (map->l_type == lt_loaded) \
- printf ("name = \"%s\", opencount = %d\n", \
- map->l_name, (int) map->l_opencount); \
+ printf ("name = \"%s\", direct_opencount = %d\n", \
+ map->l_name, (int) map->l_direct_opencount); \
fflush (stdout)
@@ -183,8 +183,8 @@ main (int argc, char *argv[])
for (map = _r_debug.r_map; map != NULL; map = map->l_next)
if (map->l_type == lt_loaded)
{
- printf ("name = \"%s\", opencount = %d\n",
- map->l_name, (int) map->l_opencount);
+ printf ("name = \"%s\", direct_opencount = %d\n",
+ map->l_name, (int) map->l_direct_opencount);
result = 1;
}
diff --git a/elf/neededtest.c b/elf/neededtest.c
index e6e99bfc6d..6c7a952066 100644
--- a/elf/neededtest.c
+++ b/elf/neededtest.c
@@ -27,7 +27,7 @@ check_loaded_objects (const char **loaded)
for (lm = _r_debug.r_map; lm; lm = lm->l_next)
{
if (lm->l_name && lm->l_name[0])
- printf(" %s, count = %d\n", lm->l_name, (int) lm->l_opencount);
+ printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
if (lm->l_type == lt_loaded && lm->l_name)
{
int match = 0;
diff --git a/elf/neededtest2.c b/elf/neededtest2.c
index cf111bc303..b682f15792 100644
--- a/elf/neededtest2.c
+++ b/elf/neededtest2.c
@@ -27,7 +27,7 @@ check_loaded_objects (const char **loaded)
for (lm = _r_debug.r_map; lm; lm = lm->l_next)
{
if (lm->l_name && lm->l_name[0])
- printf(" %s, count = %d\n", lm->l_name, (int) lm->l_opencount);
+ printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
if (lm->l_type == lt_loaded && lm->l_name)
{
int match = 0;
diff --git a/elf/neededtest3.c b/elf/neededtest3.c
index 38b3c6c6b7..ea1dcf4794 100644
--- a/elf/neededtest3.c
+++ b/elf/neededtest3.c
@@ -27,7 +27,7 @@ check_loaded_objects (const char **loaded)
for (lm = _r_debug.r_map; lm; lm = lm->l_next)
{
if (lm->l_name && lm->l_name[0])
- printf(" %s, count = %d\n", lm->l_name, (int) lm->l_opencount);
+ printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
if (lm->l_type == lt_loaded && lm->l_name)
{
int match = 0;
diff --git a/elf/neededtest4.c b/elf/neededtest4.c
index 04ab10e4c9..7514bed499 100644
--- a/elf/neededtest4.c
+++ b/elf/neededtest4.c
@@ -27,7 +27,7 @@ check_loaded_objects (const char **loaded)
for (lm = _r_debug.r_map; lm; lm = lm->l_next)
{
if (lm->l_name && lm->l_name[0])
- printf(" %s, count = %d\n", lm->l_name, (int) lm->l_opencount);
+ printf(" %s, count = %d\n", lm->l_name, (int) lm->l_direct_opencount);
if (lm->l_type == lt_loaded && lm->l_name)
{
int match = 0;
diff --git a/elf/order2.c b/elf/order2.c
new file mode 100644
index 0000000000..3dbfdd153e
--- /dev/null
+++ b/elf/order2.c
@@ -0,0 +1,46 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+
+int call_puts;
+
+static int
+do_test (void)
+{
+ call_puts = 1;
+
+ void *h1 = dlopen ("$ORIGIN/order2mod1.so", RTLD_LAZY | RTLD_GLOBAL);
+ if (h1 == NULL)
+ {
+ puts ("cannot load order2mod1");
+ return 1;
+ }
+ void *h2 = dlopen ("$ORIGIN/order2mod2.so", RTLD_LAZY);
+ if (h2 == NULL)
+ {
+ puts ("cannot load order2mod2");
+ return 1;
+ }
+ if (dlclose (h1) != 0)
+ {
+ puts ("dlclose order2mod1 failed");
+ return 1;
+ }
+ if (dlclose (h2) != 0)
+ {
+ puts ("dlclose order2mod2 failed");
+ return 1;
+ }
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+ if (call_puts)
+ puts ("5");
+}
diff --git a/elf/order2mod1.c b/elf/order2mod1.c
new file mode 100644
index 0000000000..b695db29b7
--- /dev/null
+++ b/elf/order2mod1.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+ putchar ('1');
+}
diff --git a/elf/order2mod2.c b/elf/order2mod2.c
new file mode 100644
index 0000000000..b03fb60fa3
--- /dev/null
+++ b/elf/order2mod2.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+extern int foo (void);
+extern int bar (void);
+
+void
+__attribute__ ((constructor))
+init (void)
+{
+ foo () - bar ();
+}
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+ putchar ('2');
+}
diff --git a/elf/order2mod3.c b/elf/order2mod3.c
new file mode 100644
index 0000000000..7913a79925
--- /dev/null
+++ b/elf/order2mod3.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+int
+bar (void)
+{
+ return 1;
+}
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+ putchar ('4');
+}
diff --git a/elf/order2mod4.c b/elf/order2mod4.c
new file mode 100644
index 0000000000..4f2026f041
--- /dev/null
+++ b/elf/order2mod4.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+extern int bar (void);
+
+int
+foo (void)
+{
+ return 42 + bar ();
+}
+
+static void
+__attribute__ ((destructor))
+fini (void)
+{
+ putchar ('3');
+}
diff --git a/elf/rtld.c b/elf/rtld.c
index 55a2b8a9ea..b85fcaa002 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -270,7 +270,6 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
#endif
_dl_setup_hash (&GL(dl_rtld_map));
GL(dl_rtld_map).l_real = &GL(dl_rtld_map);
- GL(dl_rtld_map).l_opencount = 1;
GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin;
GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end;
GL(dl_rtld_map).l_text_end = (ElfW(Addr)) _etext;
@@ -659,14 +658,48 @@ _dl_initial_error_catch_tsd (void)
}
#endif
+
+static unsigned int
+do_preload (char *fname, struct link_map *main_map, const char *where)
+{
+ const char *objname;
+ const char *err_str = NULL;
+ struct map_args args;
+
+ args.str = fname;
+ args.loader = main_map;
+ args.is_preloaded = 1;
+ args.mode = 0;
+
+ unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
+
+ (void) _dl_catch_error (&objname, &err_str, map_doit, &args);
+ if (__builtin_expect (err_str != NULL, 0))
+ {
+ _dl_error_printf ("\
+ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
+ fname, where);
+ /* No need to call free, this is still before
+ the libc's malloc is used. */
+ }
+ else if (GL(dl_ns)[LM_ID_BASE]._ns_nloaded != old_nloaded)
+ /* It is no duplicate. */
+ return 1;
+
+ /* Nothing loaded. */
+ return 0;
+}
+
#if defined SHARED && defined _LIBC_REENTRANT \
&& defined __rtld_lock_default_lock_recursive
-static void rtld_lock_default_lock_recursive (void *lock)
+static void
+rtld_lock_default_lock_recursive (void *lock)
{
__rtld_lock_default_lock_recursive (lock);
}
-static void rtld_lock_default_unlock_recursive (void *lock)
+static void
+rtld_lock_default_unlock_recursive (void *lock)
{
__rtld_lock_default_unlock_recursive (lock);
}
@@ -687,8 +720,6 @@ dl_main (const ElfW(Phdr) *phdr,
{
const ElfW(Phdr) *ph;
enum mode mode;
- struct link_map **preloads;
- unsigned int npreloads;
struct link_map *main_map;
size_t file_size;
char *file;
@@ -918,8 +949,6 @@ of this helper program; chances are you did not intend to run this program.\n\
main_map->l_text_end = 0;
/* Perhaps the executable has no PT_LOAD header entries at all. */
main_map->l_map_start = ~0;
- /* We opened the file, account for it. */
- ++main_map->l_opencount;
/* And it was opened directly. */
++main_map->l_direct_opencount;
@@ -1161,8 +1190,9 @@ of this helper program; chances are you did not intend to run this program.\n\
/* We have two ways to specify objects to preload: via environment
variable and via the file /etc/ld.so.preload. The latter can also
be used when security is enabled. */
- preloads = NULL;
- npreloads = 0;
+ assert (GL(dl_rtld_map).l_next == NULL);
+ struct link_map **preloads = NULL;
+ unsigned int npreloads = 0;
if (__builtin_expect (preloadlist != NULL, 0))
{
@@ -1181,14 +1211,7 @@ of this helper program; chances are you did not intend to run this program.\n\
if (p[0] != '\0'
&& (__builtin_expect (! INTUSE(__libc_enable_secure), 1)
|| strchr (p, '/') == NULL))
- {
- struct link_map *new_map = _dl_map_object (main_map, p, 1,
- lt_library, 0, 0,
- LM_ID_BASE);
- if (++new_map->l_opencount == 1)
- /* It is no duplicate. */
- ++npreloads;
- }
+ npreloads += do_preload (p, main_map, "LD_PRELOAD");
HP_TIMING_NOW (stop);
HP_TIMING_DIFF (diff, start, stop);
@@ -1260,41 +1283,14 @@ of this helper program; chances are you did not intend to run this program.\n\
runp = file;
while ((p = strsep (&runp, ": \t\n")) != NULL)
if (p[0] != '\0')
- {
- const char *objname;
- const char *err_str = NULL;
- struct map_args args;
-
- args.str = p;
- args.loader = main_map;
- args.is_preloaded = 1;
- args.mode = 0;
-
- (void) _dl_catch_error (&objname, &err_str, map_doit,
- &args);
- if (__builtin_expect (err_str != NULL, 0))
- {
- _dl_error_printf ("\
-ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
- p, preload_file);
- /* No need to call free, this is still before
- the libc's malloc is used. */
- }
- else if (++args.map->l_opencount == 1)
- /* It is no duplicate. */
- ++npreloads;
- }
+ npreloads += do_preload (p, main_map, preload_file);
}
if (problem != NULL)
{
char *p = strndupa (problem, file_size - (problem - file));
- struct link_map *new_map = _dl_map_object (main_map, p, 1,
- lt_library, 0, 0,
- LM_ID_BASE);
- if (++new_map->l_opencount == 1)
- /* It is no duplicate. */
- ++npreloads;
+
+ npreloads += do_preload (p, main_map, preload_file);
}
HP_TIMING_NOW (stop);
@@ -1348,18 +1344,9 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
if (test_fd >= 0) /* open did no fail.. */
__close(test_fd); /* avoid fd leaks */
- if (can_load != 0) {
- struct link_map *new_map;
- new_map = _dl_map_object (main_map, LIB_NOVERSION,
- 1, lt_library, 0, 0, LM_ID_BASE);
- if (++new_map->l_opencount == 1) {
- /* It is no duplicate. */
- ++npreloads;
-/* _dl_sysdep_message(" DONE\n", NULL); */
- } else {
-/* _dl_sysdep_message(" FAILED\n", NULL); */
- }
- }
+ if (can_load != 0)
+ npreloads += do_preload (LIB_NOVERSION, main_map,
+ "nonversioned binary");
HP_TIMING_NOW (stop);
HP_TIMING_DIFF (diff, start, stop);
@@ -1367,7 +1354,7 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
}
#endif
- if (__builtin_expect (npreloads, 0) != 0)
+ if (__builtin_expect (GL(dl_rtld_map).l_next != NULL, 0))
{
/* Set up PRELOADS with a vector of the preloaded libraries. */
struct link_map *l;
@@ -1464,14 +1451,9 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
HP_TIMING_DIFF (diff, start, stop);
HP_TIMING_ACCUM_NT (load_time, diff);
- /* Mark all objects as being in the global scope and set the open
- counter. */
+ /* Mark all objects as being in the global scope. */
for (i = main_map->l_searchlist.r_nlist; i > 0; )
- {
- --i;
- main_map->l_searchlist.r_list[i]->l_global = 1;
- ++main_map->l_searchlist.r_list[i]->l_opencount;
- }
+ main_map->l_searchlist.r_list[--i]->l_global = 1;
#ifndef MAP_ANON
/* We are done mapping things, so close the zero-fill descriptor. */
@@ -1481,18 +1463,22 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
/* Remove _dl_rtld_map from the chain. */
GL(dl_rtld_map).l_prev->l_next = GL(dl_rtld_map).l_next;
- if (GL(dl_rtld_map).l_next)
+ if (GL(dl_rtld_map).l_next != NULL)
GL(dl_rtld_map).l_next->l_prev = GL(dl_rtld_map).l_prev;
- if (__builtin_expect (GL(dl_rtld_map).l_opencount > 1, 1))
+ for (i = 1; i < main_map->l_searchlist.r_nlist; ++i)
+ if (main_map->l_searchlist.r_list[i] == &GL(dl_rtld_map))
+ break;
+
+ bool rtld_multiple_ref = false;
+ if (__builtin_expect (i < main_map->l_searchlist.r_nlist, 1))
{
/* Some DT_NEEDED entry referred to the interpreter object itself, so
put it back in the list of visible objects. We insert it into the
chain in symbol search order because gdb uses the chain's order as
its symbol search order. */
- i = 1;
- while (main_map->l_searchlist.r_list[i] != &GL(dl_rtld_map))
- ++i;
+ rtld_multiple_ref = true;
+
GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1];
if (__builtin_expect (mode, normal) == normal)
{
@@ -1726,7 +1712,7 @@ cannot allocate TLS data structures for initial thread");
}
else
{
- /* If LD_WARN is set warn about undefined symbols. */
+ /* If LD_WARN is set, warn about undefined symbols. */
if (GLRO(dl_lazy) >= 0 && GLRO(dl_verbose))
{
/* We have to do symbol dependency testing. */
@@ -1736,7 +1722,7 @@ cannot allocate TLS data structures for initial thread");
args.lazy = GLRO(dl_lazy);
l = main_map;
- while (l->l_next)
+ while (l->l_next != NULL)
l = l->l_next;
do
{
@@ -1747,10 +1733,11 @@ cannot allocate TLS data structures for initial thread");
&args);
}
l = l->l_prev;
- } while (l);
+ }
+ while (l != NULL);
if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
- && GL(dl_rtld_map).l_opencount > 1)
+ && rtld_multiple_ref)
_dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope,
0, 0);
}
@@ -2020,7 +2007,7 @@ cannot allocate TLS data structures for initial thread");
/* We must prepare the profiling. */
_dl_start_profile ();
- if (GL(dl_rtld_map).l_opencount > 1)
+ if (rtld_multiple_ref)
{
/* There was an explicit ref to the dynamic linker as a shared lib.
Re-relocate ourselves with user-controlled symbol definitions. */
diff --git a/elf/testobj2.c b/elf/testobj2.c
index f00ba9f3e6..7e4b610982 100644
--- a/elf/testobj2.c
+++ b/elf/testobj2.c
@@ -1,5 +1,6 @@
#include <dlfcn.h>
#include <stdlib.h>
+#include <stdio.h>
#include "testobj.h"
diff --git a/elf/unload.c b/elf/unload.c
index 4fd82b7e3a..ffb33482c0 100644
--- a/elf/unload.c
+++ b/elf/unload.c
@@ -12,8 +12,8 @@
#define OUT \
for (map = _r_debug.r_map; map != NULL; map = map->l_next) \
if (map->l_type == lt_loaded) \
- printf ("name = \"%s\", opencount = %d\n", \
- map->l_name, (int) map->l_opencount); \
+ printf ("name = \"%s\", direct_opencount = %d\n", \
+ map->l_name, (int) map->l_direct_opencount); \
fflush (stdout)
typedef struct
diff --git a/elf/unload2.c b/elf/unload2.c
index 7a38053433..e14c6f06af 100644
--- a/elf/unload2.c
+++ b/elf/unload2.c
@@ -9,8 +9,8 @@
#define OUT \
for (map = _r_debug.r_map; map != NULL; map = map->l_next) \
if (map->l_type == lt_loaded) \
- printf ("name = \"%s\", opencount = %d\n", \
- map->l_name, (int) map->l_opencount); \
+ printf ("name = \"%s\", direct_opencount = %d\n", \
+ map->l_name, (int) map->l_direct_opencount); \
fflush (stdout)
int
diff --git a/elf/unload3mod4.c b/elf/unload3mod4.c
index 4586ff7383..52f808e79b 100644
--- a/elf/unload3mod4.c
+++ b/elf/unload3mod4.c
@@ -1,5 +1,7 @@
#include <stdio.h>
+extern int foo (int x);
+
int
bar (int x)
{
diff --git a/elf/unload4.c b/elf/unload4.c
new file mode 100644
index 0000000000..6e171a22e0
--- /dev/null
+++ b/elf/unload4.c
@@ -0,0 +1,48 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <malloc.h>
+
+int
+main (void)
+{
+#ifdef M_PERTURB
+ mallopt (M_PERTURB, 0xaa);
+#endif
+
+ void *h;
+ int (*fn) (int);
+ h = dlopen ("unload4mod1.so", RTLD_LAZY);
+ if (h == NULL)
+ {
+ puts ("1st dlopen failed");
+ return 1;
+ }
+ fn = dlsym (h, "foo");
+ if (fn == NULL)
+ {
+ puts ("dlsym failed");
+ return 1;
+ }
+ int n = fn (10);
+ if (n != 28)
+ {
+ printf ("foo (10) returned %d != 28\n", n);
+ return 1;
+ }
+ dlclose (h);
+ h = dlopen ("unload4mod3.so", RTLD_LAZY);
+ fn = dlsym (h, "mod3fn2");
+ if (fn == NULL)
+ {
+ puts ("second dlsym failed");
+ return 1;
+ }
+ n = fn (10);
+ if (n != 22)
+ {
+ printf ("mod3fn2 (10) returned %d != 22\n", n);
+ return 1;
+ }
+ dlclose (h);
+ return 0;
+}
diff --git a/elf/unload4mod1.c b/elf/unload4mod1.c
new file mode 100644
index 0000000000..38c5b0168d
--- /dev/null
+++ b/elf/unload4mod1.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+extern int bar (int);
+
+int
+foo (int x)
+{
+ puts ("in foo");
+ return bar (x / 2) + 2;
+}
diff --git a/elf/unload4mod2.c b/elf/unload4mod2.c
new file mode 100644
index 0000000000..497ef5d93b
--- /dev/null
+++ b/elf/unload4mod2.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int
+baz (int x)
+{
+ puts ("in baz");
+ return x * 4;
+}
diff --git a/elf/unload4mod3.c b/elf/unload4mod3.c
new file mode 100644
index 0000000000..4b280bc05b
--- /dev/null
+++ b/elf/unload4mod3.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+int
+__attribute__((noinline))
+mod3fn1 (int x)
+{
+ puts ("in mod3fn1");
+ return x + 6;
+}
+
+int
+mod3fn2 (int x)
+{
+ puts ("in mod3fn2");
+ return mod3fn1 (x / 2) * 2;
+}
diff --git a/elf/unload4mod4.c b/elf/unload4mod4.c
new file mode 100644
index 0000000000..ba5a144d38
--- /dev/null
+++ b/elf/unload4mod4.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+baz (int x)
+{
+ abort ();
+}
+
+int
+bar (int x)
+{
+ puts ("in bar");
+ return baz (x + 1) + 2;
+}
diff --git a/elf/unload5.c b/elf/unload5.c
new file mode 100644
index 0000000000..0555052ce8
--- /dev/null
+++ b/elf/unload5.c
@@ -0,0 +1,42 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+ void *g = dlopen ("unload3mod1.so", RTLD_GLOBAL | RTLD_NOW);
+ void *h = dlopen ("unload3mod2.so", RTLD_GLOBAL | RTLD_NOW);
+ if (g == NULL || h == NULL)
+ {
+ printf ("dlopen unload3mod{1,2}.so failed: %p %p\n", g, h);
+ return 1;
+ }
+ dlopen ("unload3mod4.so", RTLD_GLOBAL | RTLD_NOW);
+ dlclose (h);
+ dlclose (g);
+
+ g = dlopen ("unload3mod3.so", RTLD_GLOBAL | RTLD_NOW);
+ h = dlopen ("unload3mod4.so", RTLD_GLOBAL | RTLD_NOW);
+ if (g == NULL || h == NULL)
+ {
+ printf ("dlopen unload3mod{3,4}.so failed: %p %p\n", g, h);
+ return 1;
+ }
+
+ int (*fn) (int);
+ fn = dlsym (h, "bar");
+ if (fn == NULL)
+ {
+ puts ("dlsym failed");
+ return 1;
+ }
+
+ int val = fn (16);
+ if (val != 24)
+ {
+ printf ("bar returned %d != 24\n", val);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in
index edd73403ba..d933f18913 100644
--- a/fedora/glibc.spec.in
+++ b/fedora/glibc.spec.in
@@ -1,4 +1,4 @@
-%define glibcrelease 2.fc3.4
+%define glibcrelease 2.fc3.5
%define auxarches i586 i686 athlon sparcv9 alphaev6
%define prelinkarches noarch
%define nptlarches i386 i686 athlon x86_64 ia64 s390 s390x sparcv9 ppc ppc64
@@ -1270,6 +1270,9 @@ rm -f *.filelist*
%endif
%changelog
+* Sat Mar 19 2005 Jakub Jelinek <jakub@redhat.com> 2.3.4-2.fc3.5
+- better fix for the dlclose bug (#145810, #150414)
+
* Thu Mar 3 2005 Jakub Jelinek <jakub@redhat.com> 2.3.4-2.fc3.4
- fix dlclose (#145810)
- clear padding in gconv-modules.cache (#146614, BZ#776)
diff --git a/include/link.h b/include/link.h
index 3078b72a87..7c801e94ee 100644
--- a/include/link.h
+++ b/include/link.h
@@ -177,7 +177,7 @@ struct link_map
Elf_Symndx l_nbuckets;
const Elf_Symndx *l_buckets, *l_chain;
- unsigned int l_opencount; /* Counter for direct and indirect usage. */
+ unsigned int l_dummy_opencount; /* Used to be l_opencount, now unused. */
unsigned int l_direct_opencount; /* Reference count for dlopen/dlclose. */
enum /* Where this object came from. */
{
@@ -199,6 +199,8 @@ struct link_map
should be called on this link map
when relocation finishes. */
unsigned int l_used:1; /* Nonzero if the DSO is used. */
+ unsigned int l_removed:1; /* Nozero if the object cannot be used anymore
+ since it is removed. */
/* Array with version names. */
unsigned int l_nversions;
struct r_found_version *l_versions;
@@ -255,7 +257,7 @@ struct link_map
ElfW(Word) l_flags;
/* Temporarily used in `dl_close'. */
- unsigned int l_idx;
+ int l_idx;
struct link_map_machine l_mach;
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index ec68e1a565..ccd997cd89 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -783,6 +783,11 @@ extern void _dl_init (struct link_map *main_map, int argc, char **argv,
initializer functions have completed. */
extern void _dl_fini (void) internal_function;
+/* Sort array MAPS according to dependencies of the contained objects. */
+extern void _dl_sort_fini (struct link_map *l, struct link_map **maps,
+ size_t nmaps, char *used, Lmid_t ns)
+ internal_function;
+
/* The dynamic linker calls this function before and having changing
any shared object mappings. The `r_state' member of `struct r_debug'
says what change is taking place. This function's address is