2004-10-27  Ulrich Drepper  <drepper@redhat.com>

	* elf/dl-fini.c (_dl_fini): Fix search for map in maps array.
	Reverse order of namespaces.
	* elf/Makefile: Add rules to build and run tst-dlmopen3.
	* elf/tst-dlmopen3.c: New file.
	* elf/tst-dlmopen1mod.c: Add check whether constructor runs.
This commit is contained in:
Ulrich Drepper 2004-10-27 20:27:40 +00:00
parent 778cddad17
commit b1f6875087
4 changed files with 93 additions and 66 deletions

View File

@ -1,3 +1,11 @@
2004-10-27 Ulrich Drepper <drepper@redhat.com>
* elf/dl-fini.c (_dl_fini): Fix search for map in maps array.
Reverse order of namespaces.
* elf/Makefile: Add rules to build and run tst-dlmopen3.
* elf/tst-dlmopen3.c: New file.
* elf/tst-dlmopen1mod.c: Add check whether constructor runs.
2004-10-27 Jakub Jelinek <jakub@redhat.com>
* sysdeps/generic/glob.c (globfree): Clear gl_pathv after freeing it.

View File

@ -154,7 +154,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \
$(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2
tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3
# reldep9
test-srcs = tst-pathopt
tests-vis-yes = vismain
@ -770,3 +770,6 @@ $(objpfx)tst-dlmopen1.out: $(objpfx)tst-dlmopen1mod.so
$(objpfx)tst-dlmopen2: $(libdl)
$(objpfx)tst-dlmopen2.out: $(objpfx)tst-dlmopen1mod.so
$(objpfx)tst-dlmopen3: $(libdl)
$(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so

View File

@ -42,23 +42,18 @@ _dl_fini (void)
using `dlopen' there are possibly several other modules with its
dependencies to be taken into account. Therefore we have to start
determining the order of the modules once again from the beginning. */
unsigned int i;
unsigned int nloaded;
struct link_map *l;
struct link_map **maps = NULL;
size_t maps_size = 0;
/* We First run the destructors of the main namespaces, then the
other ones. The order should not matter since the namespace
content is supposed to be independent. But we can have auditing
code in a auxiliaty namespace and we want it to monitor the
destructors. */
for (Lmid_t cnt = 0; cnt < DL_NNS; ++cnt)
/* 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)
{
/* Protect against concurrent loads and unloads. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
nloaded = GL(dl_ns)[cnt]._ns_nloaded;
unsigned int nloaded = GL(dl_ns)[cnt]._ns_nloaded;
/* XXX Could it be (in static binaries) that there is no object
loaded? */
@ -79,20 +74,20 @@ _dl_fini (void)
nloaded * sizeof (struct link_map *));
}
unsigned int i;
struct link_map *l;
for (l = GL(dl_ns)[cnt]._ns_loaded, i = 0; l != NULL; l = l->l_next)
{
assert (i < nloaded);
/* Do not handle ld.so in secondary namespaces. */
if (l == l->l_real)
{
assert (i < nloaded);
/* Do not handle ld.so in secondary namespaces. */
if (l == l->l_real)
{
maps[i++] = l;
maps[i++] = l;
/* Bump l_opencount of all objects so that they are not
dlclose()ed from underneath us. */
++l->l_opencount;
}
}
/* Bump l_opencount of all objects so that they are not
dlclose()ed from underneath us. */
++l->l_opencount;
}
assert (cnt != LM_ID_BASE || i == nloaded);
assert (cnt == LM_ID_BASE || i == nloaded || i == nloaded - 1);
unsigned int nmaps = i;
@ -105,46 +100,23 @@ _dl_fini (void)
/* The main executable always comes first. */
l = l->l_next;
for (; l != NULL; l = l->l_next)
{
unsigned int j;
unsigned int k;
/* 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 the place in the 'maps' array. */
for (j = 1; maps[j] != l; ++j)
;
/* Find all object for which the current one is a dependency and
move the found object (if necessary) in front. */
for (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)
/* 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];
@ -152,14 +124,37 @@ _dl_fini (void)
memmove (&maps[j] + 1,
&maps[j],
(k - j) * sizeof (struct link_map *));
maps[j] = here;
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;
}
}
}
}
}
}
/* We do not rely on the linked list of loaded object anymore from

View File

@ -3,6 +3,16 @@
#include <gnu/lib-names.h>
static int cnt;
static void
__attribute ((constructor))
constr (void)
{
++cnt;
}
int
foo (Lmid_t ns2)
{
@ -34,5 +44,16 @@ foo (Lmid_t ns2)
return 1;
}
if (cnt == 0)
{
puts ("constructor did not run");
return 1;
}
else if (cnt != 1)
{
puts ("constructor did not run exactly once");
return 1;
}
return 0;
}