diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 5 | ||||
-rw-r--r-- | elf/dl-fini.c | 127 | ||||
-rw-r--r-- | elf/tst-dlmopen1mod.c | 21 |
3 files changed, 86 insertions, 67 deletions
diff --git a/elf/Makefile b/elf/Makefile index 0bec4abbb7..028be25b2d 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -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 diff --git a/elf/dl-fini.c b/elf/dl-fini.c index 33036b5cbd..f43f4a00ed 100644 --- a/elf/dl-fini.c +++ b/elf/dl-fini.c @@ -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; - - /* 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) + /* 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]; @@ -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 diff --git a/elf/tst-dlmopen1mod.c b/elf/tst-dlmopen1mod.c index 40a4c8fa44..142488098a 100644 --- a/elf/tst-dlmopen1mod.c +++ b/elf/tst-dlmopen1mod.c @@ -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; } |