diff --git a/ChangeLog b/ChangeLog index 9b2c359bb3..5520fce35d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2006-09-19 Ulrich Drepper + + * elf/dl-close.c (_dl_close): If dependency is not unloaded make + sure no reference to the unloaded map's search list remains in the + dependency's scope. + +2006-09-16 Jakub Jelinek + + * elf/Makefile: Add rules to build and run unload7 test. + * elf/unload7.c: New test. + * elf/unload7mod1.c: New file. + * elf/unload7mod2.c: New file. + 2006-09-18 Jakub Jelinek * sysdeps/unix/sysv/linux/sys/ptrace.h (PT_GETEVENTMSG): Fix pasto. diff --git a/elf/Makefile b/elf/Makefile index 6f4b0260c0..b1a9bab022 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -87,6 +87,7 @@ distribute := rtld-Rules \ unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c \ unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \ unload6mod1.c unload6mod2.c unload6mod3.c \ + unload7mod1.c unload7mod2.c \ tst-auditmod1.c tst-audit.sh \ order2mod1.c order2mod2.c order2mod3.c order2mod4.c \ tst-stackguard1.c tst-stackguard1-static.c \ @@ -168,7 +169,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ tst-align tst-align2 $(tests-execstack-$(have-z-execstack)) \ tst-dlmodcount tst-dlopenrpath tst-deep1 \ tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \ - unload3 unload4 unload5 unload6 tst-global1 order2 \ + unload3 unload4 unload5 unload6 unload7 tst-global1 order2 \ tst-audit1 tst-audit2 \ tst-stackguard1 tst-addr1 # reldep9 @@ -211,6 +212,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ unload3mod1 unload3mod2 unload3mod3 unload3mod4 \ unload4mod1 unload4mod2 unload4mod3 unload4mod4 \ unload6mod1 unload6mod2 unload6mod3 \ + unload7mod1 unload7mod2 \ order2mod1 order2mod2 order2mod3 order2mod4 ifeq (yes,$(have-initfini-array)) modules-names += tst-array2dep tst-array5dep @@ -455,6 +457,8 @@ $(objpfx)unload4mod2.so: $(objpfx)unload4mod4.so $(objpfx)unload4mod3.so $(objpfx)unload6mod1.so: $(libdl) $(objpfx)unload6mod2.so: $(libdl) $(objpfx)unload6mod3.so: $(libdl) +$(objpfx)unload7mod1.so: $(libdl) +$(objpfx)unload7mod2.so: $(objpfx)unload7mod1.so LDFLAGS-tst-tlsmod5.so = -nostdlib LDFLAGS-tst-tlsmod6.so = -nostdlib @@ -732,6 +736,10 @@ $(objpfx)unload6: $(libdl) $(objpfx)unload6.out: $(objpfx)unload6mod1.so $(objpfx)unload6mod2.so \ $(objpfx)unload6mod3.so +$(objpfx)unload7: $(libdl) +$(objpfx)unload7.out: $(objpfx)unload7mod1.so $(objpfx)unload7mod2.so +unload7-ENV = MALLOC_PERTURB_=85 + ifdef libdl $(objpfx)tst-tls9-static: $(common-objpfx)dlfcn/libdl.a $(objpfx)tst-tls9-static.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so diff --git a/elf/dl-close.c b/elf/dl-close.c index 754dd678fe..6a2ad976a7 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -1,5 +1,5 @@ /* Close a shared object opened by `_dl_open'. - Copyright (C) 1996-2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1996-2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -330,7 +330,7 @@ _dl_close (void *_map) for (cnt = 0; imap->l_scope[cnt] != NULL; ++cnt) /* This relies on l_scope[] entries being always set either - to its own l_symbolic_searchlist address, or some other map's + to its own l_symbolic_searchlist address, or some map's l_searchlist address. */ if (imap->l_scope[cnt] != &imap->l_symbolic_searchlist) { @@ -347,6 +347,21 @@ _dl_close (void *_map) } } } + else + { + unsigned int cnt = 0; + while (imap->l_scope[cnt] != NULL) + { + if (imap->l_scope[cnt] == &map->l_searchlist) + { + while ((imap->l_scope[cnt] = imap->l_scope[cnt + 1]) + != NULL) + ++cnt; + break; + } + ++cnt; + } + } /* The loader is gone, so mark the object as not having one. Note: l_idx != -1 -> object will be removed. */ diff --git a/elf/unload7.c b/elf/unload7.c new file mode 100644 index 0000000000..198f7db286 --- /dev/null +++ b/elf/unload7.c @@ -0,0 +1,39 @@ +#include +#include + +int +main (void) +{ + void *h = dlopen ("$ORIGIN/unload7mod1.so", RTLD_LAZY); + if (h == NULL) + { + puts ("dlopen unload7mod1.so failed"); + return 1; + } + + int (*fn) (void); + fn = dlsym (h, "foo"); + if (fn == NULL) + { + puts ("dlsym failed"); + return 1; + } + + int ret = 0; + if (fn () == 0) + ++ret; + + void *h2 = dlopen ("$ORIGIN/unload7mod2.so", RTLD_LAZY); + if (h2 == NULL) + { + puts ("dlopen unload7mod2.so failed"); + return 1; + } + dlclose (h2); + + if (fn () == 0) + ++ret; + + dlclose (h); + return ret; +} diff --git a/elf/unload7mod1.c b/elf/unload7mod1.c new file mode 100644 index 0000000000..7435adce2c --- /dev/null +++ b/elf/unload7mod1.c @@ -0,0 +1,11 @@ +#include +#include + +int +foo (int i) +{ + if (dlsym (RTLD_DEFAULT, "unload7_nonexistent_symbol") == NULL) + return 1; + puts ("dlsym returned non-NULL"); + return 0; +} diff --git a/elf/unload7mod2.c b/elf/unload7mod2.c new file mode 100644 index 0000000000..6d1a0d47b7 --- /dev/null +++ b/elf/unload7mod2.c @@ -0,0 +1 @@ +int x;